September 8, 2014

Simple Ideas for a Mean Reversion Strategy with Good Results – Part 2

The Simple Ideas for a Mean Reversion Strategy with Good Results post generated lots of comments and emails about other ideas to try. This post will cover three of the most interesting ones.


See the original post for rule details. Tested from 1/1/2004 to 6/30/2014

Idea 1 – Remove MA100 rule

Comparison is on Russell 1000 only. For S&P500, Russell 3000 and NDX100 see the spreadsheet. Take the original rules and remove the rule that the Close is greater than the 100 day moving average.

New Results


Original Results


For this time period, as expected the exposure went up but the CAR did not increase that much. The max drawdown increased dramatically. Definitely in the realm of very few people could handle. The year 2008 is still positive without the MA100 which is interesting. I expected that year to get crushed.


Idea 2 – Enter on open after setup day

Starting with the initial rules we make the following changes. Instead of waiting for the stock to trigger at our limit price, we enter at the open. Three ranking methods were tested.

  • Highest 100 day Historical Volatility
  • Worst 5 day return
  • Highest 5 period ADX


Not exactly the best of results but expected. In my book Short Term Trading Strategies That Work” we show how waiting for intraday pullback improves results.


Idea 3 – Wait an extra day after setup day to enter

Starting with the initial rules we make the following changes.

  • Two days ago was set up day
  • Yesterday the stock’s low is below the limit entry price
  • Today becomes the new setup day if the condition below is satisfied. Also today must be a down day because if it was an up day, the Sell rule would trigger

o   Close below initial trigger price

o   Close above initial trigger price

o   Close below previous day’s close

o   Close less than open

o   Close above the open

  • Then enter on the next day on the open. Use the same rankings as in Idea 2.


Nothing here. Waiting for the ‘trigger’ and then entering does not work. The average % p/l is low along with the exposure.

What is a little interesting is what happens if you take the above test and remove the MA100 rule.


Entering when the Close is above the initial trigger price produces OK results.


If you’re interested in a spreadsheet of the data used to generate these tables, enter your information below, and I will send you a link to the spreadsheet. The spreadsheet includes the full Monte Carlo run data. In the spreadsheet are details on how to obtain the AmiBroker code used for Idea 2 and Idea 3.


Final Thoughts

Even though nothing really came of these ideas, I am glad we tested them. One never knows what will work and what does not. I want to share good results and poor results with you. Someone might see something in the above tests I missed for yet another round of tests.




Click Here to Leave a Comment Below

Ray Lowe - September 8, 2014 Reply

I am interested in the Amibroker code that you have to offer if it has all the right stuff. Developing the code for the trading rules is easy. Does your code limit the buys to the top positionscore values after accounting for open positions so that it generates a portfolio with a maximum of 10 open positions for back testing? Does it rebalance the number of shares for open positions? I find that I have to use static variables and the mid-level custom backtester interface to make this work. This really slows down backtesting. Perhaps your code is more efficient and worth purchasing.

    Cesar Alvarez - September 8, 2014 Reply

    For Idea 2 & Idea 3, all one needs to do to limit to top positions is set this line of code:
    SetOption(“MaxOpenPositions”, 10);

    The code does not rebalance.

      Ray Lowe - September 8, 2014 Reply

      My understanding is different. Let’s say I have 6 open positions already. When running the backtest, Amibroker will consider twice the number of open slots (10 maximum positions less 6 open positions is 4 slots times 2 = 8 top ranked stocks will be considered in this case). So Amibroker is essentially allowing any of the 8 top ranked stocks to be purchased and the portfolio performance is based on this effect. In reality I would only have an order placed for the 4 top rated stocks while Amibroker would allow trades in lower ranked stocks if any of the top 4 do not trade that day. Thus my trading does not follow the backtest results. Am I missing something here?

        Cesar Alvarez - September 8, 2014 Reply

        Now we are getting down in the subtlety of AmiBroker. I assume that you have the following two lines of code
        SetOption(“AllowPositionShrinking” , True);
        RoundLotSize=1; // or 10

        You are correct that AmiBroker has the 8 top ranked stocks in the signal list. The main reason for failing to enter a trade is that you do not have enough money to buy a full position and do not allow position shrinking. Another reason is that the share price is so high and/or your RoundLotSize is set such that you cannot even buy the minimum about of shares. These two potential problems are fixed with the code above. So given that, AmiBroker will enter the trades for the first 4 signals 99.9% of time. How can I say that. I have written code that explicitly looks for failure of entry and it rarely triggers. The usual reason is that some stock has done lots of reverse splits that the trading price is absurdly high which does not even allow me to buy one share. Now if one’s strategy would break from taking one extra signal, there are bigger issues.

        Given all that if you wanted to completely stop AmiBroker from ever looking at more than the 4 signals, one could do that using the low-level CBT.

Gerard Threels - September 8, 2014 Reply

Adding a time-based stop will improve CAR and lower the Max. Sys. % Drawdown.
A 3-bar stop will increase CAR/MDD significantly.

    Cesar Alvarez - September 8, 2014 Reply

    Adding the stop to which method? The original or one of three new ones in his post?

      Gerard Threels - September 8, 2014 Reply

      I’ve put “OR Ref( Buy, -2 )” to the original script.

        Piero - February 17, 2015 Reply

        i have a feeling that if you use that 3-day holding as a sole exit it will get even better. No evidence on that but some time ago I tried 1 to 5 days holding on mean reversion entries and it looked good.

        thank you Cesar for making your work freely available and for your patience with the occasional asshole’s arrogant comment, there is no limit….

        just one month of applying the strat to an EU exchange with real trades had 68.8% win rate, 2.4 avgW/L, 5.7 PF… again dont take me to court, it was only pure luck.

        Have fun

Michael - September 9, 2014 Reply

Pleasingly enough, I find this simple system _does_ work… on a daily timeframe (chart) of things like ES, NQ, SPX, etc.. However it fails horribly on say, currencies, crude oil. Thoughts on either “it was meant for equity indices, stick with that” or how to tweak it to make it work better on instruments which trend down harder and longer than say, SPX / ES has for the past several years?


    Cesar Alvarez - September 9, 2014 Reply

    Sorry but I don’t do much (if any) research on currencies and commodities.

Alex Argyros - September 21, 2014 Reply

Thanks for sharing your research.

You mentioned in your first post on this idea that the original system went long and short. Have you though about adding short rules to this strategy?

    Cesar Alvarez - September 21, 2014 Reply

    I did not do the short for two reasons. One, I no longer short. Two, Nick said that the short side did not add that much to the returns.

Marco - October 7, 2014 Reply

I believe this long bias has to do with the general bullish trend of the economy. It spends much more time going up than down and this affect the odds of picking up a good long trade instead of a short one. This happens nearly with every trading style, also with patterns.

Shamus - June 27, 2016 Reply

I found after many years that Amibroker back tester buys and sells on the same day open when there is no cash available to open another position. It assumes the closing of one position and the opening of a new position happens simultaneously. Any back test needs code to check available cash before opening another position. An alternative is to sell on the open to make the cash available and buy on the close.

    Cesar Alvarez - June 27, 2016 Reply

    If one has a margin account, this is possible to do in a real trading account. I do it all the time. If you do not have a margin account, then you may run into issues.

Leave a Reply: