Files
etf/docs/strategy_summaries/strategy_summary_20260607_kelly_weight.md

6.4 KiB
Raw Permalink Blame History

Kelly 仓位权重模式实现总结

日期: 2026-06-07
Commit: 8b7bcf2
相关文件:

  • rotation/simple_rotation.py
  • rotation/config_loader.py
  • rotation/config_simple.yaml

1. 背景与动机

1.1 问题提出

原有仓位管理支持两种模式:

  • equal: 等权分配 (1/N)
  • rank: 按排名三角权重 (第1名50%, 第2名33%, 第3名17%)

用户询问能否使用 Kelly 准则进行仓位分配。

1.2 Kelly 准则简介

经典 Kelly 公式: f = W - (1-W)/R*

  • W = 胜率(历史盈利交易占比)
  • R = 盈亏比(平均盈利/平均亏损)

1.3 经典 Kelly 的挑战

问题 说明
样本量不足 每个标的被持有的天数有限,统计胜率/盈亏比不稳定
非平稳性 市场环境变化导致历史统计不代表未来
极端值敏感 一次大亏会剧烈改变 Kelly 比例
需要 expanding window 回测中每天用截止当天的历史来估计,计算量大

2. 解决方案Score-Proportional Kelly 近似

2.1 核心思路

利用当前动量分数 weighted_momentum_score = annualized_return × 作为 edge 代理,构造 Kelly 近似:

w_i = max(score_i, 0) / Σ max(score_j, 0)

2.2 设计优势

  • 无需额外历史统计:每天从截面数据直接计算
  • 天然支持 expanding window:每天用最新数据
  • 负分自动排除Kelly 原则 - 不下注负期望
  • 可插拔设计:与现有 equal/rank 模式统一接口

2.3 公式推导

动量分数 score = annualized_return × 包含:

  • annualized_return: 趋势方向和强度
  • : 趋势质量(信噪比)

正 score 意味着正期望Kelly 建议按 edge 比例下注。归一化后得到仓位权重。


3. 代码实现

3.1 枚举扩展 (config_loader.py)

class WeightType(str, Enum):
    """仓位加权模式"""
    EQUAL = "equal"         # 等权
    RANK = "rank"           # 按排名加权
    KELLY = "kelly"         # Kelly准则近似

3.2 核心函数 (simple_rotation.py)

def compute_position_weights(
    ranked_holdings: List[str],
    weight_type: str = 'equal',
    scores: Dict[str, float] = None,  # 新增参数
) -> Dict[str, float]:
    """
    Schemes:
        equal:  each slot = 1/N, duplicates summed.
        rank:   slot i (0-indexed) = (N-i) / triangular(N), duplicates summed.
        kelly:  w_i = max(score_i, 0) / sum(max(score_j, 0)).
                Score-proportional weighting as Kelly criterion proxy.
                Negative scores excluded (Kelly: don't bet on negative edge).
    """
    N = len(ranked_holdings)
    if N == 0:
        return {}

    weights: Dict[str, float] = {}

    if weight_type == 'kelly':
        if not scores:
            raise ValueError("Kelly weighting requires 'scores' parameter")
        # Kelly proxy: weight proportional to positive scores
        positive_scores = {c: max(scores.get(c, 0.0), 0.0) for c in set(ranked_holdings)}
        total = sum(positive_scores.values())
        if total <= 0:
            # Fallback to equal if all scores non-positive
            w = 1.0 / len(positive_scores)
            for code in positive_scores:
                weights[code] = w
        else:
            for code in ranked_holdings:
                w = positive_scores.get(code, 0.0) / total
                weights[code] = weights.get(code, 0.0) + w

    elif weight_type == 'rank':
        triangular = N * (N + 1) / 2
        for i, code in enumerate(ranked_holdings):
            w = (N - i) / triangular
            weights[code] = weights.get(code, 0.0) + w
    else:
        # equal (default)
        w = 1.0 / N
        for code in ranked_holdings:
            weights[code] = weights.get(code, 0.0) + w

    return weights

3.3 调用点修改

# _generate_signals 中传递 scores
self._pending_weights = compute_position_weights(
    ranked_holdings, self.weight_type, scores=factors,
)

3.4 配置使用 (config_simple.yaml)

rotation:
  diversified: true
  select_num: 3
  weight: kelly  # 可选: equal, rank, kelly

4. 回测结果对比

回测区间: 2020-01-10 ~ 2026-06-08 (1550 交易日)

指标 equal rank kelly
累计收益 204.97% 255.45% 405.23%
年化收益 19.88% 22.90% 30.13%
最大回撤 -14.65% -16.27% -20.44%
夏普比率 1.13 1.12 1.15
Calmar比率 1.36 1.41 1.47
日胜率 54.07% 53.75% 54.10%
调仓次数 392 392 392

4.1 结果分析

Kelly 模式特点:

  • 收益最高: 按动量分数比例分配权重,强势标的获得更大仓位
  • 夏普最高: 风险调整后收益最优
  • Calmar 最高: 收益/回撤比最优
  • 回撤较大: 集中度更高导致波动更大

三种模式定位:

  • equal: 保守型,分散风险,适合风险厌恶
  • rank: 平衡型,按排名阶梯分配
  • kelly: 进攻型,按 edge 比例集中配置

4.2 为什么日胜率会变化?

虽然信号生成(调仓日期、持仓标的)完全相同,但仓位权重影响每日组合收益:

daily_return = Σ (weight_i × return_i)

当某天收益接近 0 时,权重分配的变化可能让它在正/负之间翻转。例如:

  • 排名第1的标的大跌
  • rank 模式给 50% 权重 → 组合收益可能变负
  • equal 模式只给 33% → 影响较小,可能仍为正

5. 设计原则

5.1 可插拔架构

  • 统一函数签名,通过 weight_type 参数切换
  • 新增模式只需添加分支,不影响现有逻辑
  • scores 参数可选,仅 kelly 模式需要

5.2 防御性设计

  • Kelly 模式校验 scores 参数
  • 全负分时自动 fallback 到等权
  • 与 bond fill 机制兼容(债券 score 通常为负)

5.3 配置驱动

  • 通过 YAML 配置切换,无需修改代码
  • 支持环境变量覆盖
  • 与现有配置体系一致

6. 后续优化方向

  1. Half-Kelly: 使用 f*/2 降低波动
  2. 动态 Kelly: 根据市场状态调整 Kelly 系数
  3. 风险预算: 结合波动率进行风险平价分配
  4. 多因子 Kelly: 综合多个因子 score 计算 edge

7. 结论

Kelly 仓位模式通过 score-proportional 近似在保持可插拔架构的同时实现了最优风险调整后收益。对于追求收益最大化的场景kelly 模式是首选对于风险厌恶场景equal 模式更稳健。