From everything-claude-trading
> Mean-variance optimization and efficient frontier construction for portfolio allocation.
npx claudepluginhub brainbytes-dev/everything-claude-tradingThis skill uses the workspace's default tool permissions.
> Mean-variance optimization and efficient frontier construction for portfolio allocation.
Provides Ktor server patterns for routing DSL, plugins (auth, CORS, serialization), Koin DI, WebSockets, services, and testApplication testing.
Conducts multi-source web research with firecrawl and exa MCPs: searches, scrapes pages, synthesizes cited reports. For deep dives, competitive analysis, tech evaluations, or due diligence.
Provides demand forecasting, safety stock optimization, replenishment planning, and promotional lift estimation for multi-location retailers managing 300-800 SKUs.
Mean-variance optimization and efficient frontier construction for portfolio allocation.
The foundational framework introduced by Markowitz (1952). The investor selects portfolio weights w to:
minimize w'Σw (portfolio variance)
subject to w'μ = μ_target (target return)
w'1 = 1 (full investment)
Key inputs:
The set of portfolios offering maximum return for each level of risk. Key points on the frontier:
MVO is notoriously sensitive to input estimates. Small changes in expected returns produce wildly different allocations. This is the single most important practical challenge:
Chopra and Ziemba (1993) showed that errors in means are roughly 10x more damaging than errors in variances, and 20x more than errors in covariances.
Expected Returns — approaches ranked by robustness:
Covariance Matrix — approaches:
Practical portfolios always require constraints beyond full investment:
# Common constraint types
constraints = {
'long_only': w >= 0, # No short selling
'box': lb <= w <= ub, # Position limits (e.g., 0-5%)
'sector': A_sector @ w <= sector_max, # Sector exposure caps
'turnover': sum(|w - w_current|) <= turnover_max, # Turnover limit
'tracking_error': sqrt((w-w_b)'Σ(w-w_b)) <= TE_max, # TE budget
'cardinality': sum(w > 0) <= K, # Max number of holdings
'min_holding': w_i >= w_min if w_i > 0, # Minimum position size
}
Cardinality and minimum holding constraints make the problem mixed-integer, requiring specialized solvers (Gurobi, CPLEX) or heuristic approaches.
Shrinkage Estimators (Ledoit-Wolf):
sklearn.covariance.LedoitWolf implements the standard approachResampled Efficient Frontier (Michaud, 1998):
Robust Optimization (worst-case):
import numpy as np
from scipy.optimize import minimize
def mean_variance_optimize(mu, sigma, target_return, long_only=True):
n = len(mu)
w0 = np.ones(n) / n
bounds = [(0, 1)] * n if long_only else [(None, None)] * n
constraints = [
{'type': 'eq', 'fun': lambda w: np.sum(w) - 1},
{'type': 'eq', 'fun': lambda w: w @ mu - target_return}
]
result = minimize(
lambda w: w @ sigma @ w,
w0, method='SLSQP',
bounds=bounds, constraints=constraints
)
return result.x
# For production, use cvxpy for convex formulation:
import cvxpy as cp
def mvo_cvxpy(mu, sigma, gamma=1.0):
"""gamma controls risk aversion: higher = more conservative"""
n = len(mu)
w = cp.Variable(n)
ret = mu @ w
risk = cp.quad_form(w, sigma)
objective = cp.Maximize(ret - gamma * risk)
constraints = [cp.sum(w) == 1, w >= 0]
prob = cp.Problem(objective, constraints)
prob.solve()
return w.value
import numpy as np
import cvxpy as cp
# 5-asset universe
mu = np.array([0.08, 0.10, 0.12, 0.06, 0.09]) # expected annual returns
# Use Ledoit-Wolf shrinkage for covariance
from sklearn.covariance import LedoitWolf
lw = LedoitWolf().fit(historical_returns)
sigma = lw.covariance_
# Trace out the frontier
target_returns = np.linspace(0.06, 0.12, 50)
frontier_risk = []
frontier_weights = []
for tr in target_returns:
w = cp.Variable(5)
prob = cp.Problem(
cp.Minimize(cp.quad_form(w, sigma)),
[cp.sum(w) == 1, w >= 0, mu @ w == tr]
)
prob.solve()
if prob.status == 'optimal':
frontier_risk.append(np.sqrt(w.value @ sigma @ w.value))
frontier_weights.append(w.value)
w_current = np.array([0.20, 0.25, 0.15, 0.20, 0.20])
max_turnover = 0.10 # 10% one-way turnover limit
w = cp.Variable(5)
turnover = cp.norm(w - w_current, 1) # L1 norm = total turnover
prob = cp.Problem(
cp.Maximize(mu @ w - gamma * cp.quad_form(w, sigma)),
[cp.sum(w) == 1, w >= 0, turnover <= 2 * max_turnover]
# Factor of 2 because L1 norm double-counts buys and sells
)
When you distrust return estimates entirely, shrink toward 1/N:
alpha = 0.5 # shrinkage intensity
mu_shrunk = alpha * mu + (1 - alpha) * np.mean(mu) * np.ones(n)
# Then optimize with mu_shrunk
DeMiguel, Garlappi, and Uppal (2009) showed 1/N outperforms many optimized portfolios out-of-sample for typical estimation windows. This is a humbling baseline.