The Analyst's Path

Phase 12 · Finance Plus, AI and the quant-code track · free

Performance & Attribution Analytics in Code

QD2.03 · 12,744 words

That last question is the one this module is built around, because it is the one most reports skip. A backtest, a fund factsheet, an in-house "signal that works" all arrive the same way: a number, stated with total confidence, that looks like evidence of…

Learning objectives

By the end you can:

  1. Compute period-over-period returns in code (simple and log) from a raw price series, know which one is additive across time and which across positions, and reconcile a chain-linked return series back to the total holding-period return exactly.
  2. Implement an annualized Sharpe ratio and Sortino ratio with an explicit, deliberately-chosen ddof and annualization scaling (never a library default nobody typed) and explain in code terms why Sortino's downside-only deviation can rank two managers differently than Sharpe does.
  3. Compute maximum drawdown, drawdown duration, and recovery time from a return series, and explain why a Sharpe ratio alone never answers "what did living through this actually feel like."
  4. Implement the Probabilistic Sharpe Ratio (PSR), adjusting for the sample's own skewness and kurtosis, and name the exact library-default trap (scipy.stats.kurtosis's fisher=True) that silently corrupts it if you do not catch it.
  5. Implement the Bailey–López de Prado deflated Sharpe ratio (DSR) end to end: the expected maximum Sharpe ratio achievable by chance across N independent trials, and the PSR of your observed Sharpe benchmarked against that bar, and use it to state, in one number, how much of an apparently "significant" Sharpe survives honest accounting for how many things were tried.
  6. Implement a Brinson-Fachler attribution that decomposes active return into allocation, selection, and interaction, reconciling exactly to the active return on every input, the reconciliation identity as a runnable assertion, not a hope.
  7. Implement a factor-based attribution that decomposes a realized return into systematic (factor-exposure-driven) and specific (residual) components, given factor exposures and factor returns as inputs.
  8. Read the whole toolkit together and render an honest verdict: separate a genuinely repeatable edge from a number that only looks good because it was the best of many, in code, with a stated confidence level, never by eyeballing a single ratio.
  9. Dissect at least one India (₹) and one US ($) performance-analytics problem end to end, in code, verified against hidden tests that defeat a hardcoded answer.
  10. (Productivity objective: R10 duality.) Use an AI coding copilot to accelerate writing and cross-checking performance-analytics code, a second, independent implementation to diff against your own, a first draft of a report's prose, without ever letting it be the thing that decides whether a number is honest.

The duality, stated once (R10). Objectives 1–9 are the understanding objective the mastery gate rewards: you pass by writing, from memory, code that computes these statistics correctly and by explaining what each one does and does not tell you. Objective 10 is the productivity payoff you keep afterward. A copilot can draft the numpy/scipy boilerplate for any of these functions in seconds, it cannot tell you that a 2.6 Sharpe ratio deserves suspicion before admiration, and it cannot know how many trials you actually ran to find it. That judgment is this module's entire content, and no tool sells it to you.


Prerequisites & connections

This page is an excerpt

The full module runs to 12,744 words and carries the worked examples, the tables, the quiz that gates the next module and the spaced-repetition deck built from it. All of it is free and none of it needs an account.