Index trend and momentum: pre-registered specification
Written 2026-10-01, before any Indian results were computed. Parameters come from the published literature and are not tuned on Indian data. If a rule is changed after results are seen, the change must be logged here with the date and the reason, and the original result kept.
Assets and data
- Equity: NSE total-return indices (bad prints repaired against the price index, see
compute/tri_check.py): Nifty 50, Nifty 500, Nifty Next 50, Nifty Midcap 150, Nifty Smallcap 250. - Gold: domestic INR price including import duty (WGC INR from 2005; USD × USD/INR before that).
- Bonds: NSE 5-year benchmark G-sec index (total return), 2001 onward.
- Cash: accrues the 91-day T-bill primary yield. This is also the risk-free rate.
- Timing: signals use closing data of day t; the position changes at the close of day t+1, so there is no look-ahead.
Trend rules (time series, long or cash, per asset)
| Code | Rule | Source | Checked |
|---|---|---|---|
sma10m | Long if the month-end level is above the average of the last 10 month-end levels | Faber (2007) | Monthly |
sma200d | Long if the close is above its 200-session average | Common practitioner rule; Brock, Lakonishok and LeBaron (1992) | Daily |
tsmom12 | Long if the trailing 12-month return beats cash over the same 12 months | Moskowitz, Ooi and Pedersen (2012) | Monthly |
blend | Exposure = share of the 1-, 3-, 6- and 12-month excess returns over cash that are positive (0, 0.25 … 1) | Hurst, Ooi and Pedersen (2017), long-only version | Monthly |
breakout | Go long on a close at a 252-session high; go to cash on a close at a 126-session low | Donchian / turtle-style breakout | Daily |
Benchmarks: buy-and-hold of the same asset, and cash.
Sector momentum (cross-sectional)
- Universe: NSE sectoral total-return indices (NSE’s “Sectoral Indices” group). A sector is eligible at a month-end only if it has 13 or more months of history then.
mom12_1: at each month-end, rank eligible sectors by total return over months t−12 to t−1 (skipping the latest month). Hold the top 3 equally weighted for the next month. (Jegadeesh and Titman 1993; Moskowitz and Grinblatt 1999)mom6_1: the same with months t−6 to t−1.- Benchmarks: equal weight across all eligible sectors (same universe, rebalanced monthly), and Nifty 500 total return.
Costs (applied to every strategy and benchmark the same way)
- Trading: 0.10% of value traded, each way.
- Fund running costs while invested: equity 0.15% a year (index fund or ETF), gold 0.50%, G-sec 0.20%, cash 0.20% (liquid fund).
- Taxes: not in v1. Pre-tax results only, labelled as such. A post-tax version (Indian STCG/LTCG rules by date) is the next step, because rules that switch often realise short-term gains.
What is reported
- For each strategy: CAGR, volatility, Sharpe (excess over cash), Sortino, maximum drawdown, Calmar, time invested, trades per year, worst calendar year.
- Periods: full sample; first and second half, split at the midpoint date; and 2012 onward.
- Multiple testing: the deflated Sharpe ratio (Bailey and López de Prado, 2014). The number of trials is every rule × asset combination run here, counted honestly, including failures. This is computed both for each strategy’s Sharpe and for its excess over buy-and-hold.
- Current state: whether the rule is in or out for each asset, the date of the last switch, and the signal’s distance from its threshold. This is descriptive only, with no recommendation.
- Negative results are published as prominently as positive ones.
Known biases, stated up front
- NSE back-calculates many indices before their launch dates. Sector definitions don’t depend on hindsight, but their constituent rules were set later. This is noted wherever pre-launch history is used.
- Total-return indices assume dividends are reinvested without cost or tax.
- India’s market history is short: about 25 years for most indices and about 20 for mid- and small-caps. Few independent trend cycles means wide uncertainty, and the reports must say so.
Results log
2026-10-01: first run (data to 2026-09-25)
These ran exactly as specified, with no parameter changes. Trend: 35 trials (7 assets × 5 rules). Momentum: 2 trials.
Trend:
- Large caps. Every rule cut the worst drawdown sharply, but none beat buy-and-hold on risk-adjusted terms after deflation.
- Nifty 50 maximum drawdown −59.5% → −27% to −39%. CAGR 0.5–4 points lower than buy-and-hold (12.3%).
- Sharpe 0.21–0.41 vs 0.35 for buy-and-hold.
dsr_vs_buy_hold≤ 0.03.
- Mid and small caps.
sma200dbeat buy-and-hold on CAGR and drawdown, but is not significant after deflation.- Midcap 150: 18.1% vs 15.4%, maximum drawdown −32% vs −73%. DSR vs buy-and-hold 0.16.
- Smallcap 250: 18.3% vs 13.8%. DSR 0.29.
- Gold and G-secs. Trend rules lowered or matched returns, with no benefit.
- Weakest rules:
tsmom12andbreakout, across assets. - Pre-tax only. Frequent switching would realise short-term gains, so after-tax results will be worse for the faster rules.
Sector momentum:
mom12_1trailed equal weight: 14.6% vs 15.7% since 2005-02, 49% monthly hit rate, DSR 0.41.mom6_1led equal weight: 17.1% vs 15.7%, 50% hit rate, DSR 0.73. Not significant.- Observation, logged and not acted on: NSE’s sectoral group has overlapping members, so the top 3 can be near-duplicates. A de-duplicated universe should be pre-registered as v2 before it is run.
2026-10-01: after-tax run (same rules; tax model added as planned)
- Tax model:
compute/aftertax.py. FIFO lots and capital-gains rates by sale date and holding period:- Equity: STCG 30% / 10% / 15% / 20% and LTCG 10% / 0% / 10% / 12.5% across the 2004, 2008, 2018 and 2024 changes, with 2018 grandfathering.
- Gold, G-sec and liquid funds: slab 30%, LTCG 20% (no indexation), the 2023 “specified fund” rule, and gold LTCG at 12.5% from 2024-07-23.
- Everything is sold at the end. Cess, the annual exemption and loss set-off are ignored.
- Result: after tax, trend rules trailed buy-and-hold on every large-cap index by 1.9–6.1 points a year.
- Nifty 50 buy-and-hold 11.98% after tax (12.31% before).
sma10m9.58%,sma200d8.28%. - The tax drag comes from short-term gains on each exit and slab tax on the cash leg’s interest.
- Nifty 50 buy-and-hold 11.98% after tax (12.31% before).
- Mid and small caps: the
sma200dpre-tax edge mostly vanishes. Midcap 150 is −0.04 points after tax (+2.69 before); Smallcap 250 is +0.98 (+4.51 before). - Gold and G-sec: trend rules lose 0.9–6.4 points after tax.
- Takeaway for a taxable Indian investor: these trend rules historically bought a smaller drawdown at a large after-tax cost. In a tax-free wrapper (e.g. inside a fund or NPS), the pre-tax numbers are the relevant ones.
2026-10-03: audit corrections (register docs/research/AUDIT.md, rows T1–T3, T5, T6); rules unchanged
Defects in the implementation, not in the rules:
- T1, timing.
backtest()earned the return from close t to t+1 on the exposure decided at close t: it traded at the signal’s own close. The spec above says the position changes at the close of t+1. The exposure is now lagged two sessions. Reported by the barometers job on 2026-10-02. - T2, partial month. The monthly rules took the latest close (for example, 1 October) as a month-end. Only completed months count now.
- T3, annualisation. CAGR assumed 252 sessions a year; NSE has about 249. This overstated every CAGR by about 1.3% of itself and under-charged running costs by the same share. Both now run on calendar time.
- T5, after-tax engine. The tax engine is now the lab’s (
lab/tax.py): indexation where it applied; set-off of losses within a financial year and carry-forward; section 50AA ending for gold on 2025-04-01, not 2024-07-23; 12.5% after 24 months for debt sold after 2024-07-23, not 20% after 3 years; a 12-month long-term threshold for debt before July 2014; and cess. The old engine taxed every whipsaw gain while ignoring the matching losses, which biased the comparison against the rules. - T6, sector momentum:
- eligibility no longer peeks at whether next month’s return exists;
- the equal-weight benchmark pays the same 0.10% on its rebalancing turnover as the strategy (the spec’s “same costs”);
- turnover is measured against drifted weights;
- the deflated Sharpe uses the variance of the two trials’ Sharpe ratios. It was 0, which made it a probabilistic Sharpe ratio.
Data: to 1 Oct 2026 (the first run used data to 25 Sep).
Old → new (full sample, pre-tax unless marked):
| Old | New | |
|---|---|---|
| Nifty 50 rules’ CAGR | 8.7–11.8% | 9.3–10.9% |
| Nifty 50 buy-and-hold CAGR | 12.2–12.5% (by rule window) | 12.2–12.3% |
| Nifty 50 rules’ worst fall | −27% to −39% | −26% to −44% (buy-and-hold −59.5%) |
| Nifty 50 rules’ Sharpe | 0.21–0.41 | 0.26–0.38 (buy-and-hold 0.35–0.36) |
Nifty 50 dsr_vs_buy_hold | ≤ 0.03 | ≤ 0.01 |
Midcap 150 sma200d | 18.0% vs 15.3%; worst fall −32% vs −73%; DSR 0.16 | 16.2% vs 15.0%; worst fall −37%; DSR 0.10 |
Smallcap 250 sma200d | 18.1% vs 13.6%; DSR 0.29 | 15.5% vs 13.4%; DSR 0.14 |
Nifty 500 sma200d | 14.2% vs 13.6% | 12.2% vs 13.3% (now behind) |
After tax (new engine):
| Old | New | |
|---|---|---|
| Large caps: trend rules behind buy-and-hold by | 1.9–6.1 points a year | 1.1–5.2 points a year (still behind on every large-cap index for every rule) |
| Nifty 50 buy-and-hold | 11.98% | 12.01% (sma200d window) |
Nifty 50 sma10m | 9.58% | 10.86% |
Nifty 50 sma200d | 8.28% | 9.98% |
Midcap 150 sma200d edge after tax | −0.04 | +0.13 (14.64% vs 14.51%) |
Smallcap 250 sma200d edge after tax | +0.98 | +1.40 (14.37% vs 12.97%) |
| Gold and G-sec | trend rules lose 0.9–6.4 points | trend rules lose 2.3–5.3 points on gold and 0.2–2.2 on G-sec |
Sector momentum (2005-02 to 2026-09, 260 months):
| Old | New | |
|---|---|---|
mom12_1 vs equal weight | 14.5% vs 15.5%, DSR 0.41 | 14.5% vs 15.5%, DSR 0.33 |
mom6_1 vs equal weight | 16.9% vs 15.5%, DSR 0.73 | 16.9% vs 15.5%, DSR 0.66 |
Conclusions: none changes. No rule beats buy-and-hold after deflation; every large-cap rule trails after tax; the mid- and small-cap 200-day edge is smaller than first reported. The new deflated values are 0.10 and 0.14.
Independent check: pipeline/tests/audit/test_trend_recalc.py recomputes all 35 runs with plain loops. Largest CAGR gap 0.0001 pp; the deflated Sharpe ratios match to 3e-6.