ApplyStop trailing stop exiting at open price instead of intraday stop price?

Because I was seeing MAE much greater than permitted by my trailing stop, I decided to test ApplyStops stopTypeTrailing to ensure that I truly understood how it works.

I performed three backtests as detailed below, and concluded that I definitely do not understand stopTypeTrailing. :dizzy_face:

Test 1:
In a backtest, I used Norgate Data, on the SPY symbol, using From-To dates of 12/13/2018 to 12/14/2018, I forced a Buy signal on 12/13, at the closing price of 265.37. The trailing stop was set using stopModePoint, using 4 points and to exit intraday at the stop price.

// Test of ApplyStop trailing stop
// Using SPY from 12/13/2018 to 12/14/2018

SetOption( "ActivateStopsImmediately", False );
SetOption( "AllowSameBarExit", False ); 
SetTradeDelays( 0, 0, 0, 0 );
BuyPrice = C; 
SellPrice = C;

Buy = 1;
Sell = Short = Cover = 0;

ApplyStop( stopTypeTrailing, stopModePoint, 4, True, False ); 

On 12/14, the low of the day was 259.85, so the stop would definitely have been triggered. However, the sell price should have been $261.37, but AB used the open price of $262.96 which is only $2.41 below the entry. AB exited on the correct bar, but at an impossible price, because the stop had not yet been hit at the open.

image
image

Test 2:
Using the same setup as in Test 1, I used the ApplyStop stopTypeLoss, also with stopModePoint, for a 4 point loss. The code was the same, except for the stop:

ApplyStop( stopTypeLoss, stopModePoint, 4, True, False ); 

Unlike the trailing stop, stopTypeLoss exited at the expected price of $261.37.
image

Test 3:
Also using Norgate Data, on the SPY symbol, using From-To dates of 11/23/2018 to 11/28/2018, I forced a Buy signal on 11/28, at the closing price of $263.25. The trailing stop was set using stopModePoint, using 4 points and to exit intraday at the stop price.

// Test of ApplyStop trailing stop
// Using SPY from 11/23/2018 to 12/31/2018

SetOption( "ActivateStopsImmediately", False );
SetOption( "AllowSameBarExit", False ); 
SetTradeDelays( 0, 0, 0, 0 );
BuyPrice = C; 
SellPrice = C;

Buy = 1;
Sell = Short = Cover = 0;

ApplyStop( stopTypeTrailing, stopModePoint, 4, True, False );

On 11/26, the high was the close at $274.58, which was also the highest high since entry. AB exited at the open of $269.60. I understand the reasoning for exiting on this bar (the low of $268.33 was more than 4 points below the highest high since entry) but using the opening price for the exit doesn't make sense to me because at the time of the open, it was the highest high.
image
image

Conclusion:
Based on the above tests, it seems that stopTypeTrailing uses the opening price instead of the intraday stop price. I haven't seen this documented in the function reference at https://www.amibroker.com/guide/afl/applystop.html, in the knowledge base, or in this forum.

Am I missing something here? Should stopTypeTrailing really be using the open price for exiting, when the stop was not actually hit until later in the day? :thinking:

What is the periodicity setting that you are using ?

@travick, periodicity is set to daily, because Norgate provides only daily data.

Well, on Daily data, what do you mean by

also you have

SetOption( "ActivateStopsImmediately", False );
SetOption( "AllowSameBarExit", False ); 

Its likely that AB is exiting next day at Open.

When you set a Periodicity, that backtest doesnt have access to lower resolution data even if your DB has it.

1 Like

@travick, thanks for thinking about this with me! I appreciate your help.

Although the daily bars don't provide the granularity of intraday data, the ApplyStops function makes an attempt to figure out what intraday price at which the trade would be exited.

As noted in test 2, the stopTypeLoss function calculated the exit price (didn't just use the open).

It doesn't seem that stopTypeTrailing is exiting the next day at the open, it just seems that it's simply using the open price on the bar where the stop was hit, instead of estimating what the intraday exit price would have been. Perhaps it was designed this way because we don't know the sequence of intraday prices when using daily data.

However, it seems to me that the function would more accurately reflect a trailing stop placed at the broker if it estimated the intraday exit price by using the highest high and subtracting the trailing amount.

By the way I forgot while typing the previous post, share the Detailed Log of the BT.

Even then, you have to decide and allow the AllowSameBarExit option if that's what you really want.

ApplyStop does not exit at open (unless open price actually triggers stop). If you change the amount you will see the exit price changes and is not equal to open. It just happens in your particular case that exit price is being equal to open price but is not that open price is used. The situation is a follows: this is an up bar (green). The open is below close, but at the same time LOW is lower than open. Which means that prices needed to travel full distance from High to Low (or from Low to High). But you don't know the trajectory the prices moved. You don't know, because you are using EOD data and you don't know what happened inside bar. You only know that "amount" threshold is violated in that bar (because this bar alone has range of 274.58-268.33 = 6.25 ), so your stop could be triggered anywhere in the range from 268.33 to 270.58 and all those points are actually equally probable.

Thanks for helping me better understand, Tomasz, and I appreciate your time and attention.

As you suggested, I experimented with different stop amounts. I repeated tests 1 and 3, above, with trailing stop amounts between 1 and 5 points. When the stop was higher than 4, the exit price varied, which I expected. And obviously as you pointed out in test 3, the range was higher than the stop amount, so it's not really possible to determine the actual exit price using daily bars.

However, in these tests, when the stop amount was between 1 and 4 points, AB always used the open price as the exit price.

Can you help me understand why, in test 1 above, the exit price was only $2.41 below the highest high since entry instead of $4 below the highest high? Is it possible that AB was using the high of the entry day ($267.49) as the highest high, even though the entry price of $265.37 was below the highest high?

Again, thank you for your assistance, I understand you're busy.

Based on this, can I assume that backtested results using a Trailing Stop with EOD data cannot be accurate and therefore should not be used?

No, that is awkward and fundamentally wrong assumption. Stops are correct.

Glad to hear that. Here is my code to try to understand trailing stops.

Buy = 1;
Sell = 0;
ApplyStop(stopTypeTrailing,stopModePoint,1,1);

Backtesting on the last 10 bars for QQQ I get the following trades...

image

Every Sell trade is showing a price equal to the Open.
Here is the Exploration.
image
So using the logic of a 1 point trailing stop, can I assume that I will
sell at the open because the prior day had a price range exceeding 1?
I'm not trying to be cute. I'd really like to understand this if indeed it
is accurate.

Your example is incomplete. You did NOT provide settings and stops DEPEND ON SETTINGS. Read this
https://www.amibroker.com/guide/h_backtest.html
especially the fragment about "Active stops immediately". It is crucial for proper stops. And use pre-defined scenarios (otherwise you would end up using wrong settings)

image

Thank you for the reply. I was not aware (or forgot) about those settings. Mine says "Custom (consult the manual)". I will experiment with these settings.