Portfolio Theory
Chapter: 5.5 Portfolio Theory Level: 5 — Mastery (cross-domain: math + statistics + coding, build/prove) Time limit: 90 minutes Total marks: 60
Instructions: Answer all three questions. Show all derivations. Where code is requested, write clean, runnable Python (NumPy) and state assumptions. Use notation for mathematics.
Question 1 — Two-Asset Optimization, Diversification & the Efficient Frontier (20 marks)
Two risky assets have the following annualised statistics:
- Asset A: expected return , volatility
- Asset B: expected return , volatility
- Correlation
(a) Derive from first principles the weight (with ) that produces the global minimum-variance portfolio (GMVP) for two assets. State the general formula, then compute numerically. (6)
(b) Compute the expected return and volatility of the GMVP. Verify that its volatility is strictly lower than and explain why this diversification benefit exists in terms of covariance. (5)
(c) Prove that as , a risk-free combination of the two assets exists, and derive the weight that achieves . (4)
(d) Write a NumPy function frontier(mu, cov, n) that returns n points on the two-asset frontier by sweeping . Explain how you would identify the efficient portion of the frontier from the output. (5)
Question 2 — CAPM, the Security Market Line & Alpha (22 marks)
The risk-free rate is and the market portfolio has , .
A fund manager reports the following realised annual data for portfolio : , , .
(a) Derive from the covariance definition, then use the Security Market Line (SML) to compute the CAPM-required return of . (5)
(b) Compute Jensen's alpha of the portfolio. Interpret the sign: is the manager adding value on a systematic-risk-adjusted basis? (4)
(c) Decompose into systematic and unsystematic components. State each as a variance and as a fraction of total variance. (5)
(d) Compute and compare the Sharpe ratio and Treynor ratio of versus the market. Explain why a portfolio can beat the market on Treynor but lose on Sharpe, and what that reveals about its unsystematic risk. (5)
(e) Prove algebraically that for a fully diversified portfolio (zero unsystematic risk) lying on the SML, the Sharpe ratio and Treynor ratio give consistent rankings relative to the market. (3)
Question 3 — Sortino Ratio: Build & Prove (18 marks)
A strategy produces the following 8 monthly excess returns (over target ), in decimal:
(a) Define the downside deviation relative to target and the Sortino ratio. Explain why Sortino differs from Sharpe in its treatment of upside volatility. (4)
(b) Compute and the Sortino ratio for the data above (use ; mean of the raw returns as the numerator; divide sum of squared shortfalls by ). (6)
(c) Write a NumPy function sortino(returns, target, periods_per_year) that returns the annualised Sortino ratio (annualise mean by periods, downside deviation by ). (4)
(d) Prove that for a return series with no observations below the target, the Sortino ratio is undefined (or ), and explain what this implies about ranking such a strategy against peers. (4)
Answer keyMark scheme & solutions
Question 1
(a) For two assets, portfolio variance is where . Setting :
Compute . . (2 formula + 2 correct numbers = 6)
(b) . (1) (2) Since , diversification lowers risk. (1) Why: because , the covariance term is smaller than it would be under perfect correlation; imperfectly correlated assets partially offset each other's fluctuations, so combined variance falls below the individual variances. (1)
(c) With , and This is a perfect square, so when , giving (2 for perfect-square form + 2 for weight = 4)
(d)
import numpy as np
def frontier(mu, cov, n):
ws = np.linspace(0, 1, n)
pts = []
for wA in ws:
w = np.array([wA, 1-wA])
mp = w @ mu
vp = w @ cov @ w
pts.append((np.sqrt(vp), mp))
return np.array(pts)Efficient portion: find the GMVP (minimum ); all points with form the efficient frontier — for any given risk level an investor prefers the higher return, so the lower branch (below GMVP return) is dominated. (3 code + 2 explanation = 5)
Question 2
(a) . (2) SML: . (3)
(b) Jensen's alpha (4.75%). (3) Positive alpha ⇒ the manager earned 4.75% above the systematic-risk-adjusted required return ⇒ adding value. (1)
(c) Systematic variance . (2) Total variance . (1) Unsystematic variance . (1) Fractions: systematic (29.16%); unsystematic . (1)
(d) Sharpe. Sharpe. (2) Treynor. Treynor. (1) So beats market on both here; but in general why divergence occurs: Treynor divides only by systematic risk (), Sharpe by total risk (). A portfolio with large unsystematic risk has high relative to , so it can look strong on Treynor (which ignores diversifiable risk) yet weak on Sharpe. Divergence therefore flags poor diversification / high idiosyncratic risk. (2)
(e) For a fully diversified portfolio, (zero residual). Then Since is a common positive constant, Sharpe and Treynor are proportional across all such portfolios, giving identical rankings. (3)
Question 3
(a) Downside deviation relative to : Sortino . It differs from Sharpe because Sharpe penalises all volatility (upside and downside) via , whereas Sortino only penalises returns below the target — investors dislike downside, not upside dispersion. (2 def + 2 why = 4)
(b) Mean . (1) Shortfalls (negatives only): . Squares: ; sum . (2) . (2) Sortino . (1)
(c)
import numpy as np
def sortino(returns, target, periods_per_year):
r = np.asarray(returns, dtype=float)
excess_mean = r.mean() - target
downside = np.minimum(r - target, 0.0)
dd = np.sqrt(np.mean(downside**2))
if dd == 0:
return np.inf
ann_mean = excess_mean * periods_per_year
ann_dd = dd * np.sqrt(periods_per_year)
return ann_mean / ann_dd(4 — must annualise mean by periods and dd by √periods, and guard dd=0)
(d) If no observation is below target, every , so . The Sortino ratio is undefined; with positive excess mean it tends to . (2) Implication: the metric cannot rank such a strategy against peers with finite downside risk — the ratio saturates at infinity for any strategy that never breaches the target, erasing differences among them. In practice one must either use a longer/finer sample, raise the target, or fall back to Sharpe for comparison. (2)
[
{"claim":"GMVP weight wA = 0.7358","code":"sA,sB,rho=0.20,0.30,0.20; sAB=rho*sA*sB; wA=(sB**2-sAB)/(sA**2+sB**2-2*sAB); result=abs(float(wA)-0.7358)<0.001"},
{"claim":"GMVP volatility 0.1806","code":"sA,sB,rho=0.20,0.30,0.20; sAB=rho*sA*sB; wA=(sB**2-sAB)/(sA**2+sB**2-2*sAB); wB=1-wA; var=wA**2*sA**2+wB**2*sB**2+2*wA*wB*sAB; result=abs(float(var**0.5)-0.1806)<0.001"},
{"claim":"rho=-1 risk-free weight wA=0.60","code":"sA,sB=0.20,0.30; wA=sB/(sA+sB); result=abs(float(wA)-0.60)<1e-9"},
{"claim":"beta=0.75 and Jensen alpha=0.0475","code":"cov,sM=0.0243,0.18; beta=cov/sM**2; rf,muM,muP=0.04,0.11,0.14; req=rf+beta*(muM-rf); alpha=muP-req; result=abs(float(beta)-0.75)<1e-9 and abs(float(alpha)-0.0475)<1e-9"},
{"claim":"systematic variance fraction 0.2916","code":"beta,sM,sP=0.75,0.18,0.25; frac=(beta**2*sM**2)/sP**2; result=abs(float(frac)-0.2916)<0.001"},
{"claim":"downside deviation 0.024749 and Sortino 0.2020","code":"import numpy as np; r=np.array([0.05,-0.02,0.03,-0.06,0.04,0.01,-0.03,0.02]); dd=float(np.sqrt(np.mean(np.minimum(r,0)**2))); s=float(r.mean()/dd); result=abs(dd-0.024749)<1e-4 and abs(s-0.2020)<1e-3"}
]