July 31


Testing Market Regime Indicators

By Jeff Swanson

July 31, 2023

adaptive, Algorithmic Trading, Automated Trading Development, EasyLanguage, filters, Migrated, regime trading

Often when designing a system it’s important to keep the big picture in mind. What is the overall market doing?

The most simple way to accomplish this is to break the market into two regimes: bullish and bearish. We are all aware that price action is a mirror of human psychology of market participants, therefore price action can often be very different between these two regimes. Bear market such as in 2008, behave much differently when contrasted to the continual grinding, upward market we saw after 2016-2019.

People behave differently under fear (how low will it go?) and pain (look at all the money I lost!) vs. doubt (this market can’t go higher) and greed (I’ll just make a bit more before I exit). Since people behave differently under these two market regimes it makes sense that we should design trading systems that take advantage of the different market characteristics for each regime.

We want to build a system that dynamically adjusts its trading behavior  based upon which market mode we’re experiencing. For example, we may want to only take long trades in a bull market and short trades in a bear market. To do this we can use any number of indicators.

The Indicators

The most simple way to divide the market is to use a 200-period simple moving average (SMA). When price is above it we are in a bull market regime. When price is below it we are in a bear market regime. Introducing this simple concept along can improve the performance of many trading systems. I’ve personally used this technique many times. Yet there are other techniques to divide a market and some of these might produce better results than our old reliable 200-day SMA. In this article I want to take a look at a few different methods.

The indicators we are going to test are:

  1. SMA(200)
  2. Rate of Change (ROC)
  3. Smoothed Adaptive Momentum
  4. Relative Strength Ranking (rsRank)

The Smoothed Adaptive Momentum and Relative Strength Ranking are two indicators you may not be aware of. First, the Smoothed Adaptive Momentum was created by John Ehlers. It’s a complex indicator and there’s more than I want to get into during this article. Google it if you wish and you can also find the EasyLanguage code here.

I will say this about the rsRank for now, traditionally it’s used as a ranking tool to compare a group of stocks or ETFs to determine which specific instrument is performing best. As its name implies, it ranks each instrument based on how well the instrument has been performing. You can then compare this score to the other stocks or ETFs in your basket of trading instruments. Thus, you can simply pick the instrument with the highest rsRank score when creating a momentum-based trading system. In this article I’m using it for a completely different purpose and I was curious on how well it would hold up.

Smoothing The Indicators

All of these indicators are also smoothed to help reduce whipsaw. Of course the SMA is a smoothed price indicator so no modification was made to this indicator. Likewise the Smoothed Adaptive Momentum indicator by John Ehlers also contains a smoothing element already applied to the indicator. However, to smoothen the ROC and rsRank indicator I used the same technique found within the Ehlers indicator. It looks like this for the rsRank indicator:

rsRankSmoothed = ( rsRankValue + rsRankValue[1]*2 + rsRankValue[2]*2 + rsRankValue[3] )/6;

The same smoothing technique is applied to ROC as well.

Look-Back Period

We are going to use a 200-day period for all our examples. The 200 days represent about 10 months of trading if you figure out that there are about 20 trading days per month. It’s also a common longer term period applied to moving averages as well. This is not a magic number by any means. It’s a large enough number that we should not see the regime switch too often between bear and bull. The idea is to capture the long term market mode, not every market gyration. Of course I encourage you to perform your own testing as well.

The Strategy Logic

The strategy code to test the effectiveness of these different indicators is rather simple. We are only going long during a bull market regime and closing our position when that bull market regime switches to a bear omarket regime. In essence we are creating a very simple trend following system. For each indicator the transition is based upon:

  1. SMA: Bull market when price is above the SMA
  2. ROC: Bull market when indicator value is above zero
  3. Smoothed Adaptive Momentum: Bull market when indicator value is above zero
  4. RS Ranking: Bull market when indicator value is above zero

Here is an example of the rsRank indicator used as a regime filter:

4 Long position opened when rsRank crosses above zero. Positions sold when rsRank crosses below zero.

Of course, this is only one possible test. For example, you can test going long during a bear market. It seems strange, but it might be worth looking into. Likewise, you could try on the short side. I won't be testing these alternative scenarios, but you're free to do so. The code for this article is available for you to download and modify as needed.

How To Quickly Test All Four Indicators

I want to quickly test these four indicators. To do that, I'm going to use a switch statement in my EasyLanguage code and creating an input called, iRegimeTest.

By simply adjusting the iRegimeTest input, I can rapidly test different indicators without needing to manually adjust or rewrite parts of the code. This is particularly useful for backtesting to identify which indicator gives the best results for a particular market.

Here is the code:



Once Clearprintlog;

Switch (iRegimeTest)
   case 1: // Simple Moving Average
      BullTrend = close > Average( Close, Period );
   case 2: // Smoothed Rate of Change
      rocValue = Rateofchange( Close, Period );
      rocValueSmoothed = ( rocValue + rocValue[1]*2 + rocValue[2]*2 + rocValue[3] )/6;
      BullTrend = rocValueSmoothed > 0;
  case 3: // Adaptive Momentum
      BullTrend = JE_Adaptive_Momentum( (h+l+c)/3, .07, 8 ) > 0;
   case 4: // Relative Strength Rank
      rsRankValue = rsRank( Period, 20,10 );
      rsRankSmoothed = ( rsRankValue + rsRankValue[1]*2 + rsRankValue[2]*2 +      rsRankValue[3] )/6;
      BullTrend = rsRankSmoothed > 0;
      BullTrend = false;

If ( BullTrend ) Then buy("LE Bull") next bar at market
Else sell("LX Bear") next bar at market;

How the Code Works:

The code essentially switches between different market indicators to determine whether the current market condition is bullish. This is done using the Switch statement, which acts upon the value of the iRegimeTest input.

  1. Simple Moving Average (SMA): An SMA is one of the most widely used indicators in trading. It calculates the average of a selected range of prices, usually closing prices, by the number of days in that range. When the current close is above the SMA, it is considered a bullish signal.
  2. Smoothed Rate of Change (ROC): The ROC is a momentum oscillator that measures the percentage change between the current price and the n-periods past price. The smoothed version here gives a less "noisy" signal, which can help in filtering out false signals.
  3. Adaptive Momentum: This measures momentum but adjusts (or "adapts") based on recent price data, making it more responsive to current market conditions.
  4. Relative Strength Rank: This appears to be a variation of the Relative Strength Index (RSI), a momentum oscillator that measures the speed and change of price movements. RSI oscillates between zero and 100. Traditionally, and according to Wilder, RSI is considered overbought when above 70 and oversold when below 30. The code seems to use a smoothed version of this rank.

Trading Environment

I coded the above rules in EasyLanguage and tested it on the SPY ETF market going back to 200. All the tests within this article are going to use the following assumptions:

  • Futures market on daily bar
  • Markts: ES, CL, S, EC
  • Starting account size of $50,000.
  • Dates tested are from 2000 through Jul  25, 2023.
  • The P&L is not accumulated to the starting equity.
  • There are no deductions for commissions and slippage
  • No stops

Performing The Test

For any given market I simply load my testing code into the chart. I then use TradeStation's optimization feature to optimize the  iRegimeTest input from 1-4. This will test each of the indicators. 

After the optimization is done, TradeStation will pick the best performing based upon the TradeStation Index (TSI). Below is the summary of the markets and which indicator performed best based upon the TSI.

Regime Testing Results - Best Indicator

Best Indicator

 E-mini S&P ES

Smoothed Rate of Change

 Crude Oil CL

Adaptive Momentum

 Soybeans S

Adaptive Momentum

 Euro Currency EC

Adaptive Momentum


Based on these limited tests, Adaptive Momentum shows superior results when determining a bull market from a bear market in most tests. The ES market does better with the Smoothed Rate of Change. Of course, these results may differ based on what you use to determine the "best" indicator. 

The point is quickly testing which indicator might be used for a given market to help you build a better trading system. In our test, we looked at taking long trades and scoring our regime filter with the TSI fitness function. This gave us an indicator to help define a bull regime for the given market.

Too often, people trade the same setup or method during different market conditions. Breaking the market into two regimes makes your trading system dynamic and adaptive to the changing market.

Does this always work? Nope. Nothing does in the trading world. This method works best on the stock index markets, in my experience. But it's worth testing!

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 great article. Can you go into more detail about how you use the RS Ranking Method as a trend indicator? I think I understand how it works as a means of comparing different markets, but not in terms of determining whether a market is in a bull trend or bear trend.

    Thanks again!

  • Hi Jeff,

    have you ever considered the importance of sample size? You draw conclusion based on samples as small as 17 (for ROC).

    Imagine what a difference just one more sample may have on your results! Now imagine it’s an outlier (i.e., 2 standard deviations away from the mean)!!!

    • Of course sample size is important, but the topic for this article was not sample size. It was ideas on creating and testing a simple regime filter to divide the market into a bullish and bearish mode. The ROC has a sample size of 25. The “since-2000” graph is a zoomed in view of the last 12.5 years. In short, I’m explaining a concept in this article and I encourage everyone to do their own testing. Thanks for the comment.

      • Hi Jeff,

        I understand and appreciate what you were trying to demonstrate.

        What I wanted to point out to you was that it might be better to do it in a “scientifically sound” way. Otherwise beginners may believe it’s OK to work with such small samples and knowledgeable people may think you don’t know better and ignore you.

        Cheers! 🙂

  • Hi Jeff. Good article. i am loading the indicators and eld but am getting a message that the ROC , je and rs smoothed indicators have been deleted. why would this be? also have you tested the ultimate oscillator? it seems to do a reasonable job overall in terms of determining the trend.

  • Thanks Jeff, for another interesting article. Would you please explain why you use a non-uniform weighting in your smoothing. I assumed you would have used a simple average. Were you intending to build in some lag to weight the previous values more – to act as hysteresis?

    • You’re welcome Peter. The formula used is from John Ehlers and is a finite impulse response (FIR) low-pass filter. That’s a lot of words to smooth data. Lots of his material is from signal processing. You can read a bit more here.

  • Hi Jeff,

    Do you know where I can find a simple strategy based on momentum (Price ROC). similar to the ROC calculated above that says go long/short when the momentum is greater than X over X amount of calculated periods?

  • Hello, Love your work. When I download Market regime study it doesn’t work on a chart. I do not get any trades and how do I get the comparison chart.

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

    Learn To Code & Build Strategies
    Using EasyLanguage.