关于 opendeviation-eval-metrics
面向研究人员的开源偏差柱数据评估参考与脚本集,用于评估机器学习模型。它提供考虑非 IID 柱序列的指标计算和报告工具。
主要功能
- 01计算交易与预测指标
- 02按日聚合计算 Sharpe
- 03分析 Walk-Forward 各折结果
- 04生成 Markdown 评估报告
- 05验证指标数据结构
适用场景
- 01比较不同折的模型结果
- 02评估不定时长柱的 Sharpe
- 03检查预测质量与模型塌缩
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ terrylica/ cc-skills --skill opendeviation-eval-metrics安装后在 Claude Code 中输入/opendeviation-eval-metrics确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
requirements.txtreferences/anti-patterns.mdbeyond-hit-rate.mdcrypto-markets.mdevolution-log.mdmetrics-schema.mdml-prediction-quality.mdrisk-metrics.mdsharpe-formulas.mdsota-2025-2026.mdstructured-logging.mdtemporal-aggregation.mdworked-examples.mdscripts/compute_metrics.pycompute_metrics.test.ts详细介绍
开放偏差柱评估指标
用于评估开放偏差柱(ODB,基于最高价到最低价的价格采样)数据的先进指标的机器可读参考资料和计算脚本。
交叉参考:项目研究仓库中 signal-archaeology 技能的项目级实验目录,包含 10 项经过 BHR 验证且 SQL 可审计的实验。
自我演进的技能:此技能会在使用过程中不断改进。如果说明有误、参数发生漂移,或需要采用变通方法,请立即修复此文件,不要拖延。仅针对真实且可复现的问题进行更新。
何时使用此技能
在以下情况下使用此技能:
- 评估 ML 模型在开放偏差柱数据上的性能
- 使用非 IID 柱序列计算 Sharpe 比率
- 运行 Walk-Forward Optimization 指标分析
- 计算 PSR 或 MinTRL 统计检验
- 根据折结果生成评估报告
不进行试验次数校正(操作规则,2026-10-15):绝不计算、报告、据此排名或引用 Deflated Sharpe Ratio、最小回测长度(MinBTL)或任何其他试验次数校正(FWER/FDR 程序,例如 Holm 或 Benjamini-Yekutieli、e-LOND 及其他在线多重检验)。应根据模型本身判断简约性,在运行前进行注册,并使用未用过的数据来防范选择偏差,同时报告每项规则自身的统计数据(Sharpe、PSR、MinTRL)。这些内容是有意从此技能中移除的;不要重新添加。此规则不涵盖 PBO/CSCV。
快速入门
# Compute metrics from predictions + actuals
python scripts/compute_metrics.py --predictions preds.npy --actuals actuals.npy --timestamps ts.npy
# Generate full evaluation report
python scripts/generate_report.py --results folds.jsonl --output report.md
指标层级
| 层级 | 用途 | 指标 | 计算方式 |
|---|---|---|---|
| 主要(5) | 研究决策 | weekly_sharpe、hit_rate、cumulative_pnl、n_bars、positive_sharpe_rate | 按折计算 + 汇总 |
| 次要/风险(5) | 补充背景 | max_drawdown、bar_sharpe、return_per_bar、profit_factor、cv_fold_returns | 按折计算 |
| ML 质量(3) | 预测健康状况 | ic、prediction_autocorr、is_collapsed | 按折计算 |
| 诊断(4) | 最终验证 | psr、autocorr_lag1、effective_n、binomial_pvalue | 仅汇总 |
| 扩展风险(5) | 深度风险分析 | var_95、cvar_95、omega_ratio、sortino_ratio、ulcer_index | 按折计算(可选) |
为什么开放偏差柱需要特殊处理
开放偏差柱违反了标准 IID 假设:
- 时长可变:柱根据价格变动形成,而非按时间形成
- 自相关:高波动时期会聚集更多柱 → 时间相关性
- 信息量不恒定:波动时期每天产生更多柱 = 每天包含更多信息
标准解决方案:在计算 Sharpe 前,通过 _group_by_day() 按日聚合。
参考资料
核心参考文件
| 主题 | 参考文件 |
|---|---|
| 夏普比率计算 | sharpe-formulas.md |
| 风险指标(VaR、Omega、Ulcer) | risk-metrics.md |
| ML 预测质量(IC、自相关) | ml-prediction-quality.md |
| 加密货币市场注意事项 | crypto-markets.md |
| 时间聚合规则 | temporal-aggregation.md |
| 指标的 JSON Schema | metrics-schema.md |
| 反模式(交易成本) | anti-patterns.md |
| SOTA 2025-2026(SHAP、BOCPD 等) | sota-2025-2026.md |
| 超越命中率(BHR)框架 | beyond-hit-rate.md |
| 实例(BTC、EUR/USD) | worked-examples.md |
| 结构化日志(NDJSON) | structured-logging.md |
相关技能
| 技能 | 关联说明 |
|---|---|
| sharpe-ratio-non-iid-corrections | ρ 校正的 PSR、MinTRL、检验功效 — 完整的非 IID 单次检验框架 |
| adaptive-wfo-epoch | 使用 weekly_sharpe、psr 计算 WFE |
依赖项
pip install -r requirements.txt
# Or: pip install numpy>=1.24 pandas>=2.0 scipy>=1.10
关键公式
日度聚合夏普比率(主要指标)
def weekly_sharpe(pnl: np.ndarray, timestamps: np.ndarray) -> float:
"""Sharpe with daily aggregation for open deviation bars."""
daily_pnl = _group_by_day(pnl, timestamps) # Sum PnL per calendar day
if len(daily_pnl) < 2 or np.std(daily_pnl) == 0:
return 0.0
daily_sharpe = np.mean(daily_pnl) / np.std(daily_pnl)
# For crypto (7-day week): sqrt(7). For equities: sqrt(5)
return daily_sharpe * np.sqrt(7) # Crypto default
信息系数(预测质量)
from scipy.stats import spearmanr
def information_coefficient(predictions: np.ndarray, actuals: np.ndarray) -> float:
"""Spearman rank IC - captures magnitude alignment."""
ic, _ = spearmanr(predictions, actuals)
return ic # Range: [-1, 1]. >0.02 acceptable, >0.05 good, >0.10 excellent
概率夏普比率(统计验证)
from scipy.stats import norm
def psr(sharpe: float, se: float, benchmark: float = 0.0) -> float:
"""P(true Sharpe > benchmark)."""
return norm.cdf((sharpe - benchmark) / se)
年化系数
| 市场 | 日度 → 周度 | 日度 → 年度 | 原因 |
|---|---|---|---|
| 加密货币(24/7) | sqrt(7) = 2.65 | sqrt(365) = 19.1 | 每周 7 个交易日 |
| 股票 | sqrt(5) = 2.24 | sqrt(252) = 15.9 | 每周 5 个交易日 |
加密货币市场绝不可使用 sqrt(252)。
关键:交易时段筛选会改变年化系数
| 视图 | 筛选条件 | days_per_week | 原因 |
|---|---|---|---|
| 按时段筛选(伦敦-纽约) | 工作日 08:00-16:00 | sqrt(5) | 类似股票交易 |
| 全部数据条(未筛选) | 无 | sqrt(7) | 加密货币全天候交易 |
对按时段筛选的数据使用 sqrt(7),会使夏普比率高估约 18%!
详细原因请参阅 crypto-markets.md。
双视图指标
如需全面分析,请使用以下两种视图计算指标:
- 按时段筛选(伦敦 08:00 至纽约 16:00):用于主要策略评估
- 全部数据条:用于市场状态检测和数据质量诊断
学术参考文献
| 概念 | 引用 |
|---|---|
| 概率夏普比率 | Bailey & López de Prado (2012) |
| 非正态分布下的夏普比率标准误 | Mertens (2002) |
| 夏普比率统计 | Lo (2002) |
| 欧米伽比率 | Keating & Shadwick (2002) |
| 溃疡指数 | Peter Martin (1987) |
超越命中率(BHR)框架
命中率是必要但不充分的指标。 务必补充结果可预测性指标。完整框架请参阅 beyond-hit-rate.md。
最低可行信号评估
每个信号都必须至少通过以下评估:
- 一项序列结构检验:对 W/L 序列进行熵、LZC 或游程检验
- 一项时间衰减检验:对权益曲线或滚动命中率进行 CUSUM 检验
- 一项市场状态感知检验:按交易时段统计命中率,或进行 HMM 分解
通过全部三项检验的信号具有稳健性。只有高命中率的信号只是噪声。
结果可预测性指数(OPI)
OPI = 0.25 * (1 - LZC_norm) + 0.25 * |z_runs| + 0.25 * Var(HR_per_regime) + 0.25 * AUC_meta
OPI 越高 = 胜负时机越可预测。OPI=0.8、命中率为 45% 的信号,比 OPI=0.1、命中率为 65% 的信号更有价值。
决策框架
研究准入标准
go_criteria:
- positive_sharpe_rate > 0.55
- mean_weekly_sharpe > 0
- cv_fold_returns < 1.5
- bhr_sequence_test_passes: true # At least one of: entropy, LZC, runs test significant
- bhr_cusum_verdict: "ALIVE" # No recent regime break
发布标准
publication_criteria:
- binomial_pvalue < 0.05
- psr > 0.85
- registered_before_run: true # Hypothesis, rule and window fixed before results were seen
- confirmed_on_unused_data: true # Holdout no run or selection step has touched
- bhr_lzc_shuffle_z < -2.0 # W/L sequence has genuine structure
- bhr_alpha_halflife > 200 # Edge persists for 200+ trades
脚本
| 脚本 | 用途 |
|---|---|
scripts/compute_metrics.py | 根据预测值/实际值计算所有指标 |
scripts/generate_report.py | 根据折叠结果生成 Markdown 报告 |
scripts/validate_schema.py | 根据架构验证指标 JSON |
修正措施(2026-01-19 多 Agent 审计)
根据 12 个子 Agent 的对抗性审计,已应用以下修复:
| 问题 | 根本原因 | 修复 | 来源 |
|---|---|---|---|
weekly_sharpe=0 | 预测值恒定 | 模型崩溃检测 + 架构修复 | model-expert |
IC=None | 预测值方差为零 | 对恒定预测值返回 1.0(语义正确) | model-expert |
prediction_autocorr=NaN | 除以零 | 对 std < 1e-10 进行保护,返回 1.0 | model-expert |
| 溃疡指数除以零 | 峰值权益 = 0 | 使用 np.where(peak > 1e-10, ...) 进行保护 | risk-analyst |
| 欧米伽比率/利润因子不可靠 | 样本过少 | min_days 参数(默认值:5) | robustness-analyst |
| BiLSTM 均值崩溃 | 架构过小 | hidden_size:16→48,dropout:0.5→0.3 | model-expert |
profit_factor=1.0 (n_bars=0) | 提前返回了错误值 | 没有可用于计算比率的数据时返回 NaN | risk-analyst |
模型崩溃检测
# ALWAYS check for model collapse after prediction
pred_std = np.std(predictions)
if pred_std < 1e-6:
logger.warning(
f"Constant predictions detected (std={pred_std:.2e}). "
"Model collapsed to mean - check architecture."
)
推荐的 BiLSTM 架构
# BEFORE (causes collapse on open deviation bars)
HIDDEN_SIZE = 16
DROPOUT = 0.5
# AFTER (prevents collapse)
HIDDEN_SIZE = 48 # Triple capacity
DROPOUT = 0.3 # Less aggressive regularization
完整实现细节请参阅参考文档。
故障排除
| 问题 | 原因 | 解决方案 |
|---|---|---|
| weekly_sharpe 为 0 | 预测值恒定 | 检查模型是否发生坍塌,并增大 hidden_size |
| IC 返回 None | 预测值的方差为 0 | 模型已坍塌——检查架构 |
| prediction_autocorr 为 NaN | 除以零 | 在自相关计算中加入 std < 1e-10 的保护 |
| Ulcer Index 除法错误 | 峰值权益为零 | 添加保护:np.where(peak > 1e-10, ...) |
| profit_factor = 1.0 | 未处理任何柱 | 当 n_bars 为 0 时返回 NaN |
| 夏普比率虚高 18% | 数据的年化方式错误 | 时段筛选数据使用 sqrt(5),全天候数据使用 sqrt(7) |
| 未计算 PSR | 缺少 scipy | 安装:pip install scipy |
| 未解析时间戳 | 格式错误 | 确保使用 Unix 时间戳,而不是 datetime 字符串 |
执行后检查
此技能执行完毕后,在结束前检查:
- 命令是否成功? — 如果没有,请修正导致失败的指令或错误表。
- 参数或输出是否发生变化? — 如果底层工具的接口发生变化,请相应更新 Usage 示例和 Parameters 表。
- 是否需要变通处理? — 如果你必须临时采用其他方法(不同的标志、额外步骤),请更新此 SKILL.md,避免下次调用时需要采用相同的变通方法。
仅在问题真实且可复现时更新,不要根据猜测更新。