Hualin Luan Cloud Native · Quant Trading · AI Engineering
返回文章

Article

量化交易系统开发实录(七):AI 工程化落地——从 speckit 到 BMAD

以交易日历与日线聚合需求为单一案例,解释 AI 工程化如何通过规格驱动、BMAD 角色交接和人工质量门禁进入真实量化系统交付。

Meta

Published

2026/3/28

Category

guide

Reading Time

约 43 分钟阅读

读者读到这一篇时,已经经历了系统边界、真实缺陷、测试防线、性能治理和架构演进。AI 工程化不应该把这些纪律替换掉,而是把它们组织成可追踪、可审计、可签收的交付闭环。

在量化交易系统里,AI 最大的价值不是“更快写出一段代码”,而是让规格、测试、实现、审查、文档和验收证据之间形成稳定链路。交易日历、跨夜归属、日线聚合、半日市处理、分层归一处理、指标增量计算和图表性能优化都不是单点函数问题。只要业务语义没有写清楚,AI 生成的代码越快,后续返工越快进入系统核心。

系列阅读顺序

推荐阅读路径是 Part1 -> Part2 -> Part3 -> Part4 -> Part5 -> Part6 -> Part7。最后再看 AI 工程化,是为了让读者先理解系统、缺陷、测试、性能和重构,再判断 AI 应该进入哪些受约束的环节。

这一篇关注四个问题:

  • 规格驱动如何把业务语义、接口、测试和验收证据连起来。
  • BMAD 多 Agent 协作如何降低单一 AI 输出的盲区。
  • 提示词工程如何从“写得更详细”升级为“边界、输入、输出、验收都可检查”。
  • 人机分工如何避免把业务语义签收、架构取舍和风险接受交给黑盒。

读者可以用一个简单判断来评估 AI 工程化是否真的生效:一次 AI 辅助交付结束后,代码库里是否能找到需求来源、澄清决策、实现计划、测试证据、性能证据和维护说明。如果只能找到一段代码和几句对话记录,这仍然是一次临时协作;如果每个关键判断都能回到工件链,AI 才真正进入工程体系。

引子:AI 写得越快,为什么维护反而可能更慢

交易系统很容易出现一个反直觉现象:AI 让代码生成速度大幅提升,但如果缺少规格、测试和质量门禁,系统维护成本会同步上升。一个“K 线聚合函数”可以很快生成,三个月后却可能成为性能瓶颈、测试盲区和业务语义债务。

常见失控信号包括:

  • 函数能跑,但没有文档,下一位维护者无法确认交易日归属规则。
  • 没有测试,跨夜、半日市、假期、数据断层只能靠人工回忆。
  • 代码只覆盖 happy path,周五夜盘、假期前夕夜盘、临时休市需要不断补丁。
  • prompt 只要求“实现功能”,没有要求类型注解、复杂度、边界条件和验收证据。
  • AI 生成的方案看似完整,但没有解释哪些决策需要人工签收。

这不是 AI 本身的问题,而是交付链路缺少工程边界。AI 可以承担候选实现、测试草案、文档初稿和结构化检查,但交易系统里的业务语义、风险接受、上线窗口、回滚条件和质量签收必须由人负责。读者真正需要关注的是:AI 输出进入代码库之前,是否已经被规格、测试、审查和证据约束住。

开源背景:Spec Kit 与 BMAD 提供了两类互补能力

读者如果想把这一套方法迁移到自己的工程体系,首先需要区分两个开源项目的定位。

Spec Kit 是 GitHub 开源的 Spec-Driven Development 工具包。它强调把软件开发的起点从“直接写代码”前移到“可执行规格”,让团队先关注产品场景和可预测结果,再进入实现。对量化交易系统来说,Spec Kit 的启发在于:交易日归属、半日市、回测与实盘一致性、性能预算这些问题,都应该先进入规格、澄清、计划和验收链路,而不是在实现阶段靠 prompt 临场补充。

BMAD-METHOD 是开源的 Agile AI-driven Development 方法和模块生态。它的核心价值不是让 AI 自动替代团队,而是通过角色化 Agent 和结构化工作流,把需求澄清、架构、实现、审查、测试和文档变成协作过程。对交易系统来说,BMAD 的启发在于:Architect、Developer、QA、Reviewer、Documenter 这些角色可以由 AI 参与,但每个角色必须交付可追踪工件,不能只留下对话结论。

这两个项目分别解决两个问题:Spec Kit 让“规格”成为实现入口,BMAD 让“多角色协作”成为质量控制手段。真正进入生产级交付时,仅有规格还不够,因为实现过程会失控;仅有多 Agent 也不够,因为角色之间可能缺少共同规格。后面讨论的 BMAD-Speckit-SDD-Flow,正是把这两类能力进一步组合成一条受治理的 AI 交付流。

第一部分:speckit——规格驱动的 AI 开发

speckit 可以理解为一套规格驱动开发流程。它不是某个单一工具,而是把需求、澄清、计划、实现和验收组织成稳定工件链:

  • Specify:明确业务需求,写成可引用的规格。
  • Clarify:消除歧义,记录技术决策和待确认问题。
  • Plan:拆解实现步骤、依赖关系、风险和验证方式。
  • Implement:在规格约束下生成或编写代码。
  • Checklist:对照规格、测试和证据完成验收。

这个流程和传统瀑布最大的区别在于:每一步都可以使用 AI 加速,但决策权仍然在人。AI 不直接决定交易日定义、不直接接受半日市风险、不直接签收指标结果;AI 负责把候选内容结构化,人负责确认语义和边界。

对量化交易系统来说,规格驱动还有一个额外价值:它把“业务正确性”和“代码正确性”分开。代码可以通过类型检查和单元测试,但业务语义仍然可能错。例如函数返回了一个日期对象,并不代表它返回了正确交易日;日线聚合能算出 OHLC,也不代表它没有把周五夜盘算进周五。speckit 要解决的正是这种语义断层。

speckit 规格驱动工件依赖图
图 1:speckit 工件流图,从业务语义到实现任务必须可追踪,不能直接从 prompt 跳到代码。

这张图回答的是一个关键问题:为什么 AI 工程化不能从 prompt 直接跳到代码。交易系统的需求通常先落在业务语义上,例如“周五夜盘归属于下周一交易日”。这个语义需要进入 Specify,再通过 Clarify 变成交易日定义、半日市规则、假期来源和异常处理策略。只有这些工件稳定后,Plan 才能拆任务,Implement 才能生成代码,Checklist 才能验证结果。

如果某一步缺失,后果通常很具体。缺少 Specify,AI 会把自然日当成交易日;缺少 Clarify,半日市和临时休市会被写成硬编码;缺少 Plan,实现顺序可能先做 UI 再补数据语义;缺少 Checklist,测试通过也无法证明真实行情边界被覆盖。规格驱动不是为了减慢速度,而是为了避免速度直接变成返工。

实战案例一:交易日历与日线聚合

交易日历与日线聚合是 AI 工程化的典型样本,因为它看起来像一个普通聚合函数,实际涉及业务语义、时区、交易所规则、数据完整性和 UI 解释。

业务复杂性至少包括四类:

  • 跨夜交易:周五夜盘 17:15 到次日 03:00 归属于下周一交易日,而不是自然日周五。
  • 假期休市:圣诞、元旦、春节等公众假期完全休市,不能生成误导性 K 线。
  • 半日休市:除夕、圣诞前夕等只开上午盘,通常 09:15 到 12:30,下午不再生成 K 线。
  • 强制收盘:半日市在 12:30 强制收盘,金融假期前夕夜盘在 03:00 强制收盘。
量化需求到实现映射图
图 2:需求到实现序列图,每个业务约束都必须落到接口、fixture、测试和验收证据。

图 2 的重点不是“流程更复杂”,而是每个业务约束都要有落点。周五夜盘归属不是一句描述,它必须对应 get_trading_day(timestamp) 的语义、覆盖周五 23:30 和周一 00:30 的 fixture、验证日线 OHLC 的测试,以及最后能被复查的验收证据。否则 AI 生成的聚合逻辑即使通过了普通样本,也可能在真实盘面里污染指标。

Specify:把业务需求写成可验收规格

交易日历与日线聚合的规格可以拆成四个用户故事。

编号优先级业务目标核心验收场景
US-001P0根据香港期货交易日历判断交易日2024-01-08 返回交易日,2024-01-06 返回非交易日,2024-01-01 公众假期返回非交易日
US-002P0周五夜盘数据归属于下周一周五 23:30 的 1 分钟 K 线归属于 2024-01-08,而不是 2024-01-05;周一 10:00 归属于周一
US-003P1正确处理半日休市除夕只返回 09:15-12:30;12:30 后不再生成 K 线;假期前夕夜盘 03:00 后不再生成 K 线
US-004P0正确聚合日线 OHLC开盘价取第一根分钟线,最高价取分钟线最高价最大值,最低价取分钟线最低价最小值,收盘价取最后一根分钟线,成交量求和

功能需求需要继续细化:

  • FR-001:支持香港期货交易所交易日历,覆盖 2020-2030。
  • FR-002:区分完整交易日和半日交易日。
  • FR-003:夜盘 17:15 到次日 03:00 归属于下一交易日。
  • FR-004:日盘 09:15-12:00、13:00-16:30 归属当日;半日市日盘 09:15-12:30。
  • FR-005:跨午夜数据 00:00-03:00 归属于同一交易日。
  • FR-006:半日市下午时段不生成 K 线。
  • FR-007:假期前夕夜盘在 03:00 强制收盘。

非功能需求也必须写入规格,而不是留在口头期望里:

  • SC-001:日历查询延迟小于 1ms。
  • SC-002:1000 根分钟线聚合为日线小于 50ms。
  • SC-003:缓存 10 年日历数据时内存占用小于 100MB。

技术约束同样不能省略:

  • 基于 Python 3.10+。
  • 可使用 pandas-market-calendars 作为基础日历能力。
  • 需要支持 HKFE 定制。
  • 需要兼容系统既有 BarData 结构。
  • 必须处理时区转换和夏令时边界。

验收标准最终落到测试清单:

  • 正常交易日识别正确。
  • 周末识别为非交易日。
  • 公众假期识别正确。
  • 周五夜盘归属下周一。
  • 半日市上午交易正常,下午休市。
  • 跨午夜数据 00:00-03:00 归属正确。
  • 日历查询满足 SC-001
  • 日线聚合满足 SC-002

Clarify:把歧义变成技术决策记录

规格写完后,还不能立刻实现。交易系统的歧义通常藏在“大家以为自己理解一致”的地方,尤其是交易日定义、半日市处理和假期来源。

第一个决策是交易日定义。系统采用港交所官方交易日定义:交易日以日盘日期为准,前一晚夜盘和次日日盘属于同一交易日,周五夜盘归属于下周一。这个决策会影响日线聚合、指标窗口、回测切片和 UI 标注。

物理时间所属交易日说明
2024-01-05 09:152024-01-05周五日盘开始
2024-01-05 17:152024-01-08下周一夜盘开始
2024-01-05 23:302024-01-08周五夜盘归属下周一
2024-01-08 00:302024-01-08跨午夜仍属于同一交易日
2024-01-08 03:002024-01-08夜盘结束
2024-01-08 09:152024-01-08日盘开始

关键实现逻辑可以保留为最小示意,而不是让长代码块淹没业务语义:

def get_trading_day(timestamp: datetime) -> date:
    """示意代码:根据香港时间戳返回所属交易日。"""
    hk_time = timestamp.astimezone(HONG_KONG_TZ)
    current_date = hk_time.date()
    current_time = hk_time.time()

    if current_time >= time(17, 15) or current_time < time(3, 0):
        return get_next_trading_day(current_date)

    return current_date

第二个决策是半日休市处理。半日市日期每年不同,疫情、台风或交易所特别安排还可能临时改变,因此规则不应硬编码在聚合函数里。更稳妥的方式是用配置表维护半日市日期、原因、上午收盘时间和夜盘强制收盘时间,例如 2024-02-09 除夕、2024-12-24 圣诞前夕、2024-12-31 新年前夕都需要独立记录。配置化的收益是规则变更时可以先更新日历和测试,再触发聚合逻辑验证。

第三个决策是假期日历来源。可以基于 pandas-market-calendars 定制 HKFE 日历,再补充香港特有假期、半日市标记和台风等特殊休市 API。这样做的关键不是依赖某个库,而是把“官方日历 + 本地修正 + 手动特殊事件”分成三层,避免把交易所规则散落到聚合器、数据导入器和 UI 提示里。

Clarify 阶段还要记录两个容易被忽略的问题:

  • 非预期休市如何处理:提供 add_holiday(date, reason) 这样的手动入口,已生成 K 线不直接删除,而是标记为“不完整交易日”,UI 显示警告。
  • 数据断层如何处理:缺失交易日不生成误导性日线,UI 显示“数据缺失”占位,并保留数据补录入口。

Plan:把规格拆成可交付阶段

计划不是任务列表堆叠,而是依赖关系、风险和验证方式的落地。

阶段目标文件或模块主要内容验证重点
Phase 1hkfe_calendar.pycalendar_config.jsonis_trading_dayis_half_dayget_trading_sessionget_trading_day完整交易日、半日市、周末、公众假期
Phase 2daily_bar_aggregator.pyaggregatehandle_night_sessionhandle_half_dayvalidate_completeness多场景日线聚合、不完整交易日标记
Phase 3vnpy_datamanagervnpy_datarecorder数据导入和记录阶段自动识别交易日夜盘数据归属、数据层兼容
Phase 4trading_day_indicator.py、图表 UI半日市、假期、不完整数据提示和数据补录界面用户可见状态和数据补录路径

这个计划的依赖关系是 Phase 1 -> Phase 2 -> Phase 3 -> Phase 4。日历语义没有稳定之前,不应该先写 UI;聚合器没有测试之前,不应该接入数据层;数据层没有归属证据之前,不应该进入回测和实盘共用路径。

计划阶段还需要明确每个阶段的退出条件。Phase 1 的退出条件不是“日历类写完”,而是关键日期样本全部通过;Phase 2 的退出条件不是“聚合函数能跑”,而是完整交易日、周五夜盘、跨午夜、半日市和缺失数据全部有断言;Phase 3 的退出条件不是“数据层接上了”,而是导入、记录和查询返回同一交易日语义;Phase 4 的退出条件不是“界面显示了提示”,而是用户能区分完整、半日、假期和不完整交易日。

Implement:在约束下生成代码

规格和决策稳定后,给 AI 的输入需要从“帮忙写一个聚合函数”升级为可执行约束:

基于交易日历与日线聚合规格实现 DailyBarAggregator。

必须满足:
1. 所有参数和返回值使用类型注解。
2. 处理空输入、跨午夜数据、非交易日数据。
3. 周五夜盘必须归属下周一。
4. 半日市 12:30 强制收盘后不再生成 K 线。
5. 不完整交易日必须标记,不能生成误导性 OHLC。
6. 每个 public 方法必须有单元测试。
7. 1000 根分钟线聚合耗时必须小于 50ms。

测试必须覆盖:
正常交易日、周五夜盘、周一跨午夜、半日市、公众假期、不完整交易日。

输出必须包含:
实现代码、pytest 单元测试、复杂度分析、边界情况说明。

这样的 prompt 不只是更长,而是让 AI 输出进入可检查边界。关键业务逻辑已经在规格和 Clarify 中定义,AI 没有自由解释“夜盘属于哪一天”的空间。

这里还需要注意一个常见误区:prompt 中写了约束,不代表约束已经被满足。约束必须有对应证据。例如“每个 public 方法必须有单元测试”对应测试文件和覆盖报告;“1000 根分钟线聚合小于 50ms”对应 benchmark 输出;“不完整交易日不生成错误 OHLC”对应异常样本和断言;“周五夜盘归属下周一”对应固定日期 fixture。没有证据的约束只是愿望。

扩展规格:分层数据归一处理

交易日历之后,系统还会遇到分层数据归一处理问题。主周期、辅助周期、指标周期和 UI 显示周期如果各自维护边界基准,策略和图表很容易出现错位。

一个可落地的决策是:以主周期,也就是图表显示周期为基准,其他周期数据按规则归一。方案对比如下:

方案复杂度精度适用判断
主周期基准 + 插值适合作为主方案,便于 UI 和策略共享时间语义
独立边界基准实现简单,但读者很难判断分段引用是否一致
全部重采样精度较高,但计算成本和边界复杂度更高

数据缺失时不能自动填充,因为填充会制造不存在的行情。更稳妥的策略是显示空位,在 UI 上标注“数据不可用”,并让策略层明确知道该周期数据缺失。这样会增加使用者的认知成本,但能避免缺失数据被静默当成真实信号。

分层计划可以拆成四个阶段:

  • Phase 1:实现 trading_calendar.pybar_aggregator.py,提供交易日历、交易时段、日线聚合和任意周期聚合。
  • Phase 2:实现 multi_timeframe_data.pytimeframe.py,封装 fetch_barsalign_timeframes、周期定义和转换。
  • Phase 3:让 chart_window.pychart_widget.pyperiod_selector.py 支持多 SubChart 和周期切换。
  • Phase 4:完成数据层与 UI 层集成,增加缓存、E2E 场景和性能验证。

给 AI 的实现输入也必须带约束:

基于规格实现 BarAggregator。

必须满足:
1. 使用类型注解和 docstring。
2. 处理空输入、数据不连续、跨夜交易。
3. 每个 public 方法必须有单元测试。
4. 10000 根分钟线聚合必须小于 50ms。
5. 归一规则必须引用跨夜交易归属决策。

输出必须包含:
实现代码、pytest 测试、复杂度分析。

这个例子说明 speckit 的作用不是生成更多文档,而是把“需求 -> 决策 -> 计划 -> 实现 -> 证据”的链路固定下来。

读者在自己的系统里落地 speckit 时,可以先从一条高风险规则开始,而不是一次性覆盖所有模块。适合切入的规则通常有三个特征:业务语义容易被误解,错误会污染指标或订单,人工复盘时很难只靠日志还原。例如跨夜归属、半日市、主力合约切换、手续费模型、滑点模型、风控冻结和撮合延迟,都适合先被规格化。

实战案例二:图表性能优化

另一个典型案例是图表加载 10000 根 K 线需要 3 秒,目标是降到 100ms 以内。如果直接让 AI “优化性能”,很容易得到缓存、并发、NumPy、异步加载等混合建议,但无法判断哪个建议对应真实瓶颈。

Clarify 阶段先记录三个决策:

  • D1 数据缓存策略:使用内存 LRU、磁盘缓存、数据库三级缓存,由 SlidingWindowBarManager 控制窗口数据。
  • D2 渲染优化:通过 VisibleAreaTracker 只计算可见范围,虚拟列表只渲染 viewport 内的 K 线。
  • D3 图片缓存:静态 K 线缓存为位图,由 LRUPictureCache 复用不变化的图形对象。

还需要记录两个权衡:

权衡候选方案选择理由
内存 vs 速度全量缓存、按需加载、滑动窗口 + 位图缓存全量缓存占用过高,按需加载交互慢,滑动窗口 + 位图缓存能在内存和响应之间取得平衡
实时性 vs 流畅度实时行情更新时全量重绘,或只重绘最后一根 K 线只重绘最后一根 K 线,避免每个 tick 触发全量绘制

这类性能规格的关键收益是把“优化方向”变成“可验证假设”。读者能清楚看到:缓存解决数据重复访问,虚拟化解决可见区域绘制,位图缓存解决静态图形重复绘制,实时更新策略解决最后一根 K 线的刷新成本。

性能优化也要避免“AI 方案堆叠”。如果 prompt 同时要求缓存、并行、NumPy、异步和渲染优化,AI 很容易给出看似全面却不可验证的组合。更稳妥的方式是先把 3 秒加载拆成数据读取、数据转换、指标计算、图形对象构建和绘制刷新,再逐段建立假设。每个假设都应该有进入条件和退出条件:进入条件是 profile 或 benchmark 证明瓶颈存在,退出条件是优化前后数据、正确性断言和回退方案都可见。

speckit 带来的收益可以从四个角度观察:

指标使用前使用后
需求返工率显著降低
架构争议时间数小时决策文档化
新人理解需求1-2 天阅读规格约 30 分钟
AI 代码质量偏低明显提升

第二部分:BMAD——多 Agent 协作开发

speckit 解决的是需求到代码的追踪问题,BMAD 解决的是代码质量和多视角审查问题。单一 AI 很容易沿着第一个可行方案一路生成下去,缺少架构、实现、审查、测试和文档之间的交叉校验。

BMAD 可以拆成五个角色:

角色输入输出主要风险控制点
Architect需求规格架构方案、接口定义、核心算法伪代码边界是否清楚,复杂度是否合理
Implementer架构方案可运行代码是否遵守接口、类型、异常和性能约束
Reviewer实现代码审查报告、问题列表是否存在边界错误、浮点误差、隐性状态
Tester代码和需求测试代码、测试报告是否覆盖正常、边界、异常和性能场景
Documenter最终代码API 文档、使用示例、注意事项下一位维护者是否能独立理解

读者需要警惕一种“形式化 BMAD”:多个角色都被调用了,但每个角色只是复述上一轮输出。真正有效的 BMAD 必须制造差异化压力。Architect 应该质疑边界,Implementer 应该暴露实现限制,Reviewer 应该找错,Tester 应该把错转成可重复样本,Documenter 应该让维护者能独立接手。角色之间没有冲突和修正,往往说明流程没有真正发挥作用。

BMAD 多角色工件交接图
图 3:BMAD 工件交接泳道图,角色之间传递的是规格、测试和证据,而不是口头判断。

这张图的重点是“工件交接”,不是“多个 Agent 看起来更热闹”。Architect 交付的是边界和接口,Implementer 交付的是受约束代码,Reviewer 交付的是问题和修复建议,Tester 交付的是可复现测试,Documenter 交付的是维护说明。任何一个角色只输出自然语言结论而没有工件,后续追踪都会断开。

完整案例:指标计算重构

指标计算模块最初使用 Pandas DataFrame 批量计算,性能成为瓶颈。目标是把 10000 根 K 线计算 RSI 的耗时从约 150ms 降到 5ms 以内,同时让回测和实时交易使用同一套指标实现。

Architect 阶段关注边界和复杂度。输入需要说明当前使用 Pandas 批量计算、需要支持增量更新、内存占用降低 50%、计算延迟小于 10ms,并要求输出核心抽象、数据流、增量 MA/EMA/RSI 伪代码、文件组织建议和风险评估。

核心抽象可以保留在一个短代码块里:

class IncrementalIndicator(ABC):
    """增量指标基类。"""

    @abstractmethod
    def update(self, bar: BarData) -> Optional[IndicatorValue]:
        pass

    @abstractmethod
    def reset(self) -> None:
        pass

    @property
    @abstractmethod
    def is_ready(self) -> bool:
        pass

class IncrementalMA(IncrementalIndicator):
    def __init__(self, period: int):
        self.period = period
        self.values = deque(maxlen=period)
        self.total = 0.0

    def update(self, bar: BarData) -> Optional[float]:
        if len(self.values) == self.period:
            self.total -= self.values[0]
        self.values.append(bar.close)
        self.total += bar.close
        return None if len(self.values) < self.period else self.total / self.period

这个抽象传达了两个重要原则:指标实例保存必要状态,update 只处理新增 Bar;状态边界明确后,回测和实时行情可以共享同一条计算路径。

这个案例里,Architect 的价值不是写出 IncrementalIndicator 这个名字,而是把指标计算的状态边界暴露出来。Pandas 批量计算的优势是表达简洁,缺点是实时路径里容易重复扫描历史窗口。增量指标的优势是单次更新成本稳定,缺点是状态初始化、回放恢复、重置和数值稳定性都要被显式管理。Architect 必须把这些收益和代价同时写出来,否则 Implementer 只会得到一个“把 Pandas 改成手写循环”的模糊任务。

Implementer 阶段实现 IncrementalRSI,约束包括:

  • 严格遵循 IncrementalIndicator 接口。
  • 支持 Wilder 平滑方法,也就是 SMMA(today) = (SMMA(yesterday) * (period - 1) + value) / period
  • 内存复杂度为 O(1),只保留必要状态。
  • 包含类型注解、docstring 和完整 pytest。
  • period 根 Bar 数据不足时返回 None
  • 价格不变时 RSI 返回 50。
  • 全涨、全跌和连续微涨时需要数值稳定性保护。

Reviewer 阶段发现的典型问题有三类:

  • 初始阶段计算错误:前 period 根 Bar 应该使用简单平均,而不是直接使用 Wilder 平滑。
  • 零除保护缺失:平均涨跌都为 0 时会出现 0/0,价格不变应该返回 50。
  • 数值稳定性不足:连续微涨或微跌时,SMMA 可能受到浮点误差影响,需要 epsilon 或明确分支。

Tester 阶段需要把这些问题转成测试,而不是只在审查报告里提醒。测试清单至少包括:

  • 第一根 Bar 返回 None
  • period - 1 根 Bar 仍返回 None
  • period 根 Bar 返回 0 到 100 之间的有效值。
  • 价格连续不变时 RSI 等于 50。
  • 连续上涨时 RSI 大于 50。
  • 连续下跌时 RSI 小于 50。
  • Wilder 平滑结果处于合理范围,并可与参考实现对照。

Documenter 阶段需要补齐使用方式、算法说明、注意事项和性能特征:

  • 使用方式:创建 IncrementalRSI(period=14),每根 Bar 调用 update,返回 None 表示数据不足。
  • 算法说明:初始阶段使用简单平均,之后使用 Wilder 平滑。
  • 注意事项:前 period - 1 根 Bar 不产出指标,价格不变返回 50,内存占用与历史数据量无关。
  • 性能特征:单次更新 O(1),固定内存,10000 根 K 线计算约 3ms,相比 Pandas 批量计算约 150ms 有明显改善。

这五轮协作形成的闭环,比任何单轮 prompt 都更重要。Architect 防止接口边界漂移,Implementer 把边界落成代码,Reviewer 找出算法和数值漏洞,Tester 把漏洞固化为回归保护,Documenter 把使用约束传递给后续维护者。没有 Reviewer,初始 RSI 计算错误可能直接进入主干;没有 Tester,价格不变返回 50 的规则会停留在口头;没有 Documenter,下一位维护者可能不知道初始阶段为什么不能直接 Wilder 平滑。

BMAD 质量门禁

BMAD 只有配合质量门禁才有意义。否则多个 Agent 只是轮流生成文本,并不能改变系统质量。

AI 工程化人工质量门禁图
图 4:人机质量门禁泳道图,AI 负责候选输出,人工负责语义签收、风险接受和证据闭环。

质量门禁可以按五级设置:

  • Architect 方案必须通过接口完整性和复杂度分析。
  • Implementer 代码必须通过单元测试、类型检查和接口约束。
  • Reviewer 审查必须无严重问题,代码质量达到约定阈值。
  • Tester 测试必须覆盖边界情况和性能约束。
  • Documenter 文档必须包含 API 说明、使用示例和注意事项。

BMAD 的收益不是“交付时间一定更短”。更现实的结果是:平均交付时间可能从 1 天增加到 1.5 天,但 Bug 逃逸率降低、边界覆盖率提升、文档完整度提升,维护成本下降。对交易系统来说,这个权衡通常是值得的,因为实盘事故和错误指标的代价远高于多半天交付时间。

质量门禁还应该保留拒绝路径。Architect 方案如果没有说明回测和实盘是否共享接口,就不能进入实现;Implementer 代码如果没有类型和异常边界,就不能进入 Review;Reviewer 发现严重问题时,不能让 Tester 用更多测试去“证明它能跑”;Tester 没有覆盖边界样本时,Documenter 不应该写成稳定能力。门禁的价值在于让失败尽早暴露,而不是让流程看起来顺利。

第三部分:AI 提示词工程最佳实践

提示词工程不是把需求写得更长,而是把角色、约束、输入、输出、示例、反问和上下文都变成可检查结构。

一个实用的判断标准是:prompt 中的每个句子是否能影响输出。如果某句话不能影响接口、测试、性能、错误处理、文档或验收,它可能只是语气修饰。交易系统里的 prompt 应该减少“尽量高质量”“写得优雅”这类不可验收表述,增加“输入为空时返回什么”“跨夜归属如何判断”“性能目标是多少”“失败时如何降级”这类可验证约束。

原则一:角色激活

角色应该具体到领域、经验和审查风格。例如“量化交易系统架构师,有 10 年高性能计算经验,专长低延迟系统设计、Python 性能优化和金融数据结构,风格注重边界情况、简洁实现和可测试性”。相比“帮忙优化一个指标”,这样的角色设置能让 AI 更倾向于讨论复杂度、状态和测试。

原则二:约束清单

约束必须区分硬性约束和建议。硬性约束包括:内存占用 O(1)、单次 update O(1)、必须包含类型注解、每个 public 方法必须有单元测试。建议可以包括:使用 deque 存储滑动窗口、考虑浮点误差、添加 benchmark。硬约束用于验收,建议用于引导实现。

原则三:输入输出格式

输入输出格式要明确到数据结构。例如输入是 List[BarData],包含 open/high/low/close/volumeperiod 是整数周期。输出包括实现代码、复杂度分析和 pytest 测试。格式明确后,AI 更容易稳定产出可接入代码,而不是写成无法落地的说明文。

原则四:反问确认

复杂任务应该先让 AI 提出 3 到 5 个澄清问题。K 线聚合函数最需要澄清的问题包括:

  • 输入 K 线是字典、类还是 DataFrame。
  • 目标周期只支持分钟转小时,还是支持任意周期。
  • 数据缺失时跳过、填充还是报错。
  • 跨夜交易如何归属,周五夜盘算周五还是下周一。
  • 性能目标是实时流式处理还是批量处理。

这些问题看起来基础,但通常正是事故来源。

原则五:迭代求精

模糊反馈会让 AI 随机重写。更好的反馈是指出具体位置、具体问题和修复要求。例如“除法缺少零保护,分母为 0 时价格不变返回 50”,“当前时间复杂度为 O(n),需要改成增量状态 O(1)”,“缺少 period > len(data) 的处理”。结构化反馈能让迭代变成收敛过程。

原则六:示例驱动

提供正常、边界和异常示例可以显著降低误解。EMA 示例可以写成:输入 [100, 101, 102, 101, 100]period=3alpha=2/(3+1)=0.5,输出依次为 [100, 100.5, 101.25, 101.125, 100.5625]。这个例子同时表达初始化方式、递推公式和预期数值。

原则七:上下文管理

大项目需要提供足够上下文,但不能把所有代码一次性塞给 AI。更有效的上下文包括:

  • 技术栈:Python 3.10、PyQt6、SQLite 或其他实际栈。
  • 已有文件:core/data.py 定义 BarDatacore/indicators.py 定义指标基类。
  • 架构约束:所有指标必须继承 IncrementalIndicator
  • 当前任务:实现 IncrementalEMAIncrementalRSI

一个完整 prompt 可以组织成这样:

角色:量化交易系统开发专家,有 8 年 Python 高性能计算经验。

任务:实现增量 EMA 计算器。

背景:
- 已有 IncrementalIndicator 基类。
- 用于实时行情推送场景,每次收到新 bar 时增量更新。
- EMA 公式为 EMA(today) = alpha * price + (1 - alpha) * EMA(yesterday)。

约束:
1. 继承 IncrementalIndicator。
2. 第一根 bar 返回 price,后续使用 EMA 公式。
3. 内存 O(1),不存储历史数组。
4. 包含类型注解、docstring 和单元测试。

示例:
输入 [100, 101, 102, 101, 100],period=3。
输出 [100, 100.5, 101.25, 101.125, 100.5625]。

实现前先提出 2-3 个需要澄清的问题。

第四部分:AI 辅助的边界与策略

AI 可以进入很多工程环节,但不同环节的签收权不能混在一起。

AI 比较擅长的任务包括:样板代码、数据类、配置解析、日志、重命名、提取函数、格式化、给定函数的单元测试、复杂代码解释、docstring 和 README 初稿。这些任务边界清晰,输出容易验证。

AI 可以承担候选实现但必须人工 Review 的任务包括:有明确规格的具体功能、复现步骤清楚的简单 Bug 修复、目标数据明确的性能优化。这类任务需要测试和审查才能进入主干。

AI 不适合直接主导的任务包括:核心架构设计、需求分析、复杂调试和技术选型。原因不是 AI 不能给出建议,而是它缺少业务上下文、团队约束、历史债务、上线风险和长期维护成本的真实感知。

人机分工可以落在下面这张表:

环节主导方AI 的作用人的责任
需求分析提出澄清问题、整理规格草案确认业务语义和优先级
架构设计提供候选方案和风险清单选择边界、接受代价
规格编写人 + AI草拟 user story、验收标准、约束签收可验收语义
代码实现AI 可主导生成候选代码Review、测试、合并
测试编写AI 可主导扩展测试用例判断断言是否代表真实风险
文档维护AI 可主导生成初稿和变更说明确认文档不误导维护者

这套分工的底线是:AI 可以产生候选,但不能独立签收语义风险。

边界策略还需要落到日常 Code Review。评审清单可以要求:AI 生成代码是否标注来源和约束,是否有对应规格,是否有边界测试,是否有性能证据,是否有人工签收的业务语义,是否有回滚路径。这样做不是为了排斥 AI,而是让 AI 产出和人工代码遵守同一套工程纪律。

第五部分:用 AI 重构遗留代码

AI 辅助重构最适合从边界清晰、风险可控的遗留模块开始。典型场景是一个 2000 行的 chart_widget.py 同时混杂数据获取、图表渲染和用户交互。随着功能增加,这个文件会成为修改禁区:改一个指标展示可能影响数据加载,改一个交互事件可能触发渲染回归。

第一步是让 AI 分析现状,但输入必须要求结构化输出:

  • 违反单一职责的位置。
  • 循环依赖。
  • 难以测试的部分。
  • 重构优先级。
  • 每个问题对应的位置、描述、建议方案和优先级。

如果 AI 只输出“建议拆分模块”,价值很低;如果它能指出数据访问、渲染状态、用户交互和事件订阅之间的耦合点,后续才有可执行入口。

第二步是让 AI 设计新架构。约束必须包括:

  • 不改变外部接口,保持向后兼容。
  • 每一层可以独立测试。
  • 使用观察者模式解耦数据变化和 UI 更新。
  • 支持未来增加新图表类型。
  • 输出文件组织建议、关键类定义和数据流说明。

第三步是让 AI 生成迁移计划。计划需要分阶段迁移,每个阶段可独立运行,每个阶段有对应测试,并且写清工作量、依赖关系和回滚策略。AI 可能生成四个阶段,团队可以根据实际风险调整为三阶段;关键不是阶段数,而是每个阶段都能独立验证。

第四步是逐阶段实现。每个阶段都应遵循同一节奏:AI 根据规格生成候选代码,人工 Review,运行测试,修复问题,再进入下一阶段。

第五步是验证。完整测试套件至少证明三件事:新旧版本功能输出一致,性能没有劣化,代码覆盖率达到约定阈值。

遗留代码重构尤其需要限制 AI 的修改半径。一次重构如果同时改文件结构、改事件模型、改渲染逻辑、改数据访问和改 UI 交互,Review 会很难判断哪个变化引入了风险。更稳妥的方式是先抽接口,保留旧路径;再让新路径和旧路径并行输出;然后用测试和用户场景确认一致;最后移除旧链路。AI 可以生成迁移步骤,但每一步是否可回滚、是否能保留旧行为,仍然需要人工判断。

重构结果可以用数据表达:

  • 代码从 2000 行单文件,变成 3 个文件约 1500 行。
  • 测试覆盖率从约 30% 提升到约 80%。
  • 修改响应时间从“改一处需要 2 天”下降到“改一处需要 2 小时”。
  • 更重要的是,团队成员重新敢于维护这个模块。

这说明 AI 辅助重构的目标不是让目录结构看起来更漂亮,而是降低维护者同时记住的上下文数量。数据层、渲染层和控制层拆开以后,测试、审查和性能定位都有了更明确的入口。

第六部分:BMAD-Speckit-SDD-Flow——把实践沉淀成受治理的交付流

前面讨论的是方法,真正落地时还会遇到更细的工程问题:规格写了,但实现入口怎么判断 ready;多 Agent 启动了,但谁决定下一条全局路径;审查做了,但失败是否真的能阻断;测试跑了,但证据是否能回到看板、评分和训练数据。这些问题在量化交易系统的 AI 工程化交付中反复出现,尤其是在交易日历、指标重构、图表性能、测试补全和遗留代码拆分这些任务上,会不断暴露“流程能跑,但治理不闭环”的风险。

BMAD-Speckit-SDD-Flow 就是在这类实践中沉淀出来的开源项目。它基于 BMAD-METHOD 与 Spec Kit 构建,把需求规范、审计流程、运行监控和评分反馈整合成一条完整交付链路。它不是再发明一个 prompt 模板,而是把 specify -> plan -> audit -> readiness gate -> runtime governance -> close-out 固化为可安装、可检查、可观测的工程面。

从技术架构看,这个项目可以理解为五层交付架构:

层级关注点对量化交易系统的意义
Product Def产品定义和业务语义交易日归属、半日市、风控边界先被定义清楚
Epic Planning史诗和跨模块计划分层数据、回测实盘统一接口、图表性能分阶段拆解
Story DevStory 生命周期每个故事都有规格、任务、测试和验收路径
Technical Implementation技术实现子代理只能执行 bounded packet,不擅自改变全局路线
Finish收口与证据通过、需修复、阻塞、重跑都会进入执行记录和看板

这套架构的关键不是层级名称,而是把“进入实现之前”和“实现结束之后”都纳入治理。很多 AI 工程流只关注中间那段代码生成,真正出问题的往往是两端:前面没有 ready baseline,后面没有 close-out 证据。

从模块角度看,项目提供了几类核心组件:

  • _bmad/:工作流模块、钩子、提示词、路由和宿主侧资产的规范源。
  • packages/scoring/:评分引擎、就绪漂移评估、看板投影、诊断输入和训练数据提取。
  • dashboard:默认运行时可观测层,用于查看运行时状态、快照和评分投影。
  • runtime-mcp:可选 MCP 工具接口,只有需要把运行时数据暴露给 Agent 工具面时才启用。
  • speckit-workflow:覆盖 Specify、Plan、GAPS、Tasks、TDD,并带强制审计循环。
  • bmad-story-assistantbmad-bug-assistantbmad-standalone-tasks:分别服务 Story、Bug 和独立任务路径,但全局路线仍由主 Agent 读取 inspect 后决定。

它重点治理五类常见 AI coding failure modes。

第一类是 requirement hallucination。AI 很容易在需求不完整时自行补全业务语义,例如默认自然日就是交易日、默认半日市没有夜盘、默认缺失数据可以填充。交易系统里,这类“看似合理的补全”会直接污染指标和回测。BMAD-Speckit-SDD-Flow 用 Specify、Clarify、GAPS 和 Cross-Document Traceability 把需求、澄清问题、假设和任务绑定起来。没有被规格和澄清记录承接的语义,不能直接变成实现。

第二类是 implementation drift。即使初始规格正确,Agent 在实现过程中也可能逐步偏离原始约束:为了让测试通过改了接口,为了简化代码绕过性能预算,为了赶进度把回测和实盘写成两套逻辑。项目用 story packet、bounded task、主 Agent inspect 和任务级 traceability 控制实现半径。子代理只执行被授权的 packet,不决定全局路线;实现结果必须回到规格、任务、测试和证据链,而不是只看代码是否能运行。

第三类是 pseudo-implementation without E2E integration evidence。这是最隐蔽的一类失败:代码、单元测试和文档都存在,但没有端到端集成证据,功能没有真正接入真实路径。量化系统里常见表现是聚合器单测通过,但 UI、数据导入、回测引擎和实盘监控没有共用同一语义。项目引入 Smoke E2E ReadinessEvidence Proof Chain,要求关键路径有最小冒烟场景、证据链和验收记录。没有 E2E 接入证据的实现,只能视为候选实现,不能视为交付完成。

第四类是 one-pass execution without critical iterative reasoning。一次性执行通常会把设计、实现、测试、修复和收口压成一轮,缺少批判性迭代。AI 可能第一轮给出可运行方案,但没有经历 Reviewer 的反例、Tester 的边界样本和重新设计。项目把审计循环、required-fixes、blocked、rerun 和 scoring 作为流程的一部分,让失败不被吞掉。对 RSI 初始化、半日市归属、性能预算这类问题,必须允许流程回退到澄清、计划或实现阶段,而不是一轮跑完就关闭。

第五类是 premature closure without reviewable delivery artifacts。很多 AI 交付会在“代码已改、测试已跑”后过早结束,但后续维护者看不到规格、决策、失败修复、E2E 证据和收口结论。项目把 close-out、packet execution truth、dashboard、coach 和 SFT extraction 串起来,让 pass、required-fixes、blocked、rerun 等结果变成可复查资产。对长期维护的交易系统来说,这意味着失败样本、修复过程、审计结论和最终证据可以服务下一轮诊断,而不是散落在聊天记录、终端输出和个人记忆里。

一个可落地的使用方式是先从消费项目安装,而不是直接改框架源码:

npx --yes --package bmad-speckit-sdd-flow@latest bmad-speckit version
npx --yes --package bmad-speckit-sdd-flow@latest bmad-speckit-init . --agent codex --full --no-package-json
npx --yes --package bmad-speckit-sdd-flow@latest bmad-speckit check
npx --yes --package bmad-speckit-sdd-flow@latest bmad-speckit dashboard-status

这类工具最适合用于高风险、长链路、证据要求高的交付场景,例如交易日历、撮合引擎、指标重构、回测实盘统一接口、风控状态机和性能治理。对普通小修复,它可能显得偏重;对真实资金风险、多人协作和长期维护来说,强制规格、审计、就绪、运行时管控和证据收口反而能降低长期成本。

总结:AI 工程化的三个核心原则

第一,规格先行。AI 需要约束,规格就是最有效的约束。花 30 分钟写清楚交易日、半日市、数据断层和验收标准,通常能省下数小时返工。

第二,多 Agent 协作。单一 AI 容易陷入局部最优。BMAD 的 Architect、Implementer、Reviewer、Tester、Documenter 可以从架构、实现、审查、测试和文档五个角度降低盲区。

第三,人机分工。AI 做候选、扩展和整理,人负责语义、风险和签收。交易系统面对的是真实行情、真实资金和长期维护,任何 AI 输出都必须经过规格、测试、审查和证据闭环。

工具与资源

开源项目入口:

  • GitHub Spec Kit:GitHub 开源的 Spec-Driven Development 工具包,用于把产品场景、规格和实现入口连接起来。
  • BMAD-METHOD:开源 Agile AI-driven Development 方法和模块生态,用角色化 Agent 与工作流强化协作质量。
  • BMAD-Speckit-SDD-Flow:基于 BMAD-METHOD 与 Spec Kit 的治理型 SDD 交付流,提供运行时管控、强制审计、看板和 npm 安装路径。

speckit 命令可以按功能组织:/speckit.specify <feature-name> 创建规格,/speckit.clarify <decision-topic> 记录技术决策,/speckit.plan 生成实现计划,/speckit.checklist 做验收检查。

BMAD Agent 可以按角色激活:/bmad-agent-bmm-architect 用于架构方案,/bmad-agent-bmm-dev 用于候选实现,/bmad-agent-bmm-qa 用于测试和质量检查。

常见工具包括 Cursor AI 编辑器、Claude Code CLI、Codex、speckit 规格模板、BMAD 多 Agent 工作流和 bmad-speckit-sdd-flow。工具本身不是重点,重点是每个输出都要进入规格、测试、审查、运行时管控和验收证据。

系列收束

AI 工程化是本系列的能力增强层。前面的系统边界、真实缺陷、测试防线、性能治理和架构演进,最终都需要交付流程承接。读者回到自己的系统时,可以先从一个最小闭环开始:选一个语义风险明确的功能,写清规格和澄清决策,拆计划,生成候选实现,补测试和文档,再用质量门禁签收。

如果 AI 让代码变快,却让证据变少,系统风险会上升。如果 AI 让规格、测试、审查和文档都变得更可追踪,它才真正进入了工程化。

Series context

你正在阅读:量化交易系统开发实录

当前为第 7 / 7 篇。阅读进度只写入此浏览器的 localStorage,用于回到系列页时定位继续阅读入口。

查看完整系列 →

Series Path

当前系列章节

点击章节会在此浏览器记录本地阅读进度;刷新后可继续阅读。

7 chapters
  1. Part 1 已在路径前序 量化交易系统开发实录(一):项目启动与架构设计的五个关键决策 以 Micang Trader 为案例,从系统边界、数据流、交易时段归属、回测实盘统一接口和 AI 协作边界出发,建立整个量化交易系统系列的架构主线。
  2. Part 2 已在路径前序 量化交易系统开发实录(二):Python Pitfalls 实战避坑指南(上) 把 Python 陷阱从长清单重组为量化交易系统的工程风险参考篇:语法与作用域、类型与状态、并发与状态三类风险如何放大为真实交易系统问题。
  3. Part 3 已在路径前序 量化交易系统开发实录(三):Python Pitfalls 实战避坑指南(下) 继续把 Python 风险重组为参考篇:GUI 生命周期、异步网络失败、安全边界和部署基础设施如何影响量化交易系统的长期稳定性。
  4. Part 4 已在路径前序 量化交易系统开发实录(四):测试驱动敏捷开发(AI Agent 辅助) 从一个跨夜交易日边界 bug 出发,重构量化交易系统的测试防线:缺陷导向测试金字塔、AI TDD 分工、边界时间、数据血缘和 CI Gate。
  5. Part 5 已在路径前序 量化交易系统开发实录(五):Python 性能调优实战 把性能优化从经验猜测改造成可验证的侦查流程:从 3 秒图表延迟出发,定位真实瓶颈,比较优化方案,建立 benchmark 与回退策略。
  6. Part 6 已在路径前序 量化交易系统开发实录(六):架构演进与重构决策 复盘 Micang Trader 的五次重构,解释系统如何从初始快照演进为更清晰的目标架构,并把技术债务和 ADR 决策纳入长期治理。
  7. Part 7 当前阅读 量化交易系统开发实录(七):AI 工程化落地——从 speckit 到 BMAD 以交易日历与日线聚合需求为单一案例,解释 AI 工程化如何通过规格驱动、BMAD 角色交接和人工质量门禁进入真实量化系统交付。

Reading path

继续沿这条专题路径阅读

按推荐顺序继续阅读 量化系统开发实战 相关内容,而不是只看同专题的随机文章。

查看完整专题路径 →

Next step

继续深入这个专题

如果这篇内容对你有帮助,下一步可以回到专题页继续系统阅读,或者订阅后续更新。

返回专题页 订阅 RSS 更新

RSS Subscribe

订阅更新

通过 RSS 阅读器订阅获取最新文章推送,无需频繁访问网站。

推荐使用 FollowFeedlyInoreader 等 RSS 阅读器

评论与讨论

使用 GitHub 账号登录参与讨论,评论将同步至 GitHub Discussions

正在加载评论...