DEV Community

shakti tiwari
shakti tiwari

Posted on

Sensex Backtesting for Free in Python (^BSESN Walkthrough)

Sensex Backtesting for Free in Python (^BSESN Walkthrough)

Sensex Backtesting for Free in Python (^BSESN Walkthrough)

By Shakti Tiwari — Nifty Option Trader, Research Analyst & XGBoost Expert

The BSE Sensex is India's oldest benchmark, and you can backtest strategies on it for free — no Bloomberg terminal, no paid data vendor. Yahoo Finance carries the index as ^BSESN, and with yfinance plus pandas you can build an honest backtest in under 60 lines. This walkthrough is code-first and India-specific, and it flags the traps that make Sensex backtests lie.

Step 1: Pull Free Sensex Data with the Right Ticker

pip install yfinance pandas numpy
Enter fullscreen mode Exit fullscreen mode

The correct symbol for the S&P BSE Sensex on Yahoo is ^BSESN (not SENSEX). Get it wrong and you'll download nothing or the wrong series.

import yfinance as yf
import pandas as pd
import numpy as np

df = yf.download("^BSESN", start="2010-01-01", end="2024-12-31", auto_adjust=True)
df = df.dropna()
print(df.head(), df.tail(), sep="\n\n")
print(f"Total trading days: {len(df)}")
Enter fullscreen mode Exit fullscreen mode

Sensex history on Yahoo goes back well over a decade — enough to cover multiple market regimes (2013 taper tantrum, 2020 COVID crash, 2021 bull run), which is exactly what you want a strategy to survive.

Step 2: Define a Strategy You Can Verify by Hand

We'll use RSI mean-reversion — buy when the index is oversold, exit when it recovers. Simple enough to sanity-check, and it behaves differently from a trend strategy, so it's a good second tool in your kit.

def rsi(series, period=14):
    delta = series.diff()
    gain = delta.clip(lower=0).rolling(period).mean()
    loss = (-delta.clip(upper=0)).rolling(period).mean()
    rs = gain / (loss + 1e-9)
    return 100 - (100 / (1 + rs))

df["rsi"] = rsi(df["Close"], 14)
df["signal"] = np.where(df["rsi"] < 30, 1, np.where(df["rsi"] > 55, 0, np.nan))
df["signal"] = df["signal"].ffill().fillna(0)
Enter fullscreen mode Exit fullscreen mode

The ffill holds the position between an entry (RSI < 30) and an exit (RSI > 55) — a common, realistic way to model a mean-reversion trade.

Step 3: Prevent Lookahead — Shift the Position

This is where most free backtests go wrong. You act on a signal only on the next bar, never the same bar it was generated.

df["position"] = df["signal"].shift(1)
df["mkt_ret"] = df["Close"].pct_change()
df["strat_ret"] = df["position"] * df["mkt_ret"]
df = df.dropna()
Enter fullscreen mode Exit fullscreen mode

If you skip the .shift(1), your RSI strategy will look like it perfectly bought every bottom — because it's cheating with future data.

Step 4: Subtract Real Costs

Every entry and exit costs money: brokerage, STT, exchange fees, and slippage. Charge them on each position change.

COST = 0.0005   # ~5 bps round-trip proxy; set to your Zerodha/Angel reality
df["trade"] = df["position"].diff().abs()
df["strat_net"] = df["strat_ret"] - df["trade"] * COST
Enter fullscreen mode Exit fullscreen mode

Step 5: Equity Curve and Honest Metrics

df["equity"] = (1 + df["strat_net"]).cumprod()
df["buyhold"] = (1 + df["mkt_ret"]).cumprod()

def metrics(r, periods=252):
    r = r.dropna()
    cagr = (1 + r).prod() ** (periods / len(r)) - 1
    sharpe = np.sqrt(periods) * r.mean() / (r.std() + 1e-9)
    eq = (1 + r).cumprod()
    maxdd = (eq / eq.cummax() - 1).min()
    return {"CAGR": round(cagr,4), "Sharpe": round(sharpe,2), "MaxDD": round(maxdd,4)}

print("Sensex RSI strategy:", metrics(df["strat_net"]))
print("Sensex buy & hold:  ", metrics(df["mkt_ret"]))
Enter fullscreen mode Exit fullscreen mode

I won't quote a specific CAGR — your window and cost assumptions change it, and a fixed number would be a fabricated stat. Run the code and read your output.

Sensex vs Nifty: Practical Differences

  • The Sensex has 30 stocks; the Nifty 50 has 50. Sensex is more concentrated in large-cap heavyweights.
  • Yahoo's ^BSESN and ^NSEI are highly correlated — a strategy that works on one usually behaves similarly on the other. Test both to check robustness.
  • There is no liquid Sensex options market comparable to Nifty. Sensex derivatives exist but Nifty F&O is far deeper, so most Indian derivative traders execute on Nifty even if they research on Sensex.

Where Free Data Ends

  • Yahoo ^BSESN is end-of-day and can have occasional missing sessions. Always dropna() and check date continuity.
  • Intraday Sensex history on Yahoo is very limited. For minute-level BSE data use Angel One SmartAPI (free, generous history) or Zerodha Kite Connect (paid). Both give exchange-grade candles.

Pitfalls Checklist

  • Wrong ticker (SENSEX instead of ^BSESN) → empty download.
  • Missing .shift(1) → lookahead, inflated results.
  • Zero-cost assumption → mean-reversion strategies especially over-trade and die once costs are real.
  • Testing a single date range → validate across regimes or use walk-forward analysis.

Takeaway

  • Backtest the Sensex for free using ^BSESN with yfinance + pandas.
  • Get the ticker right, dropna(), and always .shift(1) your position.
  • Net out realistic Indian costs; RSI mean-reversion is cost-sensitive.
  • Judge with Sharpe and max drawdown, never final return alone.
  • For intraday BSE data beyond Yahoo's limits, use Angel SmartAPI or Zerodha Kite.

Related: My book Option Trading with AI: XGBoost, Transformers & Quantized Models for the Retail Nifty Trader shows retail traders how to research and validate strategies with free tools.

Disclaimer: This article is for education only and is not financial, investment, or trading advice. SEBI-registered research rules apply — verify everything before acting.

🔗 Get the book on Amazon: https://www.amazon.in/dp/B0H9ZNTBPK

📢 Daily Nifty analysis on Telegram: https://t.me/shaktitrade

📧 Email: shaktitiwari715@gmail.com


💬 Need Help? (Free Support)

If you have any trouble building your own AI trading model, or questions about any article — I can help you for free.

📧 Email: shaktitiwari715@gmail.com
📢 Telegram: https://t.me/shaktitrade

No course, no upsell — just genuine help for retail traders.

Top comments (0)