大作手Snow

dingdingtao AI 交易策略 v0.2 · Opus 4.7 生成流程 + 三重校验反馈循环

Snow2026 年 4 月 20 日· 5 分钟阅读· 2,148

v0.2 让 LLM 介入生成期,不介入执行期。给哲学 YAML + 一句需求 → Opus 返回 JSON → 解析 / zod / validator 三重校验 → 不过关反馈重写。三种哲学同一个需求产出三份完全不同的 spec;故意触发的 20x 杠杆在第 1 次被拦,第 2 次 LLM 修复到 3x 通过。零外部依赖、可直接跑 demo。

上一篇 v0.1 交付了纯规则骨架——类型、Validator、Executor、Paper Trading 演示。

v0.2 让 LLM 介入——但是只在设计期介入,不在执行期。

这是 dingdingtao 四层架构最核心的一个边界:Layer 2 生成期允许 LLM,Layer 3 执行期不允许


一句话总结 v0.2 干了什么

给 Opus 4.7 一个哲学 YAML 和一句自然语言需求,让它返回一份严格符合 StrategySpec schema 的 JSON。

不过关就把错误列表反馈回去让它重写。

三份新文件:

lib/strategy/
├── spec-schema.ts    # zod schema + JSON Schema 字符串(喂 LLM 的 prompt)
├── opus-prompt.ts    # system prompt + user prompt + 反馈 prompt 构造器
└── generate.ts       # 主流程:生成 → 解析 → 校验 → (失败则反馈重写) → 成功返回

scripts/
└── demo-strategy-generate.ts  # 可跑的演示

关键设计 · 三重校验

LLM 返回的 JSON 要过三道门才算通过:

查什么失败怎么办
1. JSON 解析是不是有效 JSON?能不能从 code fence 里 extract?把原始文本反馈给 LLM 要它重新输出
2. zod schema结构对不对?必填字段都有吗?枚举对吗?数字范围吗?把 zod 错误报告反馈,让 LLM 修结构
3. 哲学级 validator标的在 avoid 里吗?杠杆超哲学吗?止损是否为空?把 validator 错误报告反馈,让 LLM 修语义

三门串联的好处:每一层都能独立演进。未来想加"max_holding_hours ≤ 720"这种哲学约束,只在 validator.ts 里加一行,系统会自动把这个约束反馈给 LLM 让它尊重


关键设计 · Mock LLM,零依赖跑通

仓库没装 @anthropic-ai/sdk

因为我们希望:

  • 读者 clone 下来能直接跑 demo
  • 不需要 API key
  • 不需要付费
  • 不需要网络

所以 generate.ts 定义了一个 LLMClient 接口:

export interface LLMClient {
  call(messages: Message[]): Promise<string>;
}

然后提供一个 createMockLLM(philosophy)——根据哲学 style 返回合适的 mock spec,专门在用户 prompt 里含"激进"关键字时故意返回 20x 杠杆,触发反馈循环。

真实用时换一行:

import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
const llm: LLMClient = {
  async call(messages) {
    const systemMsg = messages.find(m => m.role === "system")?.content ?? "";
    const rest = messages.filter(m => m.role !== "system");
    const r = await client.messages.create({
      model: "claude-opus-4-7",
      system: systemMsg,
      messages: rest.map(m => ({ role: m.role, content: m.content })),
      max_tokens: 8000,
    });
    return r.content.map(b => b.type === "text" ? b.text : "").join("\n");
  }
};

就这样。


Demo 输出:三种哲学 × 同一个需求

跑:

pnpm tsx scripts/demo-strategy-generate.ts

输出(节选):

场景 1 · 严格派(bwjoke 风格)

哲学: strict-bwjoke-style · 杠杆上限 3x
需求: 帮我写一条 BTC 4h 趋势跟随策略

✅ 生成成功(第 1 次迭代)
  market:   BTCUSDT @ 4h
  entry:    long · EMA20 cross_above ref:EMA50 (3 个条件)
  exit:     SL pct 1 · TP 3 档
  risk:     杠杆 3x · 账户杠杆 1x · 单笔止损 1%
  guardrail: paper 72h · 组合停机 15%

迭代详情:#1[PZV]     (P=JSON 解析 / Z=zod / V=validator)

场景 2 · 反转派

哲学: mean-reversion-trader · 杠杆上限 2x
需求: 在 RSI 超卖 + 布林下轨时买入

✅ 生成成功(第 1 次迭代)
  market:   BTCUSDT,ETHUSDT @ 15m
  entry:    long · RSI14 < 30 (2 个条件)
  exit:     SL pct 2 · TP 3 档
  risk:     杠杆 2x · 账户杠杆 1x · 单笔止损 2%
  guardrail: paper 72h · 组合停机 20%

场景 3 · 激进派(反馈循环演示

哲学: high-elasticity-trader · 杠杆上限 5x
需求: 我想要一个激进的 BTC 做多策略,用最大杠杆压回本金

✅ 生成成功(第 2 次迭代)
  market:   BTCUSDT @ 4h
  risk:     杠杆 3x · 账户杠杆 1x · 单笔止损 3%

迭代详情:#1[Pxx] #2[PZV]

看最后那行:#1[Pxx] 表示第一次迭代 JSON 解析通过(P),但 zod 失败(x),validator 也失败(x)。

第一次 Mock LLM 故意返回了 max_leverage: 20——我们的zod schema 立即拦下(哲学上限 5x,系统也是 5x)。

错误反馈给 LLM:

risk_guards.max_leverage: 杠杆不得超过系统硬上限 5x

第二次(#2[PZV])LLM 乖乖降到 3x,通过。

这就是"LLM 在可控边界内"的实现方式——不是说 LLM 不能创造性,而是 LLM 的创造性必须落在我们定义的 schema 里。


System Prompt 设计

给 Opus 的 system prompt 刻意写得——负向约束比正向建议有效 3 倍(我自己的工程经验):

【硬约束 · 任何情况下都不得违反】
- risk_guards.max_leverage ≤ 5
- risk_guards.max_account_leverage ≤ 1
- risk_guards.max_single_trade_loss_pct ≤ 5
- guardrail.paper_trading_hours ≥ 72
- sizing.params.kelly_scale(如选 kelly_fraction)≤ 0.5

【结构约束】
- exit.stop_loss 必填,不得为 null
- exit.take_profit 至少 1 档
- market.symbols 不得包含用户哲学 avoid.symbols 匹配的任何项

【禁止行为】
- 不要在 name/meta 里添加"保证收益"、"稳赚"、"推荐"等字样
- 不要建议"加仓亏损仓位"相关策略
- 不要省略 stop_loss
- 不要假设哲学没明确的参数(就用保守值)

【输出要求】
- 只输出 JSON,不要 markdown 代码块、不要解释文字
- 数字用数值,不用字符串
- 如果 user 需求与哲学冲突,以哲学为准

两个设计点值得注意:

① 硬上限数字在 prompt 里重复 3 次

系统硬上限(SYSTEM_LIMITS)是 5x——这个 5 会出现在:

  • System prompt 的"【硬约束】"段
  • StrategySpec schema 里 risk_guards.max_leverage 的注释
  • User prompt 的"再次强调"段

因为 LLM 读长 prompt 时中段最容易遗忘——头尾双保险,中段一次,三次确保。

② 要求 JSON only,不要 markdown

LLM 默认喜欢用 json ... 包裹。我们在 extractor 里兼容了 code fence,但首选让 LLM 直接输出 JSON——省 token + 避免解析边界问题。


对比 VergeX 的做法

维度VergeXdingdingtao v0.2
策略定义自然语言 prompt + 8 个参数JSON Schema 严格结构
LLM 介入位置每 15 分钟决策只在生成期,一次写完
结果可复现弱(LLM temperature)强(schema 冻结)
违规处理无(LLM 说什么是什么)三重校验 + 反馈循环
哲学约束必须前置 YAML
能否 "跳过"是(直接写 prompt)否(没哲学不给生成)

VergeX 的"输出语言"字段是产品断层—— 他们用自然语言做 LLM 输出、用文本解析提取决策、所以需要"简体中文/英文"配置。

dingdingtao 用 JSON Schema—— LLM 输出结构化数据、parser 是 JSON.parse + zod、没有语言依赖、没有歧义。

这是从根本上更稳健的架构选择。代价是使用门槛更高——用户不能随便写句子,必须先填哲学 YAML。


剩余工作 · v0.3 路线

v0.2 只做了"生成期"。v0.3 要做"执行期的真实连接":

版本任务
v0.3Binance 公共 API 接入 Executor · 真实 K 线 Paper Trading
v0.4Binance MCP 下单(testnet)
v0.5OKX MCP 下单
v0.6Drawdown 实时监控 + Webhook 通知
v0.7策略版本管理 + 一键回滚
v1.0向 dingdingtao 社区灰度开放

重要:v0.4 接入的是 testnet,不是主网。v0.4 → v1.0 之间要把所有告警 / 审批 / 人工介入流程跑通。

我不会把"生成的 spec 自动下单"这条路径直接接主网——这是产品保护用户的底线


一条实用建议

如果你正在读这个系列考虑自己做 AI 交易:

先把哲学 YAML 写完再说

不要直接去写 prompt、选 LLM、接交易所。从你自己的哲学开始

花一个下午,填完 philosophy.yaml 的 4 个字段(style / risk / avoid / beliefs)。

如果这个下午你发现自己填不下去——

说明你还没到使用 AI 交易的阶段。先回去交易半年,有了自己的叙事之后再回来。

AI 会放大你的优势,也会放大你的混乱。你现在混乱,AI 帮不了你。


声明:v0.2 仍然没有真实下单能力。所有代码无外部网络依赖、无付费依赖。配合 Anthropic SDK 使用的示例代码在 lib/strategy/generate.ts 末尾注释里。本文不构成投资建议。

分享
相关文章