Learning objectives
By the end you can:
- Explain, precisely, why a raw vendor price feed cannot be fed directly into a return calculation across a stock split or a cash dividend, and state the single sentence that separates a mechanical price change from an economic one: nothing happened to the value of the company; something happened to the accounting of how that value is sliced.
- Compute, by hand and in code, a split-adjusted price series from a raw close series and a split ratio, dividing every pre-split price by the ratio so that a return computed across the split boundary reads correctly as flat, not as a phantom crash.
- Compute, by hand and in code, a dividend-adjusted (total-return) price series from a raw close series and a cash dividend amount, using the standard
1 − dividend / previous_closefactor, and explain precisely why ignoring dividends silently understates every long-horizon return you will ever report. - Generalize both of the above into a single back-adjustment algorithm that composes an arbitrary sequence of splits and dividends, computing each event's own adjustment factor from raw (not already-adjusted) prices and applying the cumulative product working backward from the most recent date, and explain why that "compute locally, apply cumulatively" order matters.
- Build a data-quality scanner that flags suspiciously large single-day price moves as candidate signs of an un-adjusted corporate action, and correctly state the technique's real limits (false positives on genuine large moves, false negatives on small-ratio splits).
- Define point-in-time (PIT) data precisely, the distinction between when a fact became true (a fiscal period ended) and when it became knowable (it was filed/published), and build a point-in-time filter and an "as-of" lookup over a fundamentals table, using nothing more exotic than string comparison on
YYYY-MM-DDdates. - Define survivorship bias precisely, demonstrate numerically the gap between a survivors-only average return and the true full-universe average that includes every company that was ever in the universe (including the ones that failed), and explain why that gap is not a rounding error but routinely tens of percentage points.
- Synthesize adjustment, point-in-time discipline, and survivorship control into one function that builds a point-in-time, survivorship-controlled, split/dividend-adjusted panel as of any query date, the actual deliverable a real quant data pipeline exists to produce.
- Name and correctly classify the recurring mess in real vendor feeds beyond corporate actions and PIT/survivorship, missing trading days, ticker renames/reuses, currency and unit-scale traps (₹ crore vs ₹, cents vs dollars), and exchange-calendar/timezone mismatches between NSE and NYSE, and state the standard fix for each.
- Map the India and US market-data landscape: name the major paid institutional vendors, the free/official sources, and the survivorship-bias-free specialist providers, and correctly match a data need (real-time vs. historical, fundamentals vs. prices, retail-budget vs. institutional-budget) to an appropriate source in each market.
- (Productivity objective: R10 duality.) Use an AI coding assistant to accelerate exactly the parts of a pipeline you already understand by hand, drafting a first-pass adjustment function, auditing code for a PIT or survivorship leak you specify, while treating every AI-drafted number as unverified until it reproduces your own by-hand calculation and passes this module's hidden tests.
The duality, stated once (R10). Objectives 1–10 are the understanding objective: the gate (quiz ≥ 85%, code-pack ≥ 85% with hidden tests green) rewards being able to build, by hand and in code, a pipeline that gets adjustment, point-in-time, and survivorship all correct, on data you have never seen, since the hidden tests exist precisely to catch a solution that only works on the visible example. Objective 11 is the productivity objective: knowing how a working quant developer actually uses an AI copilot on this kind of code, and where that copilot cannot be trusted. A copilot can draft a plausible-looking
back_adjustfunction in five seconds. It cannot tell you, on its own authority, whether that function is correct, only your own hand-traced example and this module's hidden tests can do that, and a subtly wrong adjustment function is exactly the kind of bug that looks fine on every visible case and silently corrupts every number downstream of it.