Field note No. 03 · Intermediate
Indicators, and the 200-day moving average
What technical indicators measure, how to test one honestly, and a century of daily data on the most famous of them.
Educational material only. Not investment advice.
Contents
Abstract
Defines the main indicator families (trend, momentum, volatility, mean reversion, breadth) and six checks for testing any of them, then analyses the rule 'hold the US market above its 200-day moving average, otherwise T-bills' on daily data from 1927 to 2026: returns, drawdowns, time invested, switches, whipsaw, results by decade and in the deepest drawdowns, sensitivity to the lookback, to one day of execution delay and to costs, with the code that produced every number.
Key takeaways
- An indicator is a function of past prices; the rule, the execution lag and the costs decide whether it is worth anything.
- On US data from 1927 to 2026, the 200-day rule raised the Sharpe ratio and limited the deepest drawdowns to between a quarter and three-fifths of the market's, at the price of frequent whipsaw.
- The return advantage belongs to the years before 1990; since then the rule has returned less than the market, while keeping its risk advantage.
- Every lookback from 50 to 300 days behaves similarly on Sharpe ratio; 200 is not special.
- One day of execution delay and 10 bp a switch erase the return advantage; the Sharpe and drawdown advantages survive.
Before you start
- Field note 01 on anomalies and multiple testing
- Daily returns, compounding and drawdowns
- Reading Python with pandas
A technical indicator turns a price history into a number, and a rule turns the number into a position. The idea is old, the vocabulary is large and the evidence is mixed. This note defines the main families precisely, sets out how to test one without fooling yourself, and then takes the most widely quoted of them, the 200-day moving average of the US stock market, through a full, reproducible analysis on 99 years of daily data.
Indicators and rules
Write Pt for the closing price (or total-return index) on day t. An indicator is a function It = f(Pt, Pt−1, …) of prices up to and including the close of t. A rule maps the indicator to an exposure wt+1 held over the next day. Everything that goes wrong in practice happens in the space between those two sentences: which close the indicator uses, when the order can execute, and what the trade costs. Figure 1 shows the chain; the notation is the one used throughout the series.
The main families
Most indicators in use belong to five families. Each has a standard definition; the differences between implementations (a simple or exponential average, a close or a typical price, the smoothing of Wilder’s averages) matter less than the lookback and the execution around it.
| Family | Canonical indicator | Definition | Typical use |
|---|---|---|---|
| Trend | Simple / exponential moving average | SMAₙ = mean of the last n closes; EMA with α = 2/(n+1) | Price above average: hold; crossovers of a fast and a slow average |
| Momentum | Rate of change (ROC) | Pₜ / Pₜ₋ₙ − 1 | Sign of the past year's return (time-series momentum) |
| Volatility | Average true range (ATR); realised volatility | Wilder's average of max(high − low, |high − prev close|, |low − prev close|); stdev of returns | Position sizing and stops rather than direction |
| Mean reversion | Relative strength index (RSI) | 100 − 100 / (1 + avg gain / avg loss), Wilder smoothing | Fade short-term extremes (below 30, above 70) |
| Breadth | Share of constituents above their own 200-day average; advance–decline line | Counts across the index's members | Confirms or contradicts the index's own trend |
The ATR and RSI are due to Wilder (1978); breadth needs constituent-level data, which is why it is described here but not computed.
The trend and momentum families are two views of the same thing: a price above its n-day average has, roughly, risen over the last n days. Time-series momentum, which Field note 01 (Market anomalies) reviews, is the academic name for the second view.1 Volatility indicators are the input to Field note 02 (Volatility targeting). Wilder introduced the RSI and the ATR,2 and the RSI’s mean-reversion logic is the short-term reversal of Field note 01 (Market anomalies) in another form. Figure 2 draws four of the families on the same days.
def sma(price: pd.Series, n: int) -> pd.Series:
"""Simple moving average of the last n closes."""
return price.rolling(n, min_periods=n).mean()
def ema(price: pd.Series, n: int) -> pd.Series:
"""Exponential moving average with span n (alpha = 2 / (n + 1))."""
return price.ewm(span=n, adjust=False, min_periods=n).mean()
def roc(price: pd.Series, n: int) -> pd.Series:
"""Rate of change over n periods (time-series momentum)."""
return price / price.shift(n) - 1.0
def rsi(price: pd.Series, n: int = 14) -> pd.Series:
"""Wilder's relative strength index: 100 - 100 / (1 + avg gain / avg loss)."""
d = price.diff()
gain = d.clip(lower=0.0).ewm(alpha=1.0 / n, adjust=False, min_periods=n).mean()
loss = (-d.clip(upper=0.0)).ewm(alpha=1.0 / n, adjust=False, min_periods=n).mean()
return 100.0 - 100.0 / (1.0 + gain / loss)
def realised_vol(ret: pd.Series, n: int = 21, periods: int = 252) -> pd.Series:
"""Annualised standard deviation of the last n returns."""
return ret.rolling(n, min_periods=n).std(ddof=1) * np.sqrt(periods)How to evaluate an indicator
Indicators are easy to compute and easy to overrate. Six checks separate a result from an artefact; the analysis that follows applies each of them.
- Look-ahead. A signal computed from the close of day t cannot earn day t’s return. The error is common because in a vectorised backtest it is one missing
shift, and it is flattering: on the rule below it adds 8.7% a year. - Execution lag. Even correctly lagged, a rule that trades “at the close” assumes the signal is known in time to send a market-on-close order. Test one day later as well; the difference measures how much the result depends on precise timing.
- Costs. Charge every switch. A rule that trades a few times a year looks cheap until the switches cluster in volatile, wide-spread markets.
- Whipsaw. Count round trips that reverse within weeks, and measure what they cost. They are the price of a trend rule, and they are paid in exactly the range-bound markets where the rule adds nothing.
- Regime dependence. Report results by decade and by episode, not only in aggregate. A century-long average can be one decade’s result in disguise.
- Multiple testing. The 200-day lookback is famous because it has been examined for decades, which is itself a form of selection. Show the whole neighbourhood of lookbacks, and read Field note 01 (Market anomalies) on deflating the best of many trials.
The 200-day rule on a century of data
The rule is the simplest trend rule there is: at each close, hold the US stock market if its total-return index is above its 200-day simple moving average, otherwise hold one-month Treasury bills; trade at that close. The data are the daily CRSP value-weighted US market total return and the one-month T-bill return from the Kenneth R. French Data Library,3 1927-05-05 to 2026-08-31 after a year of warm-up. That is the broad US market rather than the S&P 500 or the SPY exchange-traded fund, which only exists since 1993: a long daily S&P 500 history is not freely licensed. As a check, the 200-day regime computed on the S&P 500 price index (FRED, 2017-07-12 to 2026-08-31) agreed with the regime on the CRSP series on 98.5% of 2,297 days.
The 200-day rule compounded at 11.5% a year against 10.2% for buy and hold, with a worst drawdown of -33.6% against -84.1%, invested 72% of the time and switching 5.7 times a year.
| 1927-05-05 to 2026-08-31 | Buy and hold | 200-day rule |
|---|---|---|
| Annual return | 10.2% | 11.5% |
| Annual volatility | 17.5% | 11.5% |
| Sharpe ratio (excess of T-bills) | 0.46 | 0.73 |
| Worst drawdown | -84.1% | -33.6% |
| Worst day | -17.4% | -9.2% |
| Time in the market | 100% | 72% |
| Switches a year | 0.0 | 5.7 |
US market total return (CRSP value-weighted, via the Kenneth R. French Data Library); the rule holds one-month T-bills when out. The moving average is computed on the total-return index. Cost is charged per unit of exposure switched.
The headline is real but needs reading carefully. The rule earned a higher return than the market with two-thirds of its volatility, so its Sharpe ratio was materially higher (0.73 against 0.46), and its worst drawdown was -34% against -84%. It achieved that by being out of the market 28% of the time and switching 5.7 times a year. Two cautions apply before any of these numbers is quoted. The return advantage comes from the years before 1990 (next section); and the 200-day drawdown is the best, not the typical, result among the lookbacks tested (Figure 4). The case trading at the close that produced the signal is also the optimistic one: the next-close row below is the conservative reading.
import sys
from pathlib import Path
import pandas as pd
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from fieldnotes import backtest, data, indicators # noqa: E402
d = data.market_daily() # daily total return, T-bill return
price = (1 + d["mkt"]).cumprod() # total-return index
signal = indicators.sma_regime(price, 200) # 1 above the 200-day average, else 0
rule = backtest.run(d["mkt"], signal, d["rf"], lag=1) # trade at the signal's close
hold = backtest.run(d["mkt"], pd.Series(1.0, index=d.index), d["rf"])
start = d.index[252] # one year of warm-up for every lookback
for name, res in (("buy and hold", hold), ("200-day rule", rule)):
r = res[res.index >= start]
print(name, {k: round(float(v), 4) for k, v in
backtest.stats(r["ret"], d["rf"][r.index], weight=r["weight"]).items()})def sma_regime(price: pd.Series, n: int = 200, band: float = 0.0) -> pd.Series:
"""1 when the close is above its n-day SMA, else 0, decided at each close.
band > 0 adds hysteresis: switch IN only above sma * (1 + band) and OUT only below
sma * (1 - band); in between, keep yesterday's state. band = 0 is the plain rule.
"""
m = sma(price, n)
up, down = price > m * (1 + band), price < m * (1 - band)
state = pd.Series(np.nan, index=price.index)
state[up] = 1.0
state[down] = 0.0
state[m.isna()] = 0.0
return state.ffill().fillna(0.0)Where the result comes from
By period
| Period | Market, annual return | Rule, annual return | Market, Sharpe | Rule, Sharpe | Market, worst drawdown | Rule, worst drawdown |
|---|---|---|---|---|---|---|
| 1927 to 1952 | 7.1% | 11.8% | 0.39 | 0.80 | -84% | -34% |
| 1953 to 1989 | 11.5% | 13.7% | 0.51 | 0.90 | -48% | -16% |
| 1990 to 2026 | 11.0% | 9.2% | 0.52 | 0.58 | -55% | -29% |
Each period compounded from one on its first day.
The century-long return advantage belongs to the years before 1990, and mostly to the first quarter-century: from 1927 to 1952 the rule compounded at 11.8% against 7.1%. From 1953 to 1989 it was ahead by 2.2 percentage points, and since 1990 it has returned less than the market (9.2% against 11.0%). What held in every period is the risk profile: a higher Sharpe ratio and a much smaller worst drawdown.
By decade
| Decade | Market, annual return | Rule, annual return | Market, worst drawdown | Rule, worst drawdown | Rule, switches |
|---|---|---|---|---|---|
| 1927-29 | 14.9% | 23.9% | -44% | -17% | 5 |
| 1930-39 | -0.4% | 8.4% | -80% | -34% | 67 |
| 1940-49 | 9.1% | 10.1% | -31% | -15% | 58 |
| 1950-59 | 18.2% | 16.7% | -21% | -12% | 58 |
| 1960-69 | 8.3% | 10.3% | -28% | -9% | 45 |
| 1970-79 | 6.1% | 10.7% | -48% | -16% | 63 |
| 1980-89 | 16.8% | 18.8% | -33% | -15% | 34 |
| 1990-99 | 17.9% | 15.8% | -22% | -14% | 42 |
| 2000-09 | -0.4% | 2.4% | -55% | -29% | 96 |
| 2010-19 | 13.6% | 8.0% | -20% | -22% | 58 |
| 2020-26 | 15.5% | 12.2% | -34% | -19% | 36 |
Each decade compounded from one on its first day; the first and last are partial.
The rule beat the market in the decades of long bear markets, the 1930s, the 1970s and the 2000s, and lagged it in strong, steady ones: the 1950s, the 1990s, so far the 2020s and, most of all, the 2010s, when it returned 8.0% a year against 13.6%. Its drawdowns were smaller in almost every decade. Anyone who adopted the rule in 2010 on the strength of the previous eighty years would have spent ten years underperforming and been right to ask whether it had stopped working.
In the deepest drawdowns
| Market peak | Trough | Recovered | Market | Rule, worst in the same span |
|---|---|---|---|---|
| 1929-09-03 | 1932-07-08 | 1945-02-06 | -84% | -34% |
| 2007-10-09 | 2009-03-09 | 2012-02-28 | -55% | -22% |
| 2000-03-24 | 2002-10-09 | 2006-10-23 | -49% | -29% |
| 1973-01-11 | 1974-10-03 | 1976-12-28 | -48% | -14% |
| 1968-11-29 | 1970-05-26 | 1971-04-27 | -37% | -9% |
This is where the rule earns its reputation: in the five deepest market drawdowns its own worst loss over the same span was between a quarter and three-fifths of the market’s. The mechanism is simple: a decline deep enough to matter lasts long enough to take the index below its average, and the rule steps aside for the rest of it.
Whipsaw
The cost of that protection is whipsaw. Of 281 round trips (an exit and the next re-entry), 247 (88%) were out of the market for 60 trading days or less, and on average the market rose 1.2% more than T-bills while those quick round trips were out. The worst are listed below; the largest, from 1939-08-18 to 1939-09-06, missed 7.8% in 15 trading days.
| First day out | First day back in | Days out | Missed, net of bills |
|---|---|---|---|
| 1939-08-18 | 1939-09-06 | 15 | 7.8% |
| 2000-04-17 | 2000-04-19 | 2 | 6.9% |
| 1932-10-11 | 1932-10-13 | 1 | 6.9% |
| 1933-03-18 | 1933-04-20 | 27 | 6.0% |
| 2010-06-07 | 2010-06-16 | 7 | 4.8% |
| 1933-10-20 | 1933-10-24 | 3 | 4.4% |
Lookback, execution and costs
The lookback
Figure 4 repeats the analysis for every lookback from 50 to 300 days in steps of ten. The Sharpe ratio ranges from 0.68 to 0.84 and the annual return from 11.1% to 12.2%; every lookback beats buy and hold on Sharpe ratio, and 200 days is not special. That flatness is reassuring, with a caveat: every lookback shares the same few bear markets, so the 26 results are far from 26 independent confirmations. The worst drawdown, by contrast, jumps around, because it is decided by how a handful of crashes happened to line up with each average. At 200 days it was -34%, the best of the 26 (tied with another lookback); the median across lookbacks was -41%. Quote the median, not the famous number.
Execution and costs
| Variant | Annual return | Sharpe | Worst drawdown | Worst day | Switches a year |
|---|---|---|---|---|---|
| Buy and hold | 10.2% | 0.46 | -84% | -17.4% | 0 |
| Rule, trade at the signal's close | 11.5% | 0.73 | -34% | -9.2% | 5.7 |
| Rule, trade at the next close | 10.6% | 0.66 | -39% | -17.4% | 5.7 |
| Rule, next close and 10 bp per switch | 10.0% | 0.61 | -41% | -17.4% | 5.7 |
| Rule with look-ahead (wrong) | 20.2% | 1.37 | -25% | -9.2% | 5.7 |
| Rule, 10 bp per switch | 10.9% | 0.68 | -34% | -9.2% | 5.7 |
| Rule, 25 bp per switch | 10.0% | 0.61 | -37% | -9.2% | 5.7 |
| Rule, ±1% band | 11.0% | 0.69 | -36% | -9.2% | 2.5 |
| Rule, ±2% band | 11.1% | 0.70 | -43% | -9.2% | 1.5 |
Costs are charged per unit of exposure switched. The band switches in only above the average by the band and out only below it by the band.
Four things in this table matter. First, look-ahead multiplies the return by 1.75: the error is not a rounding matter. Second, one day of delay costs 0.9 percentage points a year and changes the worst day from -9.2% to -17.4%. The worst-day change is a single date: the index closed below its average on Friday 16 October 1987, so selling at that close avoided Monday’s -17.4%, and selling at Monday’s close took all of it. That one day explains only part of the annual difference; the rest is spread across hundreds of switches, each a day late. Third, one day of delay and 10 bp a switch together remove the return advantage entirely (10.0% against 10.2%), while the Sharpe ratio and drawdown still favour the rule. Fourth, a band cuts the switches by more than half; at 1% it costs a little return, and at 2% it also deepens the worst drawdown to -43%, so a band is a cost decision, not a free improvement.
What the literature says
The evidence on technical rules is long and divided. Fama and Blume found that simple filter rules on individual stocks did not beat buy and hold once costs were counted.4 Brock, Lakonishok and LeBaron tested moving-average and trading-range rules on the Dow Jones index from 1897 to 1986 and found returns after buy signals that standard time-series models could not explain.5 Sullivan, Timmermann and White then corrected for the full universe of rules that could have been tried: the best rule remained significant in the original sample but not in the decade that followed.6 Lo, Mamaysky and Wang gave chart patterns a statistical footing and found that some carried incremental information,7 and Park and Irwin’s survey concluded that the positive results cluster in older samples and weaken with better controls for data snooping and costs.8
For asset allocation, Faber popularised a monthly version of this note’s rule, a 10-month average applied to several asset classes, and reported equity-like returns with much smaller drawdowns;9 Zakamulin examined the real-life performance of moving-average and momentum timing rules and found the out-of-sample advantage smaller and concentrated in bear markets.10 The wider trend-following literature puts the same idea across many markets.1,11 This note’s result sits comfortably inside that literature: protection in long declines, a price paid in whipsaw and in strong bull markets, and returns that depend on the period.
Implications
- Treat a trend indicator as a risk overlay first: its robust property is avoiding the middle of long declines.
- Lag every signal, test one day later as well, and distrust any result that hinges on a single close.
- Charge realistic costs per switch, and consider a band or a monthly check if switches cluster.
- Report the whole neighbourhood of lookbacks and the per-decade table, not a single number.
- Decide in advance how long the rule may lag the market, remembering the 2010s, before concluding that it has stopped working.
References
- Moskowitz, T. J., Ooi, Y. H., & Pedersen, L. H. (2012). Time series momentum. Journal of Financial Economics, 104(2), 228-250.
- Wilder, J. W. (1978). New concepts in technical trading systems. Trend Research, Greensboro, NC.
- French, K. R. (2026). Data Library: Fama/French factors (daily) and momentum factor (daily). Tuck School of Business, Dartmouth College. https://mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html (retrieved September 2026).
- Fama, E. F., & Blume, M. E. (1966). Filter rules and stock-market trading. Journal of Business, 39(1), Part 2, 226-241.
- Brock, W., Lakonishok, J., & LeBaron, B. (1992). Simple technical trading rules and the stochastic properties of stock returns. Journal of Finance, 47(5), 1731-1764.
- Sullivan, R., Timmermann, A., & White, H. (1999). Data-snooping, technical trading rule performance, and the bootstrap. Journal of Finance, 54(5), 1647-1691.
- Lo, A. W., Mamaysky, H., & Wang, J. (2000). Foundations of technical analysis: Computational algorithms, statistical inference, and empirical implementation. Journal of Finance, 55(4), 1705-1765.
- Park, C.-H., & Irwin, S. H. (2007). What do we know about the profitability of technical analysis? Journal of Economic Surveys, 21(4), 786-826.
- Faber, M. T. (2007). A quantitative approach to tactical asset allocation. Journal of Wealth Management, 9(4), 69-79.
- Zakamulin, V. (2014). The real-life performance of market timing with moving average and time-series momentum rules. Journal of Asset Management, 15(4), 261-278.
- Hurst, B., Ooi, Y. H., & Pedersen, L. H. (2017). A century of evidence on trend-following investing. Journal of Portfolio Management, 44(1), 15-29.