December 25

16 comments

Two Dimensional Market Environment Filter

By Jeff Swanson

December 25, 2018

automated trading, Automated Trading Development, EasyLanguage, ES, filters, free easylanguage, futures trading, S&P Emini, stock index futures

In this article I’m going to demonstrate a technique to help adapt your trading systems to the changing market conditions. In a previous article entitled, “Trend Testing Indicators“, I tested several indicators that could be used to divide the market into two modes: bullish and bearish. These two modes were then used to dictate how the trading system should execute its trades. For example, during a bull mode only open long trades. During a bear mode only open short trades. In essence, we made our system adapt to the given market conditions. However, we can take this concept further by looking at a different market characteristic: trend strength.

A market may be in a bull regime, but how strong is the trend? Is the market rising fast or is it range bound? We would like to know if the market is trending strong or not because we would like to trade them differently. It’s clear a range bound market that should be traded differently than a trending market. In general you may want to hold an open position longer if the trend is strong. By measuring the strength of the trend we can further divide the market to make our trading system more adaptive. By introducing trend strength we now create four distinct market environments that can be used to determine how an automated system trades.

Four Market Environments

Bull Market

Bear Market

Weak Trend

1

2

Strong Trend

3

4

In this article I’m going to create  a simple strategy that will focus on the market environments one and three. That is, we will look at a weak-trending bull market and a strong-trending bull market.

Trading Environment

Our strategy will be coded in EasyLanguage and tested on the SPY ETF going back to 1993. All the tests within this article are going to use the following assumptions:

  •  Starting account size of  $50,000.
  •  Dates tested are from 2006 through December 31, 2019
  •  1 Contract per trade
  •  The P&L is not accumulated to the starting equity.
  •  There are no deductions for commissions and slippage.
  • No Stops

The Baseline System

For the buy and sell signal I’m going to use the very familiar 2-period RSI Strategy from the book, ”Short Term Trading Strategies That Work”, by Larry Connors and Cesar Alvarez. The system only goes long. There is no shorting. This strategy goes long in the S&P 500 E-mini when the market experiences a pullback in a long-term uptrend. Based on our previous article, “Trend Testing Indicators“, we determined the smoothed ROC indicator which may be an effective market regime filter. So we will use a 200-period ROC calculation to determine if we are within a bull market. The 2-period RSI is used to locate pullbacks (entry points) within our bull market. An RSI value below a 10 will tell our system to open a new long position. We exit the trade when the 2-period RSI rises above 65 . The rules are:

  • 200-Period ROC calculation must be above zero.
  • Buy on close when RSI(2) is below 10.
  • Exit when RSI(2) is above 65.

This system is applied to a daily bar chart going back to 2006.

Looking at the trading rules, you can see that the Baseline System has a market mode filter (the 200-day smoothed ROC) to identify the overall bullishness or bearishness of the market. But we make no distinction between a strong trending bull market and weak trending bull market. If we are in a strong bullish market it makes sense to hold on to our trade in an attempt to capture a bigger move. On the other hand, if we are not in a strong trending market we may want to exit our long position rather quickly. Yet, our Baseline System always sells when a 2-period RSI rises above 65. The exit makes no adjustment for the trendiness of the market.

Introducing Trend Strength

Let’s use Trend Strength Indicator to gauge the trend strength of the market. Trend Strength Indicator (TSI) can be found over at Engineering Returns (no longer around). You can also download the code at the bottom of this article. Let’s also define a strong trend as >= 1.65 and a weak trend as < 1.65. These are not optimized numbers. They are simply a generalization from experience.

Now, let’s modify our exit parameter to hold longer during a strong trend. We’ll exit when a 2-period RSI rises above 95. This should allow us to hold our position longer and capture more profit during a strong trend.

The TSI indicator is provided as a download within the TradeStation ELD and within the Text File found within the download section at the conclusion of the article.

Our new bull market exit rules look like …

  • If TSI >= 1.65 Exit when RSI(2) of the close of current day is above 95

Below is a snapshot of several trades where the market trend changes from non-trending to trending. You can see that during a trending market we are holding the trade longer simply by requiring the RSI(2) value to rise above 95. The trades on the left half of the image are non-trending trades (LE_nt) while the two trades on the right half of the image are trending trades (LE_t).

Let's also change our entry rules based upon the trend strength. If we are experiencing a strong trend we want to make our entry rules a bit looser. That is, we expect pullbacks to be shallower when a market in trending strongly. So, we'll make our 2-period RSI threshold 25 instead of 10. This will allow us to enter shallower pullbacks during a strong trending market.

Now let’s take a look at the performance of this strategy.

1S VS 2D Filter

1D Filter

2D Filter

Net Profit

$10,575

$32,513

Profit Factor

1.19

1.60

Total Trades

111

88

%Winners

74%

72%

Avg.Trade Net Profit

$95

$369

Consective Losers

3

3

Annual Rate of Return

1.45%

3.79%

Net Profit / Drawdown

0.59

1.66

By introducing a simple trend strength indicator and making our strategy adapt to the trend strength, we generate more net profit and more profit per trade. We do decrease the number of trades as well. This is a good improvement and it demonstrates that we are on the right track by holding our position longer during a strong trend.

What if we simple hold all our traders (strong trend or not ) with our strong trend exit method?

1D Filter

2D Filter

Always 

Net Profit

$10,575

$32,513

Enter your text here...

Profit Factor

1.19

1.60

Cell

Total Trades

111

88

Cell

%Winners

74%

72%

Cell

Avg.Trade Net Profit

$95

$369

Cell

Consective Losers

3

3

Cell

Annual Rate of Return

1.45%

3.79%

Cell

Net Profit / Drawdown

0.59

1.66

Cell

Conclusion

There you have it. A strategy that adapts to several different market conditions. I did not cover the bear market regime, but you’re certainly free to explore that. Likewise, you can expand this concept to create a strategy that more drastically changes its trading behavior based on which of the four market environments we defined. Maybe during a strongly trending bull market you will want to use a completely different exit method than used during a non-trending market. In closing, this should provide some idea on how you can use two different types of indicators to divide the market into four different market environments.

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.

  • Thanks for the interesting articles Jeff.

    I took the accumulated RSI and averaged it out so it plots similar to basic RSI. Here’s the code. It matches up very well with the RSI Accum oversold area.

    Input:

    Price( Close ),
    Length( 2 ),
    OverSold( 20 ),
    OverBought(80),
    OverSColor( Green ),
    OverBColor(Red);

    Variables:
    MyRSI( 0 ) ;

    MyRSI = (RSI(Price[2],Length) + RSI(Price[1],Length) + RSI(Price,Length))*.33;

    if MyRSI OverBought then SetPlotColor( 1, OverBColor ) ;

    Plot1( MyRSI, “RSI”) ;
    Plot2( OverSold, “OverSold” ) ;
    Plot3( OverBought, “OverBought” ) ;

    if MyRSI crosses over OverSold then Alert( “Accum RSI buy zone” );
    if MyRSI crosses under OverBought then Alert( “Accum RSI sell zone” );

  • Thanks for the article Jeff.

    An interesting thing to do with a strategy like this is to feed some of the performance stats back into the strategy as inputs, so that parameters are updated in an “on-line” fashion.

    For example, how relevant is the 10 day ATR? Volatility might be better measured over a period equal to the typical trade – afterall that’s the volatility your position will, on average, endure.

    The best thing about this is that because the volatility is used only to size positions and not to determine entries/exits, feeding the average trade length back into the strategy in this way can have no effect on the future average trade length – you get a potentially more meaningful input with no risk of convergence on a sub-optimal solution.

    Hope that’s a useful idea to someone!

  • The tsi study is not verifying in tradestation.

    I get the following error:

    Series input not allowed here. Line 14 error (#30254)

    Smoothed is highlighted.

    Help!

    Thanks

    Rick

  • I’ve tried 150 ROC with smoothing weights = [1 2 1]/4; RSI=4 days, entry = 15, exit = 60 if TSI5. Looks good! The most sensitive parameter is the RSI window…

    • I’ve not received any other issues from other people, so this makes me think you have something unique going on with your machine. A quick fix may be 1) Remove the TSI function from your strategy code and 2) simply cut-and-paste the TSI calculations directly into your strategy. This will bypass the need to call the function which is not verifying. The TSI function is only a couple lines of code (along with a single variable). While this is not the best solution it should get you up and running quickly.

  • Thanks Jeff, i did see some issues with code

    1. the code does not verify unless you adjust the code to:
    cntrcts = _CE_Normalize_Units_vs_Volatility( AccountSize, RiskPerTrade$, Close, 20, 3, false );

    2. If EnableTrendFilter(false); then it doesnt display any trades;

    3. I couldn’t match your performance on the same set of data.

  • How can you get more trades by adding a condition that keeps you in some trades longer, especially when you didn’t change the entry condition? Something doesn’t smell right.

    • Thanks for pointing that out. The article was recently moved from a another format in WordPress and it appears during that process a paragraph was skipped. If you look at the strategy code you’ll see the entry threshold is also changed based upon the TSI indicator. I updated the article with the missing paragraph.

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

    Learn To Code & Build Strategies
    Using EasyLanguage. 

    >