Corporate actions and adjusted price
Splits, bonuses, and dividends create artificial price jumps in raw historical data that have nothing to do with market moves — if your signal logic doesn't adjust for them, it will misfire.
The problem, concretely
A 1:1 bonus issue on a stock trading at ₹2000 makes it open at ~₹1000 the next day — the company didn't lose half its value, you just have twice as many shares. A moving-average crossover strategy watching raw close prices sees this as a 50% single-day crash and may trigger a false signal.
Zerodha's historical API is *not* auto-adjusted
Unlike some data vendors, Kite Connect's historical_data() returns raw traded prices — it does not silently back-adjust for splits/bonuses. You must handle this yourself.
Practical approach
- Get corporate action data: NSE publishes a corporate actions calendar; some data vendors (or
nsepy-style free tools) expose this as structured data — split ratio, bonus ratio, ex-date. - Apply a back-adjustment factor to all prices *before* the ex-date:
def apply_split_adjustment(df: pd.DataFrame, ex_date, ratio: float) -> pd.DataFrame:
"""ratio: e.g. 0.5 for a 1:2 split (old share -> 2 new shares)."""
df = df.copy()
mask = df.index < ex_date
df.loc[mask, ["open", "high", "low", "close"]] *= ratio
df.loc[mask, "volume"] /= ratio
return df
- Keep raw and adjusted series separate — you need raw prices to match what actually traded (for live order price sanity checks, chapter 77) but adjusted prices for any signal or backtest that spans the ex-date.
Dividends matter less for price-action signals, more for total-return backtests
A stock's price does drop by roughly the dividend amount on the ex-date, but this is a real, valid price move (unlike a split) — no adjustment needed for signal purposes. It only matters if you're computing total-return performance and want to add dividends back in.
Checklist before trusting a backtest
If your backtest universe includes any stock that underwent a split or bonus during the test period and your data isn't adjusted, discard the result — the signal timing around that date is corrupted.