35 — Performance Measurement, LDI, and Asset Allocation¶
Learning objectives¶
Compute time-weighted return (TWR) and money-weighted return (MWR) for the same cash-flow history and understand exactly why they diverge; compute a pension plan's funded ratio and surplus; understand how strategic vs. tactical asset allocation reuses this repo's existing optimization tools rather than needing new ones. This closes two more gaps a curriculum-completeness audit found: no performance-measurement fundamentals, and no asset-allocation framing on top of the existing optimization machinery.
Free learning pack¶
reference/concepts/performance_measurement.mdreference/concepts/liability_driven_investing.mdreference/concepts/strategic_and_tactical_asset_allocation.md- Time-weighted return - Wikipedia https://en.wikipedia.org/wiki/Time-weighted_return
Do not search for more material until these are insufficient.
PREDICT¶
An investor starts with $100. Over year 1 the portfolio doubles to $200
- right after that, the investor adds another $200 (now $400 invested). Over year 2 the portfolio falls back to $200. Without calculating: do you expect the manager's time-weighted return and the investor's money-weighted return to be close to each other, or very different? If different, which one do you expect to look better?
Formula (TWR)¶
TWR = (1+r_1) * (1+r_2) * ... * (1+r_n) - 1 - this repo already has
this as pm.returns.cumulative_return, applied to sub-periods split at
each cash flow.
from pm.returns import cumulative_return
sub_period_returns = [1.00, -0.50] # year 1: +100%, year 2: -50%
# MANUAL FIRST:
twr = None # cumulative_return(sub_period_returns)
print("TWR:", twr)
# CHECK (uncomment after your attempt):
# import numpy as np
# assert np.isclose(twr, 0.0, atol=1e-8)
Formula (MWR)¶
sum(cash_flow_i / (1+r)^time_i) = 0 - solved numerically for r.
from pm.returns import money_weighted_return
# t=0: invest 100 (outflow); t=1: contribute another 200 (outflow);
# t=2: ending value 200 (inflow)
cash_flows = [-100.0, -200.0, 200.0]
times = [0.0, 1.0, 2.0]
# MANUAL FIRST:
mwr = None # money_weighted_return(cash_flows, times)
print("MWR:", mwr)
# CHECK (uncomment after your attempt):
# import numpy as np
# assert np.isclose(mwr, -0.26794919, atol=1e-6)
# assert mwr < twr, "MWR should come out well below the flat 0% TWR here"
Was your PREDICT right?¶
TWR says the manager broke even across the two years - a fair read of skill, since it weights each period equally regardless of how much capital was at risk. MWR says the investor actually lost about 26.8% on their money - because 4x as much capital was exposed during the losing year as during the winning one. Neither is "wrong"; they answer different questions, which is exactly why GIPS mandates TWR for composite manager reporting while MWR remains the right number for an investor asking about their own realized experience.
PREDICT (LDI)¶
A pension plan holds $90 of assets against $100 of liabilities, and rates fall sharply. If the plan's asset duration is shorter than its liability duration, does the funded ratio get better or worse purely from the rate move - even if every asset in the portfolio gained value?
Formula (funded ratio and surplus)¶
funded_ratio = assets / liabilities
surplus = assets - liabilities
from pm.allocation import funded_ratio, surplus
assets, liabilities = 90.0, 100.0
# MANUAL FIRST:
fr = None # funded_ratio(assets, liabilities)
sp = None # surplus(assets, liabilities)
print("funded ratio:", fr, " surplus:", sp)
# CHECK (uncomment after your attempt):
# import numpy as np
# assert np.isclose(fr, 0.90)
# assert np.isclose(sp, -10.0)
Was your PREDICT right?¶
Worse - a shorter asset duration means the liability's present value
(which behaves like a very long bond) rises faster than the assets' as
rates fall, shrinking the funded ratio even on a day every asset in the
portfolio was up. This is exactly what hedge_ratio and dv01
(reference/fixed_income/duration.md, dv01.md) are for - sized against
the liability's DV01 instead of a bond's, per
reference/concepts/liability_driven_investing.md.
PREDICT (SAA vs TAA)¶
A fund's policy portfolio (SAA) is 60% equity / 40% bonds. The PM believes equities are overvalued over the next quarter and tilts the portfolio to 50% equity / 50% bonds. Six months later, equities have drifted the portfolio to 65% equity / 35% bonds purely from price moves, and the PM trades back to 60/40. Which of these two portfolio changes is TAA, and which is rebalancing - and how would you tell them apart just by looking at a trade blotter with no other context?
Reference¶
reference/concepts/performance_measurement.md
reference/concepts/liability_driven_investing.md
reference/concepts/strategic_and_tactical_asset_allocation.md
Promote¶
Use pm.returns.money_weighted_return and pm.allocation.funded_ratio/
surplus only after your own implementation.
Test¶
pytest tests/test_returns.py tests/test_allocation.py
ORAL CHECK¶
Explain to a PM why GIPS requires time-weighted return for composite reporting even though it can make a manager who broke even (TWR=0%) look identical to one who actually delivered value, when the investor's own money-weighted experience was very different. Then explain, in plain language, why LDI's duration-matching math is "nothing new" - which two functions already in this repo does it reuse, and what changes about how they're applied?
Try /tutor money-weighted return or /tutor liability-driven investing
for an adaptive walkthrough.