Does financial astrology predict the Nifty? A 10-year walk-forward backtest
Short answer: No. Over 10 years of walk-forward tests the astrological calls were right 39% of the time, against 58% for simply predicting the market's usual drift.
Published 2026-10-27 · original backtest on Indian market data by TRINETRA
Date: 2026-10-27 Script: engine/scripts/bench_astro_walkforward.py Output: data/research/BENCH_astro_walkforward.json Test period: 2016-10-27 → 2026-10-19 · NIFTY · 58 windows · 173 graded cells
Verdict
NO SKILL. 39.3% hit rate on 28 directional calls, against 57.5% for the naive rule of
always predicting the market's own drift.
>
INTERVALS ARE TOO NARROW. The 80% band contained the outcome 44.5% of the time.
| metric | result | target / benchmark |
|---|---|---|
| Hit rate (directional) | 39.3% (11/28) | 57.5% naive |
| Brier | 0.2399 | 0.25 coin flip |
| 80% interval coverage | 44.5% | 80% |
| Mean absolute error | 2.81 pp | — |
| Directional calls | 28 of 173 cells | — |
| NEUTRAL calls | 145 (84%) | — |
Why this backtest is valid, and the obvious one is not
The naive version — replay 2016-2026 against BENCH_astro.json — would be grading the model on its own training data. Those benchmark cells were computed on 1985/2000-2026 history, and the last ten years are roughly half the episodes in every factor:
| factor | total episodes | ~in test period |
|---|---|---|
| Mars retrograde | 12 | 4 |
| Saturn retrograde | 27 | 10 |
| Venus retrograde | 17 | 7 |
| Mars-Ketu | 16 | 7 |
| Eclipse season | 57 | 21 |
Any "hit rate" from that is circular. This script instead recomputes each forecast from only the episodes that closed strictly before that window opened, including a point-in-time baseline. No future information enters any forecast — the same discipline the live scorecard has by construction.
What actually failed
1. The direction calls are worse than a coin flip, though not significantly so. 11 of 28 is 39%, but against a 50% null that is p = 0.34 — this is consistent with noise, not with reliable anti-skill. The honest statement is "no demonstrated skill", not "reliably wrong". With 28 calls the test cannot distinguish those.
2. The forecasts are heavily biased bearish, and that is where the loss comes from.
| issued | n | hit rate |
|---|---|---|
| BEARISH | 24 | 42% |
| BULLISH | 4 | 25% |
86% of all directional calls were bearish, in a market that rose 57.5% of the time. A standing bearish tilt against an upward-drifting index loses by construction — and the shrinkage does not correct it, because the shrinkage is symmetric about zero while the market is not.
3. Per-factor, nothing stands out above noise:
| factor | directional calls | hit rate |
|---|---|---|
| Mars-Ketu alignment | 11 | 55% |
| Jupiter retrograde | 10 | 40% |
| Venus retrograde | 3 | 33% |
| Saturn retrograde | 3 | 0% |
| Mars retrograde | 1 | 0% |
Mars-Ketu at 55% on n=11 is the best of them and is still below the 57.5% naive rule. This is the one factor that survived the transmission test, and walk-forward it adds nothing.
4. The intervals are the clearest, most actionable failure.
44.5% coverage against an 80% target is not a sample-size artifact — it is a systematic mis-specification. The bands understate uncertainty by roughly a factor of two. The 3-month check hinted at this (2 of 5 inside); 173 cells confirm it.
The cause is in forecast._interval(): the width is driven by max(|edge|×0.8, skew_gap×2, 1.5), which is anchored to the estimate rather than to the dispersion of actual outcomes. Mean absolute error is 2.81pp while the typical half-band is ~1.5pp.
What this changes
Already correct, and the backtest confirms it:
- 84% of cells published NEUTRAL — the shrinkage is doing its job of refusing to call what it cannot support
- Brier 0.2399 is marginally better than a coin flip, because the probabilities stay near the base rate rather than making confident wrong calls
Must change:
| action | |
|---|---|
| Intervals too narrow by ~2× | widen _interval(); anchor the band to realised dispersion, not to the point estimate |
| Systematic bearish tilt | the shrinkage centres on zero EXCESS, but the asset's drift is positive — a NEUTRAL call should mean "tracks the base rate", and a bearish call must clear the drift, not just zero |
| Hit rate 39% vs 57.5% naive | the live page must show both numbers; a hit rate alone looks respectable and is not |
Must NOT change: the published estimates themselves. Shrinking them further to chase a better score would be fitting to this sample. The forecasts are already small; the problem is that their uncertainty is understated and their sign is tilted.
Honest limits of this test
- 28 directional calls over 10 years. These events are rare by design. p=0.34 against a coin flip means this cannot establish anti-skill, only the absence of demonstrated skill.
- One asset (NIFTY). The live layer forecasts six; this scores the one with the longest clean history.
- Price data ends 2026-10-19, so windows opening after ~2026-09 are ungradeable at 20d.
- The factor DEFINITIONS were chosen with knowledge of the full history even though their parameters here are point-in-time. A fully clean test would have pre-registered the factor set too.
Relationship to the other astro benchmarks
| benchmark | question | result |
|---|---|---|
BENCH_astro | do 7,560 factor/asset cells predict returns? | 0 survived FDR |
BENCH_astro_transmission | do factors move markets through a causal chain? | 21 of 24 refuted; 1 held |
BENCH_astro_sectors | does a sector move when its karaka is prominent? | 0 of 118 survived |
BENCH_astro_walkforward | does the shipped forecast layer beat a naive rule? | No — 39% vs 57.5% |
Four independent tests, four negatives. The forecast layer was built to be falsifiable; this is it being falsified, a week before the live record would have started producing the same answer more slowly.