July 19

4 comments

Testing the FM Demodulator Filter

By Jeff Swanson

July 19, 2021


Within the June 2021 issues of Technical Analysis of Stocks and Commodities, you'll find an article by John Ehlers called, "Creating More Robust Trading Strategies With The FM Demodulator." This filter is purported to help reduce the variation of parameter settings. Put another way, using this filter should help with increasing the robustness of a strategy to various market conditions. 

A detailed explanation of Frequency Modulation (FM) is covered in the previous month's issue called, "A Technical Description of Market Data for Traders." The topic is well beyond what I want to write about here, so please review the original article for more details.

What I'm interested in is the practical application of an FM filter. Within the June 2021 issue, John Ehlers does just that. How? By comparing a simple trading strategy without the FM filter vs. with the FM filter.

In this article, I'll duplicate (with my modifications) what he does and then expand the testing to different markets.

The Baseline Strategy

The baseline strategy is straightforward and is for demonstration purposes only. In summary, the strategy uses the change of price to calculate a rate of change. It's a simple momentum strategy.

First, the strategy calculates the difference between today's closing price and the closing price from two days ago (Deriv). The sum of these differences is combined over four days (Z3). This Z3 variable is smoothed using an average calculation (Signal). Then the Rate of Change over the Signal is used to identify an entry point.

There are only two inputs. SigPeriod is the period to use for the average calculation. ROCPeriod is the period used for the rate of change calculation.

// TASC JUN 2021
// Creating More Robust Trading Strategies With The FM
// Demodulator
// (c) 2013 - 2021 John F. Ehlers
// Simple strategy

inputs:
SigPeriod( 8 ),
ROCPeriod( 1 );

variables:
Deriv( 0 ),
Z3( 0 ),
Signal( 0 ),
ROC( 0 );

// derivative of the price wave
Deriv = Close - Close[2];

// zeros at Nyquist and 2 * Nyquist,
// i.e. Z3 = (1 + Z^-1)*(1 + Z^-2) to integrate
// derivative
Z3 = Deriv + Deriv[1] + Deriv[2] + Deriv[3];

// smooth Z3 for trading signal
Signal = Average( Z3, SigPeriod );

// use Rate of Change to identify entry point
ROC = Signal - Signal[ROCPeriod];

if ROC crosses over 0 then
Buy next bar on Open;

if Signal crosses under 0 then
Sell next bar on Open;


In the original article, the strategy was executed on the daily S&P futures market (@ES) over 10 years. However, the author only reviewed long trades. I want to include short trades in my study, so I'm going to modify the code slightly. See the code below. My change is in BOLD.

if ROC crosses over 0 then
    Buy next bar on Open;
if Signal crosses under 0 then
    Sellshort next bar on Open

Example trades of the modified Simple Strategy

By changing the sell to a sell short, will convert the strategy code into a stop-and-reverse system. I like this because I want to incorporate the impact of short trades. Another option would be to separate the long and short sides and test them individually.

Trading Environment

I will test the baseline code on the E-mini S&P (@ES.D) market going back to 2007. Below are the assumptions used to generate the backtest:

  •  Starting account size of $25,000
  •  Dates tested are from January 1, 2007 through June 30, 2021
  • Trading 1 Contract
  • $30 deducted for slippage and commissions per round trip
  • No stops

Baseline Results

During the original test by the author, he compared a single optimization without the FM filter vs. a single optimization with the FM filter. I'm going to do it a bit differently. I don't want to select a single strategy. Why? Well, I don't want to pick a single good example from the optimization accidentally. Maybe that single example is an outlier. I want to see improvement across many instances, not a single sample. So, I'm going to review all strategies within the optimization. 

First, I will optimize the strategy for all the historical price data. Note, I'm not looking for the "best" strategy. I want to see the results of all optimizations. Later, when we add the FM filter, I want to know if we have improved any metrics. What metrics am I going to track? I will be looking at the following:

  1. Median Average Profit Per Trade
  2. Median intraday drawdown
  3. Median NP/DD (Net Profit vs Drawdown)

The two strategy inputs were optimized as follows:

  • SigPeriod (2-40 in steps of 2)
  • ROCPeriod (2-40 in steps of 2)

Using the above optimization settings on the inputs produces 400 possible combinations. I'm going to have TradeStation save all 400 optimizations. I will then export the optimization results into a spreadsheet to calculate my three metrics.

The bar graph of all 400 simulated strategies is below. We can see that 309 (77.3%) of the 400 strategies produced positive results.

Importing the results into a spreadsheet, I can calculate our three metrics.

1) Median Average Profit Per Trade = $249 STDV $393
2) Median intraday drawdown = $49,181 STDV $17,986
3) Median NP/DD = .72 STDV 1.13


Simple Strategy

Median Avg NP/Trade

$249

Standard Deviation Median Avg NP/Trade 

$393

Median Intraday Drawdown

$49,181

Standard Deviation Median Intraday Drawdown

$17,986

Median NP/DD

.72

Standard Deviation Median NP/DD

1.13

We have determined that given our 400 trading systems, 77% of them produce positive results, which seems solid. Looking at our three metrics, we have recorded our values and the standard deviation of those values. I'm planning to use the standard deviation as a metric for robustness. My thinking is, given a more robust strategy, our standard deviation values should be tighter (smaller) when moving to test the FM Demodulator filter.

So, when we test our strategy with the FM Demodulator filter, I would ideally like to see both an improvement in the metrics and improvements in the standard deviation. Ideally, I would like to see:

  1. Increasing Average Profit Per Trade & Smaller Standard Deviation
  2. Decreasing Average Profit Per Trade & Smaller Standard Deviation
  3. Increasing Net Profit / Drawdown & Smaller Standard Deviation

Adding The FM Demodulator

Now we'll add the FM Demodulator filter to our strategy.

Strategy: TASC JUN 2021 Strategy With FM Demodulator
// TASC JUN 2021
// Creating More Robust Trading Strategies With The FM
// Demodulator
// (c) 2013 - 2021 John F. Ehlers
// Simple strategy with FM demodulator

inputs:
SigPeriod( 22 ),
ROCPeriod( 10 );

variables:
Deriv( 0 ),
RMS( 0 ),
count( 0 ),
Clip( 0 ),
Z3( 0 ),
Signal( 0 ),
ROC( 0 );

// derivative of the price wave
Deriv = Close - Close[2];

// normalize Degap to half RMS and hard limit at +/- 1
RMS = 0;

for count = 0 to 49
begin
RMS = RMS + Deriv[count] * Deriv[count];
end;

if RMS <> 0 then
Clip = 2 * Deriv / SquareRoot( RMS / 50 );

if Clip > 1 then
Clip = 1;

if Clip < -1 then
Clip = -1;

// zeros at Nyquist and 2*Nyquist,
// i.e. Z3 = (1 + Z^-1)*(1 + Z^-2) to integrate
// derivative
Z3 = Clip + Clip [1] + Clip [2] + Clip [3];

// smooth Z2 for trading signal
Signal = Average( Z3, SigPeriod );

// use Rate of Change to identify entry point
ROC = Signal - Signal[ROCPeriod];

if ROC crosses over 0 then
Buy next bar on Open;

if Signal crosses under 0 then
Sell next bar on Open;

Again, I will optimize the inputs as done above to generate 400 different strategies. The bar graph of all 400 simulated strategies is below. We can see that 262 (65.5%) of the 400 strategies produced positive results. 

Already, that's not a good sign. The original code without the filter had more winning strategies during the optimization. With the filter, more strategies produce negative results. Let's look at the three metrics.

Median Average Profit Per Trade = $159 STDV $465
Median intraday drawdown = $54,45 STDV $20,888
Median NP/DD = .43 STDV .94


Simple Strategy

Simple Strategy With FM Filter


Median Avg NP/Trade

$249

$159

Standard Deviation Median Avg NP/Trade 

$393

$465

Median Intraday Drawdown

$49,181

$54,425

Standard Deviation Median Intraday Drawdown

$17,986

$20,888

Median NP/DD

.72

.43

Standard Deviation Median NP/DD

1.13

.94

Well, it looks like adding this filter did not improve any of the metrics. Overall, when we look at all possible optimizations, we're making less per trade, have a higher drawdown, and have a smaller NP/DD. Furthermore, nearly all standard deviations increased, thus showing more significant variation between the different strategies-exactly what we did not want to see. The only exception was Median NP/DD, which did see a reduction in standard deviation.

Conclusion

With this simple test, we can't demonstrate adding the FM filter to a simple strategy confers improvement over a wide range of possible inputs. Keep in mind, this conclusion only applies to the ES market since that's all we tested. Maybe it might work better with other markets. Perhaps it only works on the short side? Or the long side?

Can using the FM filter still help you find a better strategy? Maybe. As I've said, it would be worth testing on other markets. Maybe in some instances it can help improve a given strategy. In short, it still may be worth testing on your strategies.

Download The Code

You can down load John Ehlher's orginal code here, on the TradeStation forum. Look under the June 2021 issue, for the title "John F. Ehlers - Creating More Robust Trading Strategies With The FM Demodulator."

Jeff Swanson

About the author

Jeff has built and traded automated trading systems for the futures markets since 2008. He is the creator of the online courses System Development Master Class and Alpha Compass. Jeff is also the founder of EasyLanguage Mastery - a website and mission to empower the EasyLanguage trader with the proper knowledge and tools to become a profitable trader.

  • When you included the FM Demodulator did you also allow short trades. Just checking because the code you posted with the FM Demodulator does not include a sell short .

  • {"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}

    Learn To Code & Build Strategies
    Using EasyLanguage. 

    >