优化点

  • 任何里面涉及大量计算的可以考虑并行或者专门优化的库

研究prompt

  - 研究主题
  - 正式时间窗
  - Train/Test/Backtest/Holdout 切分想法
  - Universe
  - 数据源
    
 
 
 
 

研究课题

前基于以下因子假设产生了一些因子假设:
 
- BTC 是主导风险因子
- ALT 存在“滞后跟随”
- 下跌期联动更强
- 偏离过大会回归
- 下跌期波动放大可能破坏均值回归
 
可能的因子思路:
 
- 同向率
- 上涨同向
- 下跌同向
- 上涨反向
- 下跌反向
- 补涨
- 补跌
- 超涨
- 超跌

AI拆解

 
## 一句话版本
 
  先拆市场机制,再把机制压缩成可证伪的问题;先做最小闭
  环,再逐层增加复杂度。
 
  ———
 
  ## 我通常怎么拆
 
  ### 1. 先拆“市场在发生什么”,不是先拆指标
 
  我会先问 5 个问题:
 
  1. 谁是主导因子
     例如这里是 BTC。
  2. 关系是什么
     是同步、滞后、偏离、回归,还是趋势延续。
  3. 触发条件是什么
     什么情况下这种关系最明显。
  4. 破坏条件是什么
     什么情况下原假设会失效。
     例如高波动、下跌恐慌、流动性塌陷。
  5. 这件事最终能不能交易
     即使统计上成立,也可能因为费用、换手、容量而不可做。
 
  你给的那组假设,其实天然就能拆成这 5 层。
 
  ———
 
  ### 2. 把叙事假设变成“可证伪命题”
 
  研究不能停留在“我感觉会这样”。
 
  我会把每个想法改写成这种形式:
 
  - 如果 ALT 相对 BTC 出现极端正偏离,那么未来相对收益应
    更偏负。
  - 如果 ALT 相对 BTC 出现极端负偏离,那么未来相对收益应
    更偏正。
  - 如果处于下跌/高波动状态,上面的关系可能减弱或失效。
 
  这样做的目的,是让每个命题都可以被数据推翻,而不是永远
  解释得通。
 
  ———
 
  ### 3. 把候选思路分层,而不是混在一起
 
  我会把想法分成 4 类:
 
  - 主信号
    这是你真正要验证的核心机制。
    这里就是“超涨 / 超跌”。
  - 条件变量
    决定主信号在什么环境下更强或更弱。
    例如下跌期联动、高波动。
  - 过滤器
    不是产生方向,而是筛掉不适合做的样本。
    例如低覆盖、低可用率、低显著性。
  - 执行参数
    入场、出场、止损、持有期、费用模型。
 
  很多研究失败,不是因为假设错,而是把这 4 层混在一起了。
 
  ———
 
  ### 4. 第一条研究线一定选“最小闭环”
 
  面对很多候选方向时,我不会一上来全做,而是先选一条:
 
  - 最容易形式化
  - 最容易证伪
  - 自由度最少
  - 样本最充足
  - 不依赖太多额外条件
 
  所以在你这组想法里,先做“超涨 / 超跌”是合理的。
 
  因为它直接对应“偏离过大会回归”,定义清楚,闭环完整:
 
  - 先定义相对 BTC 的偏离
  - 再定义极端状态
  - 再看未来相对收益是否回归
 
  而“补涨 / 补跌”或“滞后跟随”通常更复杂,因为它们先要解
  决“谁先动、滞后多久、怎么定义传导”。
  
  ### 5. 先定义研究对象,再算结果
 
  我会先冻结这些东西:
 
  - 基准是谁
  - Universe 是谁
  - 时间标签是什么
  - future return 怎么定义
  - horizon 怎么选
  - 哪些变量属于主信号,哪些属于条件变量
 
  如果这些不先冻结,后面所有结果都可能只是“调出来的”。
 
  ———
 
  ### 6. 研究顺序必须分阶段
 
  我的原则是每个阶段只回答一个问题:
 
  - Mandate
    研究什么,不研究什么。
  - Data
    数据能不能研究。
  - Signal
    信号到底是什么。
  - Train
    只定尺子,不宣布成功。
  - Test
    只验证结构,不做收益优化。
  - Backtest
    只检验冻结后的交易规则。
  - Holdout
    只看最后有没有翻向。
 
  这背后的方法论很简单:
 
  不要让一个阶段同时承担“定义 + 筛选 + 验证 + 交易优化”四
  件事。
 
  ———
 
  ### 7. 我会先区分“统计成立”和“交易成立”
 
  这是我非常强调的一点。
 
  一个想法可能有三种状态:
 
  1. 统计上不成立
     直接停。
  2. 统计上成立,但交易上不成立
     这时不能说信号没用,可能是费用、频率、白名单、执行问
     题。
  3. 统计和交易都成立
     才值得继续推进。
 
  很多人会把第 2 种误判成第 1 种,或者反过来。
 
  ———
 
  ### 8. 我会优先找“杀死假设”的证据
 
  不是只找支持它的证据,而是先看:
 
  - 哪些窗口它失效
  - 哪些币不成立
  - 哪些 regime 会破坏它
  - 哪些成本假设下它根本不可做
 
  这样做的原因是:
 
  能活过反证的研究,才值得往下走。
 
  ———
 
  ## 这套方法论的核心原则
 
  可以压缩成 6 句话:
 
  - 先机制,后指标
  - 先主线,后分支
  - 先证伪,后优化
  - 先统计,后交易
  - 先冻结,后验证
  - 先分层,后组合
 
  ———
 
  ## 放到你这个题目里,实际就是这样走的
 
  你最开始给的是一组市场机制假设。
  我会先把它拆成两条主线:
 
  - 传导线
    同向、滞后、补涨、补跌
  - 偏离修复线
    超涨、超跌、回归、regime 破坏
 
  然后先选“偏离修复线”里的“超涨 / 超跌”作为第一条正式研究
  线,因为它最像一个最小闭环问题。
  

确认研究命题

从概念 命题

超涨超跌 “在固定 Universe、固定时间标签、固定相对 BTC 偏离定义下,ALT 的极端正偏离是否对应未来相对回落,极端负偏离是否对应未来相对反弹”

进入研究阶段

  - Mandate
    把“这次到底研究什么、不研究什么”冻结下来。
  - Data
    先确认数据是否足以支撑这个命题。
  - Signal
    把“超涨/超跌”正式定义成可计算信号。
  - Train
    只负责定阈值、分位、候选范围。
  - Test
    只验证这个结构在独立样本里是否仍成立。
  - Backtest
    只检查冻结后的交易规则能否活下来。
  - Holdout
    只看最终窗口有没有翻向。

Mandate

【mandate 要解决什么】

  - 研究什么
  - 不研究什么
  - 用什么字段语言研究
  - 参数候选空间是什么
 

【mandate阶段做什么】

 
  - 冻结研究主问题
    这条线只回答一个问题:ALT 相对 BTC 的价格层偏离,是否
    存在可重复的均值回归结构。见 outputs/
    topic_c_1s_20251211_20260309/00_mandate/
    research_scope.md
    
  - 冻结“不研究什么”
    明确排除 Topic B、补涨/补跌、盘口、订单流、资金费率、
    ML、盘中动态换池。这样后面不会一边看结果一边偷偷换
    题。见 outputs/
    topic_c_1s_20251211_20260309/00_mandate/mandate.md
    
    
  - 冻结数据和时间口径
    固定 1s 频率、固定数据源、固定 ts = open_time、固定
    rfuture_h 从 t+1 起算,避免前视。
    
  - 冻结正式时间切分
    先把 Train / Test / Backtest / Holdout 边界写死,后面
    不能再因为结果不好改窗。
    
  - 冻结 Universe
    先把候选币池写死,并规定准入只能依据样本起点可得信
    息,不能用未来缺口反向删历史样本。
    
  - 冻结允许的信号族和首轮参数边界
    先规定可以研究哪些字段、第一轮扫哪些参数,但不在这一
    步选 winner。见 outputs/
    topic_c_1s_20251211_20260309/00_mandate/
    parameter_grid.yaml
    

【超涨超跌这块如何做的】

  - 先把经济含义冻结
    这里的“超涨/超跌”不是看某个币自己涨太多跌太多,而是看
    它相对 BTC 的偏离是否过大。
    
  - 再把信号家族冻结
    这条线允许的字段被限定为 s_level、ResidualZ、OB、OS、
    OBRate、OSRate、kappa、half_life 等,而不是开放成“什
    么看起来有用都加进来”。见 outputs/
    topic_c_1s_20251211_20260309/00_mandate/mandate.md
    
  - 再把参数边界冻结
    第一轮只允许在 N_reg、N_stat、N_rate、z0、h 这些维度
    里做粗筛,比如 z0 ∈ {1.5, 2.0, 2.5, 3.0},但这一步不
    决定最终用哪个 z0。
    
  - 最后把后续纪律冻结
    Train 只能定阈值,Test 不能重估阈值,Backtest 不能重
    新选币,Holdout 不能调参数。

时间划分的思考

参数部分

建议: 首轮不要一上来做超宽暴力搜索,而是先用平衡网格做 coarse search,确认大致有效区间,再对shortlist 用窄网格做 fine search。

允许字段与禁止字段

data ready

核心问题

原始数据能否被转换为共享、可审计、可复用的数据基础层。

为什么必须独立于信号研究

团队最常见的伪发现之一,就是把数据问题误当成 alpha。缺失、对齐、去重、开收盘标签混用、补值语义不清,这些都足以制造“看起来有结构”的结果。把 Data Ready 单独成阶段,是为了强制团队先解决这些问题,再允许研究信号。

必做事项

  • 对齐统一时间栅格。

  • 保留缺失与脏数据语义,不得静默吞掉。

  • 生成 QC 汇总。

  • 审计基础腿和核心资产的覆盖。

  • 输出可复用 rolling statistics 或缓存。

【layer0要】

  - 原始表是 sparse 1s bars,还是完整 dense 秒线
  - BTCUSDT 作为基准腿能不能覆盖全窗口
  - ALT 和 BTC 怎么对齐到同一时间栅格
  - 缺失秒怎么处理,哪些能补时间点,哪些不能补价格
  - 去重、坏点、缺口、样本覆盖怎么审计
  - 哪些字段应该作为共享 rolling stats 提前缓存
  - 哪些 symbol 可以进入正式研究,哪些必须写入排除报告

产生的文件:

顶层说明和审计文件
 
  - data_contract.md:这一层最核心的“数据契约”。它定义了时间轴语义、研究窗口、去缺失规则、禁止
    forward-fill、以及三个数值产物目录各自应该有哪些列。
  - dataset_manifest.json:机器可读的清单文件。它记录这次产物对应的 config、time_split、
    universe、retry_record 的路径和哈希,以及生成时间、grid 边界、文件数量、状态告警,作用是复
    现和审计。
  - validation_report.md:校验报告。它说明 schema、时间栅格一致性、基准腿覆盖、pair 对齐、
    manifest 完整性这些检查是否通过;这里的结论是 CONDITIONAL PASS。
  - data_ready_gate_decision.md:阶段 gate 决策。它回答“这一层能不能进入下一阶段”,这里的答案
    是可以进入 02_signal_ready,但要带着缺失率偏高的保留意见继续。
  - data_contract.md 和 validation_report.md 的区别是:前者定义“应该长什么样”,后者记录“这次实
    际有没有做到”。
 
  Universe 和准入相关文件
 
  - universe_fixed.csv:本轮正式冻结下来的 30 个 symbol 清单。每一行都带了角色、候选顺序、纳入
    阶段和纳入原因,相当于“本次研究到底研究哪些币”的正式名单。
  - universe_summary.md:对 universe_fixed.csv 的文字总结,解释为什么这一步没有删币,以及当前
    universe 的主要风险提示。
  - universe_exclusions.csv:本阶段被排除的 symbol 列表。现在只有表头,表示这次 Data Ready 没
    有新增排除对象。
  - universe_exclusions.md:对上面那个空排除表的解释,说明不是数据都很好,而是 Mandate 没冻结
    数值覆盖阈值,所以不能在这一步临时改 universe。
 
  规则说明文件
 
  - dedupe_rule.md:原始秒线去重规则说明。这里明确主键是 (symbol, open_time),重复记录取
    created_at 最新值;这决定了后面 dense grid 的真实缺失语义。
  - qc_report.parquet:每个 symbol 一行的质量总表,字段是 missing_rate、stale_rate、
    outlier_rate、usable_rate_288/864 等,用来快速判断哪些币虽然进了 universe,但数据质量偏差
    很大。
    
    三个数值子目录
 
  - aligned_bars/*.parquet:每个文件对应一个 symbol 的基础秒级对齐结果,比如 aligned_bars/
    BTCUSDT.parquet、aligned_bars/ETHUSDT.parquet。里面是 dense 1s 时间轴上的原始基础列:ts、
    close、volume、r,再加 flag_missing / flag_bad_price / flag_stale / flag_outlier。它回答的
    是“这一秒这个币的基础 bar 和质量状态是什么”。
  - rolling_stats/*.parquet:每个文件对应一个 symbol 的滚动统计结果,比如 rolling_stats/
    BTCUSDT.parquet。它是在 aligned_bars 之上预计算的单币统计缓存,当前固定窗口是 288 和 864
    秒,包含 mu_r_*、std_r_*、valid_count_*、flag_low_sample_*。它回答的是“到这一秒为止,这个
    币最近一段时间的收益统计是什么”。
  - pair_stats/*.parquet:每个文件对应一个 ALT-BTC 配对,比如 pair_stats/
    ETHUSDT_BTCUSDT.parquet、pair_stats/SOLUSDT_BTCUSDT.parquet。里面是配对层的滚动统计缓存,
    字段包括 corr0_*、alpha_*、beta_*、eps_*、z_eps_*、valid_count_*。它回答的是“这个 ALT 相对
    BTCUSDT 的同步相关、回归残差和残差 z-score 是什么”。
 
  这三个目录里“每个文件”的具体含义
 
  - aligned_bars 下的每一个文件,都是“某个 symbol 的标准化基础 bar 底表”。
  - rolling_stats 下的每一个文件,都是“同一个 symbol 的单币滚动统计缓存”。
  - pair_stats 下的每一个文件,都是“某个 ALT 相对 BTCUSDT 的双边统计缓存”。
  - pair_stats 只有 29 个文件,没有 BTCUSDT_BTCUSDT.parquet,因为 BTCUSDT 在这里是基准腿,不会
    自己和自己配对。

siganal ready

核心问题

研究对象是否已经被定义成统一、可复现、可比较的信号字段合同。

为什么不能直接从数据跳到 Train

如果没有独立的信号层,团队就很容易在不同阶段对“同一个信号”用不同计算方式或不同时间标签解释。到最后即使结果看起来一致,实际比较的也不是同一个对象。

必做事项

  • 固定信号字段定义。

  • 固定主时间标签与未来收益对齐方式。

  • 生成每个对象的信号时序和覆盖报告。

  • 为后续 TrainTest 提供统一字段合同。

必备输出

  • timeseries/

  • symbol_summary.parquet

  • signal_coverage.*

  • signal_fields_contract.md

  • signal_gate_decision.md 或等价的 signal_ready.md

晋级标准

团队能够明确回答“后续所有阶段到底在用哪个字段、哪个标签、哪个参数身份”。

额外要求

如果一条研究线只有 timeseries/signal_fields_contract.mdsignal_coverage.*,但没有单独的阶段结论或 gate 文档,那么它更准确的表述应是:

  • “已经产出 signal layer artifacts”

而不是:

  • “已经正式关闭 Signal Ready 阶段”

因为前者代表“信号结果已经落盘”,后者代表“阶段门禁已经被正式记录并允许晋级”。两者不能混用。

明确禁止

  • Train 里边算边改信号定义。

  • 不记录参数身份,只靠文件名猜是哪组参数。

  • 把信号可用性问题留给 Test 才发现。

失败后的允许动作

  • 允许修正信号实现、字段命名、标签对齐。

  • 如果要改变研究信号的机制定义,则必须回退到 Mandate 或开新谱系。

【疑难问题:】

full-grid 前有个硬成本要你确认:当前单组 02_signal_ready
  实测约 3.5G,其中单组 timeseries 约 2.25G、对应 _raw 约 1.17G;按 mandate 全量合法组合算,一
  共是 264 个 param_id,用现有实现直接外推,磁盘大约会到 ~600G,串行计算时间大约 > 1 天。你还
  要我按 full-grid 继续做,还是改成先做一批 search_batch

train

  
 
**核心问题**
 
  
 
如何在不接触未来窗口的前提下,把尺子定下来。
 
  
 
**为什么它只能负责“定尺子”**
 
  
 
`Train` 的职责是校准,不是验收。它应该冻结阈值、分位切点、质量过滤、波动分层和候选参数范围,而不应该宣布哪一组已经“成功”。一旦 `Train` 开始承担“宣布胜利”的角色,后面的 `Test` 就会沦为走流程。
 
  
 
**必做事项**
 
  
 
- 冻结分位阈值。
 
- 冻结 regime 切点。
 
- 做信号可研究性过滤。
 
- 在必要时做参数粗筛,但只排除荒谬区间。
 
- 记录完整参数 ledger。
 
  
 
**必备输出**
 
  
 
- `train_thresholds.*`
 
- `train_quality.*`
 
- `train_param_ledger.csv`
 
- `train_rejects.csv`
 
  
 
**晋级标准**
 
  
 
后续 `Test` 能拿着一套已经冻结的尺子去验证,而不是一边验证一边重估。
 
  
 
**明确禁止**
 
  
 
- 根据 `test` 结果回头重算 `train` 阈值。
 
-`train` 用收益最大化方式选最终策略参数。
 
- 只保留通过的参数,不保留被淘汰的搜索轨迹。
 
  
 
**失败后的允许动作**
 
  
 
- 允许修训练内的质量门槛或冻结逻辑。
 
- 如果修复动作需要借用 `test``backtest` 的信息,视为污染,必须整体回退。

名词解释

  • 滚动回归OOS
  • 漂移验证