0

I'm very confused as to what could be causing this behavior, as I created as SuperTrend strategy which looks amazing when plotted on chart but breaks down horribly when tried on a live chart or when using the replay tool.

It is a very simple strategy which opens a long trade when SuperTrend says we are in an uptrend and short trade when SuperTrend says we are in a down trend.

To give you something tangible, I tried this side-by-side with my strategy with the exact same settings for SuperTrend (3m chart with SuperTrend's Time Frame set to 30m, ATR length to 1 and Factor also set to 1). I also set RRR to 1.5 and Stop Loss to previous swing high/low for both tests. I have limited both tests to start and end on the same date (4th November).

Here are the results from the first test where I just put the strategy on chart (no realtime calculations are done, as the market is currently closed):

static test

And here is the other test where I go through the replay tool, starting at the beginning of the day (4th November) and ending at the last bar of that day:

replay tool test

You can see that the results are completely different, especially when it comes to win rate and profit. What I saw was that with Replay Tool (and also observed on a live chart), SuperTrend changes its trend more frequently than when calculated from historical values. But why is the result so wastely different and why does this happen at all, I have no idea.

EDIT:

Here is a custom SuperTrend code with which you can actually test this:

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © marketcalls_in
// Rajandran - Founder - Marketcalls  / Co-Founder - Algomojo
//@version=4
study("Supertrend - Buy or Sell Signal", overlay = true)



//inputs
Periods = input(title="ATR Period", type=input.integer, defval=10)
Source = input(hl2, title="Source")
Multiplier = input(title="ATR Multiplier", type=input.float, step=0.1, defval=3.0)



//Compute ATR Levels
atr=  atr(Periods) 


//Creating Upper Channel

cclose = security(syminfo.tickerid, "30", close)

up=Source-(Multiplier*atr)
up1 = nz(up[1],up)
up := cclose[1] > up1 ? max(up,up1) : up

//Creating Down Channel
dn=Source+(Multiplier*atr)
dn1 = nz(dn[1], dn)
dn := cclose[1] < dn1 ? min(dn, dn1) : dn


//Compute the Trend Stream +1/-1
trend = 1
trend := nz(trend[1], trend)
trend := trend == -1 and cclose > dn1 ? 1 : trend == 1 and cclose < up1 ? -1 : trend

//Create Stoploss for Longs
upPlot = plot(trend == 1 ? up : na, title="Up Trend", style=plot.style_linebr, linewidth=2, color=color.green)

//Buy Signal
Buy = trend == 1 and trend[1] == -1

plotshape(Buy ? up : na, title="Go Long", location=location.absolute, style=shape.circle, size=size.tiny, color=color.green, transp=0)
plotshape(Buy ? up : na, title="Buy", text="Buy Mode", location=location.absolute, style=shape.labelup, size=size.tiny, color=color.green, textcolor=color.white, transp=0)

dnPlot = plot(trend == 1 ? na : dn, title="Down Trend", style=plot.style_linebr, linewidth=2, color=color.red)

//Sell Signal
Sell = trend == -1 and trend[1] == 1

plotshape(Sell ? dn : na, title="Go Short", location=location.absolute, style=shape.circle, size=size.tiny, color=color.red, transp=0)
plotshape(Sell ? dn : na, title="Sell", text="Sell Mode", location=location.absolute, style=shape.labeldown, size=size.tiny, color=color.red, textcolor=color.white, transp=0)

iPlot = plot(ohlc4, title="", style=plot.style_circles, linewidth=0)

longFillColor =  trend == 1 ? color.green : color.white
shortFillColor = trend == -1 ? color.red : color.white

fill(iPlot, upPlot, title="UpTrend Highligter", color=longFillColor)
fill(iPlot, dnPlot, title="DownTrend Highligter", color=shortFillColor)



//Alerts
alertcondition(Buy, title="SuperTrend Buy", message="SuperTrend Buy!")
alertcondition(Sell, title="SuperTrend Sell", message="SuperTrend Sell!")


buycontiue = barssince(Sell) > barssince(Buy)
sellcontinue = barssince(Buy) > barssince(Sell)

color = buycontiue[1] ? color.green : sellcontinue ? color.red : na
barcolor(color)

EDIT 2:

I may have found a partial answer to this.

Some of this behavior is because I was using the request.security() function here with barmerge.lookahead_on, which basically enabled "looking into the future" for calculations in historical bars. Setting this option to barmerge.lookahead_off helped some but there are still some discrepancies in the calculation.

EDIT 3:

There is an interesting writeup by TradingView about request.security() function here: https://www.tradingview.com/script/00jFIl5w-security-revisited-PineCoders/ ... so I guess we're out of luck when it comes to consistent historical data. My only "solution" for this was to introduce a threshold, so the custom SuperTrend implementation does not change trend until it was confirmed by going X percent into the opposite trend.

Zathrus Writer
  • 4,311
  • 5
  • 27
  • 50
  • any calculations or expressions in local scope that must be calculated on every bar to give an accurate answer should be pulled out of local scope. You have a number of them including max(). – John Baron Nov 07 '22 at 16:18
  • 1
    thanks, however that didn't help the issue... in any case, I might be on a right track, just reading through some TV docs... wil update this question if I find the answer soon – Zathrus Writer Nov 07 '22 at 22:10
  • ok, it's probably hopeless to wait for a consistent SuperTrend historical data - see my edit 3 – Zathrus Writer Nov 11 '22 at 06:52

1 Answers1

1

You are trading the 3 min and pulling data from the 30min. The 30min bar has not closed for some trades and therefore keeps changing realtime, whereas in your backtest you are using closed bars. To avoid this implement the changes described here:https://www.youtube.com/watch?v=-ZvGC0wUNAI

AE66
  • 11
  • 1
  • thank you, this is a nice video but how do you use barstate.isconfirmed on data from higher tf? I mean, barstate.isconfirmed would still be valid for my chart's TF... or does this work with request.security() somehow? – Zathrus Writer Nov 09 '22 at 13:46
  • ```request.security(syminfo.tickerid,higher_tf, my_function()[barstate.isconfirmed? 0:1])``` – John Baron Nov 11 '22 at 12:26