Two Dimensional Market Environment Filter

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



Strong Trend



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 1983 through July 5, 2013.
  •  The number of shares traded will be based on volatility estimation and risking no more than $2,000 per trade.
  •  Volatility is estimated with a three times 10-day ATR calculation. This is done to normalize the amount of risk per trade.
  •  The P&L is not accumulated to the starting equity.
  •  There are no deductions for commissions and slippage.
  •  A hard stop of $2,000 is placed for all trades.

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 1997 with $10 + .02 per share  deducted from each trade.

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).

Lets 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 equity graph and performance of this strategy.

1S VS 2D Filter

1D Filter

2D Filter

Net Profit



Profit Factor



Total Trades






Avg.Trade Net Profit



Consective Losers



Annual Rate of Return



Total Return



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 increase 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.


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.


About the Author Jeff Swanson

Jeff is the founder of System Trader Success - a website and mission to empowering the retail trader with the proper knowledge and tools to become a profitable trader the world of quantitative/automated trading.

follow me on:
  • Ninelivesz says:

    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.


    Price( Close ),
    Length( 2 ),
    OverSold( 20 ),
    OverSColor( Green ),

    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” );

    • Glad you liked it. That is an interesting twist on the indicator. Thanks for sharing.

  • […] is not unilaterally the best in all types of markets.  He’s more recently followed up with another article using the ROC, RSI, and TSI indicators in another variation of trading based on market […]

  • BlueHorseshoe says:

    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!

    • Thanks BlueHorsehoe, that’s an interesting idea. That’s the thing with trading, there are so many ideas to test!

    • Mark says:

      I’m not entirely I follow exactly what you’re getting at, BlueHorseshoe, but would walk-forward optimization be a systematic way of doing this?

  • Rick says:

    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.




  • Pietro says:

    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…

  • Rick says:

    I did both….neither would verify.


    • 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.

  • trader911 says:

    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.

  • Michael Young says:

    Have you tried an exit strategy that exits after say 3 profitable closes or 10 unprofitable closes?

    • Michael, those are good ideas. At this time I’ve have not tested those exit methods.

  • Cosmogeek says:

    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.

  • >