60/40 Portfolio With a Trend Filter: What Actually Changes?
What actually changes when you add a 200-day moving-average trend filter to a classic 60/40 stock/bond portfolio?
Over 2011–2026, adding a 200-day MA trend filter to each leg of a monthly-rebalanced 60/40 (SPY 60% + AGG 40%) cut the maximum drawdown only modestly (−21.8% → −17.4%) while cutting compound growth from 9.5% to 3.1% a year. The filter sat in cash roughly 44% of the time, and repeated whipsaws in 2015–16 and 2022–23 cost far more than the drawdown insurance was worth. As implemented, this filter fails.
- Strategy family
- Trend filter + cash / risk-off
- Universe
- SPY, AGG
- Data window
- 2011-01-03 → 2026-05-01 (evaluation window; 2010-01-04 → 2010-12-31 is the MA(200) warm-up)
- Data cutoff
- 2026-05-01
- Methodology
- c2i-research-1.2 (strategy engine: target_weight / target_weight_trend_filter, MA200, monthly, 3% threshold)
- Last reviewed
- 2026-08-09
Short answer
Adding a 200-day moving-average trend filter to each leg of a classic 60/40 portfolio (SPY 60% + AGG 40%, monthly rebalanced) reduced the maximum drawdown from −21.8% to −17.4% over the 2011–2026 evaluation window — but compound growth fell from 9.5% to 3.1% per year. The filter spent about 44% of the window in cash and produced repeated buy-high/sell-low whipsaws in 2015–16 and 2022–23. The drawdown insurance is real (it clearly helped in 2022); the price is much larger than the benefit in this configuration.
Why this question matters
“Add a trend filter” is one of the most common DIY improvements suggested for a 60/40 portfolio. The pitch is intuitive: when the stock market is below its 200-day average, why stay fully invested? Before trusting that intuition, it should be tested as a controlled experiment: same baseline, same window, same costs, one changed variable — and with the failure periods and cash exposure shown, not just the CAGR.
Hypothesis
A per-asset 200-day MA trend gate should cut the worst drawdowns of a 60/40 portfolio by moving a leg to cash when its own trend is down. The open question is the price: how much return, cash exposure and turnover change in exchange for the drawdown insurance.
Baseline and changed variable
| Baseline | Trend-filtered variant | |
|---|---|---|
| Symbols | SPY + AGG | SPY + AGG |
| Weights | 60% / 40% | 60% / 40% |
| Rebalance | Monthly, 3% threshold | Monthly, 3% threshold |
| Changed variable | — | 200-day MA trend gate per leg, exit to cash |
| Costs | $0 commission | $0 commission |
| Warm-up window | 2010-01-04 → 2010-12-31 | 2010-01-04 → 2010-12-31 |
| Evaluation window | 2011-01-03 → 2026-05-01 | 2011-01-03 → 2026-05-01 |
| Data cutoff | 2026-05-01 | 2026-05-01 |
In the trend-filtered variant each leg is evaluated independently: when a leg closes below its own 200-day moving average it moves to cash at the next monthly rebalance, and returns to its target weight only when it closes back above. A leg that is out of trend does not transfer its weight to the other leg — the freed weight sits in cash. This is the engine’s documented “trend filter + cash / risk-off” semantics.
Warm-up is explicit: the data source serves US daily prices from 2010-01-01 (shared data contract), so a 200-day MA cannot be computed until late 2010. Both variants run from 2010-01-01, but every reported metric, table and chart covers only the evaluation window starting 2011-01-03, with NAV normalized to 1 at that point. This keeps the comparison free of indicator warm-up bias.
Exact rules
- Universe: SPY (SPDR S&P 500 ETF) and AGG (iShares Core US Aggregate Bond ETF), daily adjusted closes.
- Baseline: hold 60% SPY / 40% AGG; rebalance on the first trading day of each month when a leg deviates from target by ≥ 3 percentage points.
- Variant: same rebalancing, plus a trend gate per leg — a leg is in trend when its close is above its 200-day simple moving average; out of trend means its target weight becomes 0 (cash) on the next rebalance day.
- Entries and exits are evaluated only on monthly rebalance days. An exit is therefore deferred up to one full period after a trend breaks (documented engine behavior, chosen to keep turnover low).
- Long-only, unlevered. Cash earns 0% in the engine. No leverage, no derivatives, no shorting.
- No slippage or commissions in the engine run; fee sensitivity is discussed in Limitations.
- Both variants run from 2010-01-01 (warm-up). Metrics are reported for the evaluation window 2011-01-03 → 2026-05-01 only.
Results and evidence
The metric grid, comparison table, annual returns and charts below are rendered directly from the study’s evidence file (real engine runs). Annual returns make the pattern clear: the filter helped in 2022 (−7.2% vs baseline −16.2%) and shrank the COVID drawdown, then gave back far more than it saved — 2017 +0.4% vs +14.4%, 2023 −9.5% vs +17.8%, 2025 +6.0% vs +14.0%.
| Metric | Baseline 60/40 | 60/40 + MA200 gate |
|---|---|---|
| CAGR | +9.5% | +3.1% |
| Maximum drawdown | -21.8% | -17.4% |
| Annualized volatility | +10.5% | +6.2% |
| Sharpe ratio | 0.86 | 0.49 |
| Calmar | 0.44 | 0.18 |
| Final value of $100,000 | $401,008 | $159,374 |
| Total trades | 44 | 74 |
| Trades per year | 2.9 | 4.8 |
| Dollar turnover (% of avg. AUM / yr) | +4.6% | +101.6% |
| Average cash (% of portfolio) | +0.2% | +43.8% |
| Year | Baseline 60/40 | 60/40 + MA200 gate | Difference |
|---|---|---|---|
| 2011 | +4.6% | +2.9% | -1.7 |
| 2012 | +11.2% | +6.3% | -4.8 |
| 2013 | +17.9% | +13.7% | -4.1 |
| 2014 | +10.6% | +3.9% | -6.7 |
| 2015 | +0.9% | -2.3% | -3.2 |
| 2016 | +8.6% | -0.4% | -8.9 |
| 2017 | +14.4% | +0.4% | -14.0 |
| 2018 | -2.7% | +0.5% | +3.2 |
| 2019 | +21.8% | +7.9% | -13.9 |
| 2020 | +14.7% | +8.3% | -6.4 |
| 2021 | +16.1% | +16.0% | -0.1 |
| 2022 | -16.2% | -7.3% | +8.9 |
| 2023 | +17.8% | -9.5% | -27.3 |
| 2024 | +15.3% | +6.6% | -8.7 |
| 2025 | +14.0% | +6.0% | -8.0 |
| 2026 (YTD) | +3.8% | -1.8% | -5.6 |
Where the strategy failed
- Bond-leg whipsaw: AGG was below its own 200-day MA for 31% of trading days in the evaluation window. Long stretches in 2013, 2016–17 and 2022–23 kept the ballast out of the portfolio. The filter repeatedly removes the asset a 60/40 relies on for stability.
- Equity whipsaw 2015–16: SPY crossed its 200-day MA repeatedly; the portfolio averaged roughly 45–56% cash in 2015–16 and missed the 2016–17 recovery. 2017 returned +0.4% vs baseline +14.4% — and held about 92% cash that year.
- Cash drag: the variant held ~44% cash on average across the evaluation window — about 95% in 2022, 67% in 2023, 54% in 2025. Cash earns 0% in this engine.
- Never recovered from 2022: the variant’s deepest drawdown episode started 2022-01-05 and was still open at the data cutoff (2026-05-01, −17.4%). The plain 60/40 recovered its 2022 drawdown by January 2024.
- Month-end execution: entries and exits are evaluated only at monthly rebalances, so the filter systematically buys after a rally has begun and sells after a decline has already happened — visible in the 2023 trade record above.
| Variant | Start | Trough | End | Depth |
|---|---|---|---|---|
| Baseline | 2020-02-21 | 2020-03-23 | 2020-07-14 | −21.8% |
| Baseline | 2022-01-05 | 2022-10-14 | 2024-01-24 | −20.9% |
| Trend-filtered | 2022-01-05 | 2024-04-16 | still open at cutoff | −17.4% |
| Trend-filtered | 2020-02-21 | 2020-03-12 | 2020-08-27 | −9.9% |
Limitations and counter-evidence
Counter-evidence — the filter did provide real insurance: it cut the 2022 calendar-year loss from −16.2% to −7.2%, reduced the COVID drawdown from −21.8% to −9.9%, and lowered volatility from 10.5% to 6.2%. Those benefits are real. The question this study answers is the price: a 6.4pp annual cost and ~44% average cash for a 4.4pp drawdown improvement.
- Data constraint: the shared data source serves US daily prices from 2010-01-01 only, so the MA(200) warm-up consumes 2010 and the evaluation window starts 2011-01-03. A longer history (including 2008) could change relative performance; this study cannot observe it.
- Single evaluation window: 2011–2026 contains no 2008-style equity collapse and no sustained 2000s bond bull. Relative performance is window-dependent; a different window can change the ranking of these two portfolios.
- This tests one filter design (MA200, per-asset, monthly execution, cash as the fallback). It is not a test of equity-only filters, T-bill fallbacks, slope filters, or daily execution — all of which are related research.
- Month-end execution is an engine design choice. A filter that exits immediately on a trend break (daily evaluation) would behave differently — including likely higher turnover.
- Cash earns 0% in the engine. Holding T-bills instead of cash would add a small return and change the comparison modestly.
- $0 commission assumption. The variant trades ~1.7× more (74 vs 44 trades) and has ~20× the dollar turnover, so real fees and spreads hit the filtered variant much harder than the baseline.
- Dividends are reinvested in the backtest (adjusted prices). SPY (1993) and AGG (2003) predate the window, so there is no ETF inception bias here.
- Backtest ≠ proof. Validation means executable, not trustworthy. Nothing here is investment advice.
Verdict
Reproducibility & assumptions
The rules, evidence and failure analysis above are the reader-facing research. This section preserves the audit trail needed to reproduce the experiment without making engine implementation details part of the main argument.
c2i-research-1.2
Adjusted daily OHLC via investOHLCProxy data service (same source as previously published Chat2Invest research; US daily data served from 2010-01-01; data cutoff 2026-05-01).
- Warm-up: both variants run from 2010-01-01 (data source lower bound); 2010-01-04 → 2010-12-31 is the MA(200) warm-up and is excluded from all reported metrics.
- Evaluation window: 2011-01-03 to 2026-05-01 (3855 trading days), identical for both variants; NAV normalized to 1 at window start.
- Monthly rebalancing on the first trading day of each month; 3 percentage point deviation threshold.
- Trend gate: close > MA(200) = in trend; otherwise target weight 0 (cash) at the next rebalance.
- Long-only, unlevered; cash earns 0%; $0 commission, no slippage in the engine run.
- The exact run configs below are copied from the evidence file (_provenance.baseline_config / variant_config) — what was actually run.
Advanced: exact engine configurations
These JSON configs are preserved for auditability and Agent re-runs. Most readers do not need them to understand the study.
{
"code": "research_6040_baseline",
"name": "Research: 60/40 Portfolio Baseline (SPY 60% + AGG 40%)",
"description": "Classic 60/40 stock/bond portfolio with monthly rebalancing and a 3% deviation threshold. Baseline leg of the '60/40 Portfolio With a Trend Filter' study. Same data window (2010-01-01 to 2026-05-01), symbols and costs as the trend-filter variant; the only changed variable is the 200-day trend gate.",
"strategy": {
"name": "TargetWeightStrategy",
"params": {
"weights": {
"SPY": 0.6,
"AGG": 0.4
},
"rebalance_frequency": "m",
"rebalance_threshold": 0.03
}
},
"capital_strategy": {
"name": "RebalancingCapitalStrategy",
"params": {
"initial_capital": 100000
}
},
"symbols": [
{
"symbol": "SPY",
"name": "SPDR S&P 500 ETF"
},
{
"symbol": "AGG",
"name": "iShares Core US Aggregate Bond ETF"
}
],
"commission": 0,
"start_date": "2010-01-01",
"end_date": "2026-05-01",
"currency": "USD",
"market": "US"
}{
"code": "research_6040_trend_ma200",
"name": "Research: 60/40 Portfolio with 200-Day Trend Filter (SPY 60% + AGG 40%)",
"description": "60/40 stock/bond portfolio where each leg exits to cash when its price closes below its 200-day moving average, and returns to target weight when back above. Monthly rebalancing with a 3% deviation threshold, identical symbols/costs/window to the baseline.",
"strategy": {
"name": "TargetWeightTrendFilterStrategy",
"params": {
"weights": {
"SPY": 0.6,
"AGG": 0.4
},
"signal_symbols": {},
"ma_period": 200,
"use_slope_filter": false,
"slope_lookback": 20,
"rebalance_frequency": "m",
"rebalance_threshold": 0.03
}
},
"capital_strategy": {
"name": "RebalancingCapitalStrategy",
"params": {
"initial_capital": 100000
}
},
"symbols": [
{
"symbol": "SPY",
"name": "SPDR S&P 500 ETF"
},
{
"symbol": "AGG",
"name": "iShares Core US Aggregate Bond ETF"
}
],
"commission": 0,
"start_date": "2010-01-01",
"end_date": "2026-05-01",
"currency": "USD",
"market": "US"
}I want to test a variation
Custom experiments are not open yet. If you understand this study and want to change one thing, choosing below helps us decide what to build next.