ApplyStop getting triggered at the same day as entry


the red line is my stop loss in this particular trade

I checked "activate stops immediately" in the settings because that's how I'm going to do my stop loss.

My problem is on backtesting, I get stopped even though my future stop loss gets hit first even before I enter the trade (basically no trade IRL but recorded as a loss).

Backtesting
Price hits my future stop loss (backtesting) > Breaks out > recorded as a loss (all at the same day)

IRL
Price hits my future stop loss (I'm still not on the trade) > Breaks out (I enter) > still holding

I'm only guessing the free yahoo market data doesn't have access to intraday to know which one happens first? What are my workarounds for this?

It would be much easier for people to help you if you posted your code, as described here: How to ask a good question. At a guess, you are entering at the close, and you want stops to become active on the next bar. That's the default behavior, so you should NOT be using "Activate stops immediately". See this excerpt from the documentation:

Activate stops immediately

This setting solves the problem of testing systems that enter trades on market open. In versions prior to 4.09 backtester assumed that you were entering trades on market close so built-in stops were activated from the next day. The problem was when you in fact defined open price as the trade entry price - then same day price fluctuations did not trigger the stops. There were some published workarounds based on AFL code but now you don't need to use them. Simply if you trade on open you should mark "Activate stops immediately" (pic. 1).

Incidentally, you NEVER have access to the order in which prices occur inside the bar. That's not a Yahoo thing, it's a data thing. All you know is that Open occurs first and Close occurs last. Everything else is unknown.

1 Like
stopAmount = Ref( ATR( 14 ), -1 ) * ( 1 + breakoutATR );
stopAmountTight = Ref( buyStopPrice, -1 ) - Ref( dynamicPivotLowPrice, -1 );

riskPerShare = Min( stopAmount, stopAmountTight ); 

sharesToBuy = valueRisk / riskPerShare;

totalAmount = sharesToBuy * Ref(buyStopPrice, -1);

pctSize =  positionRisk * Ref(buyStopPrice, -1) / riskPerShare;
SetPositionSize( Min(pctSize,maxPositionRisk*100) , spsPercentOfEquity );

ApplyStop( stopTypeLoss, stopModePoint, riskPerShare, 1);


Buy = Ref( buySignal, -1 ) AND High >= Ref( buyStopPrice, -1 );
BuyPrice = Ref( buyStopPrice, -1 );

Buy trigger is looking back yesterday if the "buySignal == true" and the current High price hits pass thru my "buyStopPrice".

It basically starts entering a trade at Close, but looking back to set the buyStopPrice.

So you're trying to model an intraday entry using a Buy Stop order, although you have not accounted for opening gaps above your buy stop price. Also, this code may not reflect real trading results unless you have sufficient capital to place entry orders for every instrument in your trading universe, or at least every instrument that generates a Setup condition on a particular day. Since you didn't include all your code, there's no way for anyone here to evaluate the likelihood of that.

Using daily bars, you have no way to know whether the price declined before or after your intraday entry, so the most conservative thing to do is to start enforcing stops the next day. If you enforce them on the day of entry, then your backtest will be wrong on approximately half of the trades that get stopped out on the entry day.

2 Likes

Oh you're right, thanks for pointing out to account for the gap.

What I did is this

Buy = Ref( buySignal, -1 ) AND High >= Ref( buyStopPrice, -1 ) AND 
Ref(Open, -1) <= Ref( buyStopPrice, -1 );

And I think I'll just move my stop loss just like how backtesting would do it, basically moving it the next day.

If you want to check that the price did not gap above the Buy Stop price, you should be using the current open, not the previous open. However, in live trading that means you can't enter your orders until after the open, once you've confirmed that the open was below the Buy Stop price.

I would have solved this by leaving your Buy logic alone, and instead changing the Buy Price:

BuyPrice = max(Ref( buyStopPrice, -1 ), Open);

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.