P(trending) 算法原理说明

P(trending) 算法原理说明

1. 概述

P(trending) 是 BOCPD(贝叶斯在线变点检测)的核心输出,表示"当前市场处于趋势状态"的概率。当 P(trending) > 0.8 时,动量过滤器在 Layer0 硬拦截开仓信号。

总公式

P(trending) = Σ P(r) × P(trending | r)

含义:对每个可能的 run length r,分别计算"该 regime 是否有趋势"的概率,然后按 r 自身的概率加权求和。

这个计算同时处理了两层不确定性:

  1. 变点在哪?(不确定 run length)→ 用 P(r) 加权
  2. 给定变点位置,漂移是否显著?(不确定均值大小)→ 用后验分布的尾部面积

2. 计算流程

2.1 总体结构

def trend_probability(self) -> float:
    delta = self._drift_threshold          # 0.0005(0.05%/5min)
    total = 0.0
    for i in range(len(self._log_probs)):
        prob = P(r=i)                      # 第一层:run length 的概率
        p_trend = P(trending | r=i)        # 第二层:该 run length 下的趋势概率
        total += prob * p_trend            # 加权累加
    return total

以下逐步展开每一层的计算。


3. 第一层:P(r) — run length 的概率

3.1 什么是 run length

run length r 表示"距离上一个变点已经过了多少根 K 线"。算法同时维护 r=0, 1, 2, ..., 59,每个 r 都有一个概率 P(r),所有概率之和为 1。

P(r=0) = 0.05   "刚刚发生了变点"
P(r=1) = 0.60   "当前 regime 持续了 1 根 K 线"  ← MAP(最大后验)
P(r=2) = 0.15   "当前 regime 持续了 2 根 K 线"
P(r=5) = 0.10   "当前 regime 持续了 5 根 K 线"
...

3.2 P(r) 的更新机制

每收到一根新 K 线,P(r) 通过两个路径更新:

增长路径(没有发生变点,r 加 1):

P_new(r+1) ∝ P_old(r) × π(x|r) × (1 - H)

变点路径(发生了变点,r 重置为 0):

P_new(r=0) ∝ Σ_r [ P_old(r) × π(x|r) × H ]

其中:

  • π(x|r) 是 run length r 对当前观测 x 的预测概率(似然)
  • H = 0.05 是变点先验概率(hazard rate)
  • 更新后归一化使所有 P(r) 之和为 1

4. 第二层:P(trending | r) — 给定 run length 下的趋势概率

这是 P(trending) 计算的核心。对每个 r,需要回答:"如果当前 regime 从 r 根 K 线前开始,那这段时间的数据是否表现出显著的趋势?"

4.1 μ_r 的后验分布

对 run length r,贝叶斯更新后得到 NIG 后验参数 (μ_r, κ_r, α_r, β_r)。其中 μ_r(均值的点估计)的真实值不是一个确定的数,而是服从 Student-t 分布:

μ_r 的真实值 ~ Student-t(df=2α_r, center=μ_r, scale=√(β_r/(α_r·κ_r)))

三个参数的含义:

参数 公式 含义 数据越多时
center(中心) μ_r 均值的最佳猜测 越接近真实均值
scale(尺度) √(β_r/(α_r·κ_r)) 猜测的不确定性 越小(越自信)
df(自由度) 2α_r 分布的厚尾程度 越大(越接近正态)

4.2 后验分布随数据量的变化

r=1(1 个观测)

κ₁ = 2, α₁ = 3.5, scale 较大, df = 7
→ 分布宽且厚尾,不确定性大
        ┌───────────────────────┐
       ╱                         ╲
     ╱                             ╲
   ╱                                 ╲
──╱───────────────────────────────────╲──
                  μ₁
         ←── scale 大,分布宽 ──→

r=30(30 个观测)

κ₃₀ = 31, α₃₀ = 18, scale 较小, df = 36
→ 分布窄且接近正态,不确定性小
              ┌───┐
             ╱│   │╲
           ╱  │   │  ╲
         ╱    │   │    ╲
────────╱─────│───│─────╲────────
              μ₃₀
         ←scale 小→

4.3 P(trending | r) 的计算

定义:μ 的真实值落在"无趋势区间" [-δ, +δ] 之外的概率(δ = drift_threshold = 0.0005)。

P(trending | r) = P(μ真实 > +δ) + P(μ真实 < -δ)
               = 右尾面积 + 左尾面积

图示:

                无趋势区间
                ┃←──────→┃
                ┃        ┃
      ┌─────────┃────────┃─────────┐
     ╱  左尾    ┃        ┃  右尾    ╲
    ╱ (下跌趋势)┃ (噪声) ┃(上涨趋势) ╲
──╱─────────────┃────────┃───────────╲──
           -0.0005    +0.0005
                ┃        ┃

P(trending|r) = 左尾面积 + 右尾面积
              = 阴影部分的总面积

代码实现

# 将 ±δ 转换为 Student-t 分布上的标准化位置
t_upper = (delta - mu) / scale       # +0.0005 的位置
t_lower = (-delta - mu) / scale      # -0.0005 的位置

# 计算尾部面积
p_trend = (1.0 - CDF(t_upper))      # 右尾:P(μ真实 > +δ)
        + CDF(t_lower)               # 左尾:P(μ真实 < -δ)

4.4 不同场景下的 P(trending | r)

场景 A:数据少,观测极端(r=1, μ=-0.004, scale=0.0027)

t_upper = (0.0005 - (-0.004)) / 0.0027 = 1.67
t_lower = (-0.0005 - (-0.004)) / 0.0027 = 1.30

P(trending|r=1) = (1 - CDF(1.67)) + CDF(1.30)
                ≈ 0.07 + 0.87 = 0.94

→ 94%。观测值太极端(-0.8%),即使只有 1 个数据点,
  后验分布大部分面积也在无趋势区间之外。
                   -δ    +δ
                    ┃    ┃
    ████████████████┃    ┃███
   ╱████████████████┃    ┃███╲
  ╱█████████████████┃    ┃████╲
─╱──────────────────┃────┃─────╲─
               μ₁=-0.004
     大部分面积在 -δ 左边(下跌趋势)

场景 B:数据多,均值显著(r=30, μ=-0.001, scale=0.0003)

t_upper = (0.0005 - (-0.001)) / 0.0003 = 5.0
t_lower = (-0.0005 - (-0.001)) / 0.0003 = -1.67

P(trending|r=30) = (1 - CDF(5.0)) + CDF(-1.67)
                 ≈ 0.00 + 0.95 = 0.95

→ 95%。均值只有 -0.1%,但 scale 极小(0.03%),
  算法非常自信真实均值在无趋势区间之外。
                        -δ    +δ
                         ┃    ┃
                  ████████┃    ┃
                 ╱████████┃    ┃
                ╱█████████┃    ┃
──────────────╱───────────┃────┃──
              μ₃₀=-0.001
  分布窄,几乎全部面积在 -δ 左边

场景 C:数据中等,均值不明显(r=20, μ=-0.0003, scale=0.0004)

t_upper = (0.0005 - (-0.0003)) / 0.0004 = 2.0
t_lower = (-0.0005 - (-0.0003)) / 0.0004 = -0.5

P(trending|r=20) = (1 - CDF(2.0)) + CDF(-0.5)
                 ≈ 0.03 + 0.31 = 0.34

→ 34%。均值接近 0,不确定性中等,
  大部分面积在无趋势区间之内。
                   -δ         +δ
                    ┃         ┃
              ██████┃─────────┃██████
             ╱██████┃         ┃██████╲
           ╱████████┃         ┃████████╲
─────────╱──────────┃─────────┃──────────╲──
                μ₂₀=-0.0003
  分布中等宽度,大部分面积在无趋势区间之内

场景 D:数据多,均值接近零(r=40, μ=-0.00005, scale=0.0002)

t_upper = (0.0005 - (-0.00005)) / 0.0002 = 2.775
t_lower = (-0.0005 - (-0.00005)) / 0.0002 = -2.225

P(trending|r=40) = (1 - CDF(2.775)) + CDF(-2.225)
                 ≈ 0.004 + 0.015 = 0.019

→ 1.9%。均值几乎为零,且分布很窄,
  算法自信地判定没有趋势。

5. 第三层:加权求和

将所有 r 的结果汇总:

P(trending) = Σ P(r) × P(trending | r)

5.1 完整数值示例

r P(r) μ_r scale P(trending|r) 贡献
0 5% 0.0000 50%(先验) 0.025
1 60% -0.0040 0.0027 94% 0.564
5 15% -0.0025 0.0015 88% 0.132
20 8% -0.0003 0.0004 34% 0.027
30 10% -0.0010 0.0003 95% 0.095
其他 2% ... ... ... 0.010
合计 100% 0.853

P(trending) = 0.853 > 0.8 → 触发拦截

5.2 各 r 的贡献分析

从上面的例子可以看出:

  • r=1 贡献了 0.564(占总值的 66%):概率最高且 P(trending|r) 也高,主导了结果
  • r=5 贡献了 0.132(15%):次要贡献
  • r=30 贡献了 0.095(11%):虽然概率不高(10%),但 P(trending|r) 很高(95%)
  • r=20 贡献了 0.027(3%):均值不明显,P(trending|r) 低,贡献小

6. drift_threshold 的作用

drift_threshold = 0.0005(每根 5m K 线 0.05%)是"有经济意义的最小漂移"。

6.1 为什么需要这个阈值

如果没有阈值(δ=0),那么问题变成"μ 是否恰好等于 0"。在连续分布下,P(μ=0) 永远是 0,所以 P(trending) 永远是 100%——这没有意义。

δ=0.0005 定义了一个"噪声带":收益率在 ±0.05% 以内视为正常波动,只有超出这个范围才算有趋势。

6.2 阈值对结果的影响

drift_threshold 效果
太小(如 0.00001) 几乎任何微小漂移都算趋势,P(trending) 持续偏高,频繁误拦截
合适(0.0005) 过滤掉正常波动,只捕捉有意义的趋势
太大(如 0.01) 只有极端趋势才触发,失去保护作用

7. 与 drift_mean 的区别

drift_mean P(trending)
公式 Σ P(r) × μ_r Σ P(r) × P(|μ_r| > δ | 后验)
输出 一个数值(有方向和大小) 一个概率(0~1)
考虑不确定性 否,直接用点估计 μ_r 是,用 μ_r 的完整后验分布
用途 诊断信息:趋势方向和强度 决策依据:是否拦截

关键区别:drift_mean 可能因为少量数据下 μ_r 的噪声而偏大,但 P(trending) 会通过后验分布的宽度(scale)自动降权——数据少时 scale 大,P(trending|r) 不会盲目偏高。

示例:r=1 只有 1 个观测 x=-0.002

  • drift_mean 的贡献:P(r=1) × μ₁ = 0.6 × (-0.001) = -0.0006(看起来有趋势)
  • P(trending|r=1):后验分布宽,μ 在 ±0.0005 内的概率不低 → P(trending|r=1) 可能只有 60%
  • P(trending) 的贡献:0.6 × 0.6 = 0.36(被不确定性压低了)

8. Student-t CDF 的近似实现

P(trending|r) 的计算依赖 Student-t 分布的 CDF。代码中使用两种近似:

df < 30 时:正则化不完全 Beta 函数的连分数展开

p = t² / (df + t²)
# 然后用连分数近似计算 I_p(df/2, 1/2)

df >= 30 时:正态近似(Abramowitz & Stegun 多项式逼近)

z = t × (1 - 1/(4·df)) / √(1 + t²/(2·df))
# 然后用正态 CDF 的多项式近似

这使得整个计算无需依赖 scipy 等外部库,适合在线实时环境。


9. 完整代码注释版

@property
def trend_probability(self) -> float:
    delta = self._drift_threshold                    # 0.0005

    total = 0.0
    for i in range(len(self._log_probs)):
        # ── 第一层:P(r=i) ──
        prob = math.exp(self._log_probs[i])
        if prob < 1e-8:                              # 概率太小,跳过
            continue

        # ── 第二层:构建 μ 的后验 Student-t 分布 ──
        mu, kappa, alpha, beta = self._suff[i]
        df = 2 * alpha                               # 自由度
        scale = math.sqrt(beta / (alpha * kappa))     # 不确定性尺度

        # ── 第二层:计算 P(trending | r=i) ──
        # 将 ±delta 转换为 Student-t 分布上的标准化坐标
        t_upper = (delta - mu) / scale               # +δ 的位置
        t_lower = (-delta - mu) / scale              # -δ 的位置

        # 尾部面积 = P(μ真实 > +δ) + P(μ真实 < -δ)
        p_trend = (1.0 - _student_t_cdf(t_upper, df)   # 右尾
                   + _student_t_cdf(t_lower, df))        # 左尾

        # ── 加权累加 ──
        total += prob * p_trend

    return min(1.0, max(0.0, total))

10. 算法特性总结

特性 说明
双层不确定性建模 同时处理"变点在哪"和"均值是否显著"两个不确定性
自适应置信度 数据少时后验宽(保守判断),数据多时后验窄(自信判断)
概率输出 输出连续概率而非二值判断,便于与阈值比较和跨层共享
无外部依赖 Student-t CDF 用连分数/正态近似实现,无需 scipy
在线计算 每根 K 线更新复杂度 O(R),R=60,适合实时系统
经济意义 drift_threshold 保证只检测有交易意义的趋势,过滤噪声

Read more

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

对于空间环境、“信息/逻辑”(比如代码、结构、表达)秩序追求的心理特征分析

一、为什么是“空间 + 信息”同时强化? 因为你当年面对的是“双重失控”: 1️⃣ 外部世界是脏乱 + 失序的 * 空间被污染 * 行为无边界 * 基本生活秩序崩塌 👉 所以你现在会强烈要求: * 桌面干净 * 房间有序 * 物品可控 这是在修复:“物理世界必须是可控的” 2️⃣ 人的行为和逻辑也是混乱的 * 没有规则 * 没有底线 * 没有理性 👉 所以你现在会特别在意: * 表达是否清晰 * 逻辑是否自洽 * 结构是否优雅 * 代码是否干净 这是在修复:“认知世界必须是合理的” 二、你其实构建了一个“高纯度系统” 你现在的偏好,本质上是: 👉 低噪音 + 高结构 + 强控制感 具体表现就是: * 空间:极简、整洁、可预测 * 信息:清晰、压缩、无冗余 这类人有一个很明显的优势: 👉 处理复杂问题时,

By SHI XIAOLONG