Do W.D. Gann's time rules work on the Nifty? A 2007–2026 backtest
Short answer: Four of five Gann time rules fail on the Nifty; only 'exceeding previous moves in time' survives.
Published 2026-10-19 · original backtest on Indian market data by TRINETRA
Run: 2026-10-19 · engine/scripts/bench_gann_time.py · raw JSON BENCH_gann_time.json Universe: NIFTY 50 (^NSEI) daily, 4,683 bars, 2007-09-17 → 2026-10-19 (20 calendar years) Pivots: 217 "important" swings (10-bar fractal, ≥3% alternating swing filter) Horizon: 20 trading days · Tolerance: ±3 calendar days
TL;DR
| Rule | Verdict |
|---|---|
| R1 Gann's solar-seasonal date map | ❌ NO EDGE (lift 1.12, p=0.15) |
| R2 Anniversary dates (1-5y from pivots) | ❌ NO EDGE (lift 1.04, p=0.35) |
| R3 Fractional-year divisions (13/17/26/35/39w) | ❌ NO EDGE (lift 1.06, p=0.23) |
| R4 Degree day-counts (30…360d from pivots) | ❌ NO EDGE (lift 1.03, p=0.35) |
| R5 Exceeding moves in TIME | ✅ SIGNAL — robust, +2.6% edge, 84% win |
| R6 India-empirical seasonality | ✅ Strong month effects — but NOT Gann's dates |
Four of Gann's five time constructs are statistically indistinguishable from noise on Indian equities. The fifth — the one Hima Reddy ranks FIRST and which contains no astrology, no geometry and no free parameters — is a real and unusually strong signal.
1. The date-cycle rules fail — and the coverage column shows why
This is the "skeptic's ledger #1" hazard measured directly (docs/trading-library/notes/11-gann-master-stock-market-course.md).
| Rule | Coverage of all trading days | Base pivot rate | Rate on predicted days | Lift | p |
|---|---|---|---|---|---|
| R1 solar map | 34.9% | 4.63% | 5.20% | 1.121 | 0.153 |
| R2 anniversary | 59.2% | 4.63% | 4.80% | 1.036 | 0.351 |
| R3 fractional year | 69.0% | 4.63% | 4.92% | 1.062 | 0.231 |
| R4 degree days | 92.2% | 4.63% | 4.77% | 1.029 | 0.345 |
R4 "predicts" 92.2% of all trading days. A rule that fires on nine days in ten is not a forecast. This is precisely the failure mode the notes predicted: the union of Gann's many cycles, each with a tolerance, covers essentially the whole calendar, so recall looks spectacular while precision is nil.
Had this been measured the usual way — "what % of major turns landed near a Gann date?" — R4 would have scored ~92% and been reported as a triumph. It is the control that kills it.
R1 deserves a specific note because it is Gann's most-quoted contribution. Lift 1.12 is directionally positive but p=0.15 is not significant on 20 years. Mechanistically this is expected: Gann's own stated reason for the January date is US dividend convention ("Dividends are paid on the first of January, and people buy for the dividends"), and his map is anchored to the US fiscal calendar. India's FY ends 31 March. The notes predicted this would not transfer; it does not.
2. R5 — "Exceeding moves in time" — the real finding
Gann Buying Point #4/#5, Selling Point #4/#6. Reddy ranks this first in importance.
"BUY when the first rally from the extreme bottom exceeds in time the greatest rally in
the preceding Bear Campaign."
| signal | n | avg 20d fwd | control (all bars) | edge | directional win |
|---|---|---|---|---|---|
| buy (after bear campaign) | 25 | +3.46% | +0.82% | +2.64% | 84.0% |
| sell (after bull campaign) | 15 | −5.32% | +0.82% | +6.14% | 53.3% |
Robustness — this is what makes it credible
(a) Parameter sensitivity: 24/24 configurations positive. Swept PIVOT_WIN ∈ {5,8,10,12,15,20} × MIN_SWING_PCT ∈ {2,3,5,8}:
- every one of 24 configs showed a positive edge
- min +1.97%, median +3.36%, max +10.07%
- win-rate 53.8%–95.2%
A parameter-fitted artifact does not survive that. The signal is in the data, not the knobs.
(b) NOT a "buy the dip" proxy. Signals fire at a median of just −0.94% below the trailing 60-day high — i.e. near highs, not after crashes. The matched control (any bar at least that far off its 60d high) returns +0.66%, versus the signal's +3.46%. So the edge is not drawdown-reversion.
(c) NOT one lucky regime. Signals occur in 12 distinct years (2009, 2012, 2013, 2014, 2016×6, 2017, 2018, 2019, 2021, 2022, 2023, 2025); max 6 in any single year. Excluding 2008/09 (GFC) and 2020 (Covid): n=23, +2.85%, 82.6% win.
Why it plausibly works (mechanism, not numerology)
Duration asymmetry is a structural statement about supply exhaustion: if the first counter-rally lasts longer than any rally during the whole preceding decline, the character of participation has changed — sellers are no longer able to cap advances on their old schedule. That is a regime statement, and it needs no cycles or planets.
The honest caveats
- n=25 is small. The per-config n ranges 9-60; the edge is stable but the sample is thin. Treat the magnitude as uncertain even though the sign is robust.
- It is a TREND-CHANGE detector, not an entry. Gann says so himself: after it fires, the instrument is "a safer buy on a secondary reaction." The correct engine use is a regime/stage input feeding a pullback entry, never a standalone trigger.
- Index-level only so far. Tested on NIFTY. Per-stock behaviour is unmeasured.
- The sell side is weak — 53.3% directional win is near coin-flip despite the large mean, i.e. driven by a few big declines. Do not trade the short side on this.
3. R6 — India's OWN seasonality (derived, not imported)
Control: unconditional 20d forward return +0.823%.
| Month | n | avg 20d | edge | win |
|---|---|---|---|---|
| Jan | 396 | −0.90% | −1.72% | 38.4% |
| Feb | 374 | −1.24% | −2.06% | 46.3% |
| Mar | 381 | +2.71% | +1.89% | 70.3% |
| Apr | 358 | +1.22% | +0.40% | 57.3% |
| May | 397 | +1.85% | +1.02% | 66.2% |
| Jun | 402 | +1.70% | +0.88% | 76.4% |
| Jul | 418 | +0.91% | +0.09% | 62.2% |
| Aug | 392 | +1.26% | +0.44% | 66.1% |
| Sep | 393 | +0.10% | −0.73% | 58.0% |
| Oct | 378 | +0.43% | −0.39% | 54.8% |
| Nov | 373 | +1.18% | +0.36% | 61.4% |
| Dec | 401 | +0.63% | −0.19% | 58.6% |
India-specific windows
| Window | n | avg 20d | edge | win |
|---|---|---|---|---|
| Budget (Feb 1 ±10d) | 150 | −1.06% | −1.88% | 48.7% |
| Monsoon (Jun-Sep) | 1605 | +1.00% | +0.17% | 65.7% |
| Festive (Sep 15-Nov 15) | 773 | +0.45% | −0.37% | 57.7% |
| FY-end (March) | 381 | +2.71% | +1.89% | 70.3% |
| FY-start (April) | 358 | +1.22% | +0.40% | 57.3% |
| Advance-tax weeks | 479 | +1.09% | +0.26% | 66.8% |
The two real effects are Indian, structural, and absent from Gann's map:
- March (FY-end) is the strongest month: +1.89% edge, 70.3% win. Gann's map has nothing on March 31; his nearest date is the March 21 equinox, for an unrelated reason.
- Jan-Feb is the weakest stretch (−1.72%, −2.06%) — the opposite of Gann's "January rise." His January claim is explicitly US-dividend-driven and inverts on Indian data.
- The Budget window is negative (−1.88%), consistent with event-risk de-grossing.
⚠️ Caveat on R6: these are overlapping 20-day forward windows, so observations within a month are not independent — the effective n per month is far below the nominal ~390, and the confidence intervals are correspondingly wide. Month-of-year effects are also the classic home of data-mined "anomalies." Treat R6 as context for the narrative, not a trade trigger. It is reported because it is the honest, India-derived replacement for a US map that failed — not because 12 monthly means constitute a strategy.
4. Decisions taken from this run
| Finding | Decision |
|---|---|
| R1-R4 (all Gann date cycles) | REJECTED. Will not enter the decision path. Recorded as a negative result; the "Astro/Time" UI section reports them as measured and failed, which is more useful to the user than a mystical overlay |
| R5 buy side | IMPLEMENT behind a default-OFF flag (gann_time_v1) as a regime/stage input, not a trigger. Promotion gate below |
| R5 sell side | REJECTED for trading (53% win). May be surfaced as a caution flag only |
| R6 March / Jan-Feb / Budget | SURFACE as narrative context in the macro section with explicit n and the overlapping-window caveat. Not a gate |
| Square of Nine / Hexagon / planetary | NOT IMPLEMENTED — underdetermined in the source (notes ledger #4). Implementing would mean inventing the missing half and attributing it to Gann |
Promotion gate for gann_time_v1
Flip ON only when all hold:
- Per-stock (not just index) replay over ≥3 years shows a positive edge on ≥2 regimes.
- The signal adds information beyond our existing Stage/trend gate — i.e. measured on names the current ladder would have rated differently (no double-counting).
- n ≥ 100 signals in the per-stock replay.
- 4-week shadow A/B on live picks shows no regression in avg R.
5. Reproduce
.venv/Scripts/python.exe -I engine/scripts/bench_gann_time.py
Data: data/audit/nifty_ohlc_max.csv (4,683 bars; fetched from Yahoo ^NSEI in 2-year chunks — note NIFTY history on that endpoint starts 2007-09, not 1996).
Pre-registration note: R1-R6 and all constants (PIVOT_WIN=10, TOL_DAYS=3, FWD=20, MIN_SWING_PCT=3.0) were fixed in the script's docstring before the first run. The sensitivity sweep was run after, to test robustness of the one surviving rule — not to select it.
🔴 RETRACTION — 2026-10-20: R5 is NOT a signal
The R5 verdict above ("SIGNAL — robust, +2.6% edge, 84% win") is withdrawn.
The per-stock test this report asked for in §2 ("Index-level only — per-stock behaviour is unmeasured") was run on 678 NSE symbols with ≥1,500 bars. It shows the edge is a selection artifact of the rule's own construction, not a forecast:
| control | median edge |
|---|---|
| Real series | +6.064% |
| Own returns SHUFFLED (same distribution, structure destroyed) | +6.632% |
| Genuine edge | −0.568% |
A rule that scores as well on shuffled data as on real data has found nothing.
Mechanism: the signal fires at the 80.8th percentile of its trailing 60-bar range — near local highs, right after the longest rally of the campaign. On any positively-compounding series, conditioning on "a long rally just happened" selects points whose forward path inherits the drift.
A second defect, which also affected this report: find_pivots cannot identify a pivot at index i until bar i+PIVOT_WIN, but R5 fired at s + t_max + 1 — before the anchoring swing low was knowable. On pure random walks the unguarded rule returned +2.070% over control.
Why the six controls in this report were not enough
24/24 parameter settings, not-a-buy-the-dip, 12 distinct years, excluding 2008/09 and 2020 — every one asks "is the result stable?" A mechanical selection artifact is perfectly stable. The missing control was the cheap one: does the rule also "work" on data with no structure?
New standard: any future time-based rule must clear a shuffled-series null before being reported as a signal. Stability ≠ significance.
What still stands in this report
- R1–R4 rejections (solar map p=0.15; anniversary/fractional/degree cycles, up to 92.2% coverage) — unaffected and now better supported.
- R6 India seasonality — unaffected. It is a calendar partition, not a path-dependent rule, so there is no selection mechanism available to manufacture a false edge. Still context-only, with its overlapping-window caveat.
- The coverage/precision methodology — unaffected, and it is what caught R1–R4.
Full analysis: data/research/BENCH_gann_perstock_2026-10-20.md