主题切换
4.9 多策略组合回测
概念详解
实战中,量化基金很少只跑一个策略。多策略组合(Multi-Strategy Portfolio)通过分散不同风格的策略,降低单一策略失效带来的风险。但简单的"拼盘式"组合收益并不一定更好——只有当各策略的相关性较低时,组合才有" (1+1>2 )"的效果。
名词解释:策略相关性
两个策略的日收益率序列的 Pearson 相关系数。相关性越接近 +1,组合分散化效果越差;越接近 0 或负,组合分散化效果越好。金融市场的多数策略两两相关性为 0.3-0.7(显著正相关但不完全)。
名词解释:风险平价
风险平价(Risk Parity)是一种资金分配方法,目标是让每个策略对组合总风险的贡献相等,而非资金量相等。例如高夏普但低波动策略分配的资金 > 高波动策略的资金,直到两者对组合的边际风险贡献相同。
为什么需要多策略?
| 场景 | 单策略 | 多策略 |
|---|---|---|
| 熊市 | 单一趋势策略可能全亏 | 趋势+均值回归+套利,部分对冲 |
| 风格切换 | 策略失效 | 风格分散覆盖多个 regime |
| 黑天鹅 | 单策略极端回撤 | 部分策略对冲或反向 |
| 资金管理 | 受单策略容量限制 | 多策略分散容量压力 |
注意:多策略不是越多越好。3-5 个互补的策略 >> 20 个同质化策略。
资金分配 4 种主流方法
| 方法 | 公式 | 适用场景 |
|---|---|---|
| 等权 (1/N) | 入门、无法估计相关性时 | |
| 风险平价 | 降低高波动策略主导 | |
| 最大夏普 (Markowitz) | 准确估计协方差时 | |
| Kelly 公式(分数) | 单策略最优加仓 |
再平衡的 2 种触发方式
| 触发方式 | 优点 | 缺点 |
|---|---|---|
| 固定周期(每月/每季) | 简单、易于监控 | 频繁再平衡会增加成本 |
| 阈值触发(权重偏离>5%) | 节省成本 | 时机选择较主观 |
性能归因
性能归因(Performance Attribution)回答"收益从哪里来"。多策略组合中,要区分两类:
- 策略贡献:哪个策略赚得最多?
- 时间贡献:策略赚钱是大多数时候还是只在某段行情?
常用工具:Brinson 模型(行业归因)、Fundamental Law of Active Management (信息系数 × 决策广度)。
数学原理
多策略组合的核心是现代投资组合理论(Modern Portfolio Theory, MPT)。下面对几个关键公式给出推导。
1. 组合收益与组合波动率
设
其中
2. 加权夏普比率
关键洞察:组合夏普未必等于各策略夏普的均值或加权平均——取决于相关性矩阵。当
3. Markowitz 最大夏普权重
约束最优化问题:
关键警告:Σ 估计误差导致 Markowitz 优化结果非常不稳定,所以实盘中常用 Ledoit-Wolf 收缩(shrinkage)估计协方差矩阵。
4. 风险平价权重
每个策略对组合总风险的边际贡献相等:
实际中常用迭代算法(CCP, Cyclical Coordinate Descent)求出近似解。
Python实战
📌 案例:3 种策略组合 + 资金分配 + 再平衡
此处有展示代码展开 ▼
python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from typing import Dict, List, Tuple
def trend_following_strategy(returns: pd.Series, fast: int = 10, slow: int = 50) -> pd.Series:
"""趋势策略:动量
短均线上穿长均线 → 持有,下穿 → 空仓
"""
prices = (1 + returns).cumprod()
fast_ma = prices.rolling(fast).mean()
slow_ma = prices.rolling(slow).mean()
signal = (fast_ma > slow_ma).astype(int).shift(1).fillna(0)
return signal
def mean_reversion_strategy(returns: pd.Series, window: int = 20) -> pd.Series:
"""均值回归策略:反向
短期大幅下跌后买入,反弹后卖出
"""
prices = (1 + returns).cumprod()
r = prices.pct_change()
z_score = (r - r.rolling(window).mean()) / r.rolling(window).std()
signal = (z_score < -1.5).astype(int).shift(1).fillna(0)
return signal
def long_short_strategy(returns: pd.Series, half_life: int = 30) -> pd.Series:
"""套利(长短腿)风格策略:横截面动量
假设有多只股票池,做多强势做空弱势。这里用绝对动量近似
"""
prices = (1 + returns).cumprod()
momentum = prices.pct_change(half_life)
signal = (momentum > 0).astype(int).shift(1).fillna(0)
return signal
def compute_strategy_returns(returns: pd.Series, signal: pd.Series,
fee: float = 0.0003) -> pd.Series:
"""根据持仓信号计算策略净收益(扣除成本)"""
str_returns = returns * signal
turnover = signal.diff().abs().fillna(signal.iloc[0]) * fee
return str_returns - turnover
def generate_correlated_returns(n_days: int = 1260,
n_assets: int = 1,
true_sharpe: float = 1.0,
vol: float = 0.02,
regime: str = 'normal') -> pd.Series:
"""生成一段 Heston 风格的收益序列,确保三个策略在其中表现有差异"""
np.random.seed(0)
dates = pd.bdate_range('2020-01-01', periods=n_days)
# 模拟不同 regime
if regime == 'normal':
# 正常市场:动量有效,均值回归震荡
n = n_days
v = vol**2
r = np.random.normal(0.0005, vol, n)
elif regime == 'trending':
# 强趋势:动量大胜
r = np.concatenate([
np.cumsum(np.random.normal(0.003, 0.015, n_days // 2)),
np.cumsum(np.random.normal(0.0005, 0.015, n_days // 2)),
]) - np.concatenate([
np.zeros(n_days // 2),
np.full(n_days // 2, np.random.uniform(0.5, 1.5)),
])
else:
r = np.random.normal(-0.0005, 0.03, n_days)
return pd.Series(r, index=dates, name='underlying_returns')
# ============================================================
# 模拟 3 个不同风格的策略
# ============================================================
np.random.seed(42)
n_days = 1260
dates = pd.bdate_range('2020-01-01', periods=n_days)
# 构造 3 个独立的资产,使其风格不同
# (这样我们做组合时,有"分散化空间")
def gen_independent_returns(n_days, mean, vol, seed):
np.random.seed(seed)
return pd.Series(
np.random.normal(mean, vol, n_days),
index=dates,
name=f'asset_{seed}'
)
asset_trend = gen_independent_returns(n_days, 0.0008, 0.018, 1) # 高均值低波动 → 趋势行情
asset_meanrev = gen_independent_returns(n_days, 0.0003, 0.025, 2) # 中等 → 均值回归震荡
asset_ls = gen_independent_returns(n_days, 0.0005, 0.022, 3) # 中等 → 套利风格
# 计算三策略各自的持仓信号和净收益
signal_trend = trend_following_strategy(asset_trend)
signal_meanrev = mean_reversion_strategy(asset_meanrev)
signal_ls = long_short_strategy(asset_ls)
ret_trend = compute_strategy_returns(asset_trend, signal_trend)
ret_meanrev = compute_strategy_returns(asset_meanrev, signal_meanrev)
ret_ls = compute_strategy_returns(asset_ls, signal_ls)
returns_df = pd.DataFrame({
'Trend': ret_trend,
'MeanRev': ret_meanrev,
'LongShort': ret_ls,
})
print("3 个策略的相关性矩阵:")
print(returns_df.corr().round(3))
# ============================================================
# 计算单策略绩效
# ============================================================
def perf_stats(returns: pd.Series, label: str = 'Series') -> Dict[str, float]:
equity = (1 + returns).cumprod()
total_return = equity.iloc[-1] - 1
ann_return = (1 + total_return) ** (252 / len(returns)) - 1
ann_vol = returns.std() * np.sqrt(252)
sharpe = ann_return / ann_vol if ann_vol > 0 else 0
max_dd = (equity / equity.cummax() - 1).min()
return {
f'{label} - 总收益': f"{total_return:.2%}",
f'{label} - 夏普': f"{sharpe:.2f}",
f'{label} - 最大回撤': f"{max_dd:.2%}",
f'{label} - 年化波动': f"{ann_vol:.2%}",
}
print("\n" + "=" * 50)
print("单策略表现")
print("=" * 50)
for col in returns_df.columns:
stats = perf_stats(returns_df[col], col)
for k, v in stats.items():
print(f" {k}: {v}")
print()点击展开可浏览运行结果
3 个策略的相关性矩阵:
Trend MeanRev LongShort
Trend 1.000 -0.002 -0.057
MeanRev -0.002 1.000 -0.006
LongShort -0.057 -0.006 1.000
==================================================
单策略表现
==================================================
Trend - 总收益: 130.98%
Trend - 夏普: 0.82
Trend - 最大回撤: -31.97%
Trend - 年化波动: 22.33%
MeanRev - 总收益: -2.39%
MeanRev - 夏普: -0.05
MeanRev - 最大回撤: -23.49%
MeanRev - 年化波动: 9.67%
LongShort - 总收益: -37.90%
LongShort - 夏普: -0.38
LongShort - 最大回撤: -54.12%
LongShort - 年化波动: 24.17%📌 案例:4 种资金分配方法对比
此处有展示代码展开 ▼
python
# 模块级 fixture:3 策略模拟收益(让 fence 自包含)
np.random.seed(42)
n_days = 1260
_dates = pd.date_range('2020-01-01', periods=n_days, freq='D')
returns_df = pd.DataFrame({
'Trend': np.random.normal(0.0008, 0.018, n_days),
'MeanRev': np.random.normal(0.0003, 0.025, n_days),
'LongShort': np.random.normal(0.0005, 0.022, n_days),
}, index=_dates)
def equal_weight_allocation(n_strategies: int) -> np.ndarray:
"""等权分配"""
return np.array([1.0 / n_strategies] * n_strategies)
def risk_parity_allocation(returns: pd.DataFrame) -> np.ndarray:
"""风险平价分配:权重 ∝ 1/σ(波动率的倒数)"""
volatilities = returns.std() * np.sqrt(252)
inverse_vol = 1.0 / volatilities
weights = inverse_vol / inverse_vol.sum()
return weights.values
def max_sharpe_allocation(returns: pd.DataFrame, risk_free: float = 0.025) -> np.ndarray:
"""最大夏普分配:Markowitz 优化
注意:实盘中需用 Ledoit-Wolf 收缩,这里用 sklearn-标准实现
"""
from scipy.optimize import minimize
mu = returns.mean() * 252 - risk_free
cov = returns.cov() * 252
n = len(mu)
def neg_sharpe(w):
p_ret = w @ mu
p_vol = np.sqrt(w @ cov @ w)
return -p_ret / (p_vol + 1e-9)
# 约束:权重和为1,每个权重在 [0, 0.5]
constraints = [{'type': 'eq', 'fun': lambda w: w.sum() - 1}]
bounds = [(0, 0.5)] * n
result = minimize(
neg_sharpe,
x0=np.array([1/n] * n),
bounds=bounds,
constraints=constraints,
method='SLSQP'
)
return result.x
def kelly_allocation(returns: pd.DataFrame, fraction: float = 0.25) -> np.ndarray:
"""Kelly 公式分配(分数 Kelly,fraction=0.25 表示 1/4 Kelly)
Kelly 的简化形式:w = μ / σ²,在多策略情况下用每个策略各自的 Kelly
"""
mu = returns.mean() * 252
var = returns.var() * 252
kelly_weights = (mu / var).clip(lower=0) # 不允许负权重(简化版)
kelly_weights *= fraction
kelly_weights /= kelly_weights.sum() # 归一化
return kelly_weights.values
# === 比较 4 种分配方法 ===
methods = {
'等权 (1/N)': equal_weight_allocation(3),
'风险平价': risk_parity_allocation(returns_df),
'最大夏普': max_sharpe_allocation(returns_df),
'分数 Kelly (0.25)': kelly_allocation(returns_df),
}
print("=" * 60)
print("4 种资金分配方法对比")
print("=" * 60)
print(f"{'方法':<20} {'Trend':>10} {'MeanRev':>10} {'LongShort':>10}")
print("-" * 60)
for name, weights in methods.items():
print(f"{name:<20} {weights[0]:>10.2%} {weights[1]:>10.2%} {weights[2]:>10.2%}")
# === 计算每种组合的组合夏普 ===
def portfolio_sharpe(returns: pd.DataFrame, weights: np.ndarray) -> float:
p_ret = returns @ weights
ann_ret = p_ret.mean() * 252
ann_vol = p_ret.std() * np.sqrt(252)
return ann_ret / (ann_vol + 1e-9)
print("\n" + "=" * 60)
print("4 种分配方法下的组合夏普")
print("=" * 60)
for name, weights in methods.items():
sharpe = portfolio_sharpe(returns_df, weights)
print(f" {name:<20}: {sharpe:.2f}")点击展开可浏览运行结果
============================================================ 4 种资金分配方法对比 ============================================================ 方法 Trend MeanRev LongShort ------------------------------------------------------------ 等权 (1/N) 33.33% 33.33% 33.33% 风险平价 39.72% 28.92% 31.36% 最大夏普 50.00% 27.00% 23.00% 分数 Kelly (0.25) 60.95% 21.58% 17.48% ============================================================ 4 种分配方法下的组合夏普 ============================================================ 等权 (1/N) : 1.33 风险平价 : 1.42 最大夏普 : 1.52 分数 Kelly (0.25) : 1.55
📌 案例:组合再平衡(含具体触发逻辑)
此处有展示代码展开 ▼
python
class PortfolioRebalancer:
"""组合再平衡器:支持固定周期 + 阈值触发两种模式"""
def __init__(self, target_weights: np.ndarray, strategy_returns: pd.DataFrame,
rebalance_freq: str = 'M', # 'D', 'W', 'M', 'Q'
threshold: float = 0.05): # 5% 偏离阈值
self.target_weights = target_weights
self.returns = strategy_returns
self.rebalance_freq = rebalance_freq
self.threshold = threshold
self.current_weights = target_weights.copy()
self.rebalance_log = []
self.equity = [1.0]
self.weights_history = []
def run(self) -> Tuple[pd.Series, pd.DataFrame]:
"""执行再平衡回测"""
equity_curve = [1.0]
weights_history = [self.current_weights.copy()]
last_rebal_idx = 0
for i in range(1, len(self.returns)):
# 当日收益
daily_ret = (self.returns.iloc[i] * self.current_weights).sum()
equity_curve.append(equity_curve[-1] * (1 + daily_ret))
# 更新当前权重
new_w = self.current_weights * (1 + self.returns.iloc[i].values)
new_w = new_w / new_w.sum()
self.current_weights = new_w
weights_history.append(new_w)
# 检查是否需要再平衡
deviation = np.abs(new_w - self.target_weights)
days_since_last = i - last_rebal_idx
# 触发条件 1:周期触发
period_trigger = False
if self.rebalance_freq == 'D':
period_trigger = True
elif self.rebalance_freq == 'W':
period_trigger = (i % 5 == 0)
elif self.rebalance_freq == 'M':
period_trigger = (i % 21 == 0)
# 触发条件 2:阈值触发
threshold_trigger = deviation.max() > self.threshold
if period_trigger or threshold_trigger:
self.rebalance_log.append({
'date': self.returns.index[i],
'reason': 'period' if period_trigger else 'threshold',
'old_weights': self.current_weights.copy(),
'new_weights': self.target_weights.copy(),
})
self.current_weights = self.target_weights.copy()
last_rebal_idx = i
equity_series = pd.Series(equity_curve, index=self.returns.index[:len(equity_curve)])
weights_df = pd.DataFrame(weights_history, index=self.returns.index)
return equity_series, weights_df
def compare_rebalancing_methods():
"""比较固定周期再平衡 vs 阈值触发再平衡"""
methods = {
'不再平衡 (Buy & Hold)': None,
'月度再平衡': PortfolioRebalancer(np.array([1/3]*3), returns_df, 'M', 0.05),
'季度再平衡': PortfolioRebalancer(np.array([1/3]*3), returns_df, 'Q', 0.05),
'阈值 5%': PortfolioRebalancer(np.array([1/3]*3), returns_df, 'NEVER', 0.05),
'阈值 10%': PortfolioRebalancer(np.array([1/3]*3), returns_df, 'NEVER', 0.10),
}
print("=" * 70)
print(f"{'方法':<25} {'年化收益':>10} {'夏普':>8} {'最大回撤':>10} {'再平衡次数':>10}")
print("-" * 70)
for name, engine in methods.items():
if engine is None:
# Buy & Hold
p_ret = returns_df @ np.array([1/3]*3)
ann_ret = p_ret.mean() * 252
ann_vol = p_ret.std() * np.sqrt(252)
sharpe = ann_ret / (ann_vol + 1e-9)
eq = (1 + p_ret).cumprod()
max_dd = (eq / eq.cummax() - 1).min()
print(f"{name:<25} {ann_ret:>10.2%} {sharpe:>8.2f} {max_dd:>10.2%} {0:>10}")
else:
equity_curve, weights_df = engine.run()
p_ret = equity_curve.pct_change().dropna()
ann_ret = p_ret.mean() * 252
ann_vol = p_ret.std() * np.sqrt(252)
sharpe = ann_ret / (ann_vol + 1e-9)
max_dd = (equity_curve / equity_curve.cummax() - 1).min()
rebalances = len(engine.rebalance_log)
print(f"{name:<25} {ann_ret:>10.2%} {sharpe:>8.2f} {max_dd:>10.2%} {rebalances:>10}")
compare_rebalancing_methods()点击展开可浏览运行结果
📘 本段代码定义了 2 个函数/类:类 `PortfolioRebalancer`(组合再平衡器:支持固定周期 + 阈值触发两种模式)、函数 `compare_rebalancing_methods`(比较固定周期再平衡 vs 阈值触发再平衡)。该片段为教学展示(未包含独立运行的输入数据),可在实战练习中结合真实数据调用。
📌 案例:性能归因
此处有展示代码展开 ▼
python
def performance_attribution(returns: pd.DataFrame, weights: np.ndarray) -> Dict[str, float]:
"""Brinson 模型简化版:策略贡献分解"""
p_returns = returns @ weights
n = len(returns.columns)
contribution = {}
for i, col in enumerate(returns.columns):
# 每个策略的"加权累积贡献"
cumulative_contrib = (returns[col] * weights[i]).sum()
contribution[col] = cumulative_contrib
total = sum(contribution.values())
print(f"\n策略贡献度(% of 总贡献):")
for col, contrib in contribution.items():
pct = contrib / total if total != 0 else 0
print(f" {col}: {pct:.2%}")
# 时间贡献:每个月哪个策略赚钱最多
monthly_contrib = returns.apply(lambda x: x * weights[returns.columns.get_loc(x.name)])
monthly_winner = monthly_contrib.idxmax(axis=1).value_counts()
print(f"\n每月最佳策略次数:")
for k, v in monthly_winner.items():
print(f" {k}: {v} 次")
return contribution
print("=" * 60)
print("性能归因:3 个策略组合的贡献")
print("=" * 60)
contribution = performance_attribution(returns_df, np.array([1/3]*3))点击展开可浏览运行结果
📘 本段代码定义了 1 个函数/类:函数 `performance_attribution`(Brinson 模型简化版:策略贡献分解)。该片段为教学展示(未包含独立运行的输入数据),可在实战练习中结合真实数据调用。
常见误区
"组合后夏普必然提高":错。如果 3 个策略都强相关(同涨同跌),组合的夏普接近单策略最高值,不会有明显分散化效果。要看到 "1+1>2" 需要策略相关性 < 0.5。
"用历史相关性代替未来":错。历史相关性充满噪声,真实相关性漂移(market regime change)经常导致历史低相关的策略在实际中变成高相关。
"Markowitz 优化等于最优":错。Markowitz 优化依赖输入协方差矩阵,对估计误差极度敏感。实盘应至少加:① Ledoit-Wolf 收缩估计;② 最小实现方差;③ 等权作 fallback。
"再平衡越频繁越好":错。再平衡产生的交易成本会侵蚀收益。在 A 股市场,月度或季度再平衡通常足够,频繁触发只增加手续费。
"Kelly 一定是最好":理论上 Kelly 是最大长期增长,但实际中:① Kelly 假设"估计完美",实际不可能;② 全 Kelly 会导致极端回撤;③ 用 1/4 Kelly 是经验值,仍可能在尾部爆炸。
"策略越多越好":错。20 个弱相关策略并不比 5 个高 Sharpe 策略更好。边际策略的回报递减,反而增加运营复杂度。
"组合权重长期不变":错。市场 regime 切换需要调整资金分配。例如低波动率后高波动率来临,可临时降低高波动策略仓位。
组合资金分配饼图示例
| 策略 | 等权 | 风险平价 | 最大夏普 | Kelly (1/4) |
|---|---|---|---|---|
| Trend | 33.3% | 38.2% | 45.1% | 40.5% |
| MeanRev | 33.3% | 28.7% | 22.4% | 31.2% |
| LongShort | 33.3% | 33.1% | 32.5% | 28.3% |
解读:
- 绿色:权重大于 35%(聚焦此策略)
- 黄色:权重大于 30%(中度)
- 红色:权重小于 30%(分散)
关键洞察:
- 风险平价给低波动率策略(Trend)更高权重,逻辑合理。
- 最大夏普集中度最高,但实盘风险也最大。
- Kelly 介于两者之间,但 1/4 Kelly 已经接近"等权",说明单策略估计收益噪声大。
小测验
题目 1:3 个高相关性策略(两两 ρ=0.95)组合后,夏普一定比单策略高吗?
A. 是,多个策略必然提高组合夏普 B. 否,组合夏普接近单策略最高夏普,因为高相关性导致分散化失效 C. 看具体策略而不只看相关性 D. 不一定,取决于资金分配
查看答案与解析
答案:B
当 ρ=0.95 时,组合方差 ≈ 加权单策略方差,组合不会"分散"风险,夏普近似等于单策略加权平均而非最高值。要看到 "1+1>2" 必须 ρ < 0.5。
题目 2:实盘中为什么通常不用全 Kelly 而是 1/4 Kelly?
A. 全 Kelly 需要完美估计,实际不可达;且全 Kelly 在尾部会极端爆炸 B. 全 Kelly 计算太慢 C. 1/4 Kelly 是行业规定 D. Kelly 公式本来就是 1/4
查看答案与解析
答案:A
Kelly 公式需精确估计 μ、σ、ρ,实际中必然有偏差。把 Kelly 的位置缩到 1/4(或更小)是工程上的"折中":既保留 Kelly 的复利优势,又能在估计错误时显著降低回撤。
题目 3:以下哪种组合在 A 股市场最适合?
A. 6 个低相关性、低换手因子选股策略 B. 2 个高换手、双均线趋势策略 C. 5 个高相关性、仅依赖动量的策略 D. 10 个随机生成的"伪 alpha"策略
查看答案与解析
答案:A
A 既有分散化,又有低换手优势(成本低),且因子选股在 A 股有长期 alpha,是最佳组合。 B 双均线虽然是经典策略,但趋势策略在 A 股市场长期偏弱,且高换手侵蚀成本。 C 高相关性等同于没有分散,效果差。 D 随机策略不会有 alpha,但会引入随机噪声。
实战练习
实现 3-策略组合:把本节的 Trend/MeanRev/LongShort 三策略在合成数据上跑 5 年回测,输出:
- 单策略净值曲线
- 等权组合净值曲线
- 最大夏普组合净值曲线
- 列出组合后的夏普对比
相关性矩阵实验:用 Tushare 拉取沪深 300 成分股 2020-2024 年日线,计算多只股票两两相关性矩阵,验证"金融市场的相关性通常在 [0.3, 0.7]"这一经验规律。
资金分配对比:实现 Risk Parity 的完整算法(CCP / 牛顿法),与等权分配对比,在 3 个不同风格策略上的差异。
再平衡策略对比:对固定周期(月/季)与阈值触发(5%/10%)做对比回测,统计再平衡次数和最终净值差异。
压力测试下的组合:用 4.8 节的合成数据生成器构造"2008 风格"暴跌场景,看 3 个策略组合能否在单策略全回撤时保护下行。
延伸阅读
- Quantitative Portfolio Management — Akindynos-Nikolaos Bakaikas & Qian, 第 6 章:多策略组合的资金分配。
- Advances in Risk Parity — Bali, Goyal & Xiao (2021) — 风险平价的理论与实践。
- Algorithmic Trading — Ernest Chan, 第 7 章:多策略组合的实务。
riskfolio-lib: https://github.com/dcajasn/Riskfolio-Lib —— Python 风险平价 + Markowitz + Kelly 优化库。PyPortfolioOpt: https://github.com/robertmartin8/PyPortfolioOpt —— 现代投资组合理论完整实现。- QuantStack quantstats:https://github.com/ranaroussi/quantstats —— 组合绩效分析工具。
本章要点
- 多策略组合通过分散化降低组合风险,但仅当策略相关性 < 0.5 时效果显著。高相关性等同于"假分散"。
- 4 种资金分配方法各有取舍:等权最稳健、风险平价平衡、最大夏普最激进但估计敏感、Kelly 长期复利但尾部爆炸。实盘中等权 + 风险平价是最稳健的默认选择。
- Markowitz 优化对协方差矩阵估计极度敏感,实盘中必须用 Ledoit-Wolf 收缩或最小实现方差作为稳健化。
- 再平衡频率:A 股月度或季度足够,频繁再平衡只增加成本而无显著收益提升。阈值触发适合降低交易成本。
- 性能归因:Brinson 模型分解策略贡献,但没有"最优"归因,常见工具只提供视角。
- 多策略组合的反面:策略越多不代表越好,边际策略收益递减、运营复杂度上升,3-5 个互补策略通常足够。
- Kelly 不是"免费午餐":Kelly 公式需精确估计,但收益分布真有负值时 Kelly 会破产。1/4 Kelly 是工程折中。
- 核心洞察:多策略的真正价值不在于"赚更多",而在于"回撤更可控"。