Predicting MA Crossovers

This is inspired by an article in the February 2007 Technical Analysis of Stocks and Commodities magazine.  It goes over the simple MA case.  I have made the following improvements and changes:
  1) I did the equivalent computations for EMAs as well as SMAs.
   2) I made the indicator into a +1/-1 oscillator, which is easier to graph (the magazine's version had an unrestricted range which made the graphs hard to read.
   3) I have offered a way to tune how optimistic the indicator is, at the risk of causing more false positives
Anyway, this is one way to try to predict when to MA's will cross over, at least one day in advance on daily charts.  On a 15-minute chart, it would be 15-minutes in advance... 1 bar early, in other words.

Tomorrows MA in terms of today's MA plus tomorrow's close

Ok, so let's say for example you want tomorrow's 3-period MA value.  You need 3 data points.  You'd need yesterday's value, today's value, and tomorrow's value.  You'd compute it like this:

In[81]:=

t3ma = ( c_tomorrow + c_today + c_yesterday)/3 ;

(t3ma stands for "tomorrow's 3-period moving average")  If you rearrange the terms a bit, you can put tomorrow's 3MA in terms of today's 2MA.  This is because the 2MA is i simple calculation on today's close and yesterday's close.

In[83]:=

t3ma = (c_tomorrow + 2 (c_today + c_yesterday)/2)/3 ;

In[84]:=

t3ma = (c_tomorrow + 2 ma[2])/3 ;

We can generalize this to any period MA.  From now on, we will use 'tc' to stand for "tomorrow's close."  Since we're talking about moving average crossovers, we'll go ahead and define tomorrow's MA for both a fast 'f' period, and a slow 's' period:

In[79]:=

tma[f] = (tc + (f - 1) ma[f - 1])/f ;

In[80]:=

tma[s] = (tc + (s - 1) ma[s - 1])/s ;

You can see that this is just a generalization of the t3ma example case above.  This form is useful because it keeps us from having to juggle lots of price values... everything except tomorrow's value 'tc' is rolled up into a moving average from today!

What Does Tomorrow's Close Need to be for an MA crossover event?

So, these two MAs will cross only after they become equal.  So, you can set them equal, and solve for TC.  That's the value the price has to reach tomorrow, for the MA's to cross over.

In[85]:=

Solve[tma[f] == tma[s], tc]   //Simplify

Out[85]=

{{tc→ ((-1 + f) s ma[-1 + f] - f (-1 + s) ma[-1 + s])/(f - s)}}

Let's save off this answer as tcsoln:

In[86]:=

tcsoln = %[[1, 1, 2]]

Out[86]=

((-1 + f) s ma[-1 + f] - f (-1 + s) ma[-1 + s])/(f - s)

So, for example, for a 8 vs. 20 MA crossover, tomorrow's close must be:

In[21]:=

tcsoln /.{f→8, s→20}

Out[21]=

1/12 (-140 ma[7] + 152 ma[19])

In[22]:=

Simplify[%] // N

Out[22]=

0.333333 (-35. ma[7.] + 38. ma[19.])

... or (38*MA[19] - 35*MA[7]) / 3

Example of How it Can Be Used

Let's set up some example price data with some random function I pulled out of thin air...

In[23]:=

prices = Table[30   + Sin[i] + 2 * i * Cos[i * i], {i, 0, 2 * Pi, 0.005}] ;

In[24]:=

<<Statistics`DataSmoothing`

And, now let's take the moving averages we would need to predict a 200 vs 300 MA crossover:

In[87]:=

tcsoln /.{f→200, s→300}   // Simplify

Out[87]=

-597 ma[199] + 598 ma[299]

Alright, so that's a 199 and 299 MA needed (of course, we know it's always f-1 and s-1 that's needed, but I went ahead and computed it for the two constants I'll need in a bit.

In[25]:=

ma200 = MovingAverage[prices, 200] ;

In[26]:=

ma300 = MovingAverage[prices, 300] ;

In[27]:=

ma199 = MovingAverage[prices, 199] ;

In[28]:=

ma299 = MovingAverage[prices, 299] ;

ma300 has the fewest values, since 300 values are eaten up by the first average in the moving average.  So, we'll make all the other price lists the same length... this is so we can plot them together without worrying about offsetting them in time...

In[29]:=

prices = Drop[prices, Length[prices] - Length[ma300]] ;

In[30]:=

ma200 = Drop[ma200, Length[ma200] - Length[ma300]] ;

In[31]:=

ma199 = Drop[ma199, Length[ma199] - Length[ma300]] ;

In[32]:=

ma299 = Drop[ma299, Length[ma299] - Length[ma300]] ;

Now we can plot them together...The red is the fast MA, the blue is the slow MA.  We see that they cross at several points.

In[33]:=

<<Graphics`MultipleListPlot`

In[34]:=

MultipleListPlot[prices, ma200, ma300, PlotJoined→ {True, False, False}, SymbolStyle→ {GrayLevel[0], RGBColor[1, 0, 0], RGBColor[0, 0, 1]}]

[Graphics:HTMLFiles/MA_Crossover_Prediction_28.gif]

Out[34]=

-Graphics -

So, now let's create the list of values for TC, out of the auxiliary moving averages:

In[35]:=

theTCs = -597 * ma199 + 598 * ma299 ;

Now, the article suggests the predictive power of a cross of theTCs with the today's close. An easy way to spot these points is to subtract them, and note when the sign of the answer changes.  This will create an oscillator that's always either +1 or -1, and when it changes, a cross is predicted.

In[36]:=

signs = Map[Sign, theTCs - prices] ;

Let's plot it and see what it looks like.. we'll shift the oscilattor up by 30, so it shows up on top of the graph:

In[37]:=

MultipleListPlot[prices, ma200, ma300, 30 + signs, PlotJoined→ {True, False, False, True}, SymbolStyle→ {GrayLevel[0], RGBColor[1, 0, 0], RGBColor[0, 0, 1], RGBColor[0, 1, 0]}]

[Graphics:HTMLFiles/MA_Crossover_Prediction_33.gif]

Out[37]=

-Graphics -

Let's zoom in on a couple of the crossover points, to see if our green line jumped the day before the move...  Looks like it pretty much does.

In[38]:=

[Graphics:HTMLFiles/MA_Crossover_Prediction_36.gif]

Out[38]=

-Graphics -

In[39]:=

[Graphics:HTMLFiles/MA_Crossover_Prediction_39.gif]

Out[39]=

-Graphics -

In[40]:=

[Graphics:HTMLFiles/MA_Crossover_Prediction_42.gif]

Out[40]=

-Graphics -

A Possible Improvement

As presented, a crossover is predicted when tomorrow's price does not have to move to cause a crossover tomorrow.  Of course the safest assumption about the price of a security tomorrow is that it will not move.  So, this makes sense, but it can miss a prediction if a big move in the stock causes the MAs to cross.  We might be able to be a little more optimistic about the predictions by detecting when the TC line is getting close to today's price, instead.  The idea would be, if it crosses through the Close + 1/4 ATR, then it is still likely that a crossover will happen, as long as tomorrow's close is 1/4 ATR away from today's close (in ther correct direction, of course).

The Same Predictor, Only For Exponential Averages

Now, we'll repeat everything above, only for the Exponential moving average.  It turns out to be even simpler, but I'm going to move faster, since you've just seen all these steps a minute ago.

Exponential averages make use of a constant, k, based on the period of the avereage:

In[89]:=

k = 2/(period + 1) ;

... and the formula for an EMA is:

ema_t = k c + (1 - k) ema_ (t - 1)

So, we can see that today's  3ema (at time t) makes use of yesterday's 3ema (at time t-1).  That's great, because if you shift this 1 day ahead, you'll see that tomorrow's ema depends on today's ema for the same period.  Much cleaner than the SMA case, where we had to use a 2MA to predict a 3MA.  

As before, we'll go ahead and define a tema for both a fast 'f' and slow 's' period.  As before, 'tc' will stand for "tomorrow's close".  We'll go ahead and expand out that 'k' constant for the fast and slow periods while we're at it:

In[42]:=

tema[f] = k tc + (1 - k) ema[f]   /. period→f

Out[42]=

(2 tc)/(1 + f) + (1 - 2/(1 + f)) ema[f]

In[43]:=

tema[s] = k tc + (1 - k) ema[s] /. period →s

Out[43]=

(2 tc)/(1 + s) + (1 - 2/(1 + s)) ema[s]

Once again, we set the to EMA's equal to each other, since that is the point where they will cross.  Then, we solve for what tomorrow's close would need to be to make the cross a reality.

In[44]:=

Solve[tema[f] == tema[s], tc] //Simplify

Out[44]=

{{tc→ ((-1 + f) (1 + s) ema[f] - (1 + f) (-1 + s) ema[s])/(2 (f - s))}}

In[45]:=

etcsoln = %[[1, 1, 2]]

Out[45]=

((-1 + f) (1 + s) ema[f] - (1 + f) (-1 + s) ema[s])/(2 (f - s))

So, for example, if you want to know the TC formula for 8ema vs 20ema:

In[88]:=

etcsoln /. {f→8, s→20}   // Simplify

Out[88]=

1/8 (-49 ema[8] + 57 ema[20])

...it's (57ema[20] - 49ema[8]) / 8.

Example Usage with EMA Crossover

As with the SMA, we'll create some price data and predict some average crossovers...

In[48]:=

prices = Table[30   + Sin[i] + 2 * i * Cos[i * i], {i, 0, 2 * Pi, 0.005}] ;

And, now let's take the moving averages we would need to predict a 200 vs 300 EMA crossover.  To use Mathematica's ExponentialSmoothing function for the EMA, we need to compute the constant we mentioned earlier...

In[53]:=

k100 = k/. period → 100 ; k300 = k /. period→300 ;

In[54]:=

ema100 = ExponentialSmoothing[prices, k100] ;

In[51]:=

ema300 = ExponentialSmoothing[prices, k300] ;

Note that, unlike the SMA case, we only need the 2 EMA's.  Also, all the data is the same length, so there's no need to drop any.  Those are nice properties!

Now we can plot them together...As before, the fast 100EMA is red, and the slow 300EMA is blue.

In[55]:=

MultipleListPlot[prices, ema100, ema300, PlotJoined→ {True, False, False}, SymbolStyle→ {GrayLevel[0], RGBColor[1, 0, 0], RGBColor[0, 0, 1]}]

[Graphics:HTMLFiles/MA_Crossover_Prediction_61.gif]

Out[55]=

-Graphics -

Ok, so they clearly cross... let's generate our indicator, and check, as before.  We'll plug in 100 and 300 to get the correct constants:

In[65]:=

theETCs = etcsoln /.{f→100, s→300} ;

In[68]:=

theETCs = theETCs /. {ema[100] →ema100, ema[300] →ema300} ;

... and we'll take the sign of (our TCs - today's price) to get our oscillator:

In[70]:=

signs = Map[Sign, theETCs - prices] ;

... and plot them together:

In[71]:=

MultipleListPlot[prices, ema100, ema300, 30 + signs, PlotJoined→ {True, False, False, True}, SymbolStyle→ {GrayLevel[0], RGBColor[1, 0, 0], RGBColor[0, 0, 1], RGBColor[0, 1, 0]}]

[Graphics:HTMLFiles/MA_Crossover_Prediction_67.gif]

Out[71]=

-Graphics -

As with the SMA's it looks pretty good... let's zoom in and check further:

In[76]:=

[Graphics:HTMLFiles/MA_Crossover_Prediction_70.gif]

Out[76]=

-Graphics -

That was an accurate prediction!  Let's zoom in on another one:

In[78]:=

[Graphics:HTMLFiles/MA_Crossover_Prediction_73.gif]

Out[78]=

-Graphics -

Same Possible Improvement Possible with EMA's

Just as with the simple EMA case, you can make this indicator more optimistic by triggering on a crossover of price +/-  some amount times the stock's ATR, or something.  This would cause more false positives, but give more warning on the true predictions.  I think I'll make paintbars for this that vary their intensity by how many ATRs positive move would be needed to make the crossover happen in the next bar.  Maybe pale for 1ATR, soft for 0.5ATRs, and hot for when the TC crosses todays price.


Created by Mathematica  (February 1, 2007) Valid XHTML 1.1!