Beta 体制自适应过滤器设计方案2

Beta 体制自适应过滤器设计方案

1. 问题背景

1.1 市场现象

当锚定物(BTC)回暖后,Alt 资产的 Beta 值会持续飙升:

正常态:   β ≈ 0.3 ~ 0.5   (BTC 涨 1%,Alt 涨 0.3~0.5%)
扩张态:   β ≈ 4 ~ 10       (BTC 涨 1%,Alt 涨 4~10%)

不是价格的普通上涨,而是价差的持续过大 — 协整关系的阶段性破裂。

1.2 当前系统弱点

组件 问题 影响
analysis_core.py BETA_WINDOW=100 固定窗口 OLS β 估计滞后 ≈17天才能跟上新体制
strategy.py adaptive_threshold=3.0 固定 β 飙升导致 z4h 极端,持续突破阈值
momentum_filter.py 只检测单腿价格趋势 不检测 spread/beta 层面的体制切换
健康监控 长窗口(200)/短窗口(100) 反应迟钝,等检测到已经亏了

1.3 故障场景还原

时间线(无 Beta 体制过滤器):
T+0h    BTC 开始回暖,β 从 0.5 开始上升
T+12h   β 实际已达 2.0,但 OLS(100期) β̂ 仍 ≈ 0.6
        → spread = log(alt) - 0.6×log(btc) 持续偏大
        → z4h 持续走正,adaptive_z 突破阈值
        → 系统产生做空信号(误判为均值回归机会)

T+24h   β 实际达 4.0,OLS β̂ ≈ 0.8
        → z4h 继续走高,系统再次尝试入场
        → 开仓即被 β 持续扩张吞噬利润

T+7d    β 实际达 8.0,OLS β̂ ≈ 2.0
        → 仍在追赶,z4h 仍然极端
        → 协整假设彻底失效,均值回归策略不成立

核心问题:系统用滞后 β 计算的 z4h 产生入场信号,实际上这些信号反映的是 β 正在变化,而非 spread 正在回归

1.4 新方案对比时间线

同一故障场景下,Beta 体制过滤器如何介入:

时间线(有 Beta 体制过滤器):
T+0h    BTC 开始回暖,β 从 0.5 开始上升
        β_short(20期)=0.55, β_long(100期)=0.50
        β_divergence=0.10 → STABLE, 正常交易

T+8h    β_short 开始偏离(短窗口更快响应)
        β_short=0.85, β_long=0.52
        β_divergence=0.63 → STABLE, 但 divergence 上升中

T+12h   β_short 明显领先 β_long
        β_short=1.20, β_long=0.55
        β_divergence=1.18, mean_div 近期均值≈0.90
        → EXPANDING, scale=1.10, 阈值 3.0→3.3
        → 系统产生做空信号,但因阈值提高被拦截 ✅

T+16h   β_divergence 持续走高
        β_short=1.80, β_long=0.58
        β_divergence=2.10, mean_div≈1.50
        → EXPANDING, scale=1.58, 阈值 3.0→4.75
        → 继续拦截入场 ✅

T+24h   β_divergence 超过硬拦截线
        β_short=3.50, β_long=0.65
        β_divergence=4.38, mean_div≈2.80
        → EXPANDING, hard_block=True
        → 完全禁止入场 ✅

T+7d+   β_long 逐渐跟上(100期窗口适应)
        β_short=8.20, β_long=6.50
        β_divergence=0.26, mean_div≈0.35
        → STABLE, 恢复正常交易

关键改善:T+12h 即检测到 β 偏离并提高入场门槛,比旧系统(无保护,T+12h 误入场)早 0h 拦截。整个 β 飙升期间零入场,避免了旧系统在 T+12h~T+7d 间的持续亏损。


2. 解决方案概述

2.1 核心思路

在分析层直接追踪 β 的多窗口偏离度,作为 β 体制切换的一手信号:

β_long  = OLS(100期) β     ← 已有,稳定但迟钝
β_short = OLS(20期) β      ← 新增,敏感快速响应
β_divergence = max(0, β_short - β_long) / max(|β_long|, 0.1)   ← β 上行偏离度

当 β_divergence 持续偏高 → β 正在快速上升 → 协整关系不可靠 → 拦截入场。

设计要点

  • 仅检测上行偏离max(0, β_short - β_long) 确保 β 下降(Alt 回落、协整恢复中)不触发拦截
  • 分母下限保护max(|β_long|, 0.1) 防止低 β 资产对(如 β_long=0.05)时 divergence 爆炸

2.2 方案优势

对比 z4h 行为检测(间接) β 偏离度检测(直接)
信号源 z4h 趋势是 β 变化的下游症状 β_divergence 直接测量根因
检测速度 需积累 12h+ z4h 趋势 β_short(20×4h≈3天) 立即偏离
精准度 z4h 趋势可能是正常均值回归 β 偏离只能来自结构性变化
假阳性 容易误杀正常大 z4h 只在 β 真正变化时触发
方向性 无法区分 β 上升/下降 仅拦截 β 上行扩张

2.3 架构集成

┌──────────────────────────────────────────────────────────────┐
│                    analysis_core.py                           │
│  calculate_cointegration_params_dual_window()                │
│  ├─ β_long  = OLS(beta_window=100)        [已有]              │
│  ├─ β_short = OLS(beta_short_window=20)   [新增]              │
│  └─ β_divergence = max(0, β_short-β_long)                    │
│                    / max(|β_long|, 0.1)    [新增]             │
└────────────────────────┬─────────────────────────────────────┘
                         │ β_divergence (4h 结果,每根新 4h K线更新一次)
                         ▼
┌──────────────────────────────────────────────────────────────┐
│             orchestrator.py                                   │
│  process_analysis()                                          │
│  └─ 从 multi_period_result 提取 β_divergence,传给 strategy   │
└────────────────────────┬─────────────────────────────────────┘
                         │ beta_divergence: float
                         ▼
┌──────────────────────────────────────────────────────────────┐
│             strategy.py                                       │
│  _BetaRegimeTracker                                          │
│  ├─ update(): 接收 β_divergence,去重后入缓冲                  │
│  │   └─ 仅当值变化 >0.001 时入队(4h 级去重)                  │
│  ├─ check():  判定体制状态 + 输出阈值缩放因子                   │
│  │   ├─ STABLE:    scale=1.0,正常交易                        │
│  │   └─ EXPANDING: scale>1 或硬拦截                           │
│  │                                                           │
│  _check_entry() 改动:                                        │
│  ├─ [新增] Beta 体制检查 → 硬拦截 / 动态缩放                   │
│  └─ threshold = adaptive_threshold × beta_regime_scale        │
└──────────────────────────────────────────────────────────────┘

3. 详细设计

3.1 分析层:β_short 计算

文件:src/config.py

BETA_WINDOW: int = 100        # [已有] OLS 长期 β 窗口
BETA_SHORT_WINDOW: int = 20   # [新增] OLS 短期 β 窗口(20×4h≈3.3天)

窗口选择依据

  • 20 期 × 4h = 80h ≈ 3.3 天,足以捕捉 β 快速变化
  • 比 ZSCORE_WINDOW=30 短,确保对结构性变化更敏感
  • 最少 20 个数据点满足 OLS 统计显著性要求

文件:src/utils/analysis/analysis_core.py

改动函数calculate_cointegration_params_dual_window()

在现有 OLS(beta_window=100) 之后,新增短窗口 OLS:

def calculate_cointegration_params_dual_window(
    base_klines, alt_klines,
    beta_window=None, zscore_window=None,
    beta_short_window=None,        # [新增] 短窗口大小
):
    # ... 现有逻辑不变 ...
    # beta_ols = 现有的 β_long

    # ═══ 新增:短窗口 β 估计 ═══
    if beta_short_window is None:
        beta_short_window = BETA_SHORT_WINDOW

    beta_short = beta_ols          # 默认等于长期 β
    beta_divergence = 0.0

    if len(aligned) >= beta_short_window + 1:
        short_base = np.log(aligned['base'].iloc[-beta_short_window:])
        short_alt  = np.log(aligned['alt'].iloc[-beta_short_window:])
        X_short = sm.add_constant(short_base)
        model_short = sm.OLS(short_alt, X_short).fit()
        beta_short = model_short.params.iloc[1]

        # β 上行偏离度 = max(0, β_short - β_long) / max(|β_long|, 0.1)
        # 仅检测 β 上升(Alt 跑赢 BTC),β 下降不拦截
        # 分母下限 0.1 防止低 β 资产对的 divergence 爆炸
        beta_divergence = max(0.0, beta_short - beta_ols) / max(abs(beta_ols), 0.1)

    return {
        # ... 现有字段不变 ...
        'beta_short': beta_short,
        'beta_divergence': beta_divergence,
    }

计算开销:短窗口 OLS 仅用 20 个数据点,相比现有 100 期 OLS 可忽略不计。

β_divergence 语义

β_divergence 值 含义 示例
0.0 β 下降或无变化(不拦截) β_long=0.5, β_short=0.3
0.0 ~ 0.3 β 轻微上升,短长基本一致 β_long=0.5, β_short=0.65
0.3 ~ 0.8 β 温和上升 β_long=0.5, β_short=0.90
0.8 ~ 2.0 β 显著上升(触发缩放区间) β_long=0.5, β_short=1.50
2.0+ β 剧烈飙升(触发硬拦截) β_long=0.5, β_short=1.50+

注意

  • β_divergence 是瞬时值,单次高值可能是噪声,需要在策略层跟踪其时间序列
  • β_divergence ≥ 0(设计保证),β 下降时为 0,不会误拦截协整恢复中的交易机会

低 β 资产对的分母保护

β_long β_short 无保护 divergence 有保护 divergence (分母≥0.1)
0.50 0.90 0.80 0.80(无影响)
0.10 0.20 1.00 1.00(无影响)
0.05 0.10 1.00 0.50(避免误触发)
0.02 0.04 1.00 0.20(避免误触发)

向上传播

analyze_pair_advanced():从 coint_new 结果中提取 beta_shortbeta_divergence,放入 cointegration_new dict。

analyze_multi_period():从 4h/60d 周期的 detail 中提取 beta_divergence,放入返回值:

return {
    # ... 现有字段 ...
    'beta_divergence': details.get(('4h', '60d'), {}).get('cointegration_new', {}).get('beta_divergence', 0.0),
}

只用 4h 周期的 β_divergence,因为:

  • 4h 是协整分析和交易信号的主时间框架
  • 5m/1h 周期的 β 波动大、噪声多,不适合体制判定

3.2 编排层:传递 β_divergence

文件:src/trading/orchestrator.py

改动函数process_analysis()

multi_period_result 提取 beta_divergence,传给 strategy.process_tick()

# 在调用 strategy.process_tick() 之前
beta_divergence = multi_period_result.get('beta_divergence')

entry_signal, exit_signal = self._strategy.process_tick(
    symbol, base_symbol, z4h, timestamp,
    kline_time=kline_time,
    latest_price=price_for_log,
    alt_ohlcv=alt_ohlcv,
    base_ohlcv=base_ohlcv,
    beta_divergence=beta_divergence,   # [新增]
)

无需改 process_analysis() 的方法签名multi_period_result 已经作为参数传入。


3.3 策略层:BetaRegimeTracker

文件:src/trading/config.py

StrategyParams 新增字段:

@dataclass(frozen=True)
class StrategyParams:
    # ... 现有字段 ...

    # Beta 体制自适应过滤器
    beta_regime_enabled: bool = True
    beta_regime_divergence_threshold: float = 0.8  # β_divergence 均值超此值 → 扩张
    beta_regime_hard_block_threshold: float = 2.0  # β_divergence 均值超此值 → 硬拦截
    beta_regime_scale_max: float = 2.0             # 阈值最大缩放倍数

环境变量约定:

TRADING_STRATEGY_BETA_REGIME_ENABLED=true
TRADING_STRATEGY_BETA_REGIME_DIVERGENCE_THRESHOLD=0.8
TRADING_STRATEGY_BETA_REGIME_HARD_BLOCK_THRESHOLD=2.0
TRADING_STRATEGY_BETA_REGIME_SCALE_MAX=2.0

# 币种级覆盖 (PURR)
TRADING_STRATEGY_PURR_BETA_REGIME_DIVERGENCE_THRESHOLD=1.0

文件:src/trading/strategy.py

3.3.1 _BetaRegimeState 数据类
@dataclass
class _BetaRegimeState:
    """Beta 体制检测结果"""
    regime: str              # 'stable' | 'expanding'
    mean_divergence: float   # β_divergence 滑动均值
    max_divergence: float    # β_divergence 近期最大值
    threshold_scale: float   # 阈值缩放因子 (>=1.0)
    hard_block: bool         # True = 双重确认硬拦截
    reason: str              # 诊断信息
3.3.2 _BetaRegimeTracker
class _BetaRegimeTracker:
    """Beta 体制自适应跟踪器

    跟踪 β_divergence 时间序列,检测协整 β 持续飙升。

    数据策略:
    - 每个 5m tick 接收一个 β_divergence 值
    - 去重:β_divergence 基于 4h K线计算,同一根 4h 内值不变
      通过比较与上次入队值的差异(>_DEDUP_EPSILON)实现去重
    - 实际入队频率 ≈ 每 4h 一次
    - 缓冲区 maxlen=50 → 50 根 4h K线 ≈ 8.3 天的独立观测

    判定逻辑:
    - mean(β_divergence) > hard_block_threshold  → 硬拦截
    - mean(β_divergence) > divergence_threshold  → 阈值缩放
    - 否则 → 正常交易
    """

    _BUFFER_SIZE = 50         # 50 × 4h = ~8.3天(去重后的独立观测)
    _MIN_SAMPLES = 3          # 至少 3 根 4h K线(12h)才开始判定
    _RECENT_WINDOW = 6        # 近期窗口 6 × 4h = 24h(用于检测加速)
    _DEDUP_EPSILON = 0.001    # β_divergence 变化小于此值视为同一根 4h K线

    def __init__(self, enabled: bool = True):
        self._enabled = enabled
        self._buffers: dict[PairKey, deque] = {}       # 每配对缓冲
        self._last_values: dict[PairKey, float] = {}   # 去重用:上次入队值

    def update(self, key: PairKey, beta_divergence: float) -> None:
        """每 5m tick 调用,内部去重确保仅新 4h 值入队"""
        if not self._enabled or beta_divergence is None:
            return

        # 去重:β_divergence 基于 4h OLS,同一根 4h 内值不变
        last = self._last_values.get(key)
        if last is not None and abs(beta_divergence - last) < self._DEDUP_EPSILON:
            return  # 同一根 4h K线,跳过

        if key not in self._buffers:
            self._buffers[key] = deque(maxlen=self._BUFFER_SIZE)
        self._buffers[key].append(beta_divergence)
        self._last_values[key] = beta_divergence

    def check(
        self,
        key: PairKey,
        divergence_threshold: float,
        hard_block_threshold: float,
        scale_max: float,
    ) -> _BetaRegimeState:
        """检测当前 Beta 体制状态

        Args:
            key: 配对标识
            divergence_threshold: β_divergence 均值扩张阈值
            hard_block_threshold: β_divergence 均值硬拦截阈值
            scale_max: 最大阈值缩放倍数

        Returns:
            _BetaRegimeState
        """
        if not self._enabled:
            return _BetaRegimeState('stable', 0.0, 0.0, 1.0, False, "")

        buf = self._buffers.get(key)
        if buf is None or len(buf) < self._MIN_SAMPLES:
            return _BetaRegimeState('stable', 0.0, 0.0, 1.0, False, "数据不足")

        data = list(buf)

        # 全窗口均值
        mean_div = sum(data) / len(data)
        max_div = max(data)

        # 近期窗口均值(检测加速)
        recent = data[-self._RECENT_WINDOW:] if len(data) >= self._RECENT_WINDOW else data
        recent_mean = sum(recent) / len(recent)

        # 取 max(全窗口均值, 近期均值) 作为判定值
        # 这样即使长期均值还不高,但近期急剧升高也能触发
        effective_div = max(mean_div, recent_mean)

        # ── 判定 ──
        if effective_div >= hard_block_threshold:
            return _BetaRegimeState(
                'expanding', mean_div, max_div, scale_max, True,
                f"Beta硬拦截: mean_div={mean_div:.3f} recent={recent_mean:.3f} "
                f"max={max_div:.3f} >={hard_block_threshold}"
            )

        if effective_div >= divergence_threshold:
            # 线性插值缩放:divergence_threshold → 1.0, hard_block_threshold → scale_max
            t = (effective_div - divergence_threshold) / max(
                hard_block_threshold - divergence_threshold, 1e-6
            )
            t = min(1.0, max(0.0, t))
            scale = 1.0 + t * (scale_max - 1.0)
            return _BetaRegimeState(
                'expanding', mean_div, max_div, scale, False,
                f"Beta缩放: mean_div={mean_div:.3f} recent={recent_mean:.3f} "
                f"max={max_div:.3f} scale={scale:.2f}"
            )

        return _BetaRegimeState(
            'stable', mean_div, max_div, 1.0, False,
            f"Beta稳定: mean_div={mean_div:.3f} recent={recent_mean:.3f}"
        )

    def cleanup_pair(self, key: PairKey) -> None:
        self._buffers.pop(key, None)
        self._last_values.pop(key, None)

关键设计决策

  1. 4h 级去重

    • β_divergence 基于 4h K线 OLS 计算,5m tick 内值不变
    • update() 通过 _DEDUP_EPSILON=0.001 检测值变化,仅在新 4h K线时入队
    • 避免 buffer 被 48 个相同值填满(4h/5m=48)
    • buffer 中每个元素对应一根独立的 4h K线,统计计算有效
  2. 双窗口判定max(全窗口均值, 近期24h均值)

    • 防止"短期急升但长期均值还低"的漏检
    • 近期窗口(6×4h=24h)对应 β 开始急速飙升的典型时间尺度
  3. 线性插值缩放

    divergence_threshold(0.8) → scale=1.0(刚开始偏离,不缩放)
    hard_block_threshold(2.0) → scale=2.0(最大缩放)
    中间值按线性插值
    

    避免硬切换,平滑过渡。

  4. 硬拦截 vs 缩放

    • effective_div >= 2.0(默认)→ 硬拦截(β 已剧烈偏移,协整假设彻底失效)
    • 0.8 <= effective_div < 2.0阈值缩放(β 在变化但可能是暂时的,提高门槛)
    • effective_div < 0.8正常交易
  5. scale_max=2.0 的选择(而非 3.0):

    • scale_max=3.0 时阈值从 3.0→9.0,adaptive_z 几乎不可能达到,整个缩放区间实质等同硬拦截
    • scale_max=2.0 时阈值从 3.0→6.0,z4h=5~6 在极端行情下仍可能出现
    • 缩放区间(0.8~2.0)中的中间值真正有意义:门槛提高但不封死
3.3.3 集成到 AdaptiveBollingerStrategy

__init__

self._beta_regime = _BetaRegimeTracker(
    enabled=default_params.beta_regime_enabled,
)

process_tick() / _process_tick_unlocked() 签名新增:

def process_tick(
    self, symbol, base_symbol, z4h, timestamp,
    kline_time=None, latest_price=None,
    alt_ohlcv=None, base_ohlcv=None,
    beta_divergence: float | None = None,   # [新增]
) -> tuple[EntrySignal | None, ExitSignal | None]:

_process_tick_unlocked 的新 K 线更新块中:

if is_new_candle:
    # ... 现有: z4h_history, momentum_filter update ...
    # [新增] Beta 体制跟踪(内部自动去重,仅新 4h 值入队)
    if beta_divergence is not None:
        self._beta_regime.update(key, beta_divergence)

_check_entry() 改动(在 z4h 过滤之后、方向判断之前):

# ── 现有步骤 3: z4h 绝对值过滤 ──
if abs(z4h) < params.min_zscore_abs:
    ...
    return None

# ── [新增] 步骤 4: Beta 体制检查 ──
if params.beta_regime_enabled:
    beta_state = self._beta_regime.check(
        key,
        divergence_threshold=params.beta_regime_divergence_threshold,
        hard_block_threshold=params.beta_regime_hard_block_threshold,
        scale_max=params.beta_regime_scale_max,
    )
    if beta_state.hard_block:
        logger.info(
            f"🛡️ Beta体制硬拦截 | {pair_label} | {beta_state.reason} | "
            f"az={adaptive_z:+.4f} z4h={z4h:+.4f}"
        )
        return None
    threshold_scale = beta_state.threshold_scale
else:
    beta_state = None
    threshold_scale = 1.0

# ── 步骤 5: 方向判断(应用 Beta 缩放)──
threshold = params.adaptive_threshold * threshold_scale
if adaptive_z < -threshold:
    direction = 'long'
elif adaptive_z > threshold:
    direction = 'short'
else:
    if threshold_scale > 1.01:
        logger.info(
            f"🛡️ Beta体制缩放拦截 | {pair_label} | "
            f"az={adaptive_z:+.4f} 有效阈值={threshold:.2f} "
            f"(原始={params.adaptive_threshold} ×{threshold_scale:.2f}) | "
            f"{beta_state.reason if beta_state else ''}"
        )
    return None

cleanup_pair()

self._beta_regime.cleanup_pair(key)

4. 参数调优指南

4.1 默认参数

参数 默认值 含义 调优方向
BETA_SHORT_WINDOW 20 短期 β 窗口(20×4h≈3.3天) ↓更敏感 ↑更稳定
beta_regime_divergence_threshold 0.8 开始缩放的 β 偏离度 ↓更早介入 ↑更晚介入
beta_regime_hard_block_threshold 2.0 硬拦截的 β 偏离度 ↓更保守 ↑更激进
beta_regime_scale_max 2.0 最大阈值缩放倍数 ↑更难入场 ↓影响小

4.2 参数语义示例

beta_regime_divergence_threshold = 0.8

  • β_long=0.5, β_short=0.9 → divergence=(0.9-0.5)/0.5=0.8 → 开始缩放
  • β_long=1.0, β_short=1.8 → divergence=(1.8-1.0)/1.0=0.8 → 开始缩放
  • 含义:短期 β 比长期 β 上升 80% 时开始介入

beta_regime_hard_block_threshold = 2.0

  • β_long=0.5, β_short=1.5 → divergence=(1.5-0.5)/0.5=2.0 → 硬拦截
  • 含义:短期 β 是长期 β 的 3 倍时完全禁止入场

beta_regime_scale_max = 2.0

  • 阈值从 3.0 缩放到 6.0
  • adaptive_z 需要 ±6.0 才能入场(极端行情下仍有可能,保留入场窗口)
  • 对比 scale_max=3.0:阈值到 9.0 几乎不可能入场,缩放区间与硬拦截无实质差异

β 下降方向的处理

  • β_long=0.5, β_short=0.3 → divergence=max(0, 0.3-0.5)/0.5=0.0 → 不拦截
  • 含义:β 下降意味着 Alt 回落,协整关系可能在恢复,不应阻止入场

4.3 场景模拟

场景 A:正常市场(β 稳定)

β_long=0.5, β_short=0.55
β_divergence=max(0, 0.05)/0.5=0.10
mean_divergence=0.08
→ regime=STABLE, scale=1.0
→ threshold=3.0(无变化)
→ 正常入场

场景 B:β 温和上升

β_long=0.5, β_short=0.85
β_divergence=max(0, 0.35)/0.5=0.70
mean_divergence=0.50
→ regime=STABLE, scale=1.0
→ 偏离度尚未超过 0.8 阈值
→ 正常入场,但需关注

场景 C:β 开始飙升(早期检测)

β_long=0.5, β_short=1.2
β_divergence=max(0, 0.7)/0.5=1.40
mean_divergence=0.90(近期均值=1.20)
effective_div=1.20(取较大值)
→ regime=EXPANDING, scale=1.0+(1.20-0.8)/(2.0-0.8)×1.0=1.33
→ threshold=3.0×1.33=4.0
→ 入场门槛提高,z4h<4.0 被拦截

场景 D:β 全面飙升(硬拦截)

β_long=0.5, β_short=3.0
β_divergence=max(0, 2.5)/0.5=5.0
mean_divergence=3.5(近期均值=4.2)
effective_div=4.2
→ regime=EXPANDING, hard_block=True
→ 完全禁止入场
→ 日志: "🛡️ Beta体制硬拦截 | PURR|HYPE | Beta硬拦截: mean_div=3.500 ..."

场景 E:β 飙升后企稳

β_long=2.0(已跟上),β_short=2.2
β_divergence=max(0, 0.2)/2.0=0.10
mean_divergence=0.30(历史缓冲中仍有较高值,但在衰减)
→ regime=STABLE, scale=1.0
→ threshold=3.0
→ β_long 已适应新体制,恢复正常交易

场景 F:β 下降(Alt 回落)

β_long=0.5, β_short=0.25(Alt 跑输 BTC)
β_divergence=max(0, -0.25)/0.5=0.0(方向性保护)
→ regime=STABLE, scale=1.0
→ 不拦截。β 下降 = 协整关系可能在恢复,允许入场

场景 G:低 β 资产对

β_long=0.05, β_short=0.10
β_divergence=max(0, 0.05)/max(0.05, 0.1)=0.05/0.1=0.50
→ regime=STABLE(分母保护避免了 divergence=1.0 的误触发)
→ 正常入场

5. 改动文件清单

文件 改动类型 改动内容
src/config.py 新增常量 BETA_SHORT_WINDOW = 20
src/utils/analysis/analysis_core.py 增强函数 calculate_cointegration_params_dual_window() 新增短窗口 OLS + 方向性 β_divergence
src/utils/analysis/analysis_core.py 增强函数 analyze_pair_advanced() 传播 beta_divergence
src/utils/analysis/analysis_core.py 增强函数 analyze_multi_period() 返回 beta_divergence
src/trading/config.py 新增字段 StrategyParams 增加 4 个 beta_regime 参数
src/trading/config.py 增强函数 get_strategy_params(), _build_strategy_params(), load_trading_config() 适配
src/trading/orchestrator.py 增强调用 process_analysis() 提取并传递 beta_divergence
src/trading/strategy.py 新增类 _BetaRegimeState, _BetaRegimeTracker(含去重逻辑)
src/trading/strategy.py 增强方法 process_tick() 新增 beta_divergence 参数
src/trading/strategy.py 增强方法 _check_entry() 新增 Beta 体制检查 + 阈值缩放
src/trading/strategy.py 增强方法 cleanup_pair() 清理 tracker 状态

不涉及改动的文件

  • momentum_filter.py — 不变
  • position_manager.py — 不变(不涉及平仓逻辑,见 §7.1 风险评估)
  • executor.py — 不变
  • models.py — 不变(PairTradeSignal 暂不加字段)

6. 日志设计

6.1 新增日志

时机 级别 格式
初始化 INFO 🔬 Beta体制跟踪器初始化 | enabled=True divergence_thresh=0.80 hard_block=2.00 scale_max=2.0
硬拦截 INFO 🛡️ Beta体制硬拦截 | PURR|HYPE | Beta硬拦截: mean_div=3.500 recent=4.200 max=5.100 >=2.0 | az=-8.50 z4h=-6.20
缩放拦截 INFO 🛡️ Beta体制缩放拦截 | PURR|HYPE | az=-4.50 有效阈值=4.00 (原始=3.0 ×1.33) | Beta缩放: mean_div=0.900 ...
5min摘要 INFO 📋 状态摘要 | ... | beta_regime=EXPANDING mean_div=1.20 scale=1.33
分析层 DEBUG 双窗口OLS | ... | β_short=1.20(20期) β_long=0.50(100期) β_divergence=1.40

6.2 飞书告警集成

当 Beta 体制从 STABLE → EXPANDING 转换时,可在 orchestrator 层发送飞书告警(可选增强,不在本次范围内)。


7. 风险与边界条件

7.1 已识别风险

风险 严重度 影响 缓解
已持仓风险暴露 β 飙升期间只拦截新入场,已有持仓的止损/止盈不受影响,可能面临巨大浮亏 本次仅做入场拦截;退场加固需作为 P0 后续任务尽快跟进
短窗口 β 噪声大 单次高 divergence 误触发 使用均值而非瞬时值;MIN_SAMPLES=3(12h 预热)
系统重启丢失缓冲 重启后 ~12h 无保护(3 根 4h K线预热) β 飙升是持续数天的事件,12h 空窗可接受
β_long 更新缓慢 β 企稳后 divergence 下降慢 β_long 用 100 期窗口,~17 天后完全适应;可考虑后续加快
参数不适配特定币种 某些币种 β 天然波动大 支持 per-pair 参数覆盖

7.2 不在本次范围

  • 退场逻辑调整(β 飙升时的持仓保护)— 建议作为 P0 后续任务
  • 冷却期(EXPANDING → STABLE 的过渡保护)
  • β_long 窗口自适应(根据 divergence 动态调短 β_long 窗口)
  • 飞书告警集成
  • PairTradeSignal 增加 beta_divergence 字段

8. 验证方案

8.1 单元测试

# test_beta_regime.py

def test_stable_regime():
    """β_divergence 稳定低值 → regime=STABLE, scale=1.0"""
    tracker = _BetaRegimeTracker(enabled=True)
    key = ("PURR/USDC:USDC", "HYPE/USDC:USDC")
    # 模拟 10 根 4h K线的低 divergence(每次值不同以通过去重)
    for i in range(10):
        tracker.update(key, 0.10 + i * 0.002)
    state = tracker.check(key, 0.8, 2.0, 2.0)
    assert state.regime == 'stable'
    assert state.threshold_scale == 1.0

def test_expanding_soft():
    """β_divergence 超过 divergence_threshold → 缩放"""
    tracker = _BetaRegimeTracker(enabled=True)
    key = ("PURR/USDC:USDC", "HYPE/USDC:USDC")
    for i in range(10):
        tracker.update(key, 1.20 + i * 0.002)
    state = tracker.check(key, 0.8, 2.0, 2.0)
    assert state.regime == 'expanding'
    assert 1.0 < state.threshold_scale <= 2.0
    assert not state.hard_block

def test_expanding_hard():
    """β_divergence 超过 hard_block_threshold → 硬拦截"""
    tracker = _BetaRegimeTracker(enabled=True)
    key = ("PURR/USDC:USDC", "HYPE/USDC:USDC")
    for i in range(10):
        tracker.update(key, 3.00 + i * 0.002)
    state = tracker.check(key, 0.8, 2.0, 2.0)
    assert state.regime == 'expanding'
    assert state.hard_block

def test_recent_spike():
    """长期低但近期急升 → 近期窗口触发"""
    tracker = _BetaRegimeTracker(enabled=True)
    key = ("PURR/USDC:USDC", "HYPE/USDC:USDC")
    # 30 根 4h K线低值
    for i in range(30):
        tracker.update(key, 0.10 + i * 0.002)
    # 10 根 4h K线急升
    for i in range(10):
        tracker.update(key, 1.50 + i * 0.002)
    state = tracker.check(key, 0.8, 2.0, 2.0)
    assert state.regime == 'expanding'  # 近期均值 ~1.5 > 0.8

def test_dedup():
    """相同 β_divergence 值不重复入队"""
    tracker = _BetaRegimeTracker(enabled=True)
    key = ("PURR/USDC:USDC", "HYPE/USDC:USDC")
    # 模拟同一根 4h K线的 48 个 5m tick(值相同)
    for _ in range(48):
        tracker.update(key, 1.5)
    # 应该只入队 1 次,不满足 MIN_SAMPLES=3
    state = tracker.check(key, 0.8, 2.0, 2.0)
    assert state.regime == 'stable'  # 数据不足
    assert state.reason == "数据不足"

def test_directional():
    """β 下降时 divergence=0,不触发拦截"""
    # β_divergence 由分析层计算,tracker 只接收值
    # 此测试验证分析层传入 0.0 时 tracker 行为正确
    tracker = _BetaRegimeTracker(enabled=True)
    key = ("PURR/USDC:USDC", "HYPE/USDC:USDC")
    for i in range(10):
        tracker.update(key, 0.0 + i * 0.0001)  # 微小变化通过去重
    state = tracker.check(key, 0.8, 2.0, 2.0)
    assert state.regime == 'stable'
    assert state.threshold_scale == 1.0

def test_disabled():
    """禁用时始终返回 stable"""
    tracker = _BetaRegimeTracker(enabled=False)
    key = ("PURR/USDC:USDC", "HYPE/USDC:USDC")
    for i in range(10):
        tracker.update(key, 5.0 + i * 0.002)
    state = tracker.check(key, 0.8, 2.0, 2.0)
    assert state.regime == 'stable'
    assert state.threshold_scale == 1.0

8.2 集成验证

  1. 回测:在 β 飙升的历史区间(如 2024 年 BTC 减半后的 alt season)上回测:

    • 对比有无 Beta 体制过滤的入场次数和胜率
    • 预期:过滤后入场次数减少 50%+,但胜率提升
  2. 实盘观察

    • 监控 beta_divergence 日志,验证数值范围
    • 观察 🛡️ Beta体制硬拦截🛡️ Beta体制缩放拦截 日志频率
    • 确认 β 下降场景(divergence=0.0)不产生拦截日志
    • 根据实际情况调整 divergence_thresholdhard_block_threshold

Read more

跑步的技巧(滚动落地)

“滚动落地(rolling contact / rolling foot strike)”不是一种教条式的“脚法”,而是一种 让冲击沿着整只脚、整条后链逐级传递的落地机制。 它的核心不是“你先用哪儿着地”,而是: 你的脚落地之后,冲击是不是像轮子一样滚过去,而不是像锤子一样砸下去。 这就是滚动落地的本质。 一、什么叫“滚动落地”? 你可以把它理解成两种完全不同的落地方式: 1. 砸地(撞击式) 脚像锤子一样拍到地上: * 要么后跟先砸 * 要么前掌先戳 * 冲击集中在一个点 * 一个结构瞬间吃掉大部分载荷 结果就是: * 后跟砸 → 膝盖难受 * 前掌戳 → 前脚掌磨烂 * 都不是长跑友好模式 这叫 撞击式着地(impact strike)。 2. 滚地(滚动式) 脚像轮胎一样“滚”过地面: * 不是某一点硬砸 * 而是外侧中足先轻触 * 再向前滚到前掌 * 最后从大脚趾蹬离

By SHI XIAOLONG

AMI的优越性

世界模型(World Models)的具体例子 如下,我按类型分类,便于理解。每类都附带实际实现、演示效果和应用场景。 1. Yann LeCun / Meta 的 JEPA 系列(最直接对应“世界模型”概念) 这些是 LeCun 主张的非生成式抽象预测世界模型代表。 * I-JEPA(Image JEPA,2023) 输入一张图像,模型把不同区域(context 和 target)编码成抽象表示,然后预测 target 的表示(不在像素级别重建)。 例子:给定一张遮挡了部分物体的图片,模型能预测“被遮挡物体的大致位置和属性”,构建对物体持久性和空间关系的理解。 这是一个“原始世界模型”,能学习物理常识(如物体不会凭空消失)。 * V-JEPA / V-JEPA 2(Video JEPA,

By SHI XIAOLONG

什么是:“世界模型(World Models)”

世界模型(World Models) 是人工智能领域的一个核心概念,尤其在 Yann LeCun 等研究者推动的下一代 AI 架构中占据中心位置。它指的是 AI 系统在内部构建的对现实世界的抽象模拟或内部表示,让机器能够像人类或动物一样“理解”物理世界、预测未来、规划行动。 简单比喻 想象你闭上眼睛也能“看到”房间里的物体会如何移动、碰撞或掉落——这就是你大脑里的世界模型。AI 的世界模型就是类似的“数字孪生”(digital twin)或“内部模拟器”:它不是简单记住数据,而是学习世界的动态、因果关系和物理直觉(如重力、物体持久性、遮挡、因果等)。 为什么需要世界模型? 当前主流的大型语言模型(LLM) 擅长处理文本(统计模式预测),但存在根本局限: * 缺乏对物理世界的真正理解 → 容易“幻觉”、无法可靠规划。 * 样本效率低 → 人类/

By SHI XIAOLONG

K线周期可配置化设计方案

K线周期可配置化设计方案 1. 背景与目标 当前 Beta 套利策略的 K 线周期硬编码为 "1h",分散在多个文件中。需要: 1. 将 K 线周期从 1h 改为 2h 2. 提取为环境变量 BETA_ARB_KLINE_INTERVAL,使其可在 .env 中配置 2. 影响范围分析 2.1 需要修改的文件(共 6 个) 文件 硬编码位置 修改内容 src/trading/config.py BetaArbConfig dataclass 新增 kline_interval 字段,

By SHI XIAOLONG