Trading at the Close – the Mechanics

When investing strategies are back tested, the prevailing approach is to use daily closing prices both for the signal and for the entry point. This is all well in theory, but implementing such a system in practice is far from straightforward. The most obvious problem is that the close remains unknown until the end of the day, thus, we don’t know what our action needs to be at the close before the close is in place, but that’s the end of the trading day. A form of the chicken and egg problem.

The way I approach this problem usually is by trying to compute in advance my actions for all possible and reasonable (for instance, it is unreasonable to compute the desired action for S&P500 falling 50% in a day) scenarios.

Often, we can compute the desired position by reverse engineering the strategy. For example, let’s assume we are using a crossover strategy between the price and the 200-day moving average. We don’t know the upcoming close, but based on the previous 199 closes, we can compute the point at which the next close will equal to the 200-day moving average including the new close. Once we determine this point, any close above this point would indicate a long, otherwise we would like to be out of the market.

There are two major problems with the above approach:

• It works mostly for simple models (consider reversing the stochastic indicator)
• An automated implementation would require unique code for each system
• An automated implementation would also require much different code from what we have already coded for the back testing.

Both the second and the third argument increase the likelihood of bugs and, thus, the testing cost. Even if the second and third bullet don’t apply to you (I keep hearing there are some bright individuals who write bug-free code), one still has to deal with the first, so bear with me. It’s good to have a reasonable alternative.

The simplest solution is to use brute force. It all depends on the strategy, but in general the idea is to first generate the set of possible outcomes (for example all possible closing prices for the next day), then to attach each possible outcome to the end of the series, then run the engine generating the signals (from the back testing code base) on each of these possible series and keep the results. The only optimization is to parallelize the computations.

Let’s consider for example a contrarian trading of the SPY (S&P 500) using the DVI indicator. The strategy is very simple: if the DVI is above 0.5, we want to short the SPY. Otherwise we want to buy long the market. It is unlikely that the SPY will move more than 10% either way on any given day. Thus, using the last day close we can generate all closing prices (rounding to a penny) for the next day within 10% of the today’s price. For each of these prices we compute DVI and the corresponding position. Finally, we compress the information keeping only the points where the position changes sign.

The result of such computation is what I call a table of actions. Here is an example:

Close Pct Position
\$119.79 -10.00% Long
\$132.73 -0.28% Short
\$146.40 10.01% Short

The table tells us that for any price below \$132.73, the indicated position at the end of the day is long. Otherwise – short. Easy, right?

We also need to execute the indicated trade. Even this is somewhat challenging. My favourite broker, Interactive Brokers, allows two types of orders which I find quite useful: Limit On Close (LOC) and Market On Close (MOC). MOC is simply a market order at the close. A LOC order is also executed at the close, but it’s executed only if the closing prices is better than the pre-defined limit price.

Let’s take the above action table as an example, and let’s assume that currently I am 1,000 shares long the SPY. From the table, we want to flip the position to short for any price equal or better than \$132.73. I would log in at any point during the day and put a LOC sell order of 2,000 with a limit price of \$132.73. If my order is executed, I will end up short 1,000 shares.

Some days the table of actions is even simpler:

Close Pct Position
\$119.79 -10.00% Short
\$146.40 10.01% Short

The message is clear – go short at the close. In this cases, a MOC sell order for 2,000 shares is appropriate.

Things get a little bit more complicated when we consider the action table from another indicator, a moving average crossover:

Close Pct Position
\$118.27 -10.00% None
\$129.16 -1.71% Long
\$144.55 10.01% Long

Let’s assume that we are out of the market, looking for an entry unless the market closes more than 1.71% down. This time a LOC buy order will not help, it will do (assuming the limit is \$129.16) the opposite! The reason is that for a buy order the limit requires the limit price or better, while the above table of actions implies a long position at the limit price or worse!

There are different solutions. For instance, if at 15:30pm the market is hovering around \$130 on a low volatility day, I may conclude that it is very unlikely for the market to drop below \$129.16 by 16:00pm and I may simply put a MOC order to change to short. An alternative is to prepare a market order, check the price 10 seconds before the close and decide whether to fire the order or not. One really needs to look into his brokerage software and decide what best works for him. Interactive Brokers for instance, has something called Conditional Order, which may be another solution, but I never tried it.

The table of actions doesn’t have to have a single inflection point (where the position changes from long to short or vice versa). An overbought/oversold strategy RSI(2) will have two inflection points: Long, Short and Neutral. Even worse are the table of actions coming from my ARMA indicators. On some days I am faced with the following:

Close Pct Position
\$132.20 -3.07% Long
\$137.37 0.72% Short
\$137.39 0.73% Long
\$138.85 1.80% Short
\$139.76 2.47% Long
\$139.79 2.49% Short
\$139.81 2.51% Long
\$139.82 2.51% Short
\$139.83 2.52% Long
\$140.59 3.08% Long

How realistic is this approach of trading in real life? From my experience it works exceptionally well – in my trading I manage to stay pretty close to the backtest results. Of course, it goes without saying that liquidity is important, which is of no concern to me since I trade only highly liquid ETFs.

Very interesting as a rarely see implementation related analysis. This topic is to me at least as important as the strategy itself.
When you mention “I would log in at any point during the day and put a LOC sell order of 2,000 with a limit price of \$132.73” I think this is a major issue. Imagine you submit a limit price of \$132.73 at 14:00 you get filled at 14:30 and the market closes at \$131. The trade is filled more than 1.5% away from your backtest price (\$131). This kills it all from my perspective or did I miss something?

1. ivannp says:

Hello, I think you are confused by the LOC order – LOC means Limit-On-Close. This order gets executed (if the limit is ok) only at the close of the trading day. Likewise a MOC order is Market-On-Close, it gets executed only at the close. I am using Interactive Brokers, other brokers may or may not support such orders.

My mistake…. Thank you

3. Invecus says:

Hello:

I find your blog very interesting, congrats! I have a doubt regarding the price 132,73 used to calculate the +-10% threshold when using the DVI Indicator. Is 132,73 the previous days close?
Also, is this the method DVI uses orinally (made by Varan) to take orders?
Finally, all orders from DVI system are executed MOC/LOC? In this case, what criteria DVI uses to buy MOC or LOC?

Thanks a lot! Great job with the blog, keep it up!

1. ivannp says:

The table of actions you are refering to carries the following meaning: “If the market closes today at 132.73 or higher, I should be short, otherwise – long”. Remember, we are trying to determine the position at the end of the day we haven’t seen yet.

And to your last question, whether to use a LOC or MOC order depends how the pre-generated table of actions looks like. If it’s a single range, i.e. the second example in the post, then it can be handled by a MOC order. If the table of actions consists of two ranges, like in the example with 132.73, then it should be handled by a LOC order.