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

  1. 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.
  2. 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
  1. 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.

Next: 032 — F&O instrument fields: expiry, lot size, strike