Momentum-based ZigZag (incl. QQE) NON-REPAINTING TradingView

0

 I spent a lot of time searching for the best ZigZag indicator . Difficulty with all of them is that they are always betting on some pre-defined rules which identify or confirm pivot points . Usually it is time factor - pivot point gets confirmed after a particular number of candles. This methodology is probably the best when market is moving relatively slow, but when price starts chopping up and down, there is no way the ZigZag follows accurately. On the other hand if you set it too tight (for example pivot confirmation after only 2 or even 1 candle), you will get hundreds of zigzag lines and they will tell you nothing.


My point of view is to follow the market. If it has reversed, then it has reversed, and there is no need to wait pre-defined number of candles for the confirmation. Such reversals will always be visible on momentum indicators, such as the most popular MACD . But a single-line moving average can be also good enough to notice reversals. Or my favourite one - QQE, which I borrowed (and improved) from JustUncleL, who borrowed it from Glaz, who borrowed it from... I don't even know where Quantitative Qualitative Estimation originates from. Thanks to all these guys for their input and code.

So whichever momentum indicator you choose - yes, there is a pick-your-poison-type selector as in in-famous Moving Average indicators - once it reverses, a highest (or lowest) point from the impulse is caught and ZigZag gets printed.

One thing I need to emphasize. This indicator DOES NOT REPAINT. It might look like the lines are a bit delayed, especially when compared to all the other ZigZag indicators on TradingView, but they are actually TRUE. There is a value in this - my indicator prints pivot points and Zigzag exactly on the moment they have been noticed, not earlier faking to be faster than they could be.

As a bonus, the indicator marks which impulse had strength in it. It is very nice to see a progressing impulse, but without force - a very likely that reversal on a bigger move is happening.

I'm about to publish some more scripts based on this ZigZag algo, so follow me on TradingView to get notified.

Enjoy!
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Peter_O
 
//@version=4
study("Momentum-based ZigZag", overlay=true)

var int momentum_direction = 0
color_zigzag_lines = input(true, title="Color ZigZag lines to show force direction")
momentum_select = input(title="Select Momentum Indicator:", defval="QQE", options=["MACD", "MovingAverage", "QQE"])


// ZigZag function {
zigzag(_momentum_direction) =>
    zz_goingup=_momentum_direction==1
    zz_goingdown=_momentum_direction==-1
    var float zz_peak=na
    var float zz_bottom=na
    zz_peak := (high > zz_peak[1] and zz_goingup) or (zz_goingdown[1] and zz_goingup) ? high : nz(zz_peak[1])
    zz_bottom := (low < zz_bottom[1] and zz_goingdown) or (zz_goingup[1] and zz_goingdown) ? low : nz(zz_bottom[1])
    zigzag = zz_goingup and zz_goingdown[1] ? zz_bottom[1] : zz_goingup[1] and zz_goingdown ? zz_peak[1] : na
// } End of ZigZag function

// MACD  {
fast_length = input(title="Fast Length", type=input.integer, defval=12, group="if MACD Selected", inline="macd")
slow_length = input(title="Slow Length", type=input.integer, defval=26, group="if MACD Selected", inline="macd")
src = input(title="Source", type=input.source, defval=close, group="if MACD Selected", inline="macd")
signal_length = input(title="Signal Smoothing", type=input.integer, minval = 1, maxval = 50, defval = 9, group="if MACD Selected", inline="macd")
sma_source = input(title="Oscillator MA Type", type=input.string, defval="EMA", options=["SMA", "EMA"], group="if MACD Selected", inline="macd")
sma_signal = input(title="Signal Line MA Type", type=input.string, defval="EMA", options=["SMA", "EMA"], group="if MACD Selected", inline="macd")

fast_ma = sma_source == "SMA" ? sma(src, fast_length) : ema(src, fast_length)
slow_ma = sma_source == "SMA" ? sma(src, slow_length) : ema(src, slow_length)
macd = fast_ma - slow_ma
signal = sma_signal == "SMA" ? sma(macd, signal_length) : ema(macd, signal_length)

macdUP = crossover(macd,signal)
macdDOWN = crossunder(macd,signal)
// } End of MACD

// Moving Averages {
smoothing_type = input(title="Average type", defval="SMA", options=["EMA", "SMA", "WMA", "VWMA", "HMA", "RMA", "DEMA"], inline="movingaverage", group="if Moving Average selected")
ma_length = input(20, title="Length", inline="movingaverage", group="if Moving Average selected")
moving_average(_series,_length,_smoothing) =>
      _smoothing=="EMA" ? ema(_series,_length) :
      _smoothing=="SMA" ? sma(_series,_length) :
      _smoothing=="WMA" ? wma(_series,_length) :
      _smoothing=="VWMA" ? vwma(_series,_length) :
      _smoothing=="HMA" ? hma(_series,_length) :
      _smoothing=="RMA" ? rma(_series,_length) :
      _smoothing=="DEMA" ? 2 * ema(_series, _length) - ema(ema(_series, _length), _length) : 
      ema(_series,_length)
movingaverage=moving_average(close,ma_length,smoothing_type)
maUP = movingaverage>movingaverage[1] and movingaverage[2]>movingaverage[1]
maDOWN = movingaverage
    RSI_Period = _RSI_Period
    SF = _smoothingfactor
    QQE = _qqefactor 
    ThreshHold = _threshold 
    Wilders_Period = RSI_Period * 2 - 1
    Rsi = _rsi
    RsiMa = ema(Rsi, SF)
    AtrRsi = abs(RsiMa[1] - RsiMa)
    MaAtrRsi = ema(AtrRsi, Wilders_Period)
    dar = ema(MaAtrRsi, Wilders_Period) * QQE
    longband = 0.0
    shortband = 0.0
    trend = 0
    DeltaFastAtrRsi = dar
    RSIndex = RsiMa
    newshortband = RSIndex + DeltaFastAtrRsi
    newlongband = RSIndex - DeltaFastAtrRsi
    longband := RSIndex[1] > longband[1] and RSIndex > longband[1] ? max(longband[1], newlongband) : newlongband
    shortband := RSIndex[1] < shortband[1] and RSIndex < shortband[1] ? min(shortband[1], newshortband) : newshortband
    QQExlong = 0
    QQExlong := nz(QQExlong[1])
    QQExshort = 0
    QQExshort := nz(QQExshort[1])
    qqe_goingup=barssince(QQExlong == 1)barssince(QQExshort == 1)
    var float last_qqe_high=high
    var float last_qqe_low=low
    last_qqe_high := (high > last_qqe_high[1] and qqe_goingup) or (qqe_goingdown[1] and qqe_goingup) ? high : nz(last_qqe_high[1])
    last_qqe_low := (low < last_qqe_low[1] and qqe_goingdown) or (qqe_goingup[1] and qqe_goingdown) ? low : nz(last_qqe_low[1])
    trend := crossover(RSIndex, shortband[1]) or crossover(high,last_qqe_high) ? 1 : crossunder(RSIndex, longband[1]) or crossunder(low,last_qqe_low) ? -1 : nz(trend[1], 1)
    FastAtrRsiTL = trend == 1 ? longband : shortband
    // Find all the QQE Crosses
    QQExlong := trend==1 and trend[1]==-1 ? QQExlong + 1 : 0
    QQExshort := trend==-1 and trend[1]==1 ? QQExshort + 1 : 0
    qqeLong = QQExlong == 1 ? FastAtrRsiTL[1] - 50 : na
    qqeShort = QQExshort == 1 ? FastAtrRsiTL[1] - 50 : na
    qqenew = qqeLong ? 1 : qqeShort ? -1 : na
    qqenew

qqeUP= qqenew(qqeslow,SFslow,rsi_currenttf,ThreshHold,RSI_Period)==1 
qqeDOWN= qqenew(qqeslow,SFslow,rsi_currenttf,ThreshHold,RSI_Period)==-1 
// } End of QQE


momentumUP=
     momentum_select=="MACD" ? macdUP : 
     momentum_select=="MovingAverage" ? maUP : 
     momentum_select=="QQE" ? qqeUP :
     qqeUP

momentumDOWN=
     momentum_select=="MACD" ? macdDOWN : 
     momentum_select=="MovingAverage" ? maDOWN : 
     momentum_select=="QQE" ? qqeDOWN :
     qqeDOWN

momentum_direction := momentumUP ? 1 : momentumDOWN ? -1 : nz(momentum_direction[1])

// { Force detection
rsi5=rsi(close,5)
ob=80
os=20
barssince_momentumUP=barssince(momentumUP)
barssince_momentumDOWN=barssince(momentumDOWN)
momentum_DOWN_was_force_up = momentumDOWN and (barssince_momentumUP>=barssince(rsi5>ob))[1]
momentum_UP_was_force_down = momentumUP and (barssince_momentumDOWN>=barssince(rsi5

Post a Comment

0 Comments
* Please Don't Spam Here. All the Comments are Reviewed by Admin.
Post a Comment (0)

buttons=(Accept !) days=(20)

Our website uses cookies to enhance your experience. Learn More
Accept !
To Top