高阶投资组合优化 (Modern Portfolio Optimization)¶
经典马科维茨(Markowitz)均值-方差优化(MVO)对预期收益和协方差估计误差较敏感。输入发生较小变化时,最优权重可能发生较大变化,并集中于少数资产。
1. Black-Litterman 模型:结合市场均衡与主观观点¶
高盛研发的 Black-Litterman (BL) 模型优雅地结合了客观市场的均衡规律与你的量化模型的主观观点。
- 市场均衡 (Prior): 反向应用 CAPM,逆向推导出现有市场对各项资产隐含的长期基准预期收益率。它稳固且分散。
- 主观观点 (Investor Views): 你的机器学习模型预测“AAPL 会跑赢 5%”。
- 贝叶斯融合 (Bayesian Blending): BL模型框架将“基准信念”与“偏离观点”通过置信度加以融合,得到非常平滑合理的新预期收益后验分布。
2. 凯利公式(Kelly Criterion):长期增长率与下注比例¶
如果在多次重复博弈中,已知胜率和赔率,每次下注该占总仓位多少才能实现资金长期复利最大化并避免破产?
二元赌局 Kelly 公式: $$ f^* = p - \frac{q}{b} $$ ($p$ 是胜率,$q$ 是失败率,$b$ 是赔率/盈亏比。
连续金融市场 Kelly: $$ f^* = \frac{\mu}{\sigma^2} $$ ($\mu$ 为超额期望收益,$\sigma^2$ 为策略方差。
危险与改良:Half-Kelly¶
实际估计的 $\mu$ 和 $\sigma^2$ 存在误差,Full Kelly 仓位可能造成较大回撤。Half-Kelly 使用凯利比例的一半,以降低估计误差和下行风险的影响,但也会降低理论增长率。
1. 这节究竟解决什么实际问题?¶
高阶投资组合优化 (Modern Portfolio Optimization) 的具体任务是:比较现代优化目标与现实约束,检查优化器对输入噪声的敏感性。 本节将明确输入数据、计算过程、输出及其在后续研究中的用途。
2. 前置知识¶
掌握特征、标签、训练集/测试集和基本回测概念。 对公式的理解应包括变量定义、单位、时间索引和适用条件。
3. 数据说明¶
特征默认来自固定样本或模拟样本;每个标签必须标明预测期限及其可交易时间。 运行前先检查 shape、日期范围、列名与缺失值。数据看起来能画图,不代表它适合回答研究问题。
4. 学习目标与完成标准¶
完成本节后,你应能用自己的话解释 高阶投资组合优化 (Modern Portfolio Optimization) 的输入、计算步骤、输出和局限;尤其能说明:比较现代优化目标与现实约束,检查优化器对输入噪声的敏感性。 你还应能独立改动一个参数并解释结果为什么变化,指出至少一个会让结论失真的假设。
5. 核心概念与公式¶
机器学习模型从训练样本估计输入与目标之间的关系。训练集拟合程度不能代表样本外预测能力。
训练时只能看到训练区间;特征时间不得晚于决策时间,标签与测试区间必须隔离。 看到公式时依次确认:每个符号的单位是什么?它属于哪个时点?分母会不会为零?它是描述性统计量、预测量,还是交易规则?
6. 从零实现¶
原始代码按照“准备输入 → 计算中间量 → 得到结果 → 解释输出”的顺序组织。每个单元应检查变量类型、索引、维度和代表性数值。中间变量用于核对公式实现和定位计算错误。
7. 成熟库实现¶
sklearn/PyTorch 加速建模;管道、切分和经济解释仍由研究者负责。 使用库函数前先阅读参数含义、默认值和返回对象;库输出一个数字,并不说明这个数字适合你的交易假设。
8. 两种实现的差异¶
从零实现便于核对公式、调试和识别隐含假设;成熟库适合在计算逻辑已验证后复用。两种实现依赖相同的数据口径与时点假设,使用库函数不会改变输入数据的质量。
9. 预期结果与检查范围¶
你应看到维度正确的 Series/DataFrame、日期单调递增的索引,以及能支持“比较现代优化目标与现实约束,检查优化器对输入噪声的敏感性。”这一任务的表格或图形。金融日收益率均值通常接近 0;若出现极大的连续收益、空表、全 NaN 或索引错位,应先排查数据和对齐逻辑,而不是立即相信结果。
10. 常见错误与诊断¶
随机打乱时序、Scaler 在全样本 fit、目标泄漏、调参反复查看测试集、把准确率等同收益。
诊断顺序:先打印类型与 shape,再看 head()/tail(),接着检查日期和 NaN,最后才比较数值。这样能避免在错误的对象上反复改参数。
11. 研究偏差检查¶
时间泄漏、p-hacking、多重检验和样本选择会制造虚假的 Alpha;必须报告朴素基线。 结果至少应与一个简单基线比较,并明确哪些部分只是教学演示。
12. 三层练习与答案¶
- 基础练习:验证一个中间变量、补全一段小计算,并用一句话解释输出。
- 研究练习:改变窗口、样本区间、约束或标的,记录哪些结论仍成立。
- 开放项目:把本节方法嵌入模块项目,报告基线、失败结果和限制。
题目在 ../exercises/06_ml_trading/06_advanced_portfolio_optimization_exercises.ipynb;完整推导、可运行参考实现与结果检查在 ../solutions/06_ml_trading/06_advanced_portfolio_optimization_solutions.ipynb。请先独立作答,再打开答案。
13. 延伸阅读¶
延伸材料:scikit-learn 模型选择文档。阅读记录应包括研究假设、数据频率、样本范围和结论适用条件。
14. 下一节¶
下一节是 07_leverage_and_margin。本节的概念会成为理解它的输入,而不是孤立的名词。
import matplotlib.pyplot as plt
# 1. 设置系统自带的中文字体(这里使用黑体 SimHei)
plt.rcParams['font.sans-serif'] = ['SimHei'] # 如果你想用微软雅黑,可以改成 ['Microsoft YaHei']
# 2. 解决更换字体后,负号(-)显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False
def kelly_fraction(win_prob, win_loss_ratio):
"""
简化的离散博弈 Kelly 公式
"""
if win_loss_ratio <= 0:
return 0
q = 1 - win_prob
f_star = win_prob - (q / win_loss_ratio)
return max(0, f_star) # 不能借钱,仓位最小为0
print(f"胜率 60%, 盈亏比 1:1 的理论最优押注比例 (Full Kelly): {kelly_fraction(0.60, 1.0):.2%}")
print(f"胜率 55%, 盈亏比 1.5:1 的理论最优押注比例: {kelly_fraction(0.55, 1.5):.2%}")
print(f"---- Half-Kelly 示例:降低仓位和破产风险 ----")
print(f"Half-Kelly (55%胜率, 1.5赔率): {kelly_fraction(0.55, 1.5)/2:.2%}")
胜率 60%, 盈亏比 1:1 的理论最优押注比例 (Full Kelly): 20.00% 胜率 55%, 盈亏比 1.5:1 的理论最优押注比例: 25.00% ---- Half-Kelly 示例:降低仓位和破产风险 ---- Half-Kelly (55%胜率, 1.5赔率): 12.50%
3. 不同 Kelly 比例对长期资金曲线的影响¶
为了直观展示为什么必须要用 Kelly 公式(以及为什么要打折用 Half-Kelly),我们模拟一个胜率为 60%、盈亏比为 1:1 的抛硬币赌局(典型的优秀量化策略特征)。
- 算出的 Full Kelly 最优下注比例是 20%。
- 本例比较 40% 固定仓位、**Full Kelly(20% 仓位)**和 **Half-Kelly(10% 仓位)**的表现。
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
num_flips = 300
win_prob = 0.60
# 生成 300 次赌局结果:1为赢,-1为输
results = np.random.choice([1, -1], size=num_flips, p=[win_prob, 1 - win_prob])
def simulate_bankroll(initial_capital, fraction, results):
bankroll = [initial_capital]
for r in results:
# 每天下注的绝对金额 = 昨天的总资金 * 下注比例
bet_size = bankroll[-1] * fraction
profit = bet_size * 1.0 if r == 1 else -bet_size * 1.0
bankroll.append(bankroll[-1] + profit)
return bankroll
initial_capital = 1000
bankroll_overbet = simulate_bankroll(initial_capital, 0.40, results) # 过度杠杆 (危险)
bankroll_full_kelly = simulate_bankroll(initial_capital, 0.20, results) # 理论最优
bankroll_half_kelly = simulate_bankroll(initial_capital, 0.10, results) # Half-Kelly 示例
plt.figure(figsize=(12, 6))
plt.plot(bankroll_overbet, label='Over-Betting (40% frc) - High Volatility/Ruin', color='red')
plt.plot(bankroll_full_kelly, label='Full Kelly (20% frc) - Max Growth', color='blue', linewidth=2)
plt.plot(bankroll_half_kelly, label='Half Kelly (10% frc) - Smooth & Safe', color='green', linewidth=2)
plt.yscale('log') # 资金曲线通常用对数坐标系展示复利
plt.title('Bankroll Growth: Over-Betting vs Kelly vs Half-Kelly (Log Scale)')
plt.xlabel('Number of Trades')
plt.ylabel('Capital Balance ($)')
plt.legend()
plt.grid(True, which="both", ls="--", alpha=0.5)
plt.show()
上面的图表深刻地揭示了量化资金管理的两个基本定律:
- 过度下注(Over-Betting)会降低长期增长率并增加破产风险:当下注比例超过凯利比例时,即使单次胜率为 60%,较大的资金波动也可能显著降低复合增长率。
- Half-Kelly:本次模拟中,Half-Kelly 的仓位和回撤低于 Full Kelly。结果取决于胜率、赔率和路径,不能据此把某个固定比例视为通用安全下限。
教程终章:量化之道的全景图¶
本课程已经介绍移动平均、回测、组合、机器学习和风险管理。各方法仍需要在固定数据、样本外区间和明确成本假设下验证。
本节比较了以下方法及其假设:
- 数据与信号 (Phase 1 & 2):不要相信表面的价格,去追求平稳的收益率序列(ADF检验)。不要相信短期的相关性,去寻找长期的协整吸引力(Engle-Granger)。
- 策略与提纯 (Phase 3 & 4):从固定参数的均线过渡到了能够消除未来函数、动态追踪的卡尔曼滤波器 (Kalman Filter)。从看图炒股,过渡到了用信息系数 (IC) 和 Alphalens 来评价抽象因子。
- 盾牌与组合 (Phase 4 & 5):利用 PCA 找出并剥离大盘风险,执行风险中性优化。在用机器学习构建非线性模型时,死死守住 Purged K-Fold 的底线防止泄漏;在最后下注时,用 Kelly 公式管理仓位。
量化研究需要说明概率假设、风险暴露、回撤约束和验证方法。任何模型都可能失效,样本内结果不能替代样本外检验。
后续研究应继续报告输入误差、约束敏感性、交易成本和样本外结果。
练习¶
- 推导连续形式的 Kelly 公式:f* = μ/σ²,使用你的策略历史收益率输入,计算建议的最优仓位比例。
- 在 Black-Litterman 框架的理论基础上,查阅
PyPortfolioOpt库,对 5 只真实股票实现一次完整的 BL 优化。 - 模拟 Full Kelly 与 Half Kelly 在连续 3 年的真实 SPY 周收益率上的资金曲线,分析两者的最大回撤差距。
模块索引 → ../README.md