Why Backtest?
Backtesting tests your strategy on historical data. It tells you if your strategy would have worked in the past.
Common Backtesting Mistakes
1. Look-Ahead Bias
Using future information in your strategy. Example: Using today's close to decide today's trade.
# WRONG
signal = data['Close'] > data['Close'].shift(-1) # Uses future
# CORRECT
signal = data['Close'] > data['Close'].shift(1) # Uses past2. Survivorship Bias
Testing only on stocks that exist today. Misses bankrupt companies.
3. Overfitting
Strategy works on historical data but fails live. Too many parameters, curve fitting.
4. Ignoring Costs
Not accounting for transaction costs, slippage, and taxes.
Proper Backtesting Methodology
- Time-series splits: Never use random splits
- Out-of-sample testing: Reserve last 20% for validation
- Walk-forward analysis: Rolling window optimization
- Transaction costs: Include realistic costs
Python Backtesting Framework
import backtrader as bt
class SmaCross(bt.Strategy):
def __init__(self):
sma1 = bt.ind.SMA(period=20)
sma2 = bt.ind.SMA(period=50)
self.crossover = bt.ind.CrossOver(sma1, sma2)
def next(self):
if self.crossover > 0:
self.buy()
elif self.crossover < 0:
self.sell()SEBI Disclaimer
Past performance does not guarantee future results. This article is for educational purposes only.
Calibrating Slippage With Real Order Data
The gap between a backtest and live results is dominated by one number: slippage. Guessing 0.05% per side sounds conservative until you trade a Nifty option whose spread is 5 points on a 200-point contract. The only reliable calibration is empirical:
- Run paper trades for two weeks and log the fill price versus the mid-price at decision time.
- Bucket slippage by instrument class: index futures, options near the money, options far from the money.
- Feed the distribution, not the average, back into the backtester and re-evaluate whether the strategy still earns.
A reasonable starting point for Indian liquid instruments is 0.10% of notional per side for futures and 1-2 ticks for ATM options, but your own fills will always beat these defaults.
Purged K-Fold and Walk-Forward
Standard k-fold cross-validation leaks across time because adjacent days share overlapping features. Two fixes that matter for financial series:
- Purged k-fold: drop a buffer of days on either side of the test block so label leakage from overlapping targets cannot pass through.
- Walk-forward: train on the past, test on the immediate next block, roll forward one step. This best mirrors live decision-making because every test prediction is genuinely out-of-sample.
If a strategy survives walk-forward on three different Nifty regimes (rally, crash, sideways) it has a right to exist; if it dies anywhere, that is information.
A Cost Model for NSE Futures and Options
NSE transaction costs are relentless and asymmetrical per trade. Build the model explicitly:
- STT is charged on sell side (~0.02% on Nifty futures, ~0.05% on options exercise path).
- Exchange transaction charges, GST on those charges, SEBI fees and stamp duty add up to roughly 0.02-0.03% per round trip on futures.
- Brokerage per lot, minimum charges and intraday versus overnight margin costs differ between IRDA-style discounts and full-service houses.
For a strategy producing 200 round trips a month, total friction can eat 3-6% of notional annually; measure it before worrying about a 0.2% backtest improvement.
Equity-Curve Diagnostic Plots
A single Sharpe number hides the shape of ruin. Before approving any strategy, generate these checks:
- Cumulative return plot with the drawdown duration marked; a 12-month underwater period matters even if Sharpe looks fine.
- Monthly return histogram to see if gains come from two outlier months or steady grind.
- Per-regime performance table: bull, bear, high-vol, low-vol, so you know exactly which weather this strategy needs.
Strategies that are flat for nine months then spike in one volatility event are not diversified alpha; they are a leveraged bet wearing a different name.
Account-Level, Not Trade-Level, Metrics
Backtests that score each trade independently ignore two account realities: correlated simultaneous exposure, and capital-weighted returns. Evaluate the portfolio tie:
- Compare per-trade win rate against per-account profit factor, where a losing day of ten small winners is still a losing day.
- Check peak drawdown at account level, which always exceeds the worst single-trade loss.
- Apply position sizing rules inside the backtest, not after it, because sizing changes which trades would have existed at all.
The account equity curve is the only output that can own capital; everything else is a diagnostic supporting it.