How to Backtest a Trading Algorithm Without Fooling Yourself
A backtest answers one narrow question: what would these exact rules have done on this exact stretch of past data? It does not tell you what will happen next month. Used honestly, it is still the cheapest way to find out that an idea is broken before real money is involved. Used carelessly, it produces a beautiful equity curve that falls apart on the first live day.
This is general information, not investment advice, and a good backtest result is not a promise of future returns.
Start with a written rule, not a chart
Before you touch any data, write the strategy in plain sentences that a stranger could implement:
- What instrument, and on which candle interval?
- What exactly triggers an entry? What triggers an exit?
- How big is each position, and what is the stop?
- What happens at the end of the day, and on expiry day?
If you cannot write it down without the phrase "and then I use my judgement", the rule cannot be backtested yet. Every vague word is a place where you will later, without meaning to, pick the version that worked.
Know what your data can and cannot give you
A common setup is to pull candles from a broker's historical API. Zerodha's Kite Connect documentation describes its historical endpoint as providing archived data "for instruments across various exchanges spanning back several years", with candles of timestamp, open, high, low, close and volume, in intervals from one minute to one day.
For futures and options, one point matters a great deal. Exchanges issue a new instrument token for every expiry, so NIFTYJAN18FUT and NIFTYFEB18FUT have different tokens even though the underlying is the same. The documentation also says it is "not possible to retrieve instrument_tokens for expired contracts from the API, unless you regularly download and cache them". Its continuous feature can return day candles for a live contract's expired predecessors, but the documentation limits this to NFO and MCX futures.
Two practical lessons follow. A backtest on options needs the history of contracts that no longer exist, and the continuous feature does not cover options, so do not assume that convenience applies. If you want intraday history on expired contracts, capture and store your own data from today, rather than when you first need it.
Avoid look-ahead bias
Look-ahead bias is the most common reason a backtest is too good. It happens when the test uses information that was not available at the moment of the trade.
The classic case: your rule says "buy when the 5-minute candle closes above its 20-period average". The close of that candle is only known at the end of the candle. In live trading the earliest fill is at the next candle's open or later. A backtest that fills at the same candle's close has just traded on the future.
Habits that prevent this:
- Compute every signal on data up to and including candle t, and fill at candle t + 1 or later.
- Never use a daily high or low to decide an intraday entry. You cannot know the day's high until the day is over.
- Be careful with indicators that get revised or recomputed, and with data you have "cleaned" using the full history.
- When you split data for testing (see below), never let information from the test period leak into the training period.
Count every cost
An idea that earns a little per trade before costs often loses after them, and the more often a strategy trades, the more costs matter. The charges page of a large Indian broker lists separate items for equity and F&O trades: brokerage, STT/CTT, transaction charges, GST, SEBI charges and stamp charges. The same page notes that "STT/CTT can be a lot more than the brokerage we charge".
Then add slippage: the gap between the price your backtest assumed and the price you would actually get. A rule that assumes a fill at the last traded price ignores the bid-ask spread, thin option strikes and fast markets. There is no universal number to copy, so measure slippage from paper trading or small live orders, and use a deliberately pessimistic value in the test. If the strategy only works with zero slippage, it does not work.
Test on data the strategy has never seen
A strategy with enough adjustable parameters can be tuned to fit any history. That is overfitting: the rules describe the past noise rather than a repeatable pattern.
The defence is to separate the data you build on from the data you judge on:
- Hold out a final period. Develop and tune on the earlier years only. Look at the held-out period once, at the end.
- Use walk-forward testing. Tune on one window, test on the window immediately after it, then roll both forward and repeat. You see how the strategy behaves each time it meets data it was not tuned on.
- Never shuffle time-ordered data. The scikit-learn documentation for
TimeSeriesSplitexplains that ordinary cross-validation methods "would lead to training on future data and evaluating on past data". You do not have to use that library, but the principle applies to any tool: train on the past, test on what came later. - Check that results are not hiding in one parameter value. If a moving-average length of 20 makes money and 19 and 21 lose, you have found noise, not an edge.
Read the results with the right metrics
A single headline number is easy to fool yourself with. Look at several together:
- Win rate is the share of trades that made money. By itself it says little. As purely illustrative arithmetic (invented numbers, not a real strategy), a system that wins 70% of its trades but loses five units on each losing trade for every one unit it wins on each winner has an expected value of 0.7 × 1 − 0.3 × 5 = −0.8 units per trade.
- Maximum drawdown is the largest fall from a peak to a later low in the account's equity. It tells you what holding the strategy through its worst stretch would have felt like, and whether you would have kept running it.
- Sharpe ratio compares average return with the variability of returns. It is a way to compare strategies on the same data, not a guarantee. A high ratio from a short or heavily tuned test deserves suspicion.
- Number of trades. A result built on a handful of trades is an anecdote.
Report these after costs and slippage, and keep the raw trade list so you can inspect the worst days.
Backtest results are not the end of the road
Even a clean backtest only shows that the rules were not obviously broken on past data. The sensible next steps are to run the same logic in a no-money paper mode, check that live fills resemble your assumptions, and then start with a small size and strict limits: a maximum order size, a daily loss cap and a way to switch everything off quickly.
If the strategy will place orders through a broker API, also read the rules that apply to retail algo users in India, including API access, static IP addresses and order-rate thresholds. Our plain-English guide, Is Algo Trading Legal in India?, covers them.
Where a custom build fits
Some traders build all of this themselves in Python. Others hand a written strategy to a developer. The services section of the ai-trading.in home page describes backtesting systems that report win rate, drawdown and Sharpe ratio with brokerage, slippage and STT included, along with parameter optimisation and walk-forward tests.
Software cannot make a strategy profitable. What it can do is make your rules explicit, test them honestly on data, and run them the same way every time.
Sources
All pages were last read on 20 October 2026.
- Zerodha Kite Connect documentation, historical candle data: https://kite.trade/docs/connect/v3/historical/ (archived data across exchanges; candle fields and intervals; instrument tokens change with each expiry; tokens for expired contracts not available from the API unless cached; continuous data for NFO and MCX futures)
- Zerodha, charges: https://zerodha.com/charges/ (charge types for equity and F&O trades; statement that STT/CTT can be a lot more than the brokerage)
- scikit-learn documentation, TimeSeriesSplit: https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.TimeSeriesSplit.html (time-ordered splitting; ordinary cross-validation would train on future data)
- ai-trading.in, home page: https://www.ai-trading.in/ (backtesting systems reporting win rate, drawdown and Sharpe ratio with brokerage and slippage included; parameter optimisation and walk-forward tests)
This article is general information, not legal or financial advice.