Strategy · Pine Script v4 · Own pane

Oscillator Evaluator (Analysis tool)

by regalouisei· code credited to mks17

This strategy plots in a separate pane and tests a selected oscillator with one of six entry logics: moving average, moving-average crossover, zero cross, extremes, mean reversion, or take profit.

View on GitHub

GitHub stars2on the repository
Pine versionv4older, still runs
Lines of code637
Settings36inputs
LicenceNone statedfile: MPL-2.0
Last update8 months ago25 Feb 2026

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 strategy, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart. The trades and results appear in the Strategy Tester tab; adjust the settings with the gear icon.

Source Code

637 lines of Pine Script v4 from pinescript/editors_picks/oscillator-evaluator-analysis-tool.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

oscillator-evaluator-analysis-tool.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © mks17

//@version=4
//Created for tradingview backtester

strategy(title='Oscillator Evaluator (Analysis tool)', shorttitle='Oscillator Evaluator', precision=3, initial_capital=700, pyramiding=500, default_qty_value=500, default_qty_type=strategy.cash, commission_type=strategy.commission.percent, commission_value=0.1, calc_on_every_tick=false, calc_on_order_fills=false, max_bars_back=600, overlay=false)

//--------------------Average Returns---------------------------------

avgRetR = input(title='Average Returns Ratio Adjustment', type=input.float, defval=1, minval=0.02, step=0.02)   //To change the automatic calculated avgRet parameter 

sum = 0.0
sum := nz(sum[1])
returns = (close - close[1]) * 100 / close
sum := sum + abs(returns)
avgRet = sum / bar_index
avgRet := avgRet * avgRetR
avgRet100 = avgRet / 100
avgRetClose100 = close * avgRet100


//---------------------------Inputs------------------------------------

lEntries = input(false, title="Show Long Entries Only")
sEntries = input(false, title="Show Short Entries Only")
stratSel = input(defval="MA Strategy", title="Strategy Selector", options=["MA Strategy", "MA Crossover Strategy", "Cross over 0 Strategy","Buy/Sell on Extremes Strategy", "Mean Reversion Strategy", "Take Profit Strategy"], type=input.string)
dataSel = input(defval="Oscillator 1", title="Oscillator Selector", options=["Oscillator 1", "Oscillator 2", "Oscillator 3"], type=input.string)
scale1 = input(title="Oscillator 1 Scale Adjustment", type=input.float, defval=1, minval=0, maxval=10, step=0.05)
tfadj1 = input(title="Oscillator 1 Timeframe Adjustment", type=input.float, defval=0.2, minval=0, maxval=10, step=0.05)
scale2 = input(title="Oscillator 2 Scale Adjustment", type=input.float, defval=1, minval=0, maxval=10, step=0.05)
tfadj2 = input(title="Oscillator 2 Timeframe Adjustment", type=input.float, defval=0.2, minval=0, maxval=10, step=0.05)
scale3 = input(title="Oscillator 3 Scale Adjustment", type=input.float, defval=1, minval=0, maxval=10, step=0.05)
tfadj3 = input(title="Oscillator 3 Timeframe Adjustment", type=input.float, defval=0.2, minval=0, maxval=10, step=0.05)

bool mastrat = false, macrossstrat = false, crossstrat = false, bsstrat = false, mrstrat = false, tpstrat = false

if stratSel == "MA Strategy"
    mastrat := true    
else if stratSel == "MA Crossover Strategy"
    macrossstrat := true    
else if stratSel == "Cross over 0 Strategy"
    crossstrat := true   
else if stratSel == "Buy/Sell on Extremes Strategy"
    bsstrat := true
else if stratSel == "Mean Reversion Strategy"
    mrstrat := true    
else 
    tpstrat := true

//MA Strat
malmt = input(7, "MA Strat Length")
mcthr = input(0.07, "MA Strat Range Threshold", step=0.005) //"MC Range Threshold "

//MA crossOver Strat 
mas = input(3, "MA Crossover Strat Short Length") //"MA Short Length"
mal = input(9, "MA Crossover Strat Long Length") //"MA Long Length"  

//Cross on 0 Strat
cross = input(0, "Cross Strat Horizon", step=0.1) //"Cross over 0"

//Buy Sell on Extremes Strat
bsOversold = input(-36.2, "Buy/Sell on Extremes Strat Oversold Value", step=0.1) //"Entry Max Signal"
bsOverbought = input(47.2, "Buy/Sell on Extremes Strat Overbought Value", step=0.1) //"Entry Max Signal"

//Mean Reversion Strat
mrOversold = input(-45, "Mean Reversion Strat Oversold Value", step=0.1) //"Entry Max Signal"
mrOverbought = input(45, "Mean Reversion Strat Overbought Value", step=0.1) //"Entry Max Signal"
// factor0 = input(1, step=0.1)
// factor1 = input(1, step=0.1)
// factor2 = input(1, step=0.1)
mrtp = input(0.5, "Mean Reversion Strat TP (%)", step=0.1) / 100//
mrsl = input(0.5, "Mean Reversion Strat SL (%)", step=0.1) / 100//

//Take Profit Strat
tpOversold = input(-45, "Take Profit Strat Oversold Value", step=0.1) //"Entry Max Signal"
tpOverbought = input(45, "Take Profit Strat Overbought Value", step=0.1) //"Entry Max Signal"
tp = input(10, "Take Profit Strat TP (%)", step=1) / 100//
sl = input(4, "Take Profit Strat TP (%)", step=1) / 100//

//Max loss and Max Downturn for all strategies
emaxl = input(10, "Max Loss (%)", step=1) / 100 //"Exit Max loss"
emaxdn =input(20, "Max Downturn (%)", step=1) / 100//"Exit Max Downturn"


//-------------Oscillators-----------------
//Put here your 2 oscillators of choice for comparison


//Mine is RSI

rsi1 = rsi(ohlc4, 1)
rsi2 = rsi(ohlc4, 2), rsi2 := nz(rsi2, rsi1)
rsi3 = rsi(ohlc4, 3), rsi3 := nz(rsi3, rsi2)
rsi4 = rsi(ohlc4, 4), rsi4 := nz(rsi4, rsi3)
rsi5 = rsi(ohlc4, 5), rsi5 := nz(rsi5, rsi4)
rsi6 = rsi(ohlc4, 6), rsi6 := nz(rsi6, rsi5)
rsi7 = rsi(ohlc4, 7), rsi7 := nz(rsi7, rsi6)
LTFrsi = ((rsi1 + rsi2 + rsi3 + rsi4 + rsi5 + rsi6 + rsi7) / 7) - 50

rsi12 = rsi(ohlc4, 12), rsi12 := nz(rsi12, LTFrsi)
rsi24 = rsi(ohlc4, 24), rsi24 := nz(rsi24, rsi12)
rsi36 = rsi(ohlc4, 36), rsi36 := nz(rsi36, rsi24)
rsi48 = rsi(ohlc4, 48), rsi48 := nz(rsi48, rsi36)
rsi60 = rsi(ohlc4, 60), rsi60 := nz(rsi60, rsi48)
rsi72 = rsi(ohlc4, 72), rsi72 := nz(rsi72, rsi60)
rsi84 = rsi(ohlc4, 84), rsi84 := nz(rsi84, rsi72)
HTFrsi = ((rsi12 + rsi24 + rsi36 + rsi48 + rsi60 + rsi72 + rsi84) / 7) - 50

rsi = tfadj1 * LTFrsi + (1 - tfadj1) * HTFrsi

//And Stochastic

stoch1 = sma(stoch(close, high, low, 1), 2)
stoch2 = sma(stoch(close, high, low, 2), 2), stoch2 := nz(stoch2, stoch1)
stoch3 = sma(stoch(close, high, low, 3), 2), stoch3 := nz(stoch3, stoch2)
stoch4 = sma(stoch(close, high, low, 4), 2), stoch4 := nz(stoch4, stoch3)
stoch5 = sma(stoch(close, high, low, 5), 2), stoch5 := nz(stoch5, stoch4)
stoch6 = sma(stoch(close, high, low, 6), 2), stoch6 := nz(stoch6, stoch5)
stoch7 = sma(stoch(close, high, low, 7), 2), stoch7 := nz(stoch7, stoch6)
LTFstoch = ((stoch1 + stoch2 + stoch3 + stoch4 + stoch5 + stoch6 + stoch7) / 7) - 50

stoch12 = sma(stoch(close, high, low, 12), 2), stoch12 := nz(stoch12, LTFstoch)
stoch24 = sma(stoch(close, high, low, 24), 2), stoch24 := nz(stoch24, stoch12)
stoch36 = sma(stoch(close, high, low, 36), 2), stoch36 := nz(stoch36, stoch24)
stoch48 = sma(stoch(close, high, low, 48), 2), stoch48 := nz(stoch48, stoch36)
stoch60 = sma(stoch(close, high, low, 60), 2), stoch60 := nz(stoch60, stoch48)
stoch72 = sma(stoch(close, high, low, 72), 2), stoch72 := nz(stoch72, stoch60)
stoch84 = sma(stoch(close, high, low, 84), 2), stoch84 := nz(stoch84, stoch72)
HTFstoch = ((stoch12 + stoch24 + stoch36 + stoch48 + stoch60 + stoch72 + stoch84) / 7) - 50

stoch = tfadj2 * LTFstoch + (1 - tfadj2) * HTFstoch


//Data Selector
float data = 0.0

if dataSel == "Oscillator 1"
    data := rsi * scale1

else if dataSel == "Oscillator 2"
    data := stoch * scale2    
    
else
    data := stoch * scale3


//--------------------MAs---------------------

PI = 2 * asin(1)

laguerre(src, alpha) =>
// A 4-element Laguerre filter
    L0 = 0.0, L2 = 0.0, L4 = 0.0, L6 = 0.0
    L0 := alpha * src + (1 - alpha) * nz(L0[1], src)
    L2 := -(1 - alpha) * L0 + nz(L0[1], src) + (1 - alpha) * nz(L2[1], src)
    L4 := -(1 - alpha) * L2 + nz(L2[1], src) + (1 - alpha) * nz(L4[1], src)
    L6 := -(1 - alpha) * L4 + nz(L4[1], src) + (1 - alpha) * nz(L6[1], src)
    (L0 + 2 * L2 + 2 * L4 + L6) / 6

highpassFilter(src, highpassLength) => 
    a = 0.707 * 2 * PI / highpassLength
    alpha1 = 1 + (sin(a) - 1) / cos(a)
    b = 1 - alpha1 / 2
    c = 1 - alpha1
    highpass = 0.0
    highpass := highpassLength != 0 ? b * b * (src - 2 * nz(src[1]) + nz(src[2])) + 2 * c * nz(highpass[1]) - c * c * nz(highpass[2]) : src

hilbertTransform(src) =>
    0.0962 * src + 0.5769 * nz(src[2]) - 0.5769 * nz(src[4]) - 0.0962 * nz(src[6])

computeComponent(src, mesaPeriodMult) =>
    hilbertTransform(src) * mesaPeriodMult

computeAlpha(src, fastLimit, slowLimit) =>
    mesaPeriod = 0.0, smooth = 0.0, detrender = 0.0, I2 = 0.0, Q2 = 0.0, phase = 0.0
    mesaPeriodMult = 0.075 * nz(mesaPeriod[1]) + 0.54
    smooth := (4 * src + 3 * nz(src[1]) + 2 * nz(src[2]) + nz(src[3])) / 10
    detrender := computeComponent(smooth, mesaPeriodMult)
    I1 = nz(detrender[3])
    Q1 = computeComponent(detrender, mesaPeriodMult)
    jI = computeComponent(I1, mesaPeriodMult)
    jQ = computeComponent(Q1, mesaPeriodMult)
    I2 := I1 - jQ
    Q2 := Q1 + jI
    I2 := 0.2 * I2 + 0.8 * nz(I2[1])
    Q2 := 0.2 * Q2 + 0.8 * nz(Q2[1])
    Re = I2 * nz(I2[1]) + Q2 * nz(Q2[1])
    Im = I2 * nz(Q2[1]) - Q2 * nz(I2[1])
    Re := 0.2 * Re + 0.8 * nz(Re[1])
    Im := 0.2 * Im + 0.8 * nz(Im[1])
    if Re != 0 and Im != 0
        mesaPeriod := 2 * PI / atan(Im / Re)
    if mesaPeriod > 1.5 * nz(mesaPeriod[1])
        mesaPeriod := 1.5 * nz(mesaPeriod[1])
    if mesaPeriod < 0.67 * nz(mesaPeriod[1])
        mesaPeriod := 0.67 * nz(mesaPeriod[1])
    if mesaPeriod < 6
        mesaPeriod := 6
    if mesaPeriod > 50
        mesaPeriod := 50
    mesaPeriod := 0.2 * mesaPeriod + 0.8 * nz(mesaPeriod[1])
    if I1 != 0
        phase := (180 / PI) * atan(Q1 / I1)
    deltaPhase = nz(phase[1]) - phase
    if  deltaPhase < 1
        deltaPhase := 1
    alpha = fastLimit / deltaPhase
    if  alpha < slowLimit
        alpha := slowLimit
    alpha

mama(_src, _fastlimit, _slowlimit) =>
    alpha = computeAlpha(_src, _fastlimit, _slowlimit)
    mama = 0.0   
    mama := alpha * _src + (1 - alpha) * nz(mama[1], _src)

kama(_src, _len) =>
    mom = abs(change(_src, _len))
    volatility = sum(abs(change(_src)), _len)
    er = volatility != 0 ? mom / volatility : 0
    fastAlpha = 0.6666
    slowAlpha = 0.0645
    alpha = pow((er * (fastAlpha - slowAlpha)) + slowAlpha, 2)
    kama = 0.0
    kama := alpha * _src + (1 - alpha) * nz(kama[1], _src)

percent(nom, div) => 
    100 * nom / div

vidya(_src, _len) =>
    alpha = 6 / (_len + 1)
    momm = change(_src)
    m1 = momm >= 0.0 ? momm : 0.0
    m2 = momm >= 0.0 ? 0.0 : -momm
    sm1 = sum(m1, _len)
    sm2 = sum(m2, _len)
    chandeMO = nz(percent(sm1 - sm2, sm1 + sm2))
    k = abs(chandeMO) / 100 
    vidya = 0.0
    vidya := alpha * k * _src + (1 - alpha * k) * nz(vidya[1], _src)

sSmooth(src, length) =>
//Ehlers Super Smooth Filter 
    arg = sqrt(2) * PI / length
    a1 = exp(-arg)
    coef2 = 2 * a1 * cos(arg)
    coef3 = -pow(a1, 2)
    coef1 = 1 - coef2 - coef3
    src1 = nz(src[1], src)
    src2 = nz(src[2], src1)
    ssf = 0.0
    ssf := coef1 * (src + src1) * 0.5 + coef2 * nz(ssf[1], src1) + coef3 * nz(ssf[2], src2)
    
filter(type, src, len) =>
// MA type Selector
    type == "Laguerre" ? laguerre(src, 4.0 / (1 + len)) : type == "EMA" ? ema(src, len) : type == "SMA" ?  sma(src, len) : type == "MAMA" ? mama(src, 4.5 / len, 0.45 / len) : type == "KAMA" ? kama(src, len) : type == "VIDYA" ? vidya(src, len) : type == "S Smooth" ? sSmooth(src, len) : src


//-------------------------Strategies---------------------

//-------------MA Strategy

bool bear = false, bool bull = false, bool range = false, var rangeprice = close, ma2 = 0.0

if mastrat

    ma2 := filter("Laguerre", data, malmt)   //Market Cycle MA
        
    //Average Change MA
    
    change = (ma2 - ma2[1]) / ma2
    suma4 = 0.0
    suma4 := nz(suma4[1])
    abschange = abs(change) 
    suma4 := suma4 + abschange * 100
    avgChange = suma4 / bar_index
    avgChange100 = ma2 * avgChange / 100
    
    mcthr := mcthr * avgChange100
    ma2a = ma2 + 50
    dataa = data + 50
    
    //Normal Range if ma is flat then is a range
    if (mcthr >= -0.15 * avgChange100 and mcthr <= 0.15 * avgChange100) 
        if (ma2a[1] - ma2a >= mcthr)
            bear := true
        if (ma2a - ma2a[1] >= mcthr and not(bear)) 
            bull := true 
        if (abs(ma2a - ma2a[1]) < mcthr and not(bear or bull))
            range := true
    
    //MC Change if above or below MA complete change to opossite condition
    if (mcthr < -0.15 * avgChange100) 
        if (abs(ma2a - ma2a[1]) < -mcthr - 0.15 * avgChange100)
            range := true
        if (dataa > ma2a and data > ma2a and not(range))
            bull :=  true 
        if (dataa < ma2a and data < ma2a and not(range or bull))
            bear := true
            
    //MC Range if above or below MA cahnge to range condition
    if (mcthr > 0.15 * avgChange100) 
        if (abs(ma2a - ma2a[1]) < mcthr - 0.15 * avgChange100 or (ma2a - ma2a[1] >= mcthr - 0.15 * avgChange100 and dataa < ma2a and dataa < ma2a or ma2a[1] - ma2a >= mcthr - 0.15 * avgChange100 and dataa > ma2a and dataa > ma2a))
            range := true
        if (ma2a - ma2a[1] >= mcthr - 0.15 * avgChange100 and not(range))
            bull :=  true 
        if (ma2a[1] - ma2a >= mcthr - 0.15* avgChange100 and not(range or bull))
            bear := true
            
    rangeprice := range[1] == false and range ? ma2 : range[1] and range == false ? na : rangeprice[1]

//--------------MA CrossOver Strategy

ma1 = 0.0, ma3 = 0.0

if macrossstrat
    
    ma1 := filter("EMA", data, mas)  //"MA Short"
    ma3 := filter("Laguerre", data, mal)  //"MA Long"
    

//-------------------------Entry Strategy---------------------------

longentry = 0, shortentry = 0, x2longentry = 0, x2shortentry = 0, shortexit = 0, longexit = 0, overBought = 0, overSold = 0
last_open_long = float(na), last_open_short = float(na), var last_close_long = float(na), var last_close_short = float(na)
var pyramiding = 0  //To know the current pyramiding
var longCounter = 0, var shortCounter = 0  //To keep track of the position we are in
var maxProfit = float(na)   


if (longCounter == 0 or shortCounter == 0)

    //MA Strat
    if mastrat
        
        if (longCounter == 0 and shortCounter == 0 or longCounter == 0 and shortCounter == 1) 
    
            if (bull)    
                longentry := 1
                longCounter := 1
                
                if (shortCounter != 0 and sEntries)
                    shortexit := 1
                
                shortCounter := 0
                    
        if (shortCounter == 0 and longCounter == 0 or longCounter == 1 and shortCounter == 0)        
        
            if (bear) 
                shortentry := 1
                shortCounter := 1
                
                if (longCounter != 0 and lEntries)
                    longexit := 1
                
                longCounter := 0 

    //MA CrossOver Strat
    if macrossstrat
    
        if (longCounter == 0 and ma1 >= ma3)
            longentry := 1
            longCounter := 1
            
            if (shortCounter != 0 and sEntries)
                shortexit := 1
            
            shortCounter := 0
                
        if (shortCounter == 0 and ma1 < ma3) 
            shortentry := 1
            shortCounter := 1
            
            if (longCounter != 0 and lEntries)
                longexit := 1
            
            longCounter := 0 
    
    //Cross 0 Strat
    if crossstrat
    
        if (data >= cross and longCounter == 0)     
            longentry := 1
            longCounter := 1
            
            if (shortCounter != 0 and sEntries)
                shortexit := 1
            
            shortCounter := 0
            
        if (data < cross and shortCounter == 0) 
            shortentry := 1
            shortCounter := 1
            
            if (longCounter != 0 and lEntries)
                longexit := 1
            
            longCounter := 0 
            
    //Buy/Sell on Extremes Strat
    if bsstrat
    
        if data < bsOversold
            longentry := 1
            longCounter := longCounter + 1
            
            if (shortCounter != 0 and sEntries)
                shortexit := 1
            
            shortCounter := 0
    
        
        if data > bsOverbought
            shortentry := 1
            shortCounter := shortCounter + 1
    
            if (longCounter != 0 and lEntries)
                longexit := 1
            
            longCounter := 0 
    
    //Mean Reversion Strat
    if mrstrat
    
        if (shortCounter == 0 and longCounter == 0 and data < mrOversold)
            longentry := 1
            longCounter := longCounter + 1
            
            if (shortCounter != 0 and sEntries)
                shortexit := 1
            
            shortCounter := 0
    
        
        if (longCounter == 0 and shortCounter == 0 and data > mrOverbought)
            shortentry := 1
            shortCounter := shortCounter + 1
    
            if (longCounter != 0 and lEntries)
                longexit := 1
            
            longCounter := 0 
    
    //Take Profit Strat
    if tpstrat
    
        if (shortCounter == 0 and longCounter == 0 and crossunder(data, tpOversold))
            longentry := 1
            longCounter := longCounter + 1
            
            if (shortCounter != 0 and sEntries)
                shortexit := 1
            
            shortCounter := 0
        
        if (longCounter == 0 and shortCounter == 0 and crossover(data, tpOverbought))
            shortentry := 1
            shortCounter := shortCounter + 1
        
            if (longCounter != 0 and lEntries)
                longexit := 1
            
            longCounter := 0 
            
last_open_long := longentry == 1 or x2longentry == 1 ? close : nz(last_open_long[1])
last_open_short := shortentry == 1 or x2shortentry == 1 ? close : nz(last_open_short[1])

if longCounter > 0 
    maxProfit := max(maxProfit[1], close)
else if shortCounter > 0
    maxProfit := min(maxProfit[1], close)
else 
    maxProfit := 0
if longentry == 1 or x2longentry == 1 or shortentry == 1 or x2shortentry == 1 
    maxProfit := close
    
    
//-----------------------Close Strategy-------------------------------
    
if (longCounter != 0 or shortCounter != 0)
    
    //Max Loss Exits
    
    maxlossLong = close < last_open_long * (1 - emaxl)
    maxlossShort = close > last_open_short * (1 + emaxl)

    if (longCounter != 0 and maxlossLong) 
        longexit := 4
        longCounter := 0
        shortCounter := 0
    
    if (shortCounter != 0 and maxlossShort) 
        shortexit := 4
        shortCounter := 0
        longCounter := 0 
    
    maxdowntLong = close < maxProfit * (1 - emaxdn)
    maxdowntShort = close > maxProfit * (1 + emaxdn)
    
    //Max Downturn Exits

    if (longCounter != 0 and maxdowntLong) 
        longexit := 5
        longCounter := 0
        shortCounter := 0
    
    if (shortCounter != 0 and maxdowntShort) 
        shortexit := 5
        shortCounter := 0
        longCounter := 0
    
    //Mean Reversion Strat
    if mrstrat
    
        if (longCounter != 0 and close > last_open_long * (1 + mrtp))
            longexit := 2
            longCounter := 0
        
        if (longCounter != 0 and close < last_open_long * (1 - mrsl))
            longexit := 3
            longCounter := 0
        
        if (shortCounter != 0 and close < last_open_short * (1 - mrtp))
            shortexit := 2
            shortCounter := 0
        
        if (shortCounter != 0 and close > last_open_short * (1 + mrsl))
            shortexit := 3
            shortCounter := 0
        
    //Take Profit Strat
    if tpstrat
    
        if (longCounter != 0 and close > last_open_long * (1 + tp))
            longexit := 2
            longCounter := 0
        
        if (longCounter != 0 and close < last_open_long * (1 - sl))
            longexit := 3
            longCounter := 0
        
        if (shortCounter != 0 and close < last_open_short * (1 - tp))
            shortexit := 2
            shortCounter := 0
        
        if (shortCounter != 0 and close > last_open_short * (1 + sl))
            shortexit := 3
            shortCounter := 0


//--------------------------Backtesting & Orders-----------------------------

useTB1 = input(false, title="Time Break 1")
startTime1 = input(defval = timestamp("01 Jan 2017"), title = "TB Start Time", type = input.time)
days1 = input(title="TB 1 Range (days)", type=input.integer, defval=40, minval=1)
// useTB2 = input(false, title="Time Break 2")
//startTime2 = input(defval = timestamp("01 Aug 2017 00:00 +0000"), title = "TB Start Time", type = input.time)
// days2 = input(title="TB 2 Range (days)", type=input.integer, defval=20, minval=1)
useTR = input(true, title="Time Range")
startTime = input(defval = timestamp("01 Jan 2000"), title = "TR Start Time", type = input.time)
endTime = input(defval = timestamp("01 Jun 2020"), title = "TR End Time", type = input.time)
useWF = input(true, title="Walk-Forward") 
weeks = input(title="WF Range (weeks)", type=input.integer, defval=50, minval=0)


//Time Range & Walk Forward Test

window() =>  // create function "within window of time"
    time >= startTime and time <= endTime ? true : false

finish2 = endTime + weeks * timestamp(1970, 1, 8, 00, 00)  // WF finish window
window2() =>  // To show the WF period
    time >= endTime and time <= finish2 ? true : false

window3() =>  // To include the WF period and the backtest period
    time >= startTime and time <= finish2 ? true : false

///Time Breaks

finish4 = startTime1 + days1 * timestamp(1970, 1, 2, 00, 00)
window4() =>  // create function "within window of time"
    time >= startTime1 and time <= finish4 ? true : false
    

// finish5 = startTime2 + days2 * timestamp(1970, 1, 2, 00, 00)
// window5() =>  // create function "within window of time"
//     time >= startTime2 and time <= finish5 ? true : false
    
if useTB1 and window4() //or useTB2 and window5()
    longentry := 0
    shortentry := 0
    x2longentry := 0
    x2shortentry := 0

//Strategy and Backtest Conditions

//smallOrder = (orderqty * ctorder) / close == 0 ? 2 : (orderqty * ctorder) / close
//smallOrder = strategy.equity * mcordqty / close

if useTR and useWF == false and window() or useWF and useTR == false and window2() or useWF and useTR and window3()
    
    if lEntries == false 
        strategy.entry("Short", false, oca_name="oca_short", oca_type=strategy.oca.reduce, when=shortentry == 1)
        //strategy.entry("2xShort", false, oca_name="oca_short", oca_type=strategy.oca.reduce, when=x2shortentry == 1)
        
    if sEntries == false     
        strategy.entry("Long", true, oca_name="oca_long", oca_type=strategy.oca.reduce, when=longentry == 1)
        //strategy.entry("2xLong", true, oca_name="oca_long", oca_type=strategy.oca.reduce, when=x2longentry == 1)
        
            
    if strategy.position_size != 0
        strategy.close("Short", when=shortexit == 1, comment="Exit")     //
        strategy.close("Long", when=longexit == 1, comment="Exit")     //
        strategy.close("2xShort", when=shortexit == 1, comment="Exit")     //
        strategy.close("2xLong", when=longexit == 1, comment="Exit")     //

        strategy.close_all(when=longexit == 4 or shortexit == 4, comment="Max Loss")
        strategy.close_all(when=longexit == 5 or shortexit == 5, comment="Max Downturn")
        strategy.exit("TP", qty_percent=100, stop=high, oca_name="oca_long", when=longexit == 2)
        strategy.exit("TP",  qty_percent=100, stop=low, oca_name="oca_short", when=shortexit == 2)
        strategy.exit("SL", qty_percent=100, stop=high, oca_name="oca_long", when=longexit == 3)
        strategy.exit("SL",  qty_percent=100, stop=low, oca_name="oca_short", when=shortexit == 3)
    

//-------------------------Plotting----------------------------

plotchar(longCounter - shortCounter, title="Position Counter", char="•", color=color.white, transp=100, location=location.top, size=size.tiny)
plotchar(avgRet, title="Average Returns", char="•", color=color.white, transp=100, location=location.top, size=size.tiny)
cColor = bull ? color.lime : range ? color.maroon : color.orange
plot(mastrat ? ma2 : na, color=cColor, transp=0, title="MA Strat", style=plot.style_linebr)
plot(macrossstrat ? ma1 : na, color=color.blue)
plot(macrossstrat ? ma3 : na, color=color.orange)
plot(data, color=color.black)
hline(0)
hline(50, linestyle=hline.style_solid)
hline(-50, linestyle=hline.style_solid)

Overview

Users scale and time-adjust one of three oscillators and can limit signals to long or short entries. Average absolute bar returns adjust an internal threshold. Mean reversion and take-profit modes expose percentage take-profit and stop-loss inputs, and the strategy allows many stacked entries. No market or timeframe is specified.

Details

Published by

regalouisei on GitHub

Code credit

mks17, as written in the script's header

Type

Strategy, Pine Script v4

Draws

Separate pane below the chart

Category

Oscillators & momentum, Moving averages, Mean reversion

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

  • The strategy can add several entries in the same direction

Settings

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

SettingTypeDefaultVariable
Average Returns Ratio Adjustmentfloat1avgRetR
Show Long Entries OnlyboolfalselEntries
Show Short Entries OnlyboolfalsesEntries
Strategy SelectorstringMA StrategystratSel
Oscillator SelectorstringOscillator 1dataSel
Oscillator 1 Scale Adjustmentfloat1scale1
Oscillator 1 Timeframe Adjustmentfloat0.2tfadj1
Oscillator 2 Scale Adjustmentfloat1scale2
Oscillator 2 Timeframe Adjustmentfloat0.2tfadj2
Oscillator 3 Scale Adjustmentfloat1scale3
Oscillator 3 Timeframe Adjustmentfloat0.2tfadj3
MA Strat Lengthint7malmt
Show all 36 settings
SettingTypeDefaultVariable
MA Strat Range Thresholdfloat0.07mcthr
MA Crossover Strat Short Lengthint3mas
MA Crossover Strat Long Lengthint9mal
Cross Strat Horizonint0cross
Buy/Sell on Extremes Strat Oversold Valuefloat-36.2bsOversold
Buy/Sell on Extremes Strat Overbought Valuefloat47.2bsOverbought
Mean Reversion Strat Oversold Valueint-45mrOversold
Mean Reversion Strat Overbought Valueint45mrOverbought
Mean Reversion Strat TP (%)float0.5mrtp
Mean Reversion Strat SL (%)float0.5mrsl
Take Profit Strat Oversold Valueint-45tpOversold
Take Profit Strat Overbought Valueint45tpOverbought
Take Profit Strat TP (%)int10tp
Take Profit Strat TP (%)int4sl
Max Loss (%)int10emaxl
Max Downturn (%)int20emaxdn
Time Break 1boolfalseuseTB1
TB Start Timetimetimestamp("01 Jan 2017")startTime1
TB 1 Range (days)int40days1
Time RangebooltrueuseTR
TR Start Timetimetimestamp("01 Jan 2000")startTime
TR End Timetimetimestamp("01 Jun 2020")endTime
Walk-ForwardbooltrueuseWF
WF Range (weeks)int50weeks
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

106 stars

Buy The Dips - MA200 Optimised is a mean-reversion strategy that measures short-term percentage price changes alongside a simple moving average trend filter. It opens long positions when price experiences a steep drop exceeding three percent while remaining ab

Strategy v4 Oscillators & momentumTrend
Updated 2 years ago · GPL-3.0 GitHub repository of Buy The Dips - MA200 Optimised

Greeffer BB Strategy

by SammyEnigma
18 stars

This strategy combines Bollinger Bands, Bollinger Band Width, and the Relative Strength Index (RSI) for mean-reversion trades. It enters long when price crosses below the lower band with oversold RSI, or when band width contracts under low volatility. Short en

Strategy v4 Mean reversionOscillators & momentum
Updated 6 years ago · None stated GitHub repository of Greeffer BB Strategy

Oversold

by kat3samsin
2 stars

The oversold strategy identifies oversold conditions using the relative strength index with a 14 period. It applies an arithmetic linear moving average with a 20 period for trend filtering and requires the price to stay within 15 percent of this average. Stoch

Strategy v4 Mean reversionOscillators & momentum
Updated 5 years ago · MIT GitHub repository of Oversold

WaveTrend with Crosses [LazyBear]

by avatar-lavventura
2 stars

This strategy calculates the WaveTrend oscillator using exponential moving averages of typical price and plots two signal lines alongside overbought and oversold thresholds in a separate pane. It enters long positions when the primary line crosses above the si

Strategy v4 Oscillators & momentumMoving averages
Updated 7 months ago · None stated GitHub repository of WaveTrend with Crosses [LazyBear]
1 stars

The script calculates the yield spread between long-term and short-term US Treasury yields (T10Y2Y or manual US10Y minus US02Y) and plots the spread line on a separate pane. It signals long entries on steepening beyond a user threshold in reversion mode or SMA

Strategy v6 Mean reversionSupport & resistance
Updated 2 months ago · None stated GitHub repository of TN Yield Spread Sovereign v6
330 stars

This mean-reversion strategy combines multi-timeframe exponential moving averages, Bollinger Bands, and the Relative Strength Index. It generates long and optional short trade signals when price interacts with the Bollinger Bands alongside RSI threshold confir

Strategy v5 Mean reversionMoving averages
Updated 2 months ago · None stated GitHub repository of MEMA + BB + RSI [Alorse]

More strategys

Trade Your Charts With a Regulated Broker

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

Compare brokers