Portfolio Design

Advanced concepts in stock investment portfolio design.  Fundamentals, technical analysis and many other related topics are discussed.

Momentum: Second Day of Testing

After looking over the test data I collected yesterday, I determined that the phenomenon regarding EMA(x)/EMA(y) where x=1/2*y was simply coincidence. I decided to pursue further testing in order to further characterize the band-pass filter.


I determined that backtesting from 2000 was a mistake. The extra data I was obtaining from 2000-2007 without the Bullish USD ETF (Symbol: UUP) was too ideal (curve upwards) no matter what the ranking system.  So I repeated testing from 2008 to present.  It was still a small issue because although UUP has historical data starting from late 2007, 200-day moving averages wouldn't kick in until half way through 2008. But I wanted to capture some results from 2008 simply because of the high level of volatility.

The results were reasonably encouraging, with all variations of x and y giving positive results.  Beyond that, I learned that the simulated annualized return drop off substantially when the denominator has a moving average longer than 252 days (1 year). 

Ranking System test results using EMA(n)/EMA(200) where n=10, 20, 30, .... 150

Ranking System test results using EMA(n)/EMA(252) where n=10, 20, 30, .... 150

Ranking System test results using EMA(n)/EMA(300) where n=10, 20, 30, .... 150

The attention is now focused on the two formulae:  EMA(n)/EMA(200) and EMA(n)/EMA(252), with moving averages less than 200 deemed too short and longer than 252 too long.   EMA(n)/EMA(252) appears to be quite stable across a wide range of n, although the peak annualized return is lower.  EMA(n)/EMA(200) is more sensitive to the value of n but provides the best peak returns and superior performance curves at n, and near n.


The 252-day EMA provides more noise tolerance than the 200-day EMA.

The 252-day EMA provides more noise tolerance than the 200-day EMA.

I believe that the results are demonstrating how the lag of the moving average in the denominator is affecting the results.  With a longer moving average (252-days), the shorter moving average needs to be fast(er) to make up for the extra lag. With a moving average of 200-days, the lag is less, and the shorter moving average needs to be slower in order to compensate. This seems a bit counter-intuitive, but it results in a crossover at a similar time for both examples. Ultimately the 252-day EMA enables a much wider range of EMAs in the numerator for the formula due to the extra noise tolerance.


Below are two samples of EMA(x)/EMA(200).  The first shows the poor result with x=50, and a good result with x=100.

backtest-result-ema-50-day-ema-200-day.png
backtest-result-ema-100-day-ema-200-day.png

Below are two samples of EMA(x)/EMA(252).  The first shows good results for both x=50 and x=100. Note that neither example is nearly as good as EMA(100)/EMA(200).

backtest-result-ema-50-day-ema-252-day.png
backtest-result-ema-100-day-ema-252-day.png

Now I would like to spend a bit of time on the theory of EMA(x)/EMA(y) as a momentum rule.  This formula is effectively a Band Pass Filter (BPF). Picture a financial data stream as a continuous waveform of daily data.  Actually intra-day data but in this application we don't see the intra-day data.  The BPF has corner frequencies defined by the Exponential moving averages (x and y have to be converted from time to frequency domain). The BPF eliminates high frequency noise and also low frequency information that is not of use.  The result is a normalized waveform (or string of data) that can be compared to other streams of financial data.  High frequencies that are sampled result in something called aliasing (see Nyquist frequency).

In order to minimize aliasing (digital noise), one should sample at a much higher rate than the highest frequency of interest.  Or said another way, the waveform should be filtered so that there is no high frequency content that would translate into aliasing noise. The rebalancing frequency for our portfolio simulation is weekly, so we must consider the sampling rate to be 5 days. To minimize aliasing, the data should be low pass filtered to allow frequencies no more than 1/10th of the sampling rate i.e. an Exponential Moving Average of at least 50 days. This explains why the ranking systems TotalReturn (1 year % return), and Close/EMA(x) did not work very well.  Low pass filtering filtering is required to get good results, and at least 50 days.

But low pass filtering comes at a hefty price.  It introduces significant lag into the datastream.  Now we can compensate somewhat for this by adding a high pass filter, eliminating low frequency content. A logical choice is beyond 252 days or one year. This allows our filtering system to keep any yearly seasonal cycles.   There is no need to keep frequencies slower than 1 year (in the frequency domain). The low pass filter + high pass filter becomes a band pass filter. It would be really nice if Portfolio123 offered a band pass filter in their toolset. There are such things as zero lag BPFs but unfortunately I am unable to test this possibility and am relegated to the use of moving averages.

Now this testing has been a big confidence booster that such a system could work, but there are still questions.  Will these three cherry-picked ETFs maintain the same behavior into the future?  i.e. will they exhibit strong trends, and maintain a low correlation amongst each other?  What about other asset class ETFs?  How do they perform with this momentum ranking system? These are questions that should be answered. I hope to get back to tackle these issues in the near future (but I need a break from this for a while.)

Happy trading

Steve