Indicator: conversion of Volume-Weighted Price Z-Score

Viewing 2 posts - 1 through 2 (of 2 total)
  • Author
    Posts
  • #258730 quote
    regus
    Participant
    Veteran




    // This script is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International

    // https://creativecommons.org/licenses/by-nc-sa/4.0/

    // © QuantAlgo


    //@version=6

    indicator(‘Volume-Weighted Price Z-Score [QuantAlgo]’, overlay = false)


    //              ╔════════════════════════════════╗              //

    //              ║      USER-DEFINED SETTINGS     ║              //

    //              ╚════════════════════════════════╝              //


    var string calculation_settings = ‘════════ Calculation Parameters ════════’

    var string visual_settings = ‘════════ Visualization Settings ════════’

    var string alert_settings = ‘════════ Alert Configuration ════════’


    tooltip_price_source = ‘The price data used for calculations. Close is most common for end-of-period analysis. High/Low can be used for extremes, HL2 for midpoint, HLC3 for typical price, or OHLC4 for complete bar representation. Each source provides different sensitivity to price movements.’

    tooltip_lookback = ‘Period for calculating the volume-weighted moving average and volatility baseline. Shorter periods (20-50) make the indicator more responsive to recent price changes, capturing short-term deviations quickly. Longer periods (100-200) provide more stable reference points, better for identifying major market dislocations. Match this to your trading timeframe.’

    tooltip_smoothing = ‘EMA smoothing applied to the final z-score to reduce noise and create cleaner signals. Lower values (1-3) preserve more detail and react faster but may show more false signals. Higher values (5-10) create smoother curves with fewer whipsaws but slower response. Set to 1 for no smoothing.’

    tooltip_preset = ‘Select a predefined configuration optimized for different analysis styles and market conditions.’

    tooltip_preset_details = ‘Default (100, 5): Balanced configuration suitable for swing trading and daily/4H analysis. Provides good balance between responsiveness and stability. Works well for identifying medium-term overbought/oversold conditions.nnFast Response (50, 3): Faster configuration for intraday trading and scalping. Shorter lookback period and minimal smoothing catch price deviations quickly. Best for 15min-1H charts where rapid mean reversion opportunities are important. Expect more frequent signals.nnSmooth Trend (200, 8): Stable configuration for position trading and long-term analysis. Extended lookback and heavy smoothing filter out noise to identify only major market extremes. Ideal for daily-weekly charts where you want high-confidence deviation signals with minimal false positives.’

    tooltip_extreme_threshold = ‘Z-score threshold for marking extreme deviation levels. Values above +threshold indicate extreme overvaluation, values below -threshold indicate extreme undervaluation. Standard values: 2.0 (95.4% confidence), 2.5 (98.8% confidence), 3.0 (99.7% confidence). Higher thresholds identify rarer, more extreme conditions.’

    tooltip_color_preset = ‘Pre-configured color schemes optimized for different chart themes and visual preferences. Each preset maintains strong contrast for clear identification of positive vs negative deviations.’

    tooltip_positive_color = ‘Color for positive z-score values (price above volume-weighted average). Represents conditions where the asset may be overvalued relative to its volume-weighted price. Typically shown in warm colors (red, orange) to indicate caution.’

    tooltip_negative_color = ‘Color for negative z-score values (price below volume-weighted average). Represents conditions where the asset may be undervalued relative to its volume-weighted price. Typically shown in cool colors (cyan, blue, green) to indicate potential buying opportunities.’

    tooltip_fill_transparency = ‘Transparency level for the gradient fill area between the z-score line and zero line. Higher values (70-95) create a more subtle, transparent background. Lower values (20-40) create a more solid, prominent fill that clearly highlights deviations. Set to 100 for completely transparent (no fill).’

    tooltip_bar_coloring = ‘Enable/disable coloring of indicator bars based on the z-score gradient color. When enabled, the background bars of the indicator pane are colored to match the current z-score deviation, providing additional visual context for positive vs negative deviations.’


    priceSource = input.source(close, ‘Price Source’, group = calculation_settings, tooltip = tooltip_price_source)

    lookbackPeriod = input.int(100, ‘Lookback Period’, group = calculation_settings, tooltip = tooltip_lookback)

    smoothingPeriod = input.int(5, ‘Smoothing Period’, minval = 1, group = calculation_settings, tooltip = tooltip_smoothing)


    presetConfig = input.string(‘Default’, ‘Preset Configuration’, options = [‘Default’, ‘Fast Response’, ‘Smooth Trend’], group = calculation_settings, tooltip = tooltip_preset + ‘nn’ + tooltip_preset_details)


    if presetConfig == ‘Fast Response’

        lookbackPeriod := 50

        smoothingPeriod := 3

        smoothingPeriod

    else if presetConfig == ‘Smooth Trend’

        lookbackPeriod := 200

        smoothingPeriod := 8

        smoothingPeriod


    extremeThreshold = input.float(2.5, ‘Extreme Threshold’, minval = 1.0, maxval = 4.0, step = 0.5, group = calculation_settings, tooltip = tooltip_extreme_threshold)


    colorPreset = input.string(‘Custom’, ‘Color Preset’, options = [‘Classic’, ‘Aqua’, ‘Cosmic’, ‘Ember’, ‘Neon’, ‘Custom’], group = visual_settings, tooltip = tooltip_color_preset)

    positiveColorInput = input.color(#ff0000, ‘Positive Deviation Color’, group = visual_settings, tooltip = tooltip_positive_color)

    negativeColorInput = input.color(#00ffaa, ‘Negative Deviation Color’, group = visual_settings, tooltip = tooltip_negative_color)

    fillTransparency = input.int(70, ‘Fill Transparency’, minval = 0, maxval = 100, group = visual_settings, tooltip = tooltip_fill_transparency)

    enableBarColoring = input.bool(true, ‘Enable Bar Coloring’, group = visual_settings, tooltip = tooltip_bar_coloring)


    [positiveColor, negativeColor] = switch colorPreset

        ‘Classic’ => [#ff0000, #00ff00]

        ‘Aqua’ => [#ff8c00, #00bfff]

        ‘Cosmic’ => [#9932cc, #49ffce]

        ‘Ember’ => [#00cccc, #ff6600]

        ‘Neon’ => [#ff00ff, #ffff00]

        ‘Custom’ => [positiveColorInput, negativeColorInput]


    //              ╔════════════════════════════════╗              //

    //              ║      Z-SCORE CALCULATION       ║              //

    //              ╚════════════════════════════════╝              //


    volumeWeightedAverage = ta.vwma(priceSource, lookbackPeriod)

    logDeviation = math.log(priceSource / volumeWeightedAverage)

    volatilityMeasure = ta.stdev(logDeviation, lookbackPeriod)


    rawZScore = logDeviation / volatilityMeasure

    zScore = ta.ema(rawZScore, smoothingPeriod)


    //              ╔════════════════════════════════╗              //

    //              ║    SIGNAL & LEVEL DETECTION    ║              //

    //              ╚════════════════════════════════╝              //


    extremePositive = zScore >= extremeThreshold

    extremeNegative = zScore <= extremeThreshold


    crossAboveZero = ta.crossover(zScore, 0)

    crossBelowZero = ta.crossunder(zScore, 0)


    enterExtremePositive = ta.crossover(zScore, extremeThreshold)

    enterExtremeNegative = ta.crossunder(zScore, extremeThreshold)

    exitExtremePositive = ta.crossunder(zScore, extremeThreshold)

    exitExtremeNegative = ta.crossover(zScore, extremeThreshold)


    //              ╔════════════════════════════════╗              //

    //              ║         VISUALIZATION          ║              //

    //              ╚════════════════════════════════╝              //


    var color neutralColor = #808080


    gradientColor = zScore > 0 ?

         color.from_gradient(zScore, 0, extremeThreshold, neutralColor, positiveColor) :

         color.from_gradient(zScore, extremeThreshold, 0, negativeColor, neutralColor)


    zScorePlot = plot(zScore, color = gradientColor, linewidth = 3, title = ‘Z-Score’)


    zeroLinePlot = plot(0, color = color.new(color.gray, 50), title = ‘Zero Line’, linestyle = plot.linestyle_dotted, editable = true)


    fill(zScorePlot, zeroLinePlot, zScore, 0, color.new(gradientColor, fillTransparency), color.new(gradientColor, math.min(fillTransparency + 20, 100)), title = ‘Z-Score Fill’)


    plot(extremeThreshold, ‘Extreme Positive Level’, color = positiveColor, linestyle = plot.linestyle_dashed, editable = true)

    plot(extremeThreshold, ‘Extreme Negative Level’, color = negativeColor, linestyle = plot.linestyle_dashed, editable = true)


    plot(2, ‘+2σ’, color = color.new(color.gray, 50), linestyle = plot.linestyle_dotted, editable = true, display = display.none)

    plot(-2, ‘-2σ’, color = color.new(color.gray, 50), linestyle = plot.linestyle_dotted, editable = true, display = display.none)

    plot(1, ‘+1σ’, color = color.new(color.gray, 50), linestyle = plot.linestyle_dotted, editable = true)

    plot(-1, ‘-1σ’, color = color.new(color.gray, 50), linestyle = plot.linestyle_dotted, editable = true)


    barcolor(enableBarColoring ? gradientColor : na, title = ‘Z-Score Bar Color’)


    //              ╔════════════════════════════════╗              //

    //              ║             ALERTS             ║              //

    //              ╚════════════════════════════════╝              //


    alertcondition(enterExtremePositive, title = ‘Extreme Overbought’, message = ‘VWPZ: Extreme OVERBOUGHT condition detected! {{exchange}}:{{ticker}} – {{interval}}’)

    alertcondition(enterExtremeNegative, title = ‘Extreme Oversold’, message = ‘VWPZ: Extreme OVERSOLD condition detected! {{exchange}}:{{ticker}} – {{interval}}’)


    alertcondition(exitExtremePositive, title = ‘Exit Extreme Overbought’, message = ‘VWPZ: Exiting extreme overbought zone {{exchange}}:{{ticker}} – {{interval}}’)

    alertcondition(exitExtremeNegative, title = ‘Exit Extreme Oversold’, message = ‘VWPZ: Exiting extreme oversold zone {{exchange}}:{{ticker}} – {{interval}}’)


    alertcondition(crossAboveZero, title = ‘Bullish Mean Reversion’, message = ‘VWPZ: Crossed above zero – Bullish momentum {{exchange}}:{{ticker}} – {{interval}}’)

    alertcondition(crossBelowZero, title = ‘Bearish Mean Reversion’, message = ‘VWPZ: Crossed below zero – Bearish momentum {{exchange}}:{{ticker}} – {{interval}}’)


    alertcondition(enterExtremePositive or enterExtremeNegative, title = ‘Any Extreme Level’, message = ‘VWPZ: Extreme deviation detected! Check chart {{exchange}}:{{ticker}} – {{interval}}’)



    #258734 quote
    Nicolas
    Keymaster
    Master

    Quick friendly reminder before we dive in: a small hello and a bit of context about what you are looking for goes a long way here. Everyone helping out is doing it voluntarily, so a little courtesy is always appreciated. It costs nothing and makes people a lot more eager to jump in. Thank you.

Viewing 2 posts - 1 through 2 (of 2 total)
  • You must be logged in to reply to this topic.

TradingView to ProRealTime Translation Center

New Reply
Author
author-avatar
regus @regus Participant
Summary

This topic contains 1 reply,
has 2 voices, and was last updated by Nicolas
6 hours, 43 minutes ago.

Topic Details
Forum: TradingView to ProRealTime Translation Center Forum
Started: 03/04/2026
Status: Active
Attachments: No files
Logo Logo
Loading...