Files
cbpred/docs/v1_0823.md
2026-08-23 14:30:20 +08:00

13 KiB
Raw Permalink Blame History

历史实验记录:本文保留 v1 特征复核过程。当前运行入口、正式模型和最新指标以 README.md、usage.md 和 model.md 为准。

我考虑下进行下面的尝试:

  1. 每个K线提取8个信息,其中冗余的不少,尝试压缩下;只要下降不是很多就可以保留。
  2. RSI和SMA等指标的特征考虑下进行加入对比
  3. 加入K线对应的全局概要特征,代表市场整体行情特征,这里要注意提取方式,尽量不要特别多,应该是几个数字指标代表
  4. 加入当前品种当前K线在全局的横向特征,比如涨跌幅排名,成交量排名,或者价格等其他信息,注意进行归一化确保不同品种可比

以当前的最新模型作为基线对比模型。 继续使用当前的模型ExtraTrees,然后逐个尝试上面的改动,进行模型训练,然后和基线对比,如果有变好的保留,没有变好的忽略。

分析优化尝试结果

已完成特征实验,并保留表现最好的 compact6 模型。

正式 20 棵树对比结果:

模型 特征数 测试 MAE 测试 RMSE ━━━━━━━━━━ ━━━━━━━━ ━━━━━━━━━━ ━━━━━━━━━━━ 基线 182 0.025140 0.033789 ────────── ──────── ────────── ─────────── compact6 146 0.024918 0.033563

compact6 相比基线:

  • MAE 下降约 0.88%
  • RMSE 下降约 0.67%
  • q80 覆盖率:77.50%
  • q20 下界命中率:91.60%

最终保留的特征包括:

  • 每根K线:有符号实体比例、上下影线比例、收盘位置、振幅比例、对数收益
  • 最近18根K线的法币成交量排名及相对成交量
  • 品种独有特征:训练期 ATR/价格前20%中位数、成交量前20%中位数

未保留:

  • RSI/SMA、布林带、趋势指标组合:没有稳定改善
  • 全局市场概要特征:表现变差
  • 横向排名特征:筛选阶段略有改善,但正式复核弱于 compact6

模型文件:

artifacts/v1/model.joblib

artifacts/v1/report.md

未保留部分详细分析

先说明结论:这些实验验证的是“当前这套构造方式”,不能证明 RSI、全局行情或横向排名本身无效。尤其 RSI/ SMA 只做了筛选实验,没有在最终 20 棵树配置下全部复核,因此结论需要保留一定谨慎。

一、指标类特征

指标全部在 cbpred/pipeline.py:419 的 compute_indicators() 中计算。

基线每个样本包含:

  • 最近18根K线
  • 每根K线8个基础特征
  • 每根K线2个成交量特征
  • 2个品种独有特征

所以基线是:

18 × (8 + 2) + 2 = 182个特征

指标实验不是只加入当前K线的指标,而是把指标复制到最近18根K线中的每一根。

1. RSI + SMA

对应 rsi_sma,每根K线加入3个特征:

rsi_norm sma20_gap sma50_gap

总特征数:

182 + 18 × 3 = 236

具体定义:

true_range = max( high - low, abs(high - previous_close), abs(low - previous_close) )

ATR14 = EWMA(true_range, alpha=1/14)

RSI使用上涨和下跌幅度的EWMA:

gain = EWMA(max(close_t - close_(t-1), 0)) loss = EWMA(max(close_(t-1) - close_t, 0))

RSI = 100 - 100 / (1 + gain / loss) rsi_norm = RSI / 100

代码中对极端情况做了处理:

  • 没有下跌时,rsi_norm = 1
  • 没有上涨也没有下跌时,rsi_norm = 0.5

SMA特征不是直接放均线价格,而是价格相对均线的距离:

sma20_gap = close / SMA20 - 1 sma50_gap = close / SMA50 - 1

然后裁剪到 [-2, 2]。

因此它们是无量纲特征,不会直接受到BTC价格是几万美元、某些山寨币价格只有几美分的影响。

2. RSI + 布林带

对应 rsi_bbands,每根K线加入:

rsi_norm bb_position bb_width

总特征数也是236。

布林带使用20根K线:

SMA20 = 20根收盘价平均值 std20 = 20根收盘价标准差

布林位置:

bb_position = (close - SMA20) / (2 × std20)

裁剪到 [-5, 5]。

布林带宽度:

bb_width = 4 × std20 / SMA20

裁剪到 [0, 5]。

所以:

  • bb_position 表示当前价格在布林带中的相对位置
  • bb_width 表示当前波动带宽度
  • 二者都不是绝对价格,具备跨品种可比性

3. RSI + 趋势和波动

对应 rsi_trend,每根K线加入:

rsi_norm trend_3 trend_9 volatility_18

总特征数:

182 + 18 × 4 = 254

定义为:

trend_3 = close / close_(t-3) - 1 trend_9 = close / close_(t-9) - 1 volatility_18 = 18根log_return的标准差

trend_3 和 trend_9 都裁剪到 [-2, 2],volatility_18 裁剪到 [0, 2]。

4. 完整指标组

对应 full_indicators,每根K线加入11个指标:

atr_pct atr_rank_200 rsi_norm bb_position bb_width ema9_gap ema21_gap trend_3 trend_9 volatility_18 drawdown_18

总特征数:

182 + 18 × 11 = 380

其中:

atr_pct = ATR14 / close atr_rank_200 = 当前ATR在过去200根ATR中的百分位排名

ema9_gap = close / EMA9 - 1 ema21_gap = close / EMA21 - 1

drawdown_18 = close / 最近18根最高收盘价 - 1

atr_rank_200 是 [0, 1] 的百分位排名,其他价格指标基本都是比例或收益率。

指标构造中可能存在的问题

这里最值得注意的是:虽然这些指标是无量纲的,但不一定进行了“波动率归一化”。

例如:

sma20_gap = 0.02

对高波动品种可能只是普通波动,但对低波动品种可能已经是非常大的偏离。当前没有进一步计算:

sma20_gap / 当前品种局部ATR trend_9 / 当前品种局部ATR

另外:

  • RSI、SMA偏离、EMA偏离、趋势收益本质上有较多信息重叠
  • 所有指标被复制到18根K线,特征数量快速增加
  • atr_pct 是品种自身的比例,但没有除以该品种的长期ATR基准
  • bb_position 在极低波动时容易变得不稳定,只是通过裁剪限制了极端值
  • 没有加入指标的变化速度,例如 RSI斜率、布林带宽度变化、ATR变化方向

筛选报告中结果如下,分数越低越好:

方案 相对基线变化 ━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━ RSI + SMA -0.00000288 ──────────────── ────────────── RSI + 布林带 +0.00011975 ──────────────── ────────────── RSI + 趋势波动 +0.00025359 ──────────────── ────────────── 完整指标组 +0.00032006

因此,只有 RSI+SMA 是非常微小的改善,其他指标组合都变差。这里的筛选实验使用64棵树,不能把这个结果解释 成 RSI/SMA 已经被充分验证。

二、全局市场概要特征

全局特征在 cbpred/experiments.py:168 到 cbpred/experiments.py:216 中计算。

首先,对每个品种、每个时间戳生成:

return_1 = 当前log收益 trend_3 = 3根K线收益 atr_pct = ATR14 / close body_sign = sign(close - open) quote_activity = log1p(成交额) - 该品种历史成交额前20%中位数

然后按照相同时间戳,把所有品种横向聚合成6个全局数字:

global_median_return_1 global_median_trend_3 global_median_atr_pct global_return_dispersion global_up_ratio global_median_quote_activity

具体含义:

1. 全局中位数收益

global_median_return_1 = 所有品种当前1根K线log收益的中位数

代表市场当前整体涨跌方向。

2. 全局中位数短趋势

global_median_trend_3 = 所有品种当前3根K线收益的中位数

代表市场短线趋势。

3. 全局中位数ATR比例

global_median_atr_pct = 所有品种 ATR14 / close 的中位数

代表市场整体波动水平。

4. 全局收益离散度

global_return_dispersion = 所有品种当前1根K线收益的总体标准差

代表市场分化程度。数值越大,说明不同品种当前表现越不一致。

5. 全局上涨比例

global_up_ratio = 当前阳线品种数 / 有效品种总数

这里依据的是 close > open,不是收益率大于0。

6. 全局成交活跃度

单个品种的成交活跃度先计算为:

log1p(当前成交额)

  • 该品种训练期成交额前20%中位数的log值

然后取所有品种的中位数。

这个特征代表当前市场成交量相对于各品种自身高成交量基准的整体水平。

重要问题

全局6个数字只加入样本当前锚点,不会重复加入最近18根K线。

也就是说,样本结构是:

最近18根K线特征

  • 2个品种特征
  • 当前时刻6个全局特征

而不是:

最近18个时刻 × 6个全局特征

因此它只能告诉模型“现在市场是什么状态”,不能告诉模型“过去18根K线市场状态如何变化”。

此外:

  • 使用的是所有可用品种的简单中位数
  • 没有按成交量或市值加权
  • 没有单独加入BTC、ETH等主要品种的市场基准
  • 没有加入全市场上涨比例的变化趋势
  • 没有加入全局波动率变化趋势
  • 全局特征本身没有再做统一的z-score,只依赖其比例、标准差或相对成交量形式

全局特征实验结果:

global6 +0.00052393 global_cross +0.00033642

这说明当前这6个市场概要对目标没有提供有效增益,但不能说明全局特征思路本身错误。当前最大的问题可能 是“只取当前时刻一个横截面”,时间维度太弱。

三、当前品种横向排名特征

横向排名同样在 cbpred/experiments.py:168 中计算。

对每个时间戳,把所有品种进行横向排名,加入4个特征:

cross_return_1_rank cross_trend_3_rank cross_atr_pct_rank cross_quote_activity_rank

排名使用:

rank(method="average", pct=True)

因此结果大致位于 (0, 1]:

  • 越接近1:当前在全市场中越高
  • 越接近0:当前在全市场中越低
  • 相同值使用平均排名

具体为:

1. 当前收益排名

3. 当前波动率排名

cross_atr_pct_rank

当前品种ATR/价格在所有品种中的百分位排名。

4. 当前成交活跃度排名

cross_quote_activity_rank

当前品种相对自身历史高成交量基准的成交活跃度,在所有品种中的百分位排名。

这个方案只增加4个特征:

182 + 4 = 186

同样,它们只加入当前锚点,不会给最近18根K线都增加横向排名。

横向特征存在的限制

  1. 没有加入价格相关的横向特征

当前没有:

相对自身长期价格位置排名 相对历史高点距离排名 相对自身均线偏离排名

只加入了收益、趋势、波动率和成交活跃度排名。

  1. 横截面成员数量可能变化

某个时间戳上如果部分品种缺K线,排名实际是在较小的品种集合中计算的。这样不同时间的百分位含义可能不完全 一致。

  1. 可能受低流动性品种噪声影响

所有品种简单参与排名,没有按照流动性加权。大量低流动性品种可能影响整体排名分布。

  1. 依赖全品种数据

预测单个CSV时,无法还原完整横向排名。当前预测接口明确拒绝带有全局或横向依赖的模型,见 cbpred/ pipeline.py:1476。

这也是最终没有保留 cross4 的工程原因之一:即使它在部分筛选实验中略有改善,也无法直接用单个品种数据稳 定预测。

横向排名筛选阶段比基线略好,但正式20棵树复核中:

compact6: 0.15065802 cross4: 0.15065995

所以最终保留了 compact6。

综合判断

当前未保留特征中,最可能存在构造不足的地方按优先级是:

优先级 可能问题 判断 ━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━ 1 全局和横向特征只取当前时刻,没有形成18根K线的历史序列 高置信度 ──────── ─────────────────────────────────────────────────────── ──────────── 2 SMA、趋势、ATR没有进一步除以品种局部波动率 中高置信度 ──────── ─────────────────────────────────────────────────────── ──────────── 3 全局特征没有区分主要品种、低流动性品种和市场权重 中等置信度 ──────── ─────────────────────────────────────────────────────── ──────────── 4 横向排名的品种集合随时间变化 中等置信度 ──────── ─────────────────────────────────────────────────────── ──────────── 5 指标之间高度重复,增加了大量相似特征 高置信度

因此,本次结果更准确的表述是:

当前实现的指标、全局和横向特征没有带来稳定增益;其中全局和横向特征的时间组织方式明显偏简单,RSI/SMA 等指标也没有做局部波动率归一化。不能据此断言这些特征方向本身无效。