A while ago i looked into how inside bars impact mean reversion trading for SPY. The SPY is an index ETF mirroring SP500 and is well known for its tendency to mean-revert. I’m writing this post because i wanted to understand and document how this effect plays into high momentum stocks such as the Nasdaq 100 member. In order to fully benefit from this research i recommend you read this post first.
A simple test
Let’s first look into a basic RSI(2) strategy: enter when RSI(2) is crossing under 50 and exiting above 50. No trend filter has been added. Some background about the testing methodology: all trades are close to close, no commission. I used the NDX100 member stocks as of today, didn’t adjust the historical index constitution. Trades are starting from 1998. You might notice a relatively low CAR%, that’s because i wanted to ensure that every possible trade is taken (meeting the entry criteria). Hence position size is 1% per trade (to allow for a maximum of 100 concurrent trades). Of course one wouldn’t trade 100 concurrent positions, but for this research i needed to do so.
The first column (“NO”) is taking the trade as soon as RSI(2) < 50. The second column (“1. bar”) represents performance for a system that does delay the trade by one bar in case an inside bar occurs. The third column (“2. bar”) represents a system that does check for two consecutive inside bars. Again, please read this post in order to understand the concept of nested inside bars. I know, this might be a bit confusing. Bellow you find the Amibroker AFL code in case you want to fully embrace this.
The good: basically we see an improvement on almost all metrics. The sample size is very significant > 40.000 trades.
The bad: What if the improvement seen has a different cause? Namely the effect of simply delaying the trade for one or more trades might give you a better risk reward, because RSI(2)<50 isn’t terrible efficient. A more “realistic” test might help answering this (especially when entering trades at more extreme RSI(2) readings)..
A more comprehensive test
Let’s look at a strategy that goes long only when the following criterias are met:
- Rate of change (200) > 0
- RSI(2) < 25
Again, we see better performance while reducing risk. The effect is most pronounced at the 1st. and 2nd. bar.
.
.
.
.
.
Conclusion
Entering a RSI(2) based trade at an inside bar decreases your performance. I would rather delay the entry or reduce my bet size. This is another small brick in building a robust trading system.
Having done this comprehensive test with a very large sample size on SPY ETF as well as Nasdaq 100 stocks I’m rather confident in the outcome of this research.
.
.
AFL Code
#include <generall.afl>;
#include ;
SetBacktestMode( backtestRegular);
SetOption("CommissionAmount",0.00);
SetOption("MaxOpenPositions",100);
SetOption("MaxOpenLong", 100);
SetOption("InitialEquity", 100000);
SetPositionSize( 1, spsPercentOfEquity );
i_1 = HighRef(Low,-1);
i_2 = Ref(i_1,-1) AND HighRef(Low,-2);
i_3 = Ref(i_2,-1) AND HighRef(Low,-3);
Buy = Year()>1998 AND RSI(2)<25 AND ROC(Close,200)>0 AND i_1==False AND i_2==False AND i_3==False;
Sell = RSI(2) >50 ;
#include ; #include ; SetBacktestMode( backtestRegular);SetOption("CommissionAmount",0.00);
SetOption("MaxOpenPositions",100);SetOption("MaxOpenLong", 100);SetOption("InitialEquity", 100000);SetPositionSize( 1, spsPercentOfEquity );
i_1 = HighRef(Low,-1);i_2 = Ref(i_1,-1) AND HighRef(Low,-2);i_3 = Ref(i_2,-1) AND HighRef(Low,-3);
Buy = Year()>1998 AND RSI(2)<25 AND ROC(Close,200)>0 AND i_1==False AND i_2==False AND i_3==False; Sell = RSI(2) >50 ;









Frank,
You are missing some “<" in your formula. Trying different variations of your formula. I was thinking if the Q was also RSI(2)<25, may be a confirmation of a move. It gave several percentage winners but less ending capital.
John
Hello John,
i looked at your comment / my code. The statement Ref(i_1,-1) is equal to Ref(i_2,-1) == True
At the second bar(level) of a nested inside bar i want to check if the previous bar (Ref(i_1,-1) has been an inside bar. Of course the highs and lows of this bar have to be within the boarder of the last outside bar = the bar before the first inside bar
at the third inside bar i need to know if the previous bar has been a “second inside bar” and if current high and low is “inside” the high and low of the very last outside bar, before the first inside bar occurred.
I hope this helps.
Frank
Hi Frank,
I was refering to the lines with
” HighRef(Low,-1);”
Should it be
“High<Ref(High,-1)"
Maybe I am confused but for it to be a inside bar should it not be
" HighRef(Low,-1)”
Regards,
John
Opps!
Meant
i_1 = HighRef(Low,-1);
For inside bars.
John
Hi John,
no i see your point!
The copy&past function didn’t include the symbol. Let me repost the afl-code. Sorry for the confusion.
#include ;
#include ;
SetBacktestMode( backtestRegular);
SetOption(“CommissionAmount”,0.00);
SetOption(“MaxOpenPositions”,100);
SetOption(“MaxOpenLong”, 100);
SetOption(“InitialEquity”, 100000);
SetPositionSize( 1, spsPercentOfEquity );
i_1 = HighRef(Low,-1);
i_2 = Ref(i_1,-1) AND HighRef(Low,-2);
i_3 = Ref(i_2,-1) AND HighRef(Low,-3);
Buy = Year()>1998 AND RSI(2)0 AND i_1==False AND i_2==False AND i_3==False;
Sell = RSI(2) >50 ;
Try this!
//#include ;
SetBacktestMode( backtestRegular);
SetOption(“CommissionAmount”,0.00);
SetOption(“MaxOpenPositions”,100);
SetOption(“MaxOpenLong”, 100);
SetOption(“InitialEquity”, 100000);
SetPositionSize( 1, spsPercentOfEquity );
SetForeign(“QQQQ”);
Cond1 = RSI(2) MA(C,200)AND Inside() ;
RestorePriceArrays();
i_1 = HighRef(Low,-1);
i_2 = Ref(i_1,-1) AND HighRef(Low,-2);
i_3 = Ref(i_2,-1) AND HighRef(Low,-3);
Buy = RSI(2)1998 AND AND ROC(Close,200)>0
Sell = RSI(2) >50 ;
Plot(RSI(2),”RSI2″,3,1);