CHAPTER 21/ 45
Practical Portfolio Construction
Prerequisites: Chapter 9 on convex quadratic programming and KKT conditions, Chapter 15 on multi-factor risk models, Chapter 18 on volatility estimation, and Chapter 20 on modern portfolio theory and the unconstrained analytical solution for the mean–variance tangency portfolio. After completing this chapter, you will be able to estimate covariance matrices from a training window using Ledoit–Wolf shrinkage and check conditional positive definiteness and out-of-sample risk error; transform long-only maximum-Sharpe optimization, whose objective is not concave, exactly into an equivalent convex quadratic program (convex QP); solve for an equal risk contribution (ERC) portfolio; combine market equilibrium and subjective views with the Black–Litterman model; derive the Kelly criterion's log-growth rate and explain fractional-Kelly constraints; calculate asset drift, turnover, and trading costs; and objectively evaluate portfolio out-of-sample performance after costs.
1. Chapter Objectives
After studying this chapter, you should be able to:
- Calculate estimation error in sample means and covariance matrices, and quantify why uncertainty in expected returns can damage optimized weights more severely than the covariance matrix;
- Derive the optimal shrinkage intensity toward a scaled identity matrix in Ledoit–Wolf (2004), then use training-window data to compute a positive-definite covariance matrix for out-of-sample use;
- Calculate two-sided rebalancing turnover, drifted portfolio weights, and trading-friction drag, and maintain an accounting ledger for gross and post-cost net returns;
- Distinguish dollar-neutral, beta-neutral, and sector-neutral portfolios; explain how absolute sector neutrality across mutually exclusive and exhaustive sectors implies dollar neutrality but generally does not imply beta neutrality; and explain that Euclidean projection minimizes only weight distance;
- Derive the Euler decomposition of portfolio volatility, calculate marginal risk contributions and relative risk shares, and solve for ERC weights using damped Newton's method with a Newton-decrement stopping rule;
- Restate the long-only maximum-Sharpe variable substitution proved in Chapter 9, which converts the problem into a convex quadratic program, and implement a solution workflow with a feasibility precheck for weight caps;
- Derive the Black–Litterman reverse-optimization prior, the block-Gaussian posterior mean and posterior-mean covariance, and verify the orthogonality property of view tilts;
- Derive the binary-bet log-growth optimum under the Kelly criterion, its discrete second-order expansion, and its diffusion-limit quadratic proxy; analyze the tail-ruin mechanism under full Kelly and the risk–return trade-off under half Kelly;
- Use a multi-factor risk model to decompose portfolio variance and volatility into factor and specific-risk contributions;
- Using the French 10 industry historical snapshot and Project 3's 440-month rolling backtest, objectively evaluate each strategy's post-cost rolling out-of-sample performance and statistical uncertainty on the currently revised historical snapshot, without treating it as point-in-time (PIT) tradable evidence.
You have completed the chapter when you can independently reproduce all numerical examples and pass the code assertions, understand the assumptions and failure boundaries of every model, complete all exercises in Sections 15–17, and check the full derivations and code in Section 18.
2. Why Quants Need Practical Portfolio Construction
In Chapter 20's mean–variance theory (Modern Portfolio Theory, MPT), tangency-portfolio weights are given by the analytical expression
This failure arises from three unavoidable practical challenges.
First, the inversion step sharply amplifies parameter-estimation error. Financial time series are full of low signal-to-noise-ratio observations. The annualized standard error of an expected-return estimate is often on the same order as the mean itself, while the smallest eigenvalues of a high-dimensional covariance matrix are often close to zero. Inverting a noisy matrix greatly magnifies the directions associated with these small eigenvalues, leading the optimizer to take large long and short positions in directions with the most in-sample noise. In quantitative finance, this phenomenon is sometimes called an “error maximizer.”
Second, the theoretical tangency portfolio does not model real trading frictions or constraints. The analytical solution assumes unrestricted short selling, no borrowing-rate penalty, no market-impact or liquidity cost, and no trading commissions. In institutional investing, however, managers face strict long-only rules, position limits, sector and market-risk budgets, and slippage caused by turnover. If these real-world boundaries are ignored, apparently strong paper returns can be eroded by monthly rebalancing costs.
Finally, diversification is often misunderstood in practice. A nominally equal-weighted allocation is not necessarily diversified by risk. If a portfolio contains highly volatile assets, a small number of them may dominate total portfolio risk. Likewise, a long–short portfolio described as “market neutral” may still carry substantial systematic market beta or sector-tilt risk if it satisfies only dollar neutrality.
The goal of practical portfolio construction is to use mathematically rigorous shrinkage estimation, convex-optimization transformations, risk budgeting, and Bayesian prior constraints to turn noisy forecasts into real holdings that are implementable out of sample, have controlled risk, and can withstand trading frictions.
3. Intuition: From Sample Noise to Implementable Holdings
To see why unconstrained optimization is fragile, consider a deliberately simple thought experiment.
Suppose the market has two assets, each with a true monthly excess return of
Now suppose a researcher estimates the inputs from the past 60 months. Due to sampling variation, asset 1's sample mean happens to be high at
Substituting these estimates into
This simple example reveals the core logic of practical portfolio construction:
- Shrinkage guards against covariance ill-conditioning: With a limited sample, the extreme eigenvalues of the sample covariance matrix can be badly distorted. Shrinking the matrix toward a structured target, such as a diagonal matrix or factor model, at a theoretically chosen rate can dampen very small eigenvalues and keep the inverse from turning local noise into extreme positions.
- Constraints are the first line of defense against mean-estimation errors: Long-only constraints rule out short positions and mathematically cap one mechanism by which estimated means create extreme weights. Although long-only constraints invalidate the analytical solution, they restrict optimization to the simplex and can prevent extreme hedges.
- Risk parity avoids relying on unreliable expected-return estimates: When expected returns cannot be estimated precisely, a portfolio that uses the covariance matrix to equalize assets' contributions to total risk avoids one source of estimation error. It still depends on a risk model, so any improvement in return or risk must be compared out of sample.
- Trading frictions shape the turnover boundary: Price changes cause asset weights to drift away from their targets. If the portfolio is forced back to the exact target every month, commissions and market-impact costs from turnover accumulate quickly. A balance is needed between tracking error from drift and turnover costs.
Simulation of Estimation Error and Comparison of Strategy Distributions

- Horizontal axis: Annualized population Sharpe ratio realized when each strategy's estimated weights are applied to the true population (multiplied by
); - Vertical axis: The six strategies compared (plug-in tangency, GMV sample, GMV Ledoit–Wolf, long-only max Sharpe (LW), ERC (LW), and 1/N);
- Units: Dimensionless Sharpe ratio;
- Sample and setup: The full-sample monthly first and second moments of the French 10 industries are treated as a fixed “pseudo-population.” With random seed 20261021, 500 independent Gaussian Monte Carlo samples are drawn, each 60 months long (representing a five-year rolling window);
- How to read the figure and what to look for:
- The theoretical maximum true tangency Sharpe ratio is marked by the red vertical line (about
annualized); - The unconstrained plug-in tangency portfolio performs worst, with a median annualized Sharpe ratio of just
and a 10th percentile of about (the whiskers show the 5th–95th percentiles). In addition, 57 samples failed outright because the denominator was non-positive; those failures were excluded from the plotted distribution, making the box plot substantially optimistic. The long-only max-Sharpe (LW) strategy had another 11 samples with no positive-excess-return portfolio in the training sample, triggering the input-feasibility failure described in Section 12.3; those were also excluded from the box plot; - Adding a long-only constraint raises the median for long-only max Sharpe (LW) to
, reducing dispersion caused by estimation error; - Strategies that do not rely on expected-return estimates (GMV LW, ERC LW, and 1/N) are the most stable: the median annualized Sharpe is
for GMV (LW), for ERC (LW), and a stable for 1/N;
- The theoretical maximum true tangency Sharpe ratio is marked by the red vertical line (about
- Limitation: This figure shows a statistical simulation of sampling error only. All asset returns are strictly Gaussian; real-market jumps, fat tails, and structural breaks are not included.
4. Mathematical Foundations and Notation
Before turning to the derivations, we standardize notation, matrix dimensions, and units throughout the chapter:
-
Number of assets and sample periods: The number of assets is denoted by
(or by for the cross-sectional dimension), and the number of periods in the historical training window by . -
Return vector: The vector of single-period simple returns at time
is . This chapter uses monthly decimal returns by default. Explicitly labeled annualized teaching examples are exceptions and must not be mixed with monthly empirical inputs; for example, a monthly return of is written as . -
Expected-excess-return vector:
, where , is the risk-free rate, and is the all-ones vector. -
Covariance matrix:
is the single-period return covariance matrix and is positive semidefinite (PSD). If invertibility is required, it must be positive definite (PD), denoted by . -
Portfolio-weight vector:
. is the fraction of portfolio net asset value (NAV) invested in asset . Fully invested means , and long-only means . -
Matrix Frobenius-norm convention: Following Ledoit & Wolf (2004), this chapter normalizes the Frobenius norm of a
matrix by its dimension : The matrix inner product is defined as
. Unless stated otherwise, denotes this normalized norm. -
Time and information set: Maintain strict causality. In the idealized month-boundary test, if a rebalance decision is made and executed at the end of month
, the historical training window available for that decision is restricted to (or to when a one-month data-publication lag is assumed). The current-period return is never known before the end of month . Observing returns, calculating weights, and executing at the same month-end does not guarantee real-world availability; a live system must record when data are received and when the next trade can occur.
5. Formal Definitions: Estimation Error, Neutrality Constraints, and Risk Budgets
5.1 Mean-Estimation Error and Covariance Ill-Conditioning
Suppose asset returns are independently and identically distributed, with true mean
If an asset has monthly volatility
For a hypothetical stock, if a researcher assumes an annualized excess return of only
The sample covariance matrix, centered by the sample mean and divided by
Equation (12) in Section 2.2 of Ledoit and Wolf (2004) rewrites Lemma 2.1 in terms of eigenvalues: in expectation, the dispersion of sample eigenvalues around their common mean equals the dispersion of the true eigenvalues plus
5.2 Three Definitions of Portfolio Neutrality
Quantitative investors often seek to eliminate exposure to specific macroeconomic or systematic risks. Common forms of “neutrality” include:
-
Dollar neutrality / capital neutrality:
The total market value of long positions equals that of short positions, leaving net exposure equal to 0.
-
Beta neutrality:
Letbe the vector of regression slopes of the assets relative to a benchmark index, such as the S&P 500. A beta-neutral portfolio satisfies: At the margin, the portfolio has no direct linear exposure to movements in the overall benchmark return.
-
Sector neutrality:
Suppose the market is partitioned intomutually exclusive sectors, and let be the set of asset indices in sector . Sector neutrality requires net holdings to be zero in every sector:
These conditions are distinct, but they are not independent. If the mutually exclusive sectors cover all assets, summing across sectors gives
Therefore, the absolute sector neutrality used in this chapter necessarily implies dollar neutrality, but generally does not imply beta neutrality. Dollar neutrality generally implies neither sector nor beta neutrality, and beta neutrality generally implies neither of the other two. For example, within one sector, weights
5.3 Risk Contributions and the Euler Decomposition
Portfolio volatility is the function
The derivatives and risk shares below require
This gives rise to three core definitions in the risk-contribution framework:
-
Marginal risk contribution (MRC):
The economic meaning of
is the rate of change in total portfolio volatility when the weight of asset increases by a small amount. It has the same units as return volatility (monthly decimal units here). This is a partial derivative that holds all other coordinates fixed. If increasing asset i requires selling asset j to preserve the budget, the change along the self-financing direction is MRC_i−MRC_j; it should not be read as MRC_i alone. -
Absolute risk contribution (RC):
By Euler's theorem, the absolute risk contributions of all assets sum exactly to total portfolio volatility:
. -
Risk fraction / relative risk contribution:
Relative risk shares are dimensionless and sum to one:
. They are not probabilities. If a weight and its marginal risk contribution have opposite signs, can be negative, meaning that the position offsets some risk in the current portfolio. A long position can also have a negative risk contribution; a short position multiplied by a negative marginal contribution has a positive contribution.
5.4 Equal Risk Contribution (ERC) Portfolios
An equal risk contribution (ERC) portfolio requires every asset to contribute equally in absolute terms to total portfolio volatility, over the fully invested long-only simplex:
Thus, each asset carries exactly
Check the two-asset case before memorizing an ERC formula. In this annualized-decimal teaching example,
Set the two risk contributions equal, first canceling their common positive denominator
Combining this with
Volatility is 18.59%, and the two risk shares are 50% each even though the capital weights are 60% and 40%. The two-asset cross terms cancel, so when volatility is positive and

The horizontal axis shows the two assets and the vertical axis shows shares (%). Capital weights are 60%/40%, while risk shares are 50%/50%. This figure checks only the annualized example above; it does not show that ERC has higher returns. Section 6.3 explains how to solve for a specified risk budget under a general covariance matrix.
6. Core Derivations: Shrinkage, Convex-QP Transformation, and Risk Decomposition
6.1 Deriving the Ledoit–Wolf Linear Shrinkage Estimator
Ledoit & Wolf (2004) seek a linear combination
Using an orthogonal decomposition and expanding the expectation, define three key geometric distance parameters. In this subsection,
- Expected squared distance from the sample covariance to the target:
; - Squared distance from the true covariance to the target:
; - Expected estimation error of the sample covariance relative to the true covariance:
.
First derive the result under the theoretical benchmark
The proof of Lemma 2.1 uses only
Expanding the expectation and using the first-moment unbiasedness that makes the cross term vanish gives a quadratic in the shrinkage intensity
Differentiate with respect to
Thus, the theoretically optimal shrinkage intensity is exactly the share of total dispersion attributable to estimation-error variance,
-
Estimate of the target scale:
; -
Estimate of total sample dispersion:
; -
Asymptotically unbiased estimate of estimation error: Let the rows of the centered sample matrix be
, with the outer product for each period . Since is the average of these outer products, the error variance of the average is approximately the dispersion of a single outer product multiplied by . Lemma 3.4 in the original paper therefore uses to estimate . Expanding with gives: -
Truncated shrinkage intensity:
, giving the feasible shrinkage intensity:
The resulting feasible shrinkage estimator is positive semidefinite; it is positive definite under the following condition:
Because the target matrix
6.2 Convex-QP Reformulation of Long-Only Maximum Sharpe Ratio
The original long-only optimization problem for maximizing a portfolio's Sharpe ratio is:
The objective is a ratio, not a concave function, so it cannot be passed directly to CVXPY under Disciplined Convex Programming (DCP) rules. Section 7 of Chapter 9 and exercise 9-C01 already prove the variable substitution below and its conditions. We restate it here as implemented in this chapter; Lesniewski's Baruch MFE Lecture 5 gives the same transformation.
Proof:
The discussion below concerns a finite Sharpe ratio and requires every feasible portfolio with positive excess return to have positive variance;
Keep three separate gates in view. Budget feasibility requires
Assume that at least one portfolio in the feasible set has strictly positive expected excess return, that is,
and define the scaled weight vector:
Since
-
Expected excess return is normalized:
-
The investment-budget constraint becomes:
-
The weight-cap constraint becomes:
Consider the reciprocal of the squared objective:
Thus, maximizing the Sharpe ratio is equivalent to minimizing its squared reciprocal:
subject to the linear constraints:
When
This completes the proof.
6.3 Convex Log-Barrier Formulation and Damped Newton Algorithm for Risk Budgeting (ERC)
Section 3.4 of Maillard, Roncalli, and Teiletche (2009) formulate ERC as a minimum-volatility problem subject to
where
The Hessian matrix is:
As long as
Because the variance contribution
Normalization does not change the relative proportions of the assets' risk contributions:
The denominator also needs to be checked. Let
This proves the risk-budget proportions, not the budget amounts. In the two-asset example above, set
Damped Newton Algorithm and Stopping Rule:
-
Initial point: start at the inverse-diagonal-standard-deviation point
, then normalize so that . -
Compute the Newton direction:
. -
Compute the Newton decrement (Boyd & Vandenberghe, Section 9.5):
is a quadratic-model estimate of (Boyd–Vandenberghe, Section 9.5.1), not a general strict upper bound. Stop the iteration when , then check the risk-share deviations. -
Backtracking line search: use the Armijo condition to choose a step size
, ensuring that the new point remains in the feasible region .
6.4 Bayesian Derivation of the Black–Litterman Model and Its Gain Form
The Black–Litterman model combines market-equilibrium implied returns and investor views into an expected-return vector. The original Black and Litterman (1992) paper was not available for this chapter; the setup and formulas below are based on Appendix B of He and Litterman (1999).
-
Reverse optimization determines the prior: Assume that investors as a whole hold the market portfolio
. By the first-order condition for mean–variance optimization, the market-equilibrium expected-return vector must satisfy: Here
is the aggregate risk-aversion coefficient for the market as a whole (He & Litterman 1999 commonly use ). -
Prior distribution: Treat the expected-return vector itself as a random variable with a prior normal distribution centered on equilibrium returns:
The scalar
scales confidence by the prior variance relative to the variance of realized returns. All returns here are expected excess returns at the same frequency; total returns would also include the cash return over the same period. -
View system: Suppose the investor holds
linear views, expressed in matrix form as: Here
is the view-selection matrix, is the vector of view returns, and is the covariance matrix of view errors. He and Litterman assume view errors are independent of prior expected-return errors and that errors across views are independent, which is why the view-error covariance is usually taken to be diagonal. The first independence assumption is also needed for this chapter's block-Gaussian covariance derivation. -
Deriving the posterior distribution (block-normal conditional update): The joint distribution of
and the observed views is: Applying the conditional-normal formula gives the posterior expected-return mean
and posterior-mean covariance : Define the Kalman-form gain matrix
. The update can then be written compactly as: This gain form does not require
itself to be invertible, but it does require to be invertible. When , , and , the rows of must be linearly independent. Repeating the same certain view makes singular; assigning two different values to that duplicated view is even contradictory. The core implementation raises an explicit error rather than hiding the issue with an inverse or pseudoinverse. measures posterior uncertainty about the unknown mean; it is not the covariance of next-period asset returns. If we separately model , with , and assume the new return noise is independent of the posterior mean, the law of total variance gives the posterior predictive covariance . The portfolio tilt below uses as the return-risk penalty, preserving the original model interface. If predictive risk is used instead, the objective and weights must both be recomputed; the two covariance matrices cannot be treated as interchangeable. -
Orthogonality of the optimal portfolio tilt: Substitute the posterior mean into the mean–variance optimal allocation:
Expanding and rearranging gives:
This expression shows that, without constraints, the deviation of portfolio weights from market weights lies in the column space of
, meaning it is a linear combination of the view portfolios. If a column of is all zeros (no view concerns that asset), its portfolio weight remains at the market weight, although its posterior mean can still change through correlations (asset 2 in Section 8.5). This property generally no longer holds after adding constraints such as long-only or weight caps.
6.5 The Kelly Criterion and Deriving Log Growth
Kelly (1956) studied capital-allocation rules that maximize the geometric growth rate of wealth over the long run.
Discrete binary bet:
Suppose an investor bets a fraction
Differentiate with respect to
Set
Solving gives the well-known Kelly-optimal bet fraction:
With symmetric odds (kelly_binary_fraction applies this truncation.
Notation note: On printed page 920 of Kelly's (1956) paper in the Bell System Technical Journal, the letter
Second-order expansion and quadratic proxy for discrete asset allocation:
For assets with continuous returns, let single-period excess return be
Let
The term
The code below uses a local model that also ignores the squared drift term:
This is an additional approximation. A continuous-time diffusion limit is justified only when, over a time step quadratic_log_growth calculates only gaussian_kelly_weights optimizes only this explicit proxy objective. For the full discrete second-order expression, the gradient is
Here
-
Growth-rate ratio:
; -
Return-variance ratio:
. Under half Kelly ( ): -
Under the quadratic proxy objective above, growth above the cash baseline is
of full Kelly; -
With the same input covariance, variance is
of full Kelly. Under the known-moment quadratic approximation, half Kelly gives up one quarter of the growth rate in exchange for a three-quarter reduction in variance. In an ideal wealth stochastic differential equation with bounded coefficients, no jumps, continuous rebalancing without limit, and no margin liquidation, the stochastic exponential can keep wealth positive; the current discrete monthly model offers no such guarantee. Strictly Gaussian simple returns have an unbounded left tail, so any position with nonzero variance has positive probability of , making exact ill-defined. The quadratic proxy can still return a number, but that does not make it a valid exact Kelly solution. Even if the asset price cannot fall below zero, a discrete 3.2-times position (ignoring the cash return) would exhaust net asset value after a single-period asset loss greater than 31.25%. Jumps, margin, and financing restrictions widen this model error. If estimated is too high, “full Kelly” already exceeds true Kelly; fractional Kelly provides protection against that error.
Kelly Growth-Rate and Variance Trade-Off Curves

- Horizontal axes: Bet fraction
( ) in the left panel and Kelly multiplier in the right panel; - Vertical axes: Expected log growth per period in the left panel; growth-rate and variance multiples relative to full Kelly in the right panel;
- How to read the figure and what to look for:
- In the left panel, for
, log growth peaks at , with a maximum of . At twice the Kelly position ( ), expected log growth turns negative. Under this example's assumptions of an IID bet, continued proportional betting, and infinitely many repetitions, wealth almost surely tends to zero; - In the Gaussian approximation shown in the right panel, half Kelly (the gray dashed line at
) achieves of the theoretical peak growth rate while its variance is only of full Kelly;
- In the left panel, for
- Limitation: The right panel shows only a quadratic growth proxy with known moments and the squared-mean term omitted; the 75% refers to proxy growth above the cash baseline. Gaussian simple returns also have an unbounded left tail and cannot guarantee that exact log utility exists. Fat tails, jumps, financing, and margin constraints further change the position size that can be sustained.
6.6 Factor Risk Decomposition
The factor model from Chapter 15,
Asset
7. Financial Interpretation: Leverage, Costs, and the Diversification Illusion
7.1 Leverage and Position-Exposure Measures
Long–short quantitative strategies must distinguish two measures of portfolio exposure:
- Net exposure:
. This measures net capital or net market-value exposure; market beta exposure must be calculated separately as the sum of each weight times its asset beta. For a market-neutral strategy, net exposure is usually anchored near 0. - Gross exposure:
. This measures the total capital invested as a leverage multiple. For example, with net exposure equal to 0, gross exposure of 2.0 (or ) means that, on a net asset value of 100 million yuan, the portfolio holds 100 million yuan long and 100 million yuan short. - Leverage: When weights are already normalized by net asset value, leverage is gross exposure,
; do not divide by net asset value again. If the inputs are amounts, first divide the sum of the absolute long and short market values by net asset value. With asset returns fixed and risky positions scaled by a common factor, their gross-return contribution and fees under a linear proportional-cost model scale by that factor. Financing costs, market impact, and tail liquidation risk can change nonlinearly; proportional scaling is not guaranteed.
7.2 Trading Frictions, Portfolio Drift, and Turnover Drag
Over a full investment period, asset weights change for two reasons: passive price changes create “drift,” while active portfolio rebalancing creates “turnover.”
Suppose beginning-of-period weights are
If next period's target weights are
If the one-way trading-cost rate is
This is not an exact self-financing execution ledger: actual trade amounts also depend on post-cost net asset value, so the fee fraction
7.3 The Diversification Illusion and the Failure of Geometric Projection
Intuitively, holding more assets may appear to spread risk. But when risk contributions are extremely uneven, investors fall into the diversification illusion.
Constructed example: stocks have 16% annualized volatility, bonds 5%, and their correlation is 0.2; capital weights are 60% stocks and 40% bonds. Let subscripts s and b denote stocks and bonds:
Another common conceptual error is to try to satisfy neutrality constraints using a “Euclidean projection.”
Suppose an alpha model produces weights
Its closed-form solution is:
The serious financial flaw is that Euclidean-distance minimization takes place in an abstract mathematical space with no financial dimensions. It is completely unaware of differences in asset volatility, correlations, or liquidity frictions. When constraint rows are correlated, the projection may greatly shrink the original long and short weights (in Section 8.3, gross exposure falls from 1.6 to 0.2). Whether the projection preserves the source of expected returns must be reevaluated using a risk model and return forecasts; a more common approach is to include neutrality conditions as constraints in an optimization with a risk term.
8. Numerical Examples
This section gives five benchmark numerical examples with explicit inputs, step-by-step hand calculations, and clearly specified units.
8.1 Ledoit–Wolf Covariance-Shrinkage Example by Hand (4×2 Matrix, Percentage Units)
8.2 Hand Calculation of Drift, Turnover, and the Cost Ledger
8.2.1 Checking Exact Self-Financing in Currency Amounts
8.3 Implications Among the Three Neutralities and a Geometric-Projection Failure Example
8.4 Four-Asset Risk-Budget Example from Maillard, Roncalli, and Teiletche (2009)
8.5 Black–Litterman Two-Asset Example by Hand
9. Python Implementation and Assertion Checks
Default Standalone Run Entry Point
From the root of the companion reader package, create an isolated environment following the package instructions and run:
.venv/bin/python run_notebook.py notebooks/ch21_portfolio_construction.ipynb
By default, RUN_FRENCH=False. The Notebook checks LW shrinkage, MRT four-asset risk, BL, Kelly, neutrality constraints, and drift in sequence, and checks boundary cases such as finite Sharpe ratios, ERC existence, posterior-mean covariance, and the quadratic growth proxy. It creates only the chapter's RUN_DIR, writes no CSV or PNG files, and skips the historical figures. Figures in Sections 3, 5.4, 6.5, 8.5, and 11 are existing reader materials, not outputs of this run. The chapter run directory differs from the separate runs/execution_ch21_portfolio_construction_<uuid>/ directory created by the runner, which stores an execution copy and status.
This chapter's 21-E08 uses a monthly excess mean of 0.008 and variance of 0.0025, giving a quadratic-proxy weight of 3.2. The Notebook instead uses 0.006 and 0.0016, giving a weight of 3.75; these are different constructed inputs. The exact binary half-Kelly growth ratio is about 74.9268%; the quadratic growth proxy gives 75% at half of its own optimal risky-asset weight, and this ratio should not be treated as a general result for exact binary growth. The neutrality constraint should be assessed as described in Section 5.2: absolute sector neutrality across mutually exclusive and exhaustive sectors implies dollar neutrality and generally does not imply beta neutrality.
For Project 3's standalone entry point, constructed outputs, and historical report, see the project guide. The call and assertions for the shared implementation are shown below. The course workspace root must have the course package and its dependencies installed; a bare Python interpreter in an unconfigured environment is not a complete reader entry point.
Calling the Shared Implementation
The code below shows how to call the core module src/quant_course/portfolio_construction.py and uses assertions to check Sections 8.1–8.3 and 8.5. Full code for the four-asset ERC example in Section 8.4 is in the answer to 21-P01. The code requires the course package and its dependencies.
import numpy as np
from quant_course.portfolio_construction import (
ledoit_wolf_identity, risk_contributions, risk_budget_weights,
max_sharpe_long_only, black_litterman, he_litterman_view_covariance,
kelly_binary_fraction, binary_log_growth, gaussian_kelly_weights,
quadratic_log_growth, exposure_report, project_to_constraints,
drift_weights, turnover,
)
# 1. Ledoit-Wolf 4x2 percentage-matrix shrinkage hand-check
x_hand = np.array([[3.0, 2.0], [-1.0, -2.0], [2.0, 3.0], [-4.0, -3.0]])
lw_res = ledoit_wolf_identity(x_hand)
assert np.isclose(lw_res.target_scale, 7.0)
assert np.isclose(lw_res.intensity, 8.0 / 42.5)
np.testing.assert_allclose(lw_res.sample_covariance, [[7.5, 6.5], [6.5, 6.5]], atol=1e-12)
np.testing.assert_allclose(
lw_res.covariance,
[[7.40588235, 5.27647059], [5.27647059, 6.59411765]],
atol=1e-6,
)
# 2. Black-Litterman two-asset hand-check
cov_bl = np.array([[0.04, 0.02], [0.02, 0.09]])
w_mkt = np.array([0.6, 0.4])
p_view = np.array([[1.0, 0.0]])
q_view = np.array([0.10])
tau_param = 0.05
omega_view = he_litterman_view_covariance(p_view, cov_bl, tau=tau_param)
bl_res = black_litterman(
cov_bl, w_mkt, risk_aversion=2.5, tau=tau_param,
view_matrix=p_view, view_returns=q_view, view_covariance=omega_view,
)
np.testing.assert_allclose(bl_res.equilibrium_returns, [0.08, 0.12], atol=1e-12)
np.testing.assert_allclose(bl_res.posterior_mean, [0.09, 0.125], atol=1e-12)
np.testing.assert_allclose(bl_res.weights, [0.7, 0.4], atol=1e-12)
# 3. Kelly log-growth hand-check (p=0.55, b=1)
f_star = kelly_binary_fraction(0.55, 1.0)
assert np.isclose(f_star, 0.10)
g_full = binary_log_growth(0.10, 0.55, 1.0)
g_half = binary_log_growth(0.05, 0.55, 1.0)
g_double = binary_log_growth(0.20, 0.55, 1.0)
assert np.isclose(g_full, 0.0050083668, atol=1e-6)
assert np.isclose(g_half, 0.0037526078, atol=1e-6)
assert g_double < 0 # Double Kelly: expected log growth is negative; long-run wealth almost surely tends to 0
# 4. Neutrality and projection checks
w_demo = np.array([0.5, 0.3, -0.4, -0.4])
beta_demo = np.array([1.2, 0.8, 1.0, 0.6])
sectors_demo = ["A", "B", "A", "B"]
rep = exposure_report(w_demo, beta_demo, sectors_demo)
assert np.isclose(rep.net, 0.0)
assert np.isclose(rep.beta, 0.2)
a_mat = np.vstack([np.ones(4), beta_demo, [1.0, 0.0, 1.0, 0.0]])
proj_w = project_to_constraints(w_demo, a_mat)
np.testing.assert_allclose(a_mat @ proj_w, 0.0, atol=1e-12)
# 5. Drift and turnover ledger checks
w_init = np.array([0.5, 0.5])
r_month = np.array([0.10, -0.10])
w_drift = drift_weights(w_init, r_month)
np.testing.assert_allclose(w_drift, [0.55, 0.45], atol=1e-12)
turnover_val = turnover(w_drift, w_init)
assert np.isclose(turnover_val, 0.10, atol=1e-12)
10. Visualization
This section examines four core charts generated in advance. All figures were produced from fixed seeds and frozen data.
The figures appear near the relevant discussion: the estimation-error simulation in Section 3, Kelly growth in Section 6.5, BL view confidence in Section 8.5, and French industry risk shares in Section 11. Their original inputs, axes, units, and limitations are retained. The new two-asset figure in Section 5.4 distinguishes capital shares from risk shares.
11. Empirical Example Using Real-Market Data
The empirical example uses a frozen snapshot from the Kenneth R. French Data Library:
- Asset universe: Value-weighted monthly returns for 10 U.S. equity industries (NoDur, Durbl, Manuf, Enrgy, HiTec, Telcm, Shops, Hlth, Utils, Other), plus the Fama–French three-factor risk-free rate (RF);
- Sample period: 1926-07 to 2026-08 (1,202 calendar months);
- Raw-file hash: SHA-256 for
industry_raw_zip:ebd937a4b995d821867aeb956a96f09a666386f38fa82516b7d1767ee4a49ae5; - Data status: The French data are a currently revised academic version, not a point-in-time (PIT) historical snapshot. Monthly data are published with a lag, historical values may be revised, and the local manifest does not preserve historical versions. A zero-month lag is an idealized month-boundary decision test.
For the 120-month period from 2010-01 to 2019-12, the observed performance of four representative strategies using the Ledoit–Wolf covariance estimator is recorded in outputs/ch21/ch21_results.json:
| Portfolio strategy | Monthly volatility | Highest-weight industries and weights | Lowest-weight industries and weights | Risk-diversification characteristics |
|---|---|---|---|---|
| Equal-weighted portfolio (1/N) | 3.51% | Each industry at 10.0% | Each industry at 10.0% | Uneven risk shares (Durbl 15.1% vs Utils 4.5%) |
| Long-only minimum variance | 2.73% | Utils (47.45%), NoDur (23.31%) | Durbl, Manuf, Enrgy, HiTec (0.0%) | Highly concentrated in low-volatility defensive assets; 6 industries have zero weight |
| Long-only maximum Sharpe | 2.88% | Utils (36.08%), Shops (27.40%) | NoDur, Durbl, Manuf, Enrgy, Other (0.0%) | Chases assets with high historical returns; 5 industries have zero weight |
| Equal risk contribution (ERC) | 3.24% | Utils (17.62%), NoDur (12.42%) | Durbl (6.41%), Enrgy (7.32%) | Nonzero holdings in all industries; risk share is exactly 10.0% each |
The data show that the long-only minimum-variance portfolio has the lowest volatility but pays for it with highly concentrated holdings (the two largest industries account for more than
Risk Decomposition Across the French 10 Industries in the Historical Window

- Horizontal axis: French 10 industry codes (NoDur, Durbl, Manuf, Enrgy, HiTec, Telcm, Shops, Hlth, Utils, Other);
- Vertical axis: Nominal portfolio weights (
) in the upper panel and relative risk shares ( ) in the lower panel; - Units: Percent (
); - Sample: 2010-01 to 2019-12 (120 months), using a Ledoit–Wolf shrunk covariance matrix;
- How to read the figure and what to look for:
- In the equal-weighted portfolio (1/N), every industry has a weight of exactly
, but utilities (Utils) account for only of risk in the lower panel, while durable goods (Durbl) and energy (Enrgy) account for and , respectively; - The long-only minimum-variance portfolio concentrates its weights in defensive industries (Utils
, NoDur , and Hlth ); its risk shares match its weights exactly; - In the ERC portfolio, each industry's risk share in the lower panel is
. To compensate for the low volatility of Utils, ERC raises its portfolio weight to and reduces Durbl to ; - Monthly volatility comparison: minimum variance (
) < maximum Sharpe ( ) < ERC ( ) < 1/N ( );
- In the equal-weighted portfolio (1/N), every industry has a weight of exactly
- Limitation: This figure is a static, ex-post description of one historical window, 2010–2019. It is not a rolling out-of-sample result or a live-strategy conclusion.
12. Common Mistakes and Debugging
In quantitative portfolio-construction work, researchers often encounter the following pitfalls because of floating-point precision and the interaction between solver implementations and financial constraints:
12.1 A Covariance Matrix on a Small Numerical Scale Can Produce a False Solver-Tolerance Failure
- Symptom: When calculating a long-only minimum-variance portfolio, pass a monthly covariance matrix directly to a quadratic-programming solver (its elements are often on the order of
). The solver reports optimal, but independently checking the original constraints sometimes finds a budget residualabove the default tolerance of , so the quality-control module rejects the result as designed. - Possible cause: Solver stopping rules depend on residual and duality-gap tolerances that are scaled to the problem. When quadratic coefficients are very small, the objective is insensitive to weight deviations, so the solver may report convergence before the budget residual falls below
. This section records the symptom and fix; it does not diagnose each internal CLARABEL criterion. - Fix: Before passing the problem to the mean–variance solver, normalize the covariance matrix by its largest absolute entry:
. Because the mean is zero in the pure minimum-variance problem, multiplying the entire objective by a positive scalar does not change the minimizer , but it brings the quadratic gradient back to a well-scaled range.
12.2 False Non-Convergence Stagnation in Damped Newton Log-Barrier Iterations
- Symptom: When solving the ERC log-barrier objective, setting the line-search tolerance near floating-point machine precision (for example,
) can make the algorithm stall near the optimum and falsely report “maximum iteration count exceeded without convergence.” - Mechanism: When the objective is on the scale of
, double-precision floating-point arithmetic cannot resolve a decrease on the order of , and Armijo backtracking shrinks the step size to machine zero. - Fix: Following Boyd & Vandenberghe (2004), Section 9.5, use the Newton decrement
as the convergence criterion, then check the absolute deviation in risk shares after solving ( ).
12.3 Missing a Feasibility Check for Maximum Sharpe with Weight Caps
- Symptom: The only check is whether any asset has positive excess return; if so, the convex QP is constructed and sent to the solver. With a per-asset cap such as
, CLARABEL may report infeasible. - Mechanism: A single asset with positive excess return does not imply that the simplex contains a portfolio with positive excess return. If the only asset with a positive excess return is capped at
, the remaining of capital must go to assets with negative excess returns, so the maximum excess return on the simplex may still be strictly negative. - Fix: Before constructing the QP, use a greedy fill in descending order of excess return to calculate the theoretical maximum excess return on the capped simplex. If the maximum is non-positive, raise an explanatory
OptimizationErrorin advance.
The code below independently verifies the scale-normalization fix and the feasibility precheck for weight caps:
import numpy as np
from quant_course.optimization_tools import OptimizationError, solve_mean_variance
from quant_course.portfolio_construction import max_sharpe_long_only
# 1. Covariance scale-normalization check
cov_tiny = np.array([[0.0004, 0.0001], [0.0001, 0.0009]])
cov_scaled = cov_tiny / float(np.max(np.abs(cov_tiny)))
res_scaled = solve_mean_variance(np.zeros(2), cov_scaled)
np.testing.assert_allclose(res_scaled.weights, [8 / 11, 3 / 11], atol=1e-6)
# 2. Maximum-Sharpe cap feasibility precheck
mu_infeasible = np.array([0.004, -0.004, -0.004])
cov_diag = np.diag([0.01, 0.01, 0.01])
try:
max_sharpe_long_only(
mu_infeasible, cov_diag, risk_free_return=0.0, max_weight=0.4,
)
except OptimizationError as exc:
assert exc.solver_status == "infeasible_by_inputs"
13. Quantitative Research in Practice: Project 3 Rolling Out-of-Sample Evaluation
As an end-to-end engineering check of quantitative portfolio construction, projects/project03/src/project03_backtest.py implements a rolling out-of-sample evaluation system covering 1990-01 to 2026-08 (440 evaluation months).
13.1 Backtest Design and Parameter Baseline
- Primary backtest specification:
- Training window: rolling estimation with
months; - Covariance estimator: Ledoit–Wolf shrinkage toward a scaled identity matrix;
- Constraints: long-only (
); single-asset cap for minimum variance and maximum Sharpe; 10% per asset for equal weight; no cap for ERC (the sample maximum is about 19.83%); - Rebalance timing and lag: zero-month lag (optimize with the then-current cross-section of moments and rebalance at the end of month
); - Trading-cost baseline: total two-sided turnover multiplied by
( ).
- Training window: rolling estimation with
- Strategies compared:
equal_weight: equal-weighted 1/N each month (baseline);min_variance: long-only minimum-variance portfolio with a weight cap;max_sharpe: long-only maximum-Sharpe portfolio with a weight cap;erc: equal risk contribution portfolio.
13.2 Evaluation Results and Statistical Inference
Based on projects/project03/outputs/summary.json and sensitivity.csv, the core performance statistics over 440 months are:
| Evaluation metric | Equal weight (1/N) | Minimum variance (Min Var) | Maximum Sharpe (Max Sharpe) | Equal risk contribution (ERC) |
|---|---|---|---|---|
| Annualized net excess return | 9.05% | 7.03% | 8.01% | 8.66% |
| Annualized net volatility | 14.32% | 11.78% | 14.36% | 13.37% |
| Annualized net Sharpe ratio | 0.631 | 0.596 | 0.558 | 0.648 |
| Annualized gross Sharpe ratio | 0.634 | 0.605 | 0.576 | 0.650 |
| Compound annual growth rate (CAGR) | 11.25% | 9.42% | 10.11% | 10.98% |
| Maximum drawdown | -48.09% | -36.41% | -41.49% | -45.52% |
| Average monthly turnover | 2.58% | 8.60% | 21.45% | 2.80% |
| Annualized average fees as share of prior NAV | 3.36 bps | 10.57 bps | 25.96 bps | 3.63 bps |
| Annualized average gross-to-net return difference (cost drag) | 3.37 bps | 10.65 bps | 26.20 bps | 3.64 bps |
| Average effective number of assets ( |
10.00 | 4.03 | 3.49 | 9.31 |
| Failures triggering fallback | 0 | 0 | 1 | 0 |

- Horizontal axis: Backtest month (1990-01 to 2026-08); vertical axis: cumulative net wealth from an initial investment of 1 yuan (log scale);
- Main observations:
- No optimized strategy credibly beats the naive equal-weighted 1/N portfolio on net returns. 1/N has the highest annualized net excess return (
) and the highest ending net wealth; - In this sample, the minimum-variance portfolio reduces full-period volatility (
vs ) and sharply narrows maximum drawdown from to , while its annualized average net return is lower than equal weight. These are joint observations from the same historical sample and do not identify a causal mechanism in which lower risk causes lower returns. Volatility and drawdown differences are descriptive; no confidence intervals are available for those differences, so they cannot be called statistically significant. The average-return difference has a separate, unadjusted single-comparison interval in Section 13.3; - The maximum-Sharpe strategy uses rolling sample means and has average monthly turnover of
(8.3 times that of equal weight), with an annualized average gross-to-net return difference of 26.20 basis points (average fees equal 25.96 basis points of prior NAV). After costs, its net Sharpe ratio is only , the lowest of the four strategies.
- No optimized strategy credibly beats the naive equal-weighted 1/N portfolio on net returns. 1/N has the highest annualized net excess return (
13.3 Statistical Inference (Paired Circular Block Bootstrap)
To assess the statistical significance of strategy-return and Sharpe differences, Project 3 uses 5,000 circular moving-block bootstrap samples (12-month blocks, seed 20261006). Sharpe differences use paired resampling:
- Minimum variance vs equal weight: The monthly average-return difference is
, with a confidence interval of . Only of resampled differences are above zero, so the main-specification average-return difference has an unadjusted single-comparison interval below zero. No multiple-comparison adjustment was made across three strategies and two metrics, so this is not a family-wise significance result; - Maximum Sharpe vs equal weight: The monthly average-return difference is
, with a confidence interval of , which includes 0. The Sharpe-ratio difference is , with a interval of ; there is no statistical advantage; - ERC vs equal weight: Although ERC's net Sharpe ratio (
) is slightly higher than that of equal weight ( ), their paired Sharpe difference ( ) has a confidence interval of , which clearly includes 0. Therefore, ERC cannot be claimed to be statistically significantly better than equal weight.

The horizontal axis shows the annualized average net-return difference relative to equal weight (percentage points, calculated as the monthly mean difference multiplied by 12); the vertical axis lists the three strategies. Dots show sample differences and horizontal lines show the 95% paired circular-block bootstrap intervals. Check whether each interval crosses the vertical zero-difference line. This figure does not show Sharpe differences and applies no multiple-comparison adjustment.
13.4 Cost and Window Sensitivity Analysis

The horizontal axis in the left panel shows cost per unit of combined buy-and-sell turnover (bp); the horizontal axis in the right panel shows training-window length (months). Both vertical axes show annualized net Sharpe. Compare each strategy's cost slope and changes across window lengths; do not choose parameters retrospectively from the highest point in the figure. These data come from prespecified sensitivity specifications on the same frozen sample and are not an independent out-of-sample test.
- Cost sensitivity: When trading costs rise from 0 to 50 bps:
- The annualized Sharpe ratio for equal weight declines only slightly, from
to ; - ERC declines from
to ; - Maximum Sharpe's annualized net Sharpe falls from
to (about 15.8%), indicating greater cost sensitivity; this does not establish that the wealth path collapses.
- The annualized Sharpe ratio for equal weight declines only slightly, from
- Window and lag sensitivity: With a 36-month window, maximum Sharpe has 14 fallback months under both sample covariance and Ledoit–Wolf estimation (all industry training-window excess means are negative in 8 months; in 6 months no positive-excess portfolio exists under the 40% cap). These fallbacks are caused by mean estimation and are unrelated to the covariance estimator; at 10 bp, net Sharpe falls to 0.474. Ledoit–Wolf provides a modest improvement for minimum variance (W60: 0.596 versus 0.577 with sample covariance). A one-month lag barely changes the results (ERC 0.648 versus 0.649).
The answer file also reports net Sharpe of about 0.587 for maximum Sharpe at W=24 and 25 equal-weight fallbacks. This window was proposed after seeing the main results, so it is a post hoc exploration. It is outside the 12 frozen window/covariance/lag sensitivity specifications and does not replace the W=60 primary specification. Exploration can generate a question to prespecify next time, but it does not increase the number of independent validations in this round.
13.5 Warning About Hindsight Overfitting
Use sample moments from the full evaluation period (1990-01..2026-08), with the same long-only constraint and 40% cap, to calculate a hindsight maximum-Sharpe portfolio (it uses information from the evaluation period and is not tradable):
- The monthly realized Sharpe of the fixed-weight gross-return path is
, or 0.75428 annualized, using the standard deviation of same-month excess returns as the denominator. The optimizer's objective for the supplied moments is 0.75386, using the covariance of asset gross returns as its denominator; these must not be described as the same quantity; - By comparison, the realized annualized Sharpe ratio for rolling out-of-sample maximum Sharpe is only 0.5580. With zero costs, rolling maximum Sharpe is 0.576; with the 10 bp proxy cost it is 0.558. The full-sample fit uses information from the evaluation period, and its estimation window and fixed weights also differ from the rolling weights. The difference from the rolling net figure does not isolate a causal effect of look-ahead bias or measure a tradable advantage.
14. Chapter Summary and Decision Logic
- Estimation error dominates risk: Expected-return estimation error is a primary source of failure in mean–variance optimization. Without reliable alpha forecasts, use shrinkage to control covariance ill-conditioning or fall back to minimum-variance or risk-parity portfolios.
- Long-only constraints and caps are natural forms of regularization: Long-only constraints rule out unbounded short leverage, while per-asset caps prevent a single extreme position. A maximum-Sharpe problem with these constraints can be transformed exactly into a convex quadratic program using a scale variable (proved in Chapter 9).
- Keep neutrality concepts distinct: Dollar, beta, and sector neutrality should be added explicitly as constraints in the optimizer. Euclidean projection optimizes only weight distance; if the objective includes risk and costs, use the corresponding objective function. Full-coverage sector constraints also imply dollar neutrality, so redundant rows should be removed.
- Risk budgets balance actual risk exposures: ERC distributes risk evenly across assets, preventing high-volatility assets from dominating the portfolio. Damped Newton's method with a Newton-decrement stopping rule can solve ERC efficiently and reliably.
- Trading costs can determine whether a strategy survives live trading: Portfolio managers must balance rebalancing frequency, tracking error, and turnover frictions. Without significant alpha to support it, a high-turnover strategy's net returns can be consumed by trading costs.
- Use benchmarks and try to falsify the strategy: A naive equal-weighted portfolio (1/N) should be the first benchmark for an optimized strategy. Apparent optimization gains that have not been checked against trading costs and bootstrap uncertainty are often only in-sample statistical illusions.
15. Conceptual and Mathematical Exercises
21-E01 (Scale of estimation error) Using the IID and stable-variance assumptions from Section 5.1, suppose a stock has monthly volatility of
21-E02 (Ledoit–Wolf target and intensity) Briefly explain why Ledoit–Wolf shrinkage uses the scaled identity matrix
21-E03 (Drift and turnover calculation) A portfolio contains three assets with beginning-of-period weights
21-E04 (Constructing a counterexample for the neutrality conditions) Construct a 3-asset portfolio weight vector
21-E05 (Proving the Euler risk decomposition) Under a symmetric positive-semidefinite covariance matrix, suppose portfolio volatility satisfies
21-E06 (Analytical derivation of two-asset ERC) Let two assets have volatilities
21-E07 (Recovering Black–Litterman equilibrium returns) Suppose the market contains two assets, with market weights
21-E08 (Deriving the continuous Kelly approximation) Write the second-order Taylor expansion of portfolio log growth. Let a single asset's excess return be
16. Programming Exercises
21-P01 (Numerical test of the four-asset MRT example) Write a standalone test script using the four-asset inputs from Maillard et al. (2009) in Section 8.4. Call quant_course.portfolio_construction and the optimization tools to calculate weights and risk shares for equal weight, long-only minimum variance, and ERC. Use assert to check that volatility satisfies
21-P02 (Verifying shrinkage of a rank-deficient covariance matrix) Generate a Gaussian random sample matrix of shape
21-P03 (Testing the long-only maximum-Sharpe feasibility precheck under a weight cap) Construct a 3-asset excess-mean vector OptimizationError; the budget constraint itself remains feasible, for example with equal weights.
17. Challenge Problems
21-C01 (Analytical decomposition of risk contributions under a factor model)
Suppose asset returns follow a general multi-factor model in which factors and specific returns are uncorrelated, but the factors need not be orthogonal:
- Derive the decomposition of portfolio variance into factor risk and specific risk;
- Prove that each factor's absolute risk contribution can be written as
, where ; - Construct a numerical example with 2 assets and 1 factor, and calculate the risk shares of every component in full.
21-C02 (Designing a robust portfolio-construction and backtesting protocol) For a long–short equity strategy, design a complete practical portfolio-construction plan. The plan must clearly specify:
- Data timestamps and causal separation;
- The covariance estimator and treatment of ill-conditioning;
- Risk-neutrality constraints and total-leverage controls;
- Turnover controls and logic for smoothing target weights;
- Explicit evaluation failure conditions (the quantitative evidence that would require rejecting the strategy for launch).
17.1 Integrated Review Questions
21-R01 (Fee conservation in currency amounts) Using the 55/45 pre-trade weights, 1 million yuan of net asset value, and c=10bp from Section 8.2, calculate the exact fees and purchase/sale amounts for 50/50 and 100/0 targets. Compare them with the turnover proxy based on prior net asset value. Do both examples establish actual slippage?
21-R02 (Mathematical objects and statistical judgments) Diagnose each case: (a) a fully invested long-only weight cap is feasible, but maximum excess mean is non-positive; (b) a zero-risk portfolio has positive excess return; (c) whether the BL posterior-mean covariance can directly replace return risk; and (d) lower sample volatility for MinVar, a single-comparison return-difference interval below 0, an ERC Sharpe difference interval crossing 0, and the post hoc W24 result. For each, state which conclusions can and cannot be drawn.
18. Exercise Solutions and Explanations
21-E01
-
Standard error of the monthly mean:
-
confidence interval (using the normal critical value ): -
The confidence interval is very wide and does not even establish whether true expected excess return is positive or negative. Unconstrained tangency optimization calculates
. Substituting either or could swing weights by hundreds of percentage points between extreme short and long positions, treating pure sampling noise as a certain signal.
21-E02
- Choosing the scaled identity matrix
ensures that the shrinkage target has exactly the same trace and total-energy scale as the sample covariance ( ). If the unscaled identity matrix were used, changes in the scale of asset returns (for example, converting decimals to percentages) would severely distort the overall eigenvalue scale of the shrunk matrix. - As
with fixed , the law of large numbers implies that the sample covariance matrix converges almost surely to the true covariance . Estimation-error variance , while . As long as the true is not a scaled identity matrix ( ), the feasible shrinkage intensity , and the estimator converges asymptotically back to the sample covariance . If is exactly , both quantities tend to 0 and the intensity need not tend to 0; in that case the shrinkage target itself is correct.
21-E03
-
Portfolio gross return:
-
Drifted weights:
-
Total turnover (buys and sells combined):
-
Cost drag (15 bps
):
21-E04
-
Let the weights be
. Check dollar neutrality: . -
Let the beta vector be
. The portfolio's total beta is: Thus,
.
21-E05
Every division by volatility below requires
-
Apply the chain rule to
: By the vector derivative rule for a quadratic form,
, so the derivative with respect to its -th component is . Substituting gives: -
Verify the Euler identity:
This completes the proof.
21-E06
-
For two assets, the covariance matrix is
. Calculate their absolute risk contributions: -
Set
: The cross term
cancels exactly from both sides, giving: Under the long-only constraint
, take the positive square root to obtain: -
Combining this with the fully invested constraint
: The formula contains no correlation coefficient
. This completes the proof.
21-E07
-
Calculate
: -
Multiply by
:
21-E08
The following calculations use a monthly quadratic-growth proxy relative to the cash baseline, omitting the squared-mean term; this is not exact discrete expected log utility.
-
First write the second-order expansion. Let portfolio simple return be
, with mean and variance . From , This uses
. Returns must be sufficiently small, and the ruin boundary and higher-order remainder must be controlled; the second-order expansion alone does not guarantee that exact log utility exists under an arbitrary distribution. -
This exercise then uses the lower-order monthly proxy that omits the squared-mean term
: -
Full-Kelly optimal weight:
-
Expected excess log growth under full Kelly:
-
Half-Kelly weight,
: Check:
, exactly of full-Kelly growth.
Reference Implementation and Assertions for 21-P01 to 21-P03
The Python code below can be run independently from the repository root to complete the checking assertions:
import numpy as np
from quant_course.portfolio_construction import (
ledoit_wolf_identity, risk_budget_weights, risk_contributions,
max_sharpe_long_only,
)
from quant_course.optimization_tools import solve_mean_variance, OptimizationError
# 21-P01: MRT 2009 four-asset numerical check and volatility ordering
vol_mrt = np.array([0.10, 0.20, 0.30, 0.40])
corr_mrt = np.array([
[1.0, 0.8, 0.0, 0.0],
[0.8, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, -0.5],
[0.0, 0.0, -0.5, 1.0],
])
cov_mrt = np.outer(vol_mrt, vol_mrt) * corr_mrt
# 1/N
ew_res = risk_contributions(np.full(4, 0.25), cov_mrt)
assert np.isclose(ew_res.volatility, 0.1151086, atol=1e-4)
np.testing.assert_allclose(ew_res.fractions, [0.123, 0.264, 0.141, 0.472], atol=1e-3)
# Long-only Min Var
mv_weights = solve_mean_variance(np.zeros(4), cov_mrt).weights
mv_res = risk_contributions(mv_weights, cov_mrt)
assert np.isclose(mv_res.volatility, 0.086303, atol=1e-4)
np.testing.assert_allclose(mv_weights, [0.7448, 0.0, 0.1517, 0.1034], atol=1e-3)
# ERC
erc_weights = risk_budget_weights(cov_mrt).weights
erc_res = risk_contributions(erc_weights, cov_mrt)
assert np.isclose(erc_res.volatility, 0.102934, atol=1e-4)
np.testing.assert_allclose(erc_weights, [0.3836, 0.1918, 0.2426, 0.1820], atol=1e-3)
np.testing.assert_allclose(erc_res.fractions, 0.25, atol=1e-6)
# Verify the volatility-ordering theorem
assert mv_res.volatility <= erc_res.volatility <= ew_res.volatility
# 21-P02: Shrinkage of a rank-deficient covariance matrix for T < p
rng = np.random.default_rng(20261021)
x_low_rank = rng.standard_normal((10, 20))
lw_low_rank = ledoit_wolf_identity(x_low_rank)
assert np.linalg.matrix_rank(lw_low_rank.sample_covariance) <= 10
min_eig = np.linalg.eigvalsh(lw_low_rank.covariance).min()
assert min_eig > 0.0
assert lw_low_rank.intensity > 0.0
# 21-P03: Maximum-Sharpe cap infeasibility precheck test
mu_infeasible = np.array([0.004, -0.004, -0.004])
cov_diag = np.diag([0.01, 0.01, 0.01])
try:
max_sharpe_long_only(
mu_infeasible, cov_diag, risk_free_return=0.0, max_weight=0.4,
)
except OptimizationError as exc:
assert "capped long-only portfolio has positive expected excess return" in str(exc)
else:
raise AssertionError("expected OptimizationError was not raised")
21-C01
Conditions:
-
Variance decomposition: Under the factor model
, the return covariance matrix is . Total portfolio variance is: Here
is the portfolio's net exposure to the common factors. -
Factor risk-contribution decomposition: Write the result from step 1 as a sum over components:
Divide both sides by
and define Then
. Treating as a function of factor exposure and specific weights gives , so is exactly the Euler form “exposure × marginal risk.” -
Two-asset, one-factor example: Let
, factor variance , specific covariance , and weights . - Portfolio factor exposure:
; - Factor-variance component:
; - Specific-variance component:
; - Total portfolio variance:
( ); - Absolute factor risk contribution:
(share ); - Absolute specific risk contribution:
(share ).
- Portfolio factor exposure:
21-C02
Scoring rubric (10 points total):
- Timing and causal separation (2 points): At decision time
, use only historical data that are available; generate signals strictly before the opening or rebalance; never use future returns to estimate means or covariance. - Covariance estimation and numerical robustness (2 points): Use Ledoit–Wolf shrinkage or a structured factor-model estimate; never directly invert an ill-conditioned sample covariance matrix; include scale normalization and positive-definiteness safeguards in the optimizer.
- Realistic constraint architecture (2 points): Clearly specify total exposure (leverage), per-stock caps, sector-neutrality and beta-neutrality constraints; do not use a purely geometric Euclidean projection that discards information.
- Cost and turnover controls (2 points): Include a turnover penalty (such as a quadratic or absolute-value cost term) or buffer rules in target weights, and calculate actual net returns after costs.
- Rigorous falsification and launch thresholds (2 points): Prespecify non-negotiable falsification criteria. For this challenge, one may propose an illustrative teaching threshold (not a universal industry standard): under this example's governance rule, reject the strategy for launch if its net Sharpe ratio does not significantly outperform the 1/N benchmark under paired bootstrap, if it is too sensitive to trading costs (a 10 bps cost increase reduces Sharpe by more than
), or if optimizer failures trigger fallback in more than of backtest periods. Readers may propose different thresholds but must explain the risk budget, economic objective, and evidence requirements set in advance. 1/N is not the only suitable benchmark for every trading task.
21-R01
50/50 target: q=0.0001, fees are 100 yuan, and the new holdings are 499,950 yuan each. Sell 50,050 yuan and buy 49,950 yuan; the 100-yuan difference pays the fee. Total traded amount is 100,000 yuan, matching the proxy. For a 100/0 target: q=0.0009/1.001=0.0008991009, fees are 899.1009 yuan, and the new amount in asset 1 is 999,100.8991 yuan. Buy 449,100.8991 yuan of asset 1 from the initial 550,000 yuan position and sell 450,000 yuan of asset 2; the 899.1009-yuan difference pays the fee. Total traded amount is 899,100.8991 yuan, which yields the fee when multiplied by 0.001. The proxy charges 900 yuan on 900,000 yuan of turnover. The capital-conservation check holds, but the model has no actual slippage, market impact, orders, or capacity data, so it does not establish live trading costs.
21-R02
(a) Budget feasibility does not imply that the positive-Sharpe transformation is available. Preserve the reason for an equal-weight fallback; do not call every position infeasible. (b) The denominator of an ordinary finite Sharpe ratio is 0. A positive-semidefinite convex QP may return an objective of 0, but this cannot be read as a finite optimal ratio. (c) V_BL represents uncertainty in the estimated mean; only under a hierarchical model with independent new noise is predictive risk Sigma+V_BL. The original BL allocation uses Sigma, and changing the risk objective requires solving again. (d) Lower volatility or drawdown is only a sample description. An unadjusted mean-difference interval supports only that single primary-specification comparison; it does not establish family-wise significance or significant volatility differences. An ERC interval crossing 0 is neither proof of equivalence nor a probability of superiority. W24 is a post hoc exploration; it does not add a prespecified sensitivity validation or replace the primary specification.
19. Further Reading
- Must Know:
- Ledoit & Wolf (2004), read Sections 2.1 and 3 of the authors' working-paper version to learn the derivation of the feasible shrinkage-intensity estimator and the Frobenius-norm definition;
- Maillard, Roncalli & Teiletche (2009/2010), read Sections 1–3.4 to learn the Euler decomposition of volatility, the two-asset independence result, and the convex log-barrier formulation.
- Should Know:
- He & Litterman (1999), read Appendix B to learn how reverse optimization determines the prior, how the gain-form posterior mean is derived, and why view tilts are orthogonal;
- DeMiguel, Garlappi & Uppal (2009), read Section 3 of the NBER conference-paper version to understand rolling out-of-sample backtesting, turnover calculated from pre-trade drifted weights, and the practical challenges of the naive 1/N benchmark.
- Advanced:
- Boyd & Vandenberghe, Convex Optimization, Section 9.5, for convergence analysis of damped Newton's method and the Newton-decrement stopping criterion;
- Kelly (1956), read printed pages 919–920 of the Bell System Technical Journal scan to understand the binary geometric log-growth maximum theorem and ruin boundary.
- Optional:
- Lesniewski's Baruch MFE Lecture 5 (2019 file), “Maximizing the Sharpe ratio,” for comparison with the variable substitution in Chapter 9;
- Browse the companion core code src/quant_course/portfolio_construction.py and applied module projects/project03/src/project03_backtest.py.
20. References
- CH21_LEDOITWOLF2004: Olivier Ledoit and Michael Wolf, “A well-conditioned estimator for large-dimensional covariance matrices,” Journal of Multivariate Analysis, 88(2), 365–411, 2004. DOI: 10.1016/S0047-259X(03)00096-4. Working-paper version: http://www.ledoit.net/ole1a.pdf. The actual reading scope is documented in the source reading record.
- CH21_MRT2009: Sébastien Maillard, Thierry Roncalli, and Jérôme Teiletche, “On the properties of equally-weighted risk contributions portfolios,” Journal of Portfolio Management, 36(4), 60–70, 2010. DOI: 10.3905/jpm.2010.36.4.060. Working-paper version: http://www.thierry-roncalli.com/download/erc.pdf. The actual reading scope is documented in the source reading record.
- CH21_HELITTERMAN1999: Guangliang He and Robert Litterman, “The Intuition Behind Black-Litterman Model Portfolios,” Goldman Sachs Asset Management Research, 1999. Duke-hosted copy: https://people.duke.edu/~charvey/Teaching/BA453_2006/GS_The_intuition_behind.pdf. The actual reading scope is documented in the source reading record.
- CH21_KELLY1956: J. L. Kelly, Jr., “A New Interpretation of Information Rate,” Bell System Technical Journal, 35(4), 917–926, 1956. DOI: 10.1002/j.1538-7305.1956.tb03809.x. Scan: https://archive.org/details/bstj35-4-917. The actual reading scope is documented in the source reading record.
- CH21_DGU2009: Victor DeMiguel, Lorenzo Garlappi, and Raman Uppal, “Optimal versus naive diversification: How inefficient is the 1/N portfolio strategy?” Review of Financial Studies, 22(5), 1915–1953, 2009. DOI: 10.1093/rfs/hhm075. NBER conference-paper version: https://users.nber.org/~confer/2006/si2006/ap/uppal.pdf. The actual reading scope is documented in the source reading record.
- SHARPE1994: William F. Sharpe, “The Sharpe Ratio,” Journal of Portfolio Management, Fall 1994 (volume, issue, and pages were not verified in the webpage read). Author's webpage: https://web.stanford.edu/~wfsharpe/art/sr/sr.htm.
- LESNIEWSKI2019: Andrew Lesniewski, “Optimization Techniques in Finance — 5. Convex optimization. II,” Baruch College MFE lecture notes (file name Opt_Lecture5_2019.pdf). https://mfe.baruch.cuny.edu/wp-content/uploads/2014/12/Opt_Lecture5_2019.pdf.
- BOYD: Stephen Boyd and Lieven Vandenberghe, Convex Optimization, Cambridge University Press, 2004. https://web.stanford.edu/~boyd/cvxbook/.
- CVXPY: Steven Diamond and Stephen Boyd, “CVXPY: A Python-embedded modeling language for convex optimization,” Journal of Machine Learning Research, 17(83), 1–5, 2016. https://www.cvxpy.org/.
- FRENCH: Kenneth R. French Data Library, 10 Industry Portfolios and Fama/French Factors. The data snapshot and hashes are recorded in the local manifest; the actual reading scope is documented in the source reading record.