Skip to main content
EMAIndicator

Open methodology

How we classify EMA regime, count whipsaws, and call alignment.

No black box. Every formula and parameter is published below. We compute everything from EOD and intraday OHLCV; no proprietary feed, no hand-tuning per market session. The 5-year regime backtest is recomputed nightly from the same code path that drives the live site.

1 — Exponential Moving Average (EMA)

For a closing-price series P and length L:

α = 2 / (L + 1)
EMAt = α · Pt + (1 − α) · EMAt−1
EMA0 = P0

We use pandas' .ewm(span=L, adjust=False), which produces the recursive form above. No lookahead.

2 — Regime classifier

Three conditions must agree for a directional regime call:

  1. EMA alignment: fast EMA > slow EMA (Bull) or fast EMA < slow EMA (Bear)
  2. Slow-EMA slope: |Δ over last 5 bars / |EMAt−5|| ≥ 5 bps
  3. Price position: close on the trend side of the fast EMA

If all three agree → Trending Bull/Bear. Otherwise → Ranging.

SLOPE_UP = +0.0005  # 5 bps over 5 bars
SLOPE_DN = −0.0005

if fast > slow and slope > SLOPE_UP and close > fast: → "Trending Bull"
elif fast < slow and slope < SLOPE_DN and close < fast: → "Trending Bear"
else: → "Ranging"

1-hour timeframe uses 20/50 EMA. Daily uses 50/200. These are the conventional pairs for those horizons on Indian indices.

3 — Whipsaw counter

A whipsaw is a fast/slow EMA crossover that reverses within min_bars bars (default 3). For each pair of consecutive crossovers in the 30-day window, if the second flip lands within 3 bars of the first, we count it as one whipsaw.

Window: last 30 calendar days, queried from our ohlcv Postgres table — not from a rolling Yahoo fetch. EMA pair: 9/21. Bar size: 5-minute and 15-minute.

4 — Multi-timeframe alignment

Per timeframe, we compute fast and slow EMAs and call:

  • Bull if fast > slow × 1.0002 (2-bps cushion)
  • Bear if fast < slow × 0.9998
  • Flat otherwise

The cushion stops EMAs that are within 2 bps of each other from flickering Bull/Bear/Bull every bar.

5 — Backtest of the regime classifier

For every historical day in our database, we classify the regime using the rules above, then measure the close-to-close return of the next day. The table below summarises forward returns by regime — a regime call has predictive value if the mean and win-rate differ across regimes.

NIFTY — daily, fast=50, slow=200

Sample: 2022-02-23 → 2026-06-10 · 1058 days

Regime N days Mean fwd 1d return Win rate Std dev t-stat
Trending Bull 589 +0.034% 54.5% 0.739% 1.12
Trending Bear 123 +0.108% 48.8% 1.143% 1.05
Ranging 346 +0.022% 52.0% 0.915% 0.46

BANKNIFTY — daily, fast=50, slow=200

Sample: 2022-02-23 → 2026-06-10 · 1057 days

Regime N days Mean fwd 1d return Win rate Std dev t-stat
Trending Bull 583 +0.005% 51.6% 0.886% 0.13
Trending Bear 94 +0.142% 54.3% 1.318% 1.05
Ranging 380 +0.098% 56.8% 1.187% 1.62

Caveats: forward-return statistics over a 5-year window include 2022's strong uptrend, 2023 chop, 2024 volatility, and 2025–26 mixed regime. Survivorship bias is not a concern (we use the index, not constituents). The numbers above are unconditional — no transaction costs, no slippage, no position sizing. They measure the information value of the regime call, not the P&L of any specific trading rule.

6 — EMA vs SMA

Everything above uses exponential moving averages. The classic Golden Cross / Death Cross signals are typically defined with simple moving averages instead. We publish the SMA equivalent side by side — see the EMA vs SMA comparison page and the 50/200 SMA crossover page.

7 — Data and cadence

  • Source: Yahoo Finance chart API (^NSEI, ^NSEBANK), accessed via curl_cffi with chrome TLS fingerprint to avoid WAF blocks on cloud IPs.
  • Cadence: refresh every 5 minutes. Each refresh persists fresh bars to ohlcv and writes a snapshot row.
  • History: 5 years of daily bars, 2 years of hourly, 60 days of 15-minute and 5-minute. Backfilled on first start, then top-up only.
  • Timezone: Asia/Kolkata for display, UTC for storage.