1. 这节究竟解决什么实际问题?¶
6.7 杠杆与保证金管理 (Leverage & Margin) 的具体任务是:量化杠杆、保证金和强平风险,避免把高收益误读为高能力。 本节将明确输入数据、计算过程、输出及其在后续研究中的用途。
2. 前置知识¶
掌握特征、标签、训练集/测试集和基本回测概念。 对公式的理解应包括变量定义、单位、时间索引和适用条件。
3. 数据说明¶
特征默认来自固定样本或模拟样本;每个标签必须标明预测期限及其可交易时间。 运行前先检查 shape、日期范围、列名与缺失值。数据看起来能画图,不代表它适合回答研究问题。
4. 学习目标与完成标准¶
完成本节后,你应能用自己的话解释 6.7 杠杆与保证金管理 (Leverage & Margin) 的输入、计算步骤、输出和局限;尤其能说明:量化杠杆、保证金和强平风险,避免把高收益误读为高能力。 你还应能独立改动一个参数并解释结果为什么变化,指出至少一个会让结论失真的假设。
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/07_leverage_and_margin_exercises.ipynb;完整推导、可运行参考实现与结果检查在 ../solutions/06_ml_trading/07_leverage_and_margin_solutions.ipynb。请先独立作答,再打开答案。
13. 延伸阅读¶
延伸材料:scikit-learn 模型选择文档。阅读记录应包括研究假设、数据频率、样本范围和结论适用条件。
14. 下一节¶
完成本模块后,进入下一模块的概览页,并把本节的检查清单带到后续研究中。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
np.random.seed(42)
print('Libraries loaded')
Libraries loaded
import matplotlib.pyplot as plt
# 1. 设置系统自带的中文字体(这里使用黑体 SimHei)
plt.rcParams['font.sans-serif'] = ['SimHei'] # 如果你想用微软雅黑,可以改成 ['Microsoft YaHei']
# 2. 解决更换字体后,负号(-)显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False
1. 杠杆的双刃剑效应¶
杠杆 (Leverage) 指你实际控制的资产价值与你的自有资本之比:
$$\text{杠杆倍数} = \frac{\text{持仓市值}}{\text{净资产}}$$
- 2 倍杠杆意味着:借入等额资金,实际持仓是净资产的 2 倍
- 如果股票涨 5%,你赚 10%(2 倍)
- 如果股票跌 5%,你亏 10%(2 倍) 或 更多(加上融资利率)
# 模拟不同杠杆倍数下的资金曲线
np.random.seed(42)
n_days = 252 * 3 # 3 年
# 基础策略:年化 8%,波动 15%
base_returns = np.random.normal(0.08/252, 0.15/np.sqrt(252), n_days)
# 融资利率(年化)
margin_rate = 0.04 # 年化 4%
daily_margin_cost = margin_rate / 252
leverage_ratios = [1.0, 1.5, 2.0, 3.0, 4.0]
colors = ['blue', 'green', 'orange', 'red', 'darkred']
plt.figure(figsize=(13, 6))
for lev, color in zip(leverage_ratios, colors):
# 杠杆后收益 = 原始收益 * 杠杆倍数 - 融资成本 * (杠杆-1)
leveraged_returns = lev * base_returns - (lev - 1) * daily_margin_cost
cumulative = (1 + leveraged_returns).cumprod()
plt.plot(cumulative, color=color, linewidth=1.5, label=f'{lev}x 杠杆')
final = cumulative[-1]
max_dd = (cumulative / np.maximum.accumulate(cumulative) - 1).min()
print(f'{lev}x 杠杆: 3年总收益={final-1:.2%}, 最大回撤={max_dd:.2%}')
plt.title(f'不同杠杆倍数下的资金曲线(基础策略: 年化8%, 波动15%, 融资利率4%)')
plt.xlabel('交易日')
plt.ylabel('累积净值')
plt.legend()
plt.grid(alpha=0.3)
plt.show()
1.0x 杠杆: 3年总收益=7.84%, 最大回撤=-19.52% 1.5x 杠杆: 3年总收益=2.90%, 最大回撤=-30.41% 2.0x 杠杆: 3年总收益=-3.42%, 最大回撤=-40.27% 3.0x 杠杆: 3年总收益=-19.01%, 最大回撤=-56.98% 4.0x 杠杆: 3年总收益=-36.41%, 最大回撤=-69.93%
2. 最优杠杆:Merton 分数¶
对于给定的预期收益和波动率,存在一个数学意义上的最优杠杆倍数:
$$L^* = \frac{\mu - r}{\sigma^2}$$
其中 $\mu$ 是策略年化预期收益,$r$ 是融资利率,$\sigma$ 是年化波动率。
在给定的连续时间假设和目标函数下,该结果与 Kelly Criterion 的最优增长率解一致。
annual_mu = 0.08 # 策略年化预期收益 8%
annual_r = 0.04 # 融资利率 4%
annual_sigma = 0.15 # 波动率 15%
optimal_leverage = (annual_mu - annual_r) / (annual_sigma ** 2)
print(f'最优杠杆倍数(Merton Division): {optimal_leverage:.2f}x')
print(f'Half-Merton(实盘常用): {optimal_leverage/2:.2f}x')
# 可视化:杠杆 vs 预期长期增长率
leverage_range = np.linspace(0, 5, 200)
# 长期增长率 = (μ-r) * L - 0.5 * σ² * L²
long_run_growth = (annual_mu - annual_r) * leverage_range - 0.5 * annual_sigma**2 * leverage_range**2
plt.figure(figsize=(10, 5))
plt.plot(leverage_range, long_run_growth * 100, color='blue', linewidth=2)
plt.axvline(optimal_leverage, color='red', linestyle='--', linewidth=2,
label=f'最优杠杆 = {optimal_leverage:.2f}x')
plt.axvline(optimal_leverage/2, color='green', linestyle='--', linewidth=2,
label=f'Half-Merton = {optimal_leverage/2:.2f}x')
plt.axhline(0, color='black', alpha=0.3)
plt.xlabel('杠杆倍数')
plt.ylabel('预期长期增长率 (%/年)')
plt.title('预期长期增长率 vs 杠杆倍数(过度杠杆导致负增长)')
plt.legend()
plt.grid(alpha=0.3)
plt.show()
最优杠杆倍数(Merton Division): 1.78x Half-Merton(实盘常用): 0.89x
3. 爆仓风险分析¶
使用过高杠杆时,即使是短暂的市场下跌也可能导致净资产清零(爆仓)。 保证金水平通常要求净资产保持在持仓价值的一定比例以上。
# 模拟爆仓风险场景
margin_call_threshold = 0.2 # 净资产跌到 20% 以下触发爆仓
np.random.seed(123)
bankruptcy_counts = {}
for lev in [1.0, 2.0, 3.0, 4.0, 5.0]:
bankrupt = 0
for trial in range(500):
equity = 1.0 # 起始净资产归一化为 1
for _ in range(252 * 3):
r = np.random.normal(0.08/252, 0.15/np.sqrt(252))
equity = equity + lev * equity * r - (lev - 1) * equity * daily_margin_cost
if equity / lev < margin_call_threshold: # 爆仓条件
bankrupt += 1
break
bankruptcy_counts[lev] = bankrupt / 500
print(f'{lev}x 杠杆: {bankrupt}/500 次模拟爆仓 ({bankrupt/500:.1%})')
# 可视化爆仓概率
plt.figure(figsize=(8, 5))
plt.bar([str(k)+'x' for k in bankruptcy_counts], [v*100 for v in bankruptcy_counts.values()],
color=['green', 'yellow', 'orange', 'red', 'darkred'])
plt.xlabel('杠杆倍数')
plt.ylabel('3年内爆仓概率 (%)')
plt.title('不同杠杆倍数下的 3 年爆仓概率(500次蒙特卡洛模拟)')
plt.grid(alpha=0.3, axis='y')
plt.show()
1.0x 杠杆: 0/500 次模拟爆仓 (0.0%) 2.0x 杠杆: 21/500 次模拟爆仓 (4.2%) 3.0x 杠杆: 214/500 次模拟爆仓 (42.8%) 4.0x 杠杆: 393/500 次模拟爆仓 (78.6%) 5.0x 杠杆: 487/500 次模拟爆仓 (97.4%)
练习¶
- 将基础策略修改为夏普比率 = 0.5(如年化 8%,波动 16%),重新计算最优杠杆。结果如何变化?
- 对当前的 Beta 对冲组合(市场中性,年化 5%,波动 5%),计算其理论最优杠杆。
- 模拟一个每月动态调整杠杆的框架(当近期夏普下降时降低杠杆),观察爆仓概率如何变化。
模块索引 → ../README.md