Indicator · Pine Script v4 · Own pane

Whiplash

by Anderson-ALGO· code credited to eylwithsteph

Whiplash is a separate-pane indicator that smooths the difference between close and open with a user-selected moving average, then converts that series into a Z-score over a fixed lookback.

View on GitHub

GitHub stars9on the repository
Pine versionv4older, still runs
Lines of code430
Settings5inputs
LicenceNone statedfile: MPL-2.0
Last update5 years ago30 Nov 2020

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

430 lines of Pine Script v4 from Pine/PineScript/Miscellaneous/WhipLash.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

WhipLash.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © eylwithsteph
// This is a study to determine if small candles bodies (little difference between open and close) regardless of overall candle length (high/low)
// can be used to filter choppy markets. The indicator will calculate the selected average "MA Mode" of (close-open). To standardize this result
// and ensure any filters/thresholds do not need to be recalculated for each instrument the result will be used to calculate the Z Score. 
// The idea is that when candle bodies are small there is very little actual price movement, and therefore price is choppy. When considering the
// Z Score of that result, any outliers ie larger candle bodies, could show a potential trend forming. This indicator is similar to QStick but
// allows more customization by the user
// Multiple MA Options Credits to @Fractured
// Bits and Pieces from @AlexGrover, @Montyjus, and @Jiehonglim 
// As always, trade at your own risk. 
//@version=4
study("Whiplash", resolution="")

PriceSmoothing = input(15, title="Price Smoothing")

Mode = input(title = "MA Mode", defval="SMMA", options=["TMA","ALMA", "EMA", "DEMA", "TEMA", "WMA", "VWMA", "SMA", "SMMA", "HMA", "LSMA", "JMA", "VAMA", "FRAMA", "ZLEMA", "KAMA", "Kijun", "Kijun v2", "McGinley", "IDWMA", "FLMSA", "PEMA", "HCF", "TIF", "MF", "ARMA", "DAF","WRMA", "RMA", "RAF", "GF", "A2RMA", "EDSMA"])

vq0_th = input(1.68, title="Threshold 1")
vq0_th2 = input(1.96, title="Threshold 2")
vq0_th3 = input(2.58, title="Threshold 3")

vq0_mid = 0

zlength = 100
    
lsma_offset  = 0
alma_offset  = 0.85
alma_sigma   = 6
jurik_phase = 50
jurik_power = 2
volatility_lookback =51
frama_FC = 1
frama_SC = 200
kama_fast_len = 2
kama_slow_len = 30
center = 10

//MF
beta = 0.8
feedback = false
z = 0.5
//ARMA
gamma = 3
zl = false

//GF
zeta = 1

//EDSMA
ssfLength = 20
ssfPoles = 2

//IDWMA
calcWeight(src, length, i) =>
    distanceSum = 0.0
    for j = 0 to length - 1
        distanceSum := distanceSum + abs(nz(src[i]) - nz(src[j]))
    distanceSum

//HCF
//study("Hybrid Convolution Filter",overlay=true)
//length = input(14)
//----
f(x) => 
    .5*(1 - cos(x*3.14159))

d(x,length) => 
    f(x/length) - f((x-1)/length)
//----
filter(a,b,length) =>
    sum = 0.
    for i = 1 to length
        sgn = f(i/length)
        sum := sum + (sgn*b + (1 - sgn)*a[i-1]) * d(i,length)
    sum
//----

//A2RMA
ama(er,x)=>
    a = 0.
    a := er*x+(1-er)*nz(a[1],x)


//EDSMA
get2PoleSSF(src, length) =>
    PI = 2 * asin(1)
    arg = sqrt(2) * PI / length
    a1 = exp(-arg)
    b1 = 2 * a1 * cos(arg)
    c2 = b1
    c3 = -pow(a1, 2)
    c1 = 1 - c2 - c3
    
    ssf = 0.0
    ssf := c1 * src + c2 * nz(ssf[1]) + c3 * nz(ssf[2])

get3PoleSSF(src, length) =>
    PI = 2 * asin(1)

    arg = PI / length
    a1 = exp(-arg)
    b1 = 2 * a1 * cos(1.738 * arg)
    c1 = pow(a1, 2)

    coef2 = b1 + c1
    coef3 = -(c1 + b1 * c1)
    coef4 = pow(c1, 2)
    coef1 = 1 - coef2 - coef3 - coef4

    ssf = 0.0
    ssf := coef1 * src + coef2 * nz(ssf[1]) + coef3 * nz(ssf[2]) + coef4 * nz(ssf[3])


ma(type, src, len) =>
    float result = 0
    if type=="TMA"
        result := sma(sma(src, ceil(len / 2)), floor(len / 2) + 1)
    if type=="SMA" // Simple
        result := sma(src, len)
    if type=="EMA" // Exponential
        result := ema(src, len)
    if type=="DEMA" // Double Exponential
        e = ema(src, len)
        result := 2 * e - ema(e, len)
    if type=="TEMA" // Triple Exponential
        e = ema(src, len)
        result := 3 * (e - ema(e, len)) + ema(ema(e, len), len)
    if type=="WMA" // Weighted
        result := wma(src, len)
    if type=="VWMA" // Volume Weighted
        result := vwma(src, len) 
    if type=="SMMA" // Smoothed
        w = wma(src, len)
        result := na(w[1]) ? sma(src, len) : (w[1] * (len - 1) + src) / len
    if type=="HMA" // Hull
        result := wma(2 * wma(src, len / 2) - wma(src, len), round(sqrt(len)))
    if type=="LSMA" // Least Squares
        result := linreg(src, len, lsma_offset)
    if type=="ALMA" // Arnaud Legoux
        result := alma(src, len, alma_offset, alma_sigma)
    if type=="JMA" // Jurik
        /// Copyright © 2018 Alex Orekhov (everget)
        /// Copyright © 2017 Jurik Research and Consulting.
        phaseRatio = jurik_phase < -100 ? 0.5 : jurik_phase > 100 ? 2.5 : jurik_phase / 100 + 1.5
        beta = 0.45 * (len - 1) / (0.45 * (len - 1) + 2)
        alpha = pow(beta, jurik_power)
        jma = 0.0
        e0 = 0.0
        e0 := (1 - alpha) * src + alpha * nz(e0[1])
        e1 = 0.0
        e1 := (src - e0) * (1 - beta) + beta * nz(e1[1])
        e2 = 0.0
        e2 := (e0 + phaseRatio * e1 - nz(jma[1])) * pow(1 - alpha, 2) + pow(alpha, 2) * nz(e2[1])
        jma := e2 + nz(jma[1])
        result := jma
    if type=="VAMA" // Volatility Adjusted
        /// Copyright © 2019 to present, Joris Duyck (JD)
        mid=ema(src,len)
        dev=src-mid
        vol_up=highest(dev,volatility_lookback)
        vol_down=lowest(dev,volatility_lookback)
        result := mid+avg(vol_up,vol_down)
    if type=="FRAMA" // Fractal Adaptive
        int len1 = len/2
        e = 2.7182818284590452353602874713527
        w = log(2/(frama_SC+1)) / log(e) // Natural logarithm (ln(2/(SC+1))) workaround
        H1 = highest(high,len1)
        L1 = lowest(low,len1)
        N1 = (H1-L1)/len1
        H2_ = highest(high,len1)
        H2 = H2_[len1]
        L2_ = lowest(low,len1)
        L2 = L2_[len1]
        N2 = (H2-L2)/len1
        H3 = highest(high,len)
        L3 = lowest(low,len)
        N3 = (H3-L3)/len
        dimen1 = (log(N1+N2)-log(N3))/log(2)
        dimen = iff(N1>0 and N2>0 and N3>0,dimen1,nz(dimen1[1]))
        alpha1 = exp(w*(dimen-1))
        oldalpha = alpha1>1?1:(alpha1<0.01?0.01:alpha1)
        oldN = (2-oldalpha)/oldalpha
        N = (((frama_SC-frama_FC)*(oldN-1))/(frama_SC-1))+frama_FC
        alpha_ = 2/(N+1)
        alpha = alpha_<2/(frama_SC+1)?2/(frama_SC+1):(alpha_>1?1:alpha_)
        frama = 0.0
        frama :=(1-alpha)*nz(frama[1]) + alpha*src
        result := frama
    if type=="ZLEMA" // Zero-Lag EMA
        f_lag = (len - 1) / 2
        f_data = src + (src - src[f_lag])
        result := ema(f_data, len)
    if type=="KAMA" // Kaufman Adaptive
        mom = abs(change(src, len))
        volatility = sum(abs(change(src)), len)
        er = volatility != 0 ? mom / volatility : 0
        fastAlpha = 2 / (kama_fast_len + 1)
        slowAlpha = 2 / (kama_slow_len + 1)
        sc = pow((er * (fastAlpha - slowAlpha)) + slowAlpha, 2)
        kama = 0.0
        kama := sc * src + (1 - sc) * nz(kama[1])
        result := kama
    if type=="Kijun" //Kijun-sen
        kijun = avg(lowest(len), highest(len))
        result :=kijun
    if type=="Kijun v2"
        kijun = avg(lowest(len), highest(len))
        conversionLine = avg(lowest(len/2), highest(len/2))
        delta = (kijun + conversionLine)/2
        result :=delta
    if type=="McGinley"
        mg = 0.0
        mg := na(mg[1]) ? ema(src, len) : mg[1] + (src - mg[1]) / (len * pow(src/mg[1], 4))
        result :=mg
    if type=="IDWMA"
        sum = 0.0
        weightSum = 0.0
        for i = 0 to len - 1
            weight = calcWeight(src, len, i)
            sum := sum + nz(src[i]) * weight
            weightSum := weightSum + weight
        idwma = sum / weightSum
        result := idwma
    if type=="FLMSA"
        n = bar_index
        b = 0.
        e = sma(abs(src - nz(b[1])),len)
        z = sma(src - nz(b[1],src),len)/e 
        r = (exp(2*z) - 1)/(exp(2*z) + 1) 
        a = (n - sma(n,len))/stdev(n,len) * r
        b := sma(src,len) + a*stdev(src,len)    
        result := b
    if type=="PEMA"
        // Copyright (c) 2010-present, Bruno Pio
        // Copyright (c) 2019-present, Alex Orekhov (everget)
        // Pentuple Exponential Moving Average script may be freely distributed under the MIT license.
        ema1 = ema(src, len)
        ema2 = ema(ema1, len)
        ema3 = ema(ema2, len)
        ema4 = ema(ema3, len)
        ema5 = ema(ema4, len)
        ema6 = ema(ema5, len)
        ema7 = ema(ema6, len)
        ema8 = ema(ema7, len)
        pema = 8 * ema1 - 28 * ema2 + 56 * ema3 - 70 * ema4 + 56 * ema5 - 28 * ema6 + 8 * ema7 - ema8    
        result := pema
    if type=="HCF"
        output = 0.
        output := filter(src, nz(output[1],src), len)
        result := output
    if type=="TIF"
        b = 0.0
        a = rising(src,len) or falling(src,len) ? 1 : 0
        b := ema(a*src+(1-a)*nz(b[1],src),center)
        result := b
    if type=="MF"
        ts=0.,b=0.,c=0.,os=0.
        //----
        alpha = 2/(len+1)
        a = feedback ? z*src + (1-z)*nz(ts[1],src) : src
        //----
        b := a > alpha*a+(1-alpha)*nz(b[1],a) ? a : alpha*a+(1-alpha)*nz(b[1],a)
        c := a < alpha*a+(1-alpha)*nz(c[1],a) ? a : alpha*a+(1-alpha)*nz(c[1],a)
        os := a == b ? 1 : a == c ? 0 : os[1]
        //----
        upper = beta*b+(1-beta)*c
        lower = beta*c+(1-beta)*b 
        ts := os*upper+(1-os)*lower
        result := ts
    if type=="ARMA"
    //----
        ma = 0.
        mad = 0.
        //----
        src2 = zl ? src + change(src,len/2) : src
        ma := nz(mad[1],src2)
        d = cum(abs(src2[len] - ma))/bar_index * gamma
        mad := sma(sma(src2 > nz(mad[1],src2) + d ? src2 + d : src2 < nz(mad[1],src) - d ? src2 - d : nz(mad[1],src2),len),len)
        result := mad
    if type=="DAF"
        AC = zl ? 1 : 0
        out = 0.
        K = 0.
        //----
        src2 = src + (src - nz(out[1],src))
        out := nz(out[1],src2) + nz(K[1])*(src2 - nz(out[1],src2)) + AC*(nz(K[1])*(src2 - sma(src2,len)))
        K := abs(src2 - out)/(abs(src2 - out) + stdev(src2,len)*len)
        result := out
    if type=="WRMA"
        //----
        alpha = 2/(len+1)
        p1 = zl ? len/4 : 1
        p2 = zl ? len/4 : len/2
        //----
        a = 0.0
        b = 0.0
        A = 0.0
        B = 0.0
        a := nz(a[1]) + alpha*nz(A[1]) 
        b := nz(b[1]) + alpha*nz(B[1])
        y = ema(a + b,p1)
        A := src - y
        B := src - ema(y,p2)
        result := y
        //----
    if type=="RMA"
        ma = sma(src,len*3) + sma(src,len*2) - sma(src,len)
        result := ma
    if type=="RAF"
        altma = 0.0
        AR = 2*(highest(len) - lowest(len))
        BR = 2*(highest(len*2) - lowest(len*2))
        k1 = (1 - AR)/AR
        k2 = (1 - BR)/BR
        //
        alpha = k2/k1
        R1 = sqrt(highest(len))/4 * ((alpha - 1)/alpha) * (k2/(k2 + 1))
        R2 = sqrt(highest(len*2))/4 * (alpha - 1) * (k1/(k1 + 1))
        Factor = R2/R1 
        //
        AltK = fixnan(pow(Factor >= 1 ? 1 : Factor,sqrt(len)))*(1/len)
        altma := AltK*src+(1-AltK)*nz(altma[1],src)
        result := altma
    if type=="GF"
        ////////////////////////////////////////////////////////////////
        //Coefficients Table :
        //
        //MA : beta = 2/gamma = 0.5
        //EMA : beta = 3/gamma = 0.4
        //HMA = beta = 4/gamma = 0.85
        //LSMA : beta = 3.5/gamma = 0.9 
        //QLSMA : beta = 5.25/gamma = 1
        //JMA : beta = pow*2/gamma = 0.5
        //3 Poles Butterworth Filter : beta = 5.5/gamma = 0.5/zeta = 0
        //
        ////////////////////////////////////////////////////////////////
        b = 0.0
        d = 0.0
        p = len/beta
        a = src - nz(b[p],src)
        b := nz(b[1],src) + a/p*gamma
        c = b - nz(d[p],b)
        d := nz(d[1],src) + (zeta*a+(1-zeta)*c)/p*gamma
        result := d
    if type=="A2RMA"
        er = abs(change(src,len))/sum(abs(change(src)),len)
        //----
        ma = 0.
        d = cum(abs(src - nz(ma[1],src)))/bar_index * gamma
        ma := ama(er,ama(er,src > nz(ma[1],src) + d ? src + d : src < nz(ma[1],src) - d ? src - d : nz(ma[1],src)))
        //----
        result := ma
    if type=="EDSMA"
    
        zeros = src - nz(src[2])
        avgZeros = (zeros + zeros[1]) / 2
        
        // Ehlers Super Smoother Filter 
        ssf = ssfPoles == 2
             ? get2PoleSSF(avgZeros, ssfLength)
             : get3PoleSSF(avgZeros, ssfLength)
        
        // Rescale filter in terms of Standard Deviations
        stdev = stdev(ssf, len)
        scaledFilter = stdev != 0
             ? ssf / stdev
             : 0
        
        alpha = 5 * abs(scaledFilter) / len
        
        edsma = 0.0
        edsma := alpha * src + (1 - alpha) * nz(edsma[1])
        result :=  edsma
    result

//---parameters
calc = (close - open)
ma_value = ma(Mode, calc, PriceSmoothing)

///// Z SCORE CALCULATION

Whip_Lash = ma_value
xStdDev = stdev(Whip_Lash, zlength)
xMA = sma(Whip_Lash, zlength)
z2=(Whip_Lash-xMA)/xStdDev

secolor = z2 > (vq0_mid + vq0_th) and z2 < (vq0_mid + vq0_th2) ? color.aqua : z2 > (vq0_mid + vq0_th2) and z2 < (vq0_mid + vq0_th3) ? color.aqua : z2 > (vq0_mid + vq0_th3) ? color.aqua : z2 < (vq0_mid - vq0_th) and z2 > (vq0_mid - vq0_th2) ? color.aqua : z2 < (vq0_mid - vq0_th2) and z2 > (vq0_mid - vq0_th3) ? color.aqua : z2 < (vq0_mid - vq0_th3) ? color.aqua : color.gray

LA1 = z2 > (vq0_mid + vq0_th) and z2 < (vq0_mid + vq0_th2)
LA2 = z2 > (vq0_mid + vq0_th2) and z2 < (vq0_mid + vq0_th3)
LA3 = z2 > (vq0_mid + vq0_th3)
SA1 = z2 < (vq0_mid - vq0_th) and z2 > (vq0_mid - vq0_th2)
SA2 = z2 < (vq0_mid - vq0_th2) and z2 > (vq0_mid - vq0_th3)
SA3 = z2 < (vq0_mid - vq0_th3)

LTA1 = LA1 and not LA1[1]
LTA2 = LA2 and not LA2[1]
LTA3 = LA3 and not LA3[1]
STA1 = SA1 and not SA1[1]
STA2 = SA2 and not SA2[1]
STA3 = SA3 and not SA3[1]

PAL = (z2 > 0)
PAS = (z2 < 0)

chgPAL = PAL and not PAL[1]
chgPAS = PAS and not PAS[1]

alertcondition(LTA1, title ="Long Threshold 1 Breached", message="Long YELLOW Alert - Threshold 1 Breached {{ticker}}")
alertcondition(LTA2, title ="Long Threshold 2 Breached", message="Long ORANGE Alert - Threshold 2 Breached {{ticker}}")
alertcondition(LTA3, title ="Long Threshold 3 Breached", message="Long RED Alert - Threshold 3 Breached {{ticker}}")
alertcondition(STA1, title ="Short Threshold 1 Breached", message="Short YELLOW Alert - Threshold 1 Breached {{ticker}}")
alertcondition(STA2, title ="Short Threshold 2 Breached", message="Short ORANGE Alert - Threshold 2 Breached {{ticker}}")
alertcondition(STA3, title ="Short Threshold 3 Breached", message="Short RED Alert - Threshold 3 Breached {{ticker}}")
alertcondition(chgPAL, title ="Price Action Change", message="Price Action LONG - Close Short Entries")
alertcondition(chgPAS, title = "Price Action Change", message="Price Action SHORT - Close Long Entries")

plot(z2, title = "Z Score WhipLash", color=secolor,style=plot.style_histogram, transp=0)


bgcolor(STA3 ? #00bcd4 : LTA3 ? #ff0000 : na, transp=50, title="Change in Price Action")

hline(0, title = "Zero", color=color.white, linestyle=hline.style_dotted, linewidth=1)
hline(1.64, title = "90% Line - Threshold 1", color=color.aqua, linestyle=hline.style_dotted, linewidth=1)
hline(-1.64, title = "90% Line - Threshold 1", color=color.aqua, linestyle=hline.style_dotted, linewidth=1)
hline(1.96, title = "95% Line - Threshold 2", color=color.aqua, linestyle=hline.style_dotted, linewidth=1)
hline(-1.96, title = "95% Line - Threshold 2", color=color.aqua, linestyle=hline.style_dotted, linewidth=1)
hline(2.58, title = "99% Line - Threshold 3", color=color.purple, linestyle=hline.style_dotted, linewidth=1)
hline(-2.58, title = "99% Line - Threshold 3", color=color.purple, linestyle=hline.style_dotted, linewidth=1)

Overview

Small candle bodies near zero are treated as chop, while readings beyond three thresholds mark unusually large bodies that may hint at a developing trend. Price smoothing and the moving-average mode change the calculation. It plots the result for visual filtering and does not place trades or define exits.

Details

Published by

Anderson-ALGO on GitHub

Code credit

eylwithsteph, as written in the script's header

Type

Indicator, Pine Script v4

Draws

Separate pane below the chart

Category

Candlestick patterns, Oscillators & momentum

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Price Smoothingint15PriceSmoothing
MA ModestringSMMAMode
Threshold 1float1.68vq0_th
Threshold 2float1.96vq0_th2
Threshold 3float2.58vq0_th3
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

Commitment Gauge

by harryguiacorn
219 stars

This indicator measures directional momentum by evaluating candlestick body proportions and volume over a user-defined lookback window. It computes the ratio of candle body to total range, weights the cumulative value by volume and absolute body size, and dete

Indicator v4 VolumeCandlestick patterns
Updated 1 year ago · None stated GitHub repository of Commitment Gauge

Qstick Indicator

by mihakralj
99 stars

This indicator calculates the Qstick value as a simple or exponential moving average of the difference between a chosen close source and open source. It plots that oscillator in a separate pane as a yellow line, draws a dashed zero line, and shades the backgro

Indicator v6 Oscillators & momentumCandlestick patterns
Updated 4 weeks ago · Apache-2.0 GitHub repository of Qstick Indicator
24 stars

This indicator plots a Cipher B-style oscillator in a separate pane and can source its calculations from Heikin Ashi candles when that option is on. It draws WaveTrend lines with optional buy, gold, sell, and divergence dots, plus overbought and oversold level

Indicator v5 Oscillators & momentumDivergence
Updated 4 years ago · MPL-2.0 GitHub repository of Cipher B Heikin Ashi

The Candle Pressure Index measures buying versus selling pressure from candle geometry and relative volume. Each bar combines close location, body ratio, and volume rank into a raw pressure value. An exponential moving average of that pressure forms the CPI os

Indicator v6 Oscillators & momentumVolume
Updated yesterday · MIT GitHub repository of Candle Pressure Index [WavesUnchained]

Heikin Ashi Delta Smoothed

by lunarticktrading
7 stars

This indicator calculates the difference between Heikin-Ashi close and open values to quantify directional candle spread. It smooths this delta value using a simple moving average and plots the resulting oscillator as a line in a separate pane. Traders can cus

Indicator v6 Oscillators & momentumCandlestick patterns
Updated 2 weeks ago · None stated GitHub repository of Heikin Ashi Delta Smoothed

Cerebr Bloop

by jerryinyang
5 stars

Cerebr Bloop is a momentum oscillator calculated by applying Heikin-Ashi candle logic to a zero-centered Relative Strength Index (RSI). Displayed in a separate pane, it visualizes smoothed RSI momentum candles alongside customizable overbought and oversold thr

Indicator v4 Oscillators & momentumCandlestick patterns
Updated 2 years ago · None stated GitHub repository of Cerebr Bloop

More indicators

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers