本节摘要:决策门的架构(Context 进、Choice 出)定下来之后,门后面的判断引擎是可以替换的。默认选项是 Jev 托管服务——QuantDinger 与 Jev System One 的集成开箱即用(官方 README 口径),代价是判断上下文要出境给外部服务、且依赖其可用性。替代选项是自托管 Kev 或 Laya:两者与 Jev 在决策协议上同构(即 Decision Context 与 typed Choice 的接口形态可以对接),换来自主可控、数据不出域与成本结构的变化,代价是运维责任回到自己手里。本节给一张选型小表、切换时的影子验证方法,以及一份"什么时候该换"的判断清单。Kev 与 Laya 的内部细节不在本书展开,分别见《Kev 实战:训练并运行你自己的决策模型》第 01 章《协议与兼容》与《Laya 实战:多语言轻量决策引擎与路由》第 04 章。
QuantDinger 与 Jev System One 集成(官方 README 口径),决策门默认走 Jev 托管服务。对绝大多数读者,这是正确的起点,原因有三:
托管的代价也要如实写:每次判断的 Context 要发往外部服务,持仓与信号信息出境;判断质量依赖服务方的迭代;账单随调用量线性增长。这三条是否构成问题,取决于你的数据边界要求、合规要求与用量规模。
当托管的代价不可接受时,协议同构的自托管引擎是替代路径。同构的含义:Decision Context 与 typed Choice 这套接口形态不只 Jev 能说,Kev 与 Laya 也实现了兼容的协议层——门的架构(9.1 节)不动,引擎在后面换掉:
门架构不变,引擎可换 Decision Context V2 ──▶ ┌──────────────┐ ──▶ typed Choice │ Jev(托管) │ 默认 │ Kev(自托管) │ 自训模型路线 │ Laya(自托管) │ 轻量路由路线 └──────────────┘ 三者协议同构:换引擎不改门的上下游代码
两条自托管路线的一句话定位(细节见各自的书,本书不展开):
| 引擎 | 路线定位 | 深入阅读 |
|---|---|---|
| Kev | 训练并运行你自己的决策模型,判断逻辑完全自主 | 《Kev 实战:训练并运行你自己的决策模型》第 01 章《协议与兼容》 |
| Laya | 多语言轻量决策引擎,侧重路由与低资源部署 | 《Laya 实战:多语言轻量决策引擎与路由》第 04 章 |
协议兼容的细节(字段映射、版本对齐、置信度口径)以两本书的协议章节与 QuantDinger 官方文档为准——"同构"降低的是改造成本,不是归零成本,切换工程量要在计划里如实估计。
| 维度 | Jev 托管 | Kev/Laya 自托管 |
|---|---|---|
| 接入成本 | 最低,配置即用 | 中到高:部署、协议对接、验证 |
| 数据边界 | Context 出境给服务方 | 数据不出你的基础设施 |
| 判断质量迭代 | 随服务方升级 | 随自己的模型/规则迭代,自主也自负 |
| 运维责任 | 无(可用性由 9.2 节容错兜底) | 门引擎进入第 11 章运维清单 |
| 成本结构 | 按量计费,随调用量增长 | 基础设施与人力,固定为主 |
| 合规适配 | 需确认服务方数据处理条款 | 自主可控,自己负责 |
选型的诚实问法不是"哪个更好",而是三个具体问题:我的 Context 能不能出境(数据与合规);我的调用量下两种成本结构谁划算(量级测算);我有没有能力运维一个判断服务(人力现实)。三个问题都指向托管,就用托管;任何一个答案是硬约束,再启动自托管评估。
引擎切换的正确姿势与 9.1 节启用门时相同——影子先行:
| 序 | 步骤 | 通过标准 |
|---|---|---|
| 1 | 新引擎并行接入(影子模式,只记录不影响订单) | 稳定运行,无协议报错 |
| 2 | 双引擎 choice 一致率统计 | 一致率与分歧分布成文可解释 |
| 3 | 分歧样本逐条复核 | 分歧来源定位(口径差/能力差) |
| 4 | 延迟分布对比 | 新引擎在预算内(9.2 节) |
| 5 | 切换窗口执行 | 低峰切换,观察一个完整交易日 |
| 6 | 保留回切预案 | 旧引擎配置保留,一键切回 |
第 2 步的一致率没有普适标准,重要的是第 3 步:分歧不是噪声,是新引擎的"性格说明书"。低于预期的同意率可能意味着新引擎更保守,此时直接切上去等于改了门的松紧——先理解分歧,再谈切换。
第 2 步的统计同样可以脚本化(纯标准库):
# agreement.py —— 双引擎 choice 一致率统计(切换验证第 2 步的工具) def agreement(rows_a, rows_b): """rows_x: [{signal_id, choice}];按 signal_id 配对后统计一致与分歧""" b = {r["signal_id"]: r["choice"] for r in rows_b} same = diff = unpaired = 0 mismatch = [] for r in rows_a: other = b.get(r["signal_id"]) if other is None: unpaired += 1 # 只有一个引擎出过 choice elif other == r["choice"]: same += 1 else: diff += 1 mismatch.append((r["signal_id"], r["choice"], other)) total = same + diff return { "agreement": round(same / total, 3) if total else None, "diff_count": diff, "unpaired": unpaired, # 未配对本身是重要信号:一侧超时或报错 "diff_samples": mismatch[:20], # 抽样供第 3 步逐条复核 }
注意 unpaired 一行:只在一个引擎留下记录的信号,往往是一侧超时或报错——它们不算"分歧",但算"可用性差异",切换决策里要单独看,而不是顺手丢掉。
把六步走成时间线(示意):影子并行第一至二周只做第 1、2 步——稳定运行与一致率成文;第三周做第 3 步,把 diff_samples 逐条看完并归类(口径差还是能力差);第 4 步延迟对比若不达标,先回引擎侧调配置而不是放宽预算;切换窗口选低峰时段,切换日盯完一个完整交易日;第 6 步的回切预案不是摆设——旧引擎配置保留到新引擎平稳运行满一个观察周期(量级建议:一至两周)为止。
该启动评估的信号:数据出境条款变化或合规要求收紧;调用量增长使托管成本曲线失控;你已建立模型能力且判断质量成为明确的瓶颈。不该换的信号同样重要:仅仅因为"自托管看起来更极客";门还在影子期、连默认引擎的分布都没摸清;系统里还有比门更薄弱的环节(对账、备份、应急演练)没做完——把工程预算花在最弱的一环,是本章贯穿始终的优先级判断。
| 问题 | 排查方向 | 要点 |
|---|---|---|
| 自托管引擎协议对接报错 | 字段映射、版本对齐、置信度口径 | 回两本书的协议章节核对,不同构点列清单 |
| 一致率很高但仍不敢切 | 分歧样本太少还是太集中 | 集中在某类行情的分歧比零星分歧更值得先解释 |
| 切换后否决率明显变化 | 新引擎性格差异,非策略变化 | 回看影子期分布,这本就该预料到 |
| 自托管引擎延迟波动大 | 资源竞争、批量调用 | 对照 9.2 节延迟预算,波动本身就是风险 |
| 想回切但旧配置已删 | 回切预案保留期没写死 | 教训入档:第 6 步的保留期要落成文字 |
第二行值得展开:一致率的数字好看,不等于可以切换。如果仅有的几次分歧全部集中在高波动时段,说明两个引擎对"什么时候该谨慎"的刻画不同——这恰恰是交易场景里最要紧的分歧,样本再少也要解释清楚。反过来,分歧均匀散落在各种行情里、理由五花八门,更接近噪声,切换风险反而小。一致率告诉你像不像,分歧的结构才告诉你能不能换。
决策门是 QuantDinger 自己用的判断防线。下一章把视角转向外部:Agent Gateway 与 MCP server 让你自己的智能体也能调用这台交易系统——查行情、跑回测、下 paper 单,全部走作用域 token 的分级权限,以及那组按下去就能救命的多重应急开关。