前面七篇都在讲方案——这一篇代码落地。
lib/strategy/ 下 v0.1 代码骨架提交完毕,一个可跑的 Paper Trading 演示跟着。
这还不是能接真交易所的产品。这是方案的可执行证明——让你看 validator 怎么拦 / executor 怎么跑 / Paper Trading cutoff 怎么评估。
v0.1 的文件
lib/strategy/
├── types.ts # 类型系统(Philosophy / StrategySpec / Action)
├── validator.ts # 校验器(Philosophy & Spec 双层)
├── executor.ts # 纯函数 Executor
└── examples/
├── philosophy.example.yaml # 哲学模板
└── spec.example.json # 示例 StrategySpec
scripts/
└── demo-strategy-paper-trading.ts # Paper Trading 演示脚本
跑一下:
pnpm tsx scripts/demo-strategy-paper-trading.ts
代码走读:四个核心决策
决策 1 · 系统级硬上限写死在 types.ts
// lib/strategy/types.ts
export const SYSTEM_LIMITS = {
MAX_LEVERAGE_PER_POSITION: 5,
MAX_ACCOUNT_LEVERAGE: 1,
MAX_SINGLE_TRADE_LOSS_PCT: 5,
MAX_DAILY_LOSS_PCT: 10,
MAX_DRAWDOWN_STOP_PCT: 30,
MAX_CONCURRENT_POSITIONS: 5,
MIN_PAPER_TRADING_HOURS: 72,
MAX_KELLY_SCALE: 0.5,
} as const;
这不是配置,是常量。
任何通过 API 传进来的 spec、任何 Opus 生成的 spec、任何用户填的哲学 YAML——都不能突破这些数字。Validator 会一律拦下。
决策 2 · Validator 返回错误列表,不是抛异常
export interface ValidationResult {
ok: boolean;
errors: ValidationError[];
warnings: ValidationError[];
}
为什么不抛异常?因为 Opus 4.7 生成的 spec 不过关时,我们要把错误列表返还给 LLM 让它重写。一次抓全部错误效率最高。
跑演示时:"故意违反哲学"的 bad spec 一次性拦下 4 个错误:
❌ Spec 校验失败(4 个阻断错误)
🚫 risk_guards.max_leverage
实际: 20 · 预期: ≤ 5
原因: 突破系统级单仓杠杆硬上限
🚫 risk_guards.max_leverage
实际: 20 · 预期: ≤ 5 (philosophy.risk.max_leverage)
原因: 超过哲学声明的单仓杠杆上限
🚫 market.symbols: "PEPEUSDT"
实际: PEPEUSDT · 预期: 不匹配 philosophy.avoid.symbols 中的 "*PEPE*"
原因: 标的在哲学 avoid list 里,必须剔除
🚫 exit.stop_loss
实际: null · 预期: 必填
原因: 止损不能为空
四个维度同时校验 · 一次性返回 · 清晰可读。
决策 3 · Executor 是纯函数
export function runStrategy(
spec: StrategySpec,
tick: MarketTick,
state: StrategyState,
): Action[] {
// 1. 检查是否允许新开仓
// 2. 评估 entry 条件
// 3. 检查现有仓位的出场
// 4. 输出 Action[]
}
没 new Date()(时间戳从 tick 传入)、没 fetch、没 env。
同 spec + 同 tick + 同 state = 永远同 Actions。
这是我们和 VergeX 最本质的不同。VergeX 的 "Executor" 是 LLM——每次调用结果都可能不一样。我们的 Executor 是 if-else,跑 10000 次给 10000 个相同答案。
可复现性 = 可审计性 = 真·合规性的起点。
决策 4 · Paper Trading 必须走完 Cutoff
guardrail: {
paper_trading_hours: 72,
paper_cutoff: {
min_sharpe: 1.0,
max_drawdown_pct: 20,
min_trades: 20,
},
portfolio_drawdown_stop_pct: 20
}
演示脚本跑完后自动输出 Cutoff 检查:
Paper Trading Cutoff 检查
━━━━━━━━━━━━━━━━━━━━━━━━━
交易数 ≥ 20: ❌ (0)
最大回撤 ≤ 20%: ✅ (0.00%)
夏普 ≥ 1: ⏸ 需要更长样本估算
结论: 🔴 未通过 cutoff,需要迭代 spec
演示里 0 笔交易是故意的——示例 spec 的 cross_above 入场条件在我的简化 evaluator 里不实现,所以没有机会开仓。
这恰好示范了"严格评估 vs LLM 松评"的差异。如果换成 VergeX 的 LLM:
- 给它同样的数据
- 同样的提示词"EMA20 上穿 EMA50 做多"
- LLM 会模糊地觉得"现在趋势还可以,开一单吧"——开了 50 笔
我们的 if-else 说:没满足严格的 cross_above 条件就不开仓。
哪种对? 两者都"对"——它们服务不同的心智模型。但如果你的定位是"纪律执行器",你必须选 if-else。
还没做的(v0.2 路线图)
v0.1 刻意只做骨架,不做真实执行:
| 功能 | v0.1 | v0.2+ |
|---|---|---|
| Philosophy / Spec 类型 | ✅ | — |
| 双层 Validator | ✅ | — |
| 纯函数 Executor | ✅ | 补 cross_above 历史状态 |
| 3 种 sizing method | ✅(fixed/kelly/vol-target 有定义) | 补完整实现 |
| Paper Trading demo | ✅(合成数据) | 接入 Binance 历史 K 线 |
| Opus 4.7 生成流程 | ❌ | v0.2 首要 |
| Binance MCP 下单 | ❌ | v0.3 |
| OKX MCP 下单 | ❌ | v0.4 |
| Drawdown 实时监控 | ❌ | v0.5 |
| Webhook 通知 | ❌ | v0.6 |
v0.2 的核心任务:实现 lib/strategy/generate.ts——给 Opus 4.7 喂 philosophy + 需求,返回通过 validator 的 spec。
预计 v0.2 要解决的工程问题:
- Opus 4.7 的 JSON Schema 强制输出
- Validator 失败时的"重写循环"(feedback loop)
- 系统 prompt 的 token 效率(不能一次喂 2000 字)
- 测试:10 种不同哲学,每种生成 5 条 spec,看是否全部过 validator
哲学 YAML 示例长什么样
# lib/strategy/examples/philosophy.example.yaml
trader_id: dingdingtao
version: 2026-04-19
style:
primary: trend_following
timeframe: [4h, 1d]
beliefs:
- "BTC 是主趋势,山寨是杠杆"
- "胜率 40% 足够,盈亏比 2.5:1 才是核心"
risk:
max_single_trade_loss_pct: 2
max_daily_loss_pct: 5
max_drawdown_hard_stop_pct: 20
max_leverage: 5
max_account_leverage: 1
max_concurrent_positions: 3
avoid:
symbols:
- "*PEPE*"
- "*SHIB*"
- "*DOGE*"
- "/\\w+FLOKI\\w+/"
scenarios:
- "FOMC day ±4h"
- "主流交易所维护窗口"
behaviors:
- chase_big_candle
- average_down
- pyramid_loss
- trade_during_fomc
23 行 YAML 完整表达一个交易者的哲学。
这是强制前置的——没填哲学的用户,系统不给你生成策略。这是我们和 VergeX 最大的产品边界:我们不取悦懒人。
怎么用
如果你是在 dingdingtao 仓库里跑演示
pnpm install
pnpm tsx scripts/demo-strategy-paper-trading.ts
会看到 4 步:
- Philosophy 校验 ✅
- 合法 Spec 校验 ✅
- 非法 Spec 校验 ❌(4 errors)
- Paper Trading 模拟(300 根 4h K 线)
如果你想在自己的项目里用这套类型
直接把 lib/strategy/types.ts + validator.ts + executor.ts 拷出去,三个文件,约 800 行 TS,无外部依赖(只依赖 TS 本身)。
import type { StrategySpec, Philosophy } from "./types";
import { validateSpec, formatValidationReport } from "./validator";
import { runStrategy } from "./executor";
const r = validateSpec(mySpec, myPhilosophy);
if (!r.ok) {
console.error(formatValidationReport(r));
throw new Error("spec invalid");
}
const actions = runStrategy(mySpec, currentTick, currentState);
系列真正的落地
#216-#222 都是论述。这一篇是落地的起点。
后面 v0.2-v1.0 每一版都会有一篇 /posts 对应的更新文章。关注 dingdingtao 的 RSS 可以不漏过。
主轴一句话不变:
AI 是纪律执行者,不是行情预测者。 构建策略的人,比策略本身更重要。 约束的价值,比信号的价值更重要。
v0.1 把"约束"这个词从理论变成了代码。
声明:v0.1 代码只包含 类型定义 + 校验器 + 纯函数 Executor + Paper Trading 演示,没有任何真实下单能力。本仓库目前仍然只做只读的交易所数据聚合(lib/exchanges/)。所有代码采用 MIT 兼容的内部许可,跟着项目主许可走。本文不构成投资建议。