halo 的技术博客

返回

现代投资组合理论的核心思想#

1952年,Harry Markowitz提出了现代投资组合理论(MPT),颠覆了传统投资理念:

“不要把鸡蛋放在同一个篮子里” —— 但多少人真正理解这句话的数学含义?

传统思维 vs Markowitz思维#

传统思维:挑选最好的股票(高增长、低估值) Markowitz思维:挑选组合,使得在给定风险下收益最大,或在给定收益下风险最小

两个关键概念#

  1. 预期收益(Expected Return):组合中各股票预期收益的加权平均

    E(R_p) = Σ w_i * E(R_i)
    plaintext
  2. 风险(Risk):用方差标准差衡量,但不是简单的加权平均!

    σ²_p = Σ Σ w_i * w_j * σ_i * σ_j * ρ_ij
    plaintext

    关键:资产间的相关性会显著影响组合风险(这就是分散化的数学基础)

数学推导:有效前沿的诞生#

1. 组合预期收益#

E(R_p) = w' * μ
plaintext

其中:

  • w = 权重向量 (n x 1)
  • μ = 预期收益向量 (n x 1)

2. 组合风险(方差)#

σ²_p = w' * Σ * w
plaintext

其中:

  • Σ = 协方差矩阵 (n x n)

3. 优化问题#

目标函数(最小化风险):

min w' * Σ * w
plaintext

约束条件

s.t. w' * μ = R_target  (目标收益)
     w' * 1 = 1          (权重和为1)
     w_i ≥ 0              (不允许卖空,可选)
plaintext

Python实战:构建中国股票组合#

Step 1: 获取股票数据#

Step 2: 计算预期收益和协方差#

Step 3: 构建有效前沿#

Step 4: 可视化有效前沿#

Step 5: 寻找最大夏普组合#

考虑实际约束的优化#

1. 限制单一资产权重#

# 限制任何资产不超过40%
bounds = tuple((0, 0.4) for _ in range(len(tickers)))

# 或者设置最小权重(避免完全剔除某资产)
bounds = tuple((0.05, 0.4) for _ in range(len(tickers)))
python

2. 考虑交易成本#

3. 引入风险预算约束#

def risk_contribution(weights, cov_matrix):
    """计算各资产对组合风险的贡献度"""
    port_vol = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
    marginal_risk = np.dot(cov_matrix, weights) / port_vol
    risk_contrib = weights * marginal_risk / port_vol
    return risk_contrib

# 约束:单一资产风险贡献不超过30%
constraints = (
    {'type': 'eq', 'fun': lambda x: np.sum(x) - 1},
    {'type': 'ineq', 'fun': lambda x: 0.3 - risk_contribution(x, cov_matrix)}
)
python

中国市场的特殊考虑#

1. A股的交易制度#

# T+1交易制度:当天买入不能当天卖出
# 在回测中需要加入这个约束

def t_plus_one_constraint(weights_today, weights_yesterday):
    """确保不违反T+1制度"""
    # 卖出的量不能超过昨天持有的量
    sell_amount = np.maximum(weights_yesterday - weights_today, 0)
    return np.all(sell_amount <= weights_yesterday + 1e-6)

# 涨跌停限制:±10%(ST股票±5%)
# 在优化时需要加入价格限制的预期
python

2. 行业暴露限制#

3. 流动性约束#

动态再平衡策略#

定期再平衡#

阈值再平衡#

实战回测与评估#

完整的回测框架#

常见陷阱与解决方案#

陷阱1:代入估计误差(Error Maximization)#

问题:用历史均值和协方差直接优化,会放大估计误差

解决方案:使用收缩估计(Shrinkage Estimation)

from sklearn.covariance import LedoitWolf

# Ledoit-Wolf收缩估计
lw = LedoitWolf()
cov_shrunk = lw.fit(returns).covariance_

# 用收缩估计的协方差矩阵重新优化
max_sharpe_shrunk = maximize_sharpe_ratio(mean_returns, cov_shrunk, risk_free_rate)
python

陷阱2:过度集中#

问题:优化结果可能集中在少数资产上

解决方案:加入集中度约束

from scipy.optimize import minimize

def herfindahl_index(weights):
    """赫芬达尔指数(衡量集中度)"""
    return np.sum(weights ** 2)

# 约束:赫芬达尔指数不超过0.3(相当于等权重的3倍集中度)
constraints = (
    {'type': 'eq', 'fun': lambda x: np.sum(x) - 1},
    {'type': 'ineq', 'fun': lambda x: 0.3 - herfindahl_index(x)}
)
python

陷阱3:忽略黑天鹅#

问题:正态分布假设无法捕捉极端风险

解决方案:使用CVaR优化

总结与实战建议#

核心要点#

  1. 分散化不是简单持有多只股票,而是通过相关性结构降低风险
  2. 有效前沿是理论理想,实际使用需要结合约束和交易成本
  3. 输入参数的准确性比优化算法更重要(Garbage In, Garbage Out)
  4. 再平衡频率需要在交易成本和偏离成本之间权衡

实战建议#

  1. 用收缩估计代替样本协方差(Ledoit-Wolf或Oracle Approximating)
  2. 限制单一资产和行业的权重(避免过度集中)
  3. 考虑交易成本和流动性(A股T+1、涨跌停)
  4. 定期复盘和重新估计参数(市场结构会变化)
  5. 结合主观判断(量化模型是工具,不是替代品)

下一步学习#

  • Black-Litterman模型:融合市场均衡和投资者观点
  • 风险平价策略:等风险贡献,而非等权重
  • 因子投资:基于风险因子的资产配置

完整代码仓库

下期预告:Black-Litterman模型——当量化遇见主观判断

Markowitz均值方差模型实战:用Python构建最优投资组合
https://blog.halo26812.eu.org/blog/2026-06-14-markowitz-portfolio-optimization
Author halo
Published at 2026年6月14日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨