Will strategies close intrabar when a condition has been met?

163 views Asked by At

I have a strategy that I am trying to improve with a trailing stop. Everything is working well except that the strategy will not close the trade until the close of the bar. I am wanting the strategy to close the trade on the tick that the low crosses the trailing stop on long trades and on the tick that the high crosses the trailing stop on short trades.

I have tried a million different ways but cannot get it to work. I have tried. strategy.close(), strategy.exit(), strategy.close_all(), immediately=true, process_orders_on_close=true, and process_order_on_close=false. I have also changed the other strategy settings such as calc_on_every_tick=true, use_bar_magnifier=true (I am a premium user) etc.

I have searched on multiple sites online but can't find the answer and have submitted a ticked with TV without an answer.

Can anyone help?

2

There are 2 answers

1
Mario On

The problem is that strategies on historical data will execute one bar after calculation.
To solve that problem you should use limit orders instead,
which will execute on the price given.
But still then it will calc only after barmerge.isconfirmed.
This behaviour will change when using live data and using calc_on_every_tick = true.

Here is an example...

//@version=5
strategy("My strategy", calc_on_every_tick = true)

float sma = ta.sma(close, 20)
bool longCondition = ta.crossover(close, sma)

var tp  = float(na) // take profit
var tsl = float(na) // trailing stop loss

if longCondition
    strategy.entry("My Long ID", strategy.long)
    tp  := 0.02 * close + close
    tsl := close - (0.01 * close)
    strategy.exit("My Long Exit ID", "My Long ID", limit = tp, comment_profit = "TP", stop = tsl, comment_loss = "TSL")
    log.warning("New Order")

else if strategy.position_size > 0
    float tsl_new = math.round_to_mintick(close - (close * 0.01))
    if tsl_new > tsl
        tsl := tsl_new
        strategy.exit("My Long Exit ID", limit = tp, comment_profit = "TP", stop = tsl, comment_loss = "TSL")
        log.info("TSL Change")

plot(sma, "SMA")

There are other ways too.
But to help you with that we need a compile-able code example first.

0
a1cturner On

I'll attempt to post what I have and point out where the problem is...

//////////////////////////////////////////////////////////////////////////
//TRAIL STOP

TrailingStopMultiplier = input.float(2, "Trailing Stop Multiplier", 1, 5, step=0.1, tooltip="Multiplier x Risk")
LongTrailStop        = high - (MaxDrawdownDollarsPerShare * Risk * TrailingStopMultiplier)
ShortTrailStop       = low + (MaxDrawdownDollarsPerShare * Risk * TrailingStopMultiplier)
LongTrailStop1       = nz(LongTrailStop[1], LongTrailStop)
ShortTrailStop1      = nz(ShortTrailStop[1], ShortTrailStop)

if strategy.position_size>0
    LongTrailStop    := math.max(LongTrailStop, LongTrailStop1)
    LongTrailStop
if strategy.position_size<0
    ShortTrailStop   := math.min(ShortTrailStop, ShortTrailStop1)
    ShortTrailStop

LongTrailStopPlot    = plot(strategy.position_size>0?LongTrailStop:na, "Long Trail Stop", color.rgb(255, 59, 59), 3, plot.style_linebr, display=display.pane)
ShortTrailStopPlot   = plot(strategy.position_size<0?ShortTrailStop:na, "Short Trail Stop", color.rgb(255, 59, 59), 3, plot.style_linebr, display=display.pane)

//if LongTrailStop>LongStopLoss
//    LongStopLoss:=LongTrailStop
//if ShortTrailStop<ShortStopLoss
//    ShortStopLoss:=ShortTrailStop

//////////////////////////////////////////////////////////////////////////
//STRATEGY
ShowPlots = input(false, "Show Plots", group = "Options")

MaxIntradayLoss = input.int(3000, "Max Intraday Loss $", step=100, tooltip="Max Intraday Loss Before All Trades Closed", group="Position Setup", confirm=true)
strategy.risk.max_intraday_loss(MaxIntradayLoss, strategy.cash, "Maximum Daily Loss Achieved. Halted Trading for the Day")

if barstate.isconfirmed and strategy.position_size==0 and BuyingHours and Long and NoEarningsIn48
    strategy.entry('long', strategy.long, TradeSize)
    alert(str.tostring(LicenseID)
     +',buy,' + Ticker
     +',risk=' + str.tostring(TradeSize)
     +',sl=' + str.tostring(StopLoss)
     +',trailtrig=' + str.tostring(TrailTrig)
     +',traildist=' + str.tostring(TrailDist)
     +',trailstep=' + str.tostring(TrailStep)
     +',tp=' + str.tostring(TakeProfit),alert.freq_once_per_bar_close)
plotshape(ShowPlots and strategy.position_size==0 and BuyingHours and Long and NoEarningsIn48, title = "Long Entry", style = shape.xcross, location = location.top, color = color.green, text = "Long")

//if strategy.position_size>0 and session.ismarket
//    strategy.exit('exit long', stop=LongTrailStop, comment='TS_Long')
//    alert(str.tostring(LicenseID)
//     +',closelong,' + Ticker,alert.freq_once_per_bar)

if barstate.isconfirmed and strategy.position_size>0 and SellingHours and Long!=true and ((low<=LongStopLoss) or (high>=LongTakeProfit))
    strategy.close('long', 'Long Close', immediately=true)
    alert(str.tostring(LicenseID)
     +',closelong,' + Ticker,alert.freq_once_per_bar_close) //or once per bar? Leave it on close if it works
plotshape(ShowPlots and strategy.position_size>0 and SellingHours and Long!=true and ((low<=LongStopLoss) or (high>=LongTakeProfit)), title = "Long Close", style = shape.xcross, location = location.top, color = color.red, text = "Close")

if barstate.isconfirmed and strategy.position_size==0 and BuyingHours and Short and NoEarningsIn48
    strategy.entry('short', strategy.short, TradeSize)
    alert(str.tostring(LicenseID)
     +',sell,' + Ticker
     +',risk=' + str.tostring(TradeSize)
     +',sl=' + str.tostring(StopLoss)
     +',trailtrig=' + str.tostring(TrailTrig)
     +',traildist=' + str.tostring(TrailDist)
     +',trailstep=' + str.tostring(TrailStep)
     +',tp=' + str.tostring(TakeProfit),alert.freq_once_per_bar_close)
plotshape(ShowPlots and strategy.position_size==0 and BuyingHours and Short and NoEarningsIn48, title = "Short Entry", style = shape.xcross, location = location.bottom, color = color.red, text = "Short")

//if strategy.position_size<0 and session.ismarket
//    strategy.exit('exit short', stop=ShortTrailStop, comment='TS_Short')
//    alert(str.tostring(LicenseID)
//     +',closeshort,' + Ticker,alert.freq_once_per_bar)

if barstate.isconfirmed and strategy.position_size<0 and SellingHours and Short!=true and ((high>=ShortStopLoss) or (low<=ShortTakeProfit))
    strategy.close('short', 'Short Close', immediately=true)
    alert(str.tostring(LicenseID)
     +',closeshort,' + Ticker,alert.freq_once_per_bar_close) //or once per bar? Leave it on close if it works
plotshape(ShowPlots and strategy.position_size<0 and SellingHours and Short!=true and ((high>=ShortStopLoss) or (low<=ShortTakeProfit)), title = "Short Close", style = shape.xcross, location = location.bottom, color = color.green, text = "Close")

if strategy.position_size!=0 and (TradingEnd or (NoEarningsIn48==false))
    strategy.close_all("End of Day")
    alert(str.tostring(LicenseID)
     +',closelongshort,' + Ticker)
plotshape(ShowPlots and strategy.position_size!=0 and TradingEnd, title = "End of Day", style = shape.xcross, location = location.abovebar, color = color.purple, text = "End")

As you can see, I have commented out the strategy.exit because it isn't working properly. It is exiting on my trail stop as it should but it is completely ignoring the if statement before it, specifically the session.ismarket. It is processing trades at 0300 CST and obviously I don't want that.

I have tried strategy.exit(limit=LongTrailStop) but that results in the strategy taking profit immediately vs a stop loss.

I have also tried strategy.close(immediately=true) but the strategy only closes on the close of the bar. It will however respect the if statement of session.ismarket and low<=LongTrailStop

I have tried using stop, limit, trail_points, trail_price, close_all, close, exit, loss, trail_offset etc etc and no combination will do both, exit on my stop and respect my "if statement"

Everything else works perfectly so don't worry about that. I am strictly trying to get my LongTrailStop and ShortTrailStop working properly.