SPB Git

spb/wp41_uqo

Public
2.3 KB · 46 lines python
1"""Corporate-action policy (docs/DATA_CARD.md §adjustments).23- Splits: applied explicitly from the instrument master (`/instruments/{symbol}`: action_type=split, ex_date, value);4  for a bar in session d < ex_date, prices /= ratio and volume *= ratio for every split with ex_date > d. This equals the5  server-side `adjustment=split` series (verified in tests/integration/test_live_api.py on real rows).6- Cash dividends are NOT applied to intraday returns: a dividend adjustment rescales all history before the ex-date and7  therefore makes any windowed return depend on the end of the download range (window-dependent artifact). Intraday8  log returns within a session are invariant to the dividend factor; the only affected quantity is the overnight gap9  feature across an ex-dividend date, which we leave raw and flag.10- Mergers / spin-offs: not available from the vendor; a symbol disappears (delisted suffix) and the series ends.11"""12from __future__ import annotations1314import numpy as np15import pandas as pd16import polars as pl171819def split_factor_by_session(session_dates: np.ndarray, splits: list[dict]) -> np.ndarray:20    """Cumulative split ratio applying to each session date (product of ratios with ex_date > session)."""21    sd = pd.to_datetime(pd.Series(session_dates)).to_numpy().astype("datetime64[D]")22    factor = np.ones(len(sd), dtype=np.float64)23    for s in splits:24        if s.get("action_type") != "split":25            continue26        ex = np.datetime64(str(s["ex_date"]), "D")27        ratio = float(s["value"])28        if ratio <= 0:29            continue30        factor[sd < ex] *= ratio31    return factor323334def apply_splits(bars: pl.DataFrame, splits: list[dict]) -> pl.DataFrame:35    """Return split-adjusted copy (raw columns kept as *_raw)."""36    f = split_factor_by_session(bars["session_date"].to_numpy(), splits)37    out = bars.with_columns(pl.Series("split_factor", f))38    return out.with_columns([39        (pl.col(c) / pl.col("split_factor")).alias(c) for c in ("open", "high", "low", "close")40    ] + [(pl.col("volume") * pl.col("split_factor")).alias("volume")]).with_columns(41        pl.lit("split").alias("adjustment_type"))424344def ex_dividend_sessions(actions: list[dict]) -> set[str]:45    return {str(a["ex_date"]) for a in actions if a.get("action_type") == "dividend"}46
Files · main
Menu

Theme