How to test intraday mean-reversion on daily bars

This post is about how to test intraday mean-reversion strategies using limit orders based on daily bars. While in earlier posts my focus has been on the strategy itself, this post is going to focus on how to get as realistic as possible back test results.

Data: daily or minute bars

For my testing I’m only using daily bars as I think daily bars have the highest quality in terms of data consistency.  Furthermore it’s difficult to get minute bars for delisted stocks which I think is necessary to avoid survivorship bias in my back testing.  Assuming one would have 1min. data in high quality for all Nasdaq100 stocks going back to 2001, you run into another issue: computing power.  Testing a Nasdaq100 stock based system on daily bars requires to process  100 stocks * 10year * 252bars = 252.000 bars per run. Looking at 1 minutes bars this has to be multiplied by 6.5h * 60minutes = 98.280.000. Of course this can be reduced by using higher granularity bars such as 10min. or so, but then again the benefit of knowing whether a particular trade would have been filled is gone. Bottom line: I will stick to daily bars as I consider these are the limitations of being a retail trader (for now).

.

Limit orders

In my last post I discussed three different ways how to trade the system presented. I decided that I want to submit the limit orders prior market open. Hence the system presented last time creates unrealistic results as it assumes you will look for stocks that fall below the limit order regardless the ranking, but in reality you can only set a limited numbers of limit orders. Please review this example:

In reality you got 5 orders ( Rank 1 – 5). Two of the 5 get a fill, but in AmiBrokers backtest you will get 5 fills. So the main issue is the number of fills you will get in reality and the fact that  your capital is allocated but not working.

The Solution!

In my last post I was writing:  “… As you don’t know what stocks fall bellow the entry criteria you have to set limit orders for all NDX100 stocks. While this is technically possible the broker won’t allow you to do this as this will likely exceed your margin level.”

A reader left a comment regarding a special order type called: OCA (one cancels all) . Please read here for more information. OCA orders allow you to group multiple limit orders and in case one limit order get’s hit all other orders will be canceled. This way you can go beyond your margin requirement without actually over-leveraging as per order group only one order will be executed. Assuming you would like to have max. 5 position in the market, you then create 5 order groups with N orders per group. Thank you much to the reader who posted this fantastic comment.

.

How to do OCA grouping?

So OCA orders help you to increase your chances of oneoOrder (-group) getting filled significantly. In order to have realistic backtest results you need a way to simulate the behavior of submitting multiple order groups: when one order get’s hit from the group all order orders need to be disregarded. Furthermore you need to know the position within the ranking as you want to do the ranking according to stocks individual rank, e.g. order group one with stocks from 1-10, order group 2 with stocks from 11 – 20 … etc.

I did this with the AmiBroker CBT (custom backtest).  It resulted in a rather complex AFL code, but I believe it works. I spend the last couple of weeks in developing this. Bellow you find the code. Please send me an email (fhinbox-trading (at) yahoo.de) in case you find a bug.

.

Final results

Background

  • 5 order groups, with 10 orders each
  • Limit = yesterday’s close – 0.9 of yesterday’s ATR21
  • Ranking: Rate of change 20
  • In case the open price is bellow the limit order, the open will be the execution price
  • Based on NDX100 stocks (survivorship free: historical index adjustment + delisted stocks)
  • No commission / slippage
  • Explanation of the key performance indicators being used (link)

.

Limitations, improvements and next steps.

Limitations: The system still has a minor flaw in terms of matching the TRUE reality! Within an order group it will pick the stock with the highest position score. In reality that’s not necessarily the case. However, it’s good enough for me and my confidence in the approach.

Improvements: This post is rather technical in it’s nature as it focused on how to backtest intraday mean-reversion as close as possible to the reality. I don’t trade the system as presented. My system has some significant changes to when it’s trading, definition of the limit order and how it does rank the stocks. The main focus of the improvement has to be on increasing the average percentage per trade. However this will give you a very good starting point.

Next steps: I want to historically validate the execution for some of the entries by validating one minute bars. This will give me a possible further prove point if this is a viable strategy. Furthermore I need to look into how to automate my order submission as I don’t want to enter 50 orders manually everyday.

Comments

  1. Frank,

    great post. we can also look at the options. may be look for highly liquid stocks in sp500 and which is optionable. that way we wont have liquidity crunch as a big issue.

    thanks
    Bill

  2. Hi Bill,

    I’ve never been working with Options … how do you test option based strategies? Do you use AmiBroker?

  3. Another option would be if you have a 100k+ plus account with IB then apply for portfolio margin. Then you could use Order Sends Order to have any individual stock’s fill trigger an offsetting short SPY position. If you are transacting enough shares per month then the liquidity rebate you get for your limit orders could offset a significant portion of your SPY market orders. Of course this would be an entirely different strategy but just a though.

    Josh

  4. Frank,

    its very difficult to test anything option based strategy, probably we will have to have to hand pick and back test it.

    In stockfetcher you can look for stocks which are optionable. so it can be screened for. Also thinkorswim retains data for options for quites some time so it can be manually back tested.

    this are just some of my thoughts. It can probably be just a small part of the overall strategy.

    thanks
    bill

  5. Hi Frank, I am not sure if I understand how you decide what stocks to place in each of the 5 groups. You rank them according to the rate of chage of the past 20 sessions, but then how do you allocate this ranked list to the 5 groups of stocks?

  6. Hi Frank
    I am not yet sure that the system will work. For my experience, the stocks bought are the worst ones. Look at your May-2010 results. In May the stock exchange dropped sharply, and the system earns a lot. That wasn’t my experience, as for many other months.
    Of course, a backtest with intraday data may help to see if it works.
    Another strategy would be to pre-select 5 or 10 stocks prior to the open, based in Position Score; and only trade those stocks. It would have a small market exposure, but the backtest would be very reliable..
    But you’ve done a great job!

    • I read again my post and I want to tell something else: My system is not exactly as Frank’s, although similar. So I can not assure the Frank’s system does not work, perhaps it does..
      Never knows until you try.. 🙂

  7. Hi Frank,

    All looks correct and feasible to me. It is interesting that with the OCA groups, the missed trades causes a significant drop to the CAR down to 108%, but increase the average % per trade to 0.63%. What is the actual drop in number of trades taken?

    – Alfred

    • Hello Alfred,

      The first model had about 10.000 trades vs. 6.000 for the final one.

      Regarding the avg. size per trade … it has mainly to do with the ranking method – I used ROC20.
      ROC20 is by definition not adjusted for volatility, hence some of the more interesting entries might be in the middle to end of the stack.

      – Frank

      • I actually would have thought that the ROC20 ranking doesn’t make much difference to the result. Although it is selecting trades from the top 50% of the ranking, it distributes them in 10% bands which implies it isn’t playing a role as a selection criteria for the trades. In other words, if you formed the groups randomly, I suspect you would see the similar results.

        I think the reason for the improvement is that the grouping themselves reduces the exposure of the strategy (because each execution within a group cancels 4 other trades) whereas the original strategy had much higher exposure because it did not cancel trades. Perhaps this is important on days when the whole market tanks?

        It is a shame that in order to test the effect of OCA groups, you need the custom backtester in Amibroker – that has put me off testing refinements to my own strategy because of the complexity. Also, I have never backtested against actual minute bars which would add a lot of confidence to the results.

        Inspired by your results, I removed all my filters from my intraday system and instead simply bought X groups on a dip of %d of the ATR(N). However, I kept my exit (instead of exiting on EOD). I saw great results too that achieved very decent CAGRs on a lot of trades. My existing system produces much higher average trades but much fewer of them. I’m tempted to start trading this new strategy already but will wait until I get some more $s to play with and maybe read what you find when you test minute bars against your strategy 😉

        BTW, to enter InteractiveBroker trades automatically, I have written a C# applet in Visual Studio Express (free tool) that uses the IB ActiveX API to enter trades. I copy the results of the explorer pane from Amibroker into the clipboard, then paste it into the app. It was fairly simple to write and works great. I enter exit trades manually but there are far fewer of them, of course.

  8. Frank, fantastic work. Really fantastic!
    However, I don’t see the code anywhere in the post?
    Thanks so much for your hard work,
    Wood

  9. Hi Frank,

    you wrote:

    “Furthermore I need to look into how to automate my order submission as I don’t want to enter 50 orders manually everyday”

    I use this way: With “Tradesignal” it is possible to export Data in x-cel. So Tradesignal calculates the data and fills the IAB-xcel-API with the necessary information (Stocksymbol, Limt-Price, Ordergoups, Size…..etc). With another click all orders are submitted to IAB. This daily step takes me only seconds.

    Joachim

  10. Hi Frank,

    iI don’t understand how OCO-groups can solve the core of the problem. In my eyes OCO-groups only help to limit the amount of filled orders. Thats all.

    The system will in average buy the worst performing stocks, because the “weak” stocks will hit the limit-price first, the “stronger” stocks will hit the limit-price later. At the end of the day you seldom get your 5 best ranked stocks, even if the top five hit the limit-price during the day.

    What do you think of this approach?

    A stock hits the limit-price, but it has a bad rank-position. In this case one can calculate the odds of stocks with a good rank-position to hit the limit price until the end of the day (how far is the good-ranked stock away from its limit-price, is it downtrending, …..) Only if the odds of the good ranked stocks to hit the limit price are low, then the bad ranked stock should be bought. When the odds of the good ranked stocks to hit the limit-price are high, one wait (and hope:-) to buy the good-ranked stocks later.

    Greetings, Joachim

    • Hello Joachim,

      the basic problem with back-testing the strategy: the “bad” stocks are likely to hit the limit first. So you one will be loaded with the bad stocks at the time the good stocks are hitting the limit. (assuming good stocks are likely to hit later). One approach to mitigate that challenge is to simple give bad stocks a lower limit order.

      Frank

    • Hi Frank,

      you askes about the technical realization.

      Let me mention first, I don’t trade the approach I described. But I think, I could technically realize the approach with my setup.

      I use Tradesignal Standard Edition (for Backtesting as well as Realtime-Trading).

      First I tried to use the Tradesginal build-in connection to IAB. But because of the poor variety of ordertypes/ -attributes and the delay of the realtime-data, it didn’t work out. Now Tradesignal writes data in the IAB-XCEL-API. Visal-Basic-Makros are sending (modifying and deleting) Stop- and Limit-Orders to IAB – according to the decisions of Tradesignal.

      It works pretty fine most of the time.

      Problems occur sometimes with the performance of Tradesignal. The systems gets in time-delay when the amount of underlyings is to big and the tradings-scripts are complex. So I can work with a maximum of 100 Stocks at the same time. Perhaps a technical setup with more performance would help.

      Greetings, Joachim

  11. Hi Joachim,

    thanks for the reply!

    Just went live with my strategy TODAY.. let’s see how it’s going.

    Frank

  12. How are things going with this system Frank, if you don’t mind me asking? Have you had the problem (or figured out a solution to) the fact that on days when the market drops the first stocks that fire won’t give you the average return of all the stocks for the day aka the worse ones trigger first? After playing with this a bit and simulating it using minute bars that seems to be the major issue.

    Thanks… good luck.

    • Hello Mike,

      I tried to address the issue by giving stocks with a lower rank, a “deeper” limit entry. The main problem with this system: reality won’t match with the backtested results.

      Regards,
      Frank

  13. Hi Frank, where’s the code? Hows it doing in real time?

    • Hi,

      It took me a week to write the basic code, hence I decided not to release it. I’m trading the system. If you want to buy it send me an email to hassler(dot)frank(at)gmail.com

      Regards,
      Frank

  14. Hi Frank,

    I trade a system very similar to this. I have the same expected problem: my live trading results dont match the back-test vlaues either! So, I did tried the following to close the gap:
    1. Include commission
    2. Use Bid/Ask price + Slippage (0.05%)
    3. Ignore data points where trade volume is less than your limit order size. Also, exclude the extreme prices (0.5% outlier ticks), if the stock is not very liquid.

    I wonder if you would share your live results for the last 7 months and how you tried to improve your backtesting.

    Thanks,

    Sid

  15. Hi frank,

    I had been following you for a long time. I am planning to test something like this.
    Can you do a quick post on how the system is doing in this current volatile environment. Did it have major losses on august downswing. Do we need to put a filter to stay out during this time. Have you considered a short system during negative times.

    Thanks
    Bill

    • Hello Bill,

      I spent considerable amount of time turning that idea into something “tradeable” … even traded that for about a year with limited amount of money. My system went sideways (mostly) as most mean-reversion strategies during that time. I’m tracking my system along with the overall mean-reversion tendency in the market …

      Frank

  16. Hello Bill,

    I spent considerable amount of time turning that idea into something “tradeable” … even traded that for about a year with limited amount of money. My system went sideways (mostly) as most mean-reversion strategies during that time. I’m tracking my system along with the overall mean-reversion tendency in the market …

    Frank

  17. Thanks for updating us.

    Please do post some performance charts with latest data. Its really disappointing for such a nice system with high rate of return to fail. What can we do to stop this from happening. I have put a filter based on 70 day slope and other volatility filters. Most of my DVO based systems are out of market. What i am seeing is markets are getting pulled to extreme and then reversing. One great idea is to use V chart developed Mark W. Helweg. Those are still capturing mean reversion ok.

    • Hi Bill,

      currently pretty busy closing a few projects (maybe I can do an update early next year).

      DVI also does a good job of identify OS/OB intermediate term levels.

      Regards,
      Frank

  18. Hi, Neat post. There’s an issue along with your site in internet explorer, may check this? IE still is the marketplace leader and a big component to people will miss your wonderful writing due to this problem.

Trackbacks

Leave a comment