Skip to content

MarketData 与宿主运行契约方案

本文档定义 zelqor 在完成策略加载与统一运行之后,下一步最值得推进的能力:把 marketData 和宿主调用契约正式化。

一句话总结:

当前仓库已经解决了“策略怎么被框架运行”,下一步要解决的是“外部宿主怎么稳定、明确、可扩展地调用这套运行系统”。

1. 为什么下一步应该做这个

当前仓库已经具备:

  • strategy request schema
  • python_file / python_module 策略加载
  • run_backtest(...) 真实执行
  • run-backtest --request-file ... 真实执行

这说明:

  • 策略接入链路已经不是主要瓶颈
  • CLI 已经不再是 scaffold
  • request schema 已经能驱动真实回测

但当前仍有一个明显短板:

  • marketData 仍然是“最小可用”建模
  • request 还缺少更明确的宿主控制项
  • 外部系统调用这套能力时,缺少更稳的契约边界

因此下一步更有价值的事情,不是继续扩展策略形态,而是把“宿主如何调用”这件事产品化。

2. 当前边界

当前 BacktestRequest 里关于宿主运行契约的字段主要是:

  • marketData
  • strategy
  • dateRange
  • capital
  • execution
  • costs
  • params

其中 marketData 当前正式支持:

{
  "type": "clickhouse",
  "source": {
    "mode": "config_file",
    "configPath": "config.toml"
  }
}

并且 request 里已经有最小宿主输出控制:

{
  "runtime": {
    "output": {
      "includeDailyPools": true,
      "includeDailyDecisions": true,
      "includeTrades": true,
      "includePositionsByDate": true,
      "includeEquityCurve": true
    }
  }
}

旧的扁平字段:

  • configPath
  • useEnv

已经不再是正式 schema 的一部分。

这已经比原来更清晰,但还不够完整地表达宿主调用方式,比如:

  • provider 配置到底来自哪里
  • provider 专属配置如何建模
  • 是否允许不同运行环境覆盖配置
  • 回测结果输出粒度如何控制
  • debug / metadata 是否需要显式约束

3. 目标

这一阶段建议聚焦三个目标。

3.1 目标一:正式化 marketData schema

建议把 marketData 从“最小兼容结构”升级为“明确的 provider 配置入口”。

最少应明确:

  • provider 类型
  • provider 配置来源
  • provider 专属配置结构

对 ClickHouse 来说,当前已经统一到:

  • source.mode == "config_file"
  • source.mode == "env"

后面再决定是否允许 inline config

3.2 目标二:正式化宿主运行控制项

当前 request 已经能描述“运行什么”,但还不够清晰地描述“输出什么”和“保留什么”。

建议后续增加或正式化:

  • 输出粒度控制
  • 是否保留 dailyPools
  • 是否保留 dailyDecisions
  • 是否保留 trades
  • 是否保留 positionsByDate
  • debug / metadata 输出控制

这类字段不一定要一次性全部实现,但应该开始设计统一入口。

3.3 目标三:把 request 当成宿主契约来测试

当前测试更多是在验证:

  • loader 是否正常
  • API 是否能跑通
  • CLI 是否能跑通

下一阶段应增加一层面向宿主的契约测试,覆盖:

  • 最小 request
  • 完整 request
  • 非法 provider 配置
  • 空交易日区间
  • strategy.kind 不匹配
  • provider 类型不支持
  • provider 配置缺失

4. 推荐 schema 演进方向

4.1 marketData

建议保留统一入口:

{
  "marketData": {
    "type": "clickhouse",
    ...
  }
}

但内部进一步细化成更稳定的形状,例如:

{
  "marketData": {
    "type": "clickhouse",
    "source": {
      "mode": "config_file",
      "configPath": "config.toml"
    }
  }
}

或者:

{
  "marketData": {
    "type": "clickhouse",
    "source": {
      "mode": "env"
    }
  }
}

这样做的好处是:

  • provider 来源更清晰
  • 未来支持更多 provider 时更容易扩展
  • 不会让顶层 request 长出太多 provider 细节字段

4.2 runtime

建议新增独立的宿主运行控制对象,例如:

{
  "runtime": {
    "output": {
      "includeDailyPools": true,
      "includeDailyDecisions": true,
      "includePositionsByDate": false
    }
  }
}

这层不是策略逻辑本身,而是宿主如何消费结果的配置。

4.3 metadata

如果后面桌面端、服务端或任务系统要接入,建议允许 request 带一层宿主元数据,例如:

{
  "metadata": {
    "requestId": "bt_20260326_001",
    "caller": "desktop",
    "profile": "research"
  }
}

这样更利于:

  • 审计
  • 日志关联
  • 调试
  • 宿主区分

5. 推荐实现顺序

5.1 第一步:写清 marketData 的下一版 shape

先形成统一约定:

  • 当前保留什么
  • 哪些旧字段需要淘汰
  • 哪些字段属于 provider 通用层
  • 哪些字段属于 ClickHouse 专用层

5.2 第二步:补 provider 配置契约测试

增加:

  • marketData.type 错误测试
  • configPath 缺失测试
  • configPath/useEnv 字段拒绝测试
  • 配置文件不存在测试

5.3 第三步:引入 runtime 控制层

先不必一次性让所有输出控制都生效,但建议先把 request 结构定出来。

5.4 第四步:补宿主调用示例

建议增加:

  • 一个最小宿主 request 示例
  • 一个完整宿主 request 示例
  • 一个错误 request 示例

6. 当前不建议优先做什么

这一阶段不建议优先做:

  • 新增更多策略模式
  • 分钟级回测
  • 更复杂 broker 撮合
  • 参数扫描调度系统
  • UI 层联动逻辑

这些都应该排在“宿主契约稳定”之后。

7. 风险与取舍

7.1 过早把 marketData 设计得太重

建议:

  • 先围绕 ClickHouse 抽象
  • 不急着假装已经支持很多 provider

7.2 把宿主控制项和策略参数混在一起

建议明确分层:

  • params 给策略
  • runtime 给宿主
  • marketData 给 provider

7.3 让 request 顶层继续膨胀

建议把宿主相关字段拆进:

  • marketData
  • runtime
  • metadata

而不是把所有东西都塞在顶层。

8. 验收标准

这一阶段建议以这些结果作为完成标志:

  • marketData 的下一版 shape 形成正式约定
  • request 中宿主控制层有明确位置
  • provider 配置错误有清晰报错
  • 宿主 request 示例与契约测试补齐

9. 结论

zelqor 当前下一步最应该做的,不是继续证明策略模式,而是正式定义:

  • provider 怎么接入
  • request 怎么表达宿主意图
  • 宿主怎么稳定消费运行结果

也就是说,下一阶段的关键词不是“更多策略”,而是:

  • 更清晰的宿主运行契约

完成这一阶段后,仓库会从:

  • 策略能被加载
  • 回测能被执行

进一步进入:

  • provider 配置边界清晰
  • request 契约更稳定
  • 更适合桌面端、服务端或任务系统接入