From the pieces to a working optimizer
A minimum-variance portfolio on paper has no rules. A real mandate is long-only, fully invested and pays to trade, and the only way to see what those rules do is to build the optimizer yourself and test it on days it never saw. This capstone uses three ideas from the skill: gradient descent for the loop, a projection for the long-only budget rule and an L1 limit on the trades. Only NumPy is needed, and no library solver is allowed.
Projected gradient descent takes an ordinary gradient step on the variance wᵀΣw, whose gradient is 2Σw, and then maps the result back to the nearest long-only, fully invested portfolio with the projection Π. The step 1/L, with L=2λₘₐₓ(Σ) the largest Hessian eigenvalue, is always stable. The projection onto {w≥0, Σw=1} has an exact answer: sort the vector in decreasing order, take cumulative sums minus one, find the last position ρ where the sorted value still exceeds its cumulative sum divided by k, set θ to that cumulative sum over ρ+1, and return max(v-θ,0). Every weight is shifted by the same amount and the ones that would go negative are cut at zero.
Turnover is the L1 norm of the trade, ‖w-w₀‖₁. To keep it below a limit τ while staying feasible, move only the fraction α of the way from the current portfolio w₀ to the optimizer's target wₜ. A point on the straight line between two long-only, fully invested portfolios is again long-only and fully invested, and the L1 norm grows linearly along the line, so the trade is exactly min(gap,τ). Each rebalance then costs c times its turnover, which the backtest subtracts from the first day of the holding block. Weights for a block may use only the days before it, and the result to report is the volatility and return of the joined, net, out-of-sample days.
- Projected gradient descent: gradient step 2Σw with step 1/L, then the projection onto the simplex.
- Turnover limit: move the fraction α=min(1,τ/gap) along the line to the target; the portfolio stays feasible.
- Honest backtest: estimate on the last
windowdays, hold forstepdays, subtract the costs and report the joined out-of-sample numbers.
Lab · what's graded
- Projection onto the simplex20 pts
- Projected gradient descent25 pts
- A turnover limit15 pts
- A rolling backtest with costs25 pts
- Comparing the policies15 pts