00 — Orientation: How to Use This Repo, and the Math You Need First¶
Who this is for¶
If you've never taken a portfolio-theory or linear-algebra course, start
here before notebook 01. If you already know what a covariance matrix is
and have pm importing cleanly, skip straight to
curriculum/bootcamp_01_foundations/README.md — this notebook has no
new PM content, only the setup and math foundation everything else
assumes.
1. Confirm your environment works¶
Every notebook after this one does from pm... import .... If that
fails with ModuleNotFoundError: No module named 'pm', you haven't
installed the package into the environment your notebook kernel is
using. Fix:
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
Then make sure your Jupyter kernel is actually .venv's Python (in
Jupyter: Kernel -> Change Kernel), not your system Python — installing
into one environment does not make pm importable from a different one.
See docs/getting-started.md for the full setup sequence.
# Run this cell. It should print a number with no error.
# If it raises ModuleNotFoundError, fix your environment per the cell above
# before going any further - nothing else in this repo will work either.
from pm.returns import sharpe_ratio
test_value = sharpe_ratio([0.02, 0.04, 0.03], risk_free_rate=0.0, periods_per_year=1)
print("Environment OK - sharpe_ratio returned:", test_value)
assert abs(test_value - 3.0) < 1e-9
2. The learning cycle this repo uses¶
Every notebook after this one follows the same shape, repeated per concept:
- Free learning pack — a short reading list. Read it before coding; don't search further than what's listed.
- PREDICT — a question with no calculation. Answer it in your head (or out loud) before touching code. This is the step most people skip and shouldn't — committing to a guess first is what makes the answer stick.
- HAND CALCULATION (where present) — pencil-and-paper arithmetic on small numbers, before any code.
- MANUAL FIRST — a code cell with blanks (
variable = None) and a# CHECKblock commented out below it. Fill in the blanks yourself; only uncomment the# CHECKasserts after you've made an honest attempt. If they fail, that's the useful part — it tells you exactly what's wrong, not just that something is. - Experiment — change an assumption and see what moves.
- Reference — the matching
reference/*.mdpage, for the formal definition and worked example. - Promote — the real, tested implementation in
src/pm/, to compare against your own. - Test — the
pytestcommand that actually checkssrc/pm's version. - ORAL CHECK — explain the concept out loud, in plain language, to an imagined PM. If you can't, you don't understand it yet, no matter what the asserts say.
No one — human or AI assistant — should fill in a MANUAL FIRST cell or
answer a PREDICT/ORAL CHECK question for you. That's the whole point;
see AGENTS.md if you're using an AI coding assistant alongside this
repo.
3. The one piece of math every notebook after this one assumes¶
Almost everything in this curriculum reduces to one operation: a
quadratic form, w' Sigma w — "w transpose Sigma w." If matrix
notation isn't yet second nature, work through this by hand once here so
it's automatic later.
Vectors and dot products. A portfolio's weights are a vector,
w = [w_1, w_2, ...]. The dot product of two vectors multiplies matching
entries and adds them up: a . b = sum_i(a_i * b_i). A portfolio's
expected return is a dot product: E[r_p] = w . mu = sum_i(w_i * mu_i).
Matrix-vector products. A covariance matrix Sigma is a grid: entry
Sigma[i][j] is the covariance between asset i and asset j (and
Sigma[i][i] is asset i's own variance). Sigma @ w (matrix times
vector) produces a new vector, one entry per asset, where entry i is
the dot product of Sigma's row i with w.
The quadratic form. w' Sigma w means: first compute Sigma @ w
(a vector), then dot that result with w again (a scalar). This scalar
is portfolio variance — sigma_p^2 = w' Sigma w.
MANUAL FIRST¶
Two assets, weights w = [0.6, 0.4],
Sigma = [[0.04, 0.01], [0.01, 0.09]] (asset 1's variance is 0.04, asset
2's is 0.09, their covariance is 0.01).
Compute this by hand first (pencil and paper, or just arithmetic in your head), in two steps:
Sigma @ w— for each row ofSigma, multiply bywelementwise and add.- Dot that 2-vector with
wagain to get the scalarw' Sigma w.
Then fill in the cell below and confirm your hand answer matches.
import numpy as np
w = np.array([0.6, 0.4])
Sigma = np.array([[0.04, 0.01], [0.01, 0.09]])
# MANUAL FIRST:
# step 1: Sigma @ w
Sigma_w = None
# step 2: w . (Sigma @ w)
quadratic_form = None
print("Sigma @ w:", Sigma_w)
print("w' Sigma w:", quadratic_form)
# CHECK (uncomment after your hand calculation and the cell above):
# assert np.allclose(Sigma_w, [0.028, 0.042])
# assert np.isclose(quadratic_form, 0.0336)
# # and the fully-expanded scalar formula should give the identical number:
# expanded = w[0]**2*Sigma[0,0] + w[1]**2*Sigma[1,1] + 2*w[0]*w[1]*Sigma[0,1]
# assert np.isclose(expanded, quadratic_form)
Why this matters¶
Every risk formula in this repo is a variation on this one operation:
portfolio_variance (w' Sigma w directly), tracking_error
(the same thing applied to active weights w_p - w_b), marginal_risk_contribution
((Sigma @ w) / sigma_p — literally step 1 above, divided by the
volatility), factor_model_covariance (B F B' + D, the same
matrix-multiplication pattern one layer deeper). None of it is new math
once this one operation is automatic — it's the same few lines of linear
algebra, applied to different inputs.
ORAL CHECK¶
Explain, without writing any formula, what "portfolio variance" is
actually adding up — what role each entry of Sigma plays, and why the
off-diagonal (covariance) terms matter as much as the diagonal (variance)
terms.
Next¶
curriculum/bootcamp_01_foundations/README.md — start Day 1 with
notebooks/foundations/01_returns_and_compounding.ipynb. Or, to have
the curriculum sequence itself for you rather than picking manually,
type /pmexpert — see docs/mastery-guide.md.