工具链

用 Claude Code 在 90 秒内回测 Pine 策略

走一遍 @pineforge/codegen-mcp:一条 npx 命令安装,让 Claude 把你的 Pine transpile 成 C++,用 Docker 跑回测并读交易列表。OHLCV 不离开本机。

约 7 分钟阅读#mcp#ai#claude#cursor#tooling

几个月以来,PineForge codegen 一直躲在 curl 后面;从这周起,它也在 Model Context Protocol 服务器背后——你可以在任意支持 MCP 的客户端里(Claude Desktop、Claude Code、Cursor、Continue.dev 等)把回测一路跑完。

这是一篇端到端 walk-through:从空仓库到拿到 JSON 回测报告,墙上时钟大约 90 秒,外加首次 docker pull 的一次性成本。

服务器到底做什么

npm 上的 @pineforge/codegen-mcp 是一层很薄的本地 stdio 桥。它向 AI 客户端暴露 四个工具

Tool运行位置成本
transpile_pine托管 codegen API占用配额(编译失败会退回)
get_quota托管 codegen API免费
backtest_pine本机 Docker计 1 次(内含那次 transpile)
pull_engine_image本机 Docker免费

值得停顿一下的是 隐私面。Pine 源码会发到托管 codegen(codegen.pineforge.dev)。OHLCV CSV 不会发。 backtest_pine 在你本机 Docker 里用生成的 strategy.cpp 对着你指定的文件跑;CSV 只读挂载进容器。运行时容器 没有外出网络数据留在你的笔记本上。

安装(一条命令)

npx -y @pineforge/codegen-mcp

够了。首次运行会下载包、即时编译 TypeScript,然后开始用 stdio 讲 MCP。不必全局安装,也不必单独 build。

你需要准备好三件事:

  • Node ≥ 20
  • 本机 Docker 正在运行(backtest_pinedocker run
  • 通过 pineforge.dev 候补名单拿到的 pf_… API key

接入 Claude Desktop

打开配置文件:

  • macOS:~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows:%APPDATA%\Claude\claude_desktop_config.json

mcpServers 下加上:

{
  "mcpServers": {
    "pineforge-codegen": {
      "command": "npx",
      "args": ["-y", "@pineforge/codegen-mcp"],
      "env": {
        "PINEFORGE_API_KEY": "pf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
      }
    }
  }
}

重启 Claude Desktop。侧边栏「可用工具」里会出现该服务器。第一次调用会打到托管 codegen,并触发运行时镜像的 docker pull——大约 250 MB,只做一次

Claude Code(CLI)

如果你已经在终端里,这样更短:

claude mcp add pineforge-codegen \
  --transport stdio \
  --env PINEFORGE_API_KEY=pf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
  -- npx -y @pineforge/codegen-mcp

重新开会话后四个工具可用。

Cursor

Settings → MCP → New MCP Server → 粘贴同一段 JSON。Cursor 负责进程生命周期。

用自然语言驱动

接好后,交互就是普通中文/英文提示词。略压缩的真实对话:

你: ./strategy.pine 里是 Pine v6 策略,./eth_15m.csv 是 7 天 15 分钟 ETHUSDT。跑回测,告诉我 Sharpe 和最大回撤。

Claude: 正在对这两个文件调用 backtest_pine
[backtest_pine({ source: "...", ohlcv_csv_path: "./eth_15m.csv" }) 约 3 秒返回]
完成。7 天窗口 49 笔交易。净盈亏 −$190.85,Sharpe 0.21,最大回撤 $312。第三次亏损后做空再也没爬起来——要我挖触发条件,还是扫一遍入场阈值?

这就是生产力表面:模型握着工具说明,知道 backtest_pine 返回什么,可以在你不手写 curl 的情况下串下一次调用。「改 Pine → 保存 → 切 TradingView → 重载图表 → 读数 → 回到编辑器」的摩擦,塌缩成 一段对话

报告长什么样

backtest_pine 返回与独立 Docker 镜像 相同形状的 JSON。摘要块:

{
  "engine": "pineforge",
  "summary": {
    "total_trades": 49,
    "net_pnl": -190.85,
    "max_drawdown": 312.0,
    "sharpe": 0.21,
    "profit_factor": 0.78,
    "win_rate": 0.43
  },
  "trades": [
    /* 49 条含时间戳、价格、PnL */
  ],
  "elapsed_seconds": 0.0042,
  "_meta": {
    "strategy_cpp_bytes": 5079,
    "image": "ghcr.io/pineforge-4pass/pineforge-engine:latest"
  }
}

模型拿到完整结构后,可以回答「最差的一笔是哪笔?」这类追问——自行扫 trades[]常常不需要第二次工具调用

配额意识

凡是走 codegen API 的对话都会扣配额。为了在昂贵参数扫描前先摸底,提供了 get_quota。免费档 每月 100 次 transpile—— hobby 和 CI 冒烟够了;若是迭代优化循环可能会紧。

实用做法:在项目的 CLAUDE.md(或等价物)里写一句:若被要求优化策略,在发起超过 5 次 transpile 之前先调用 get_quota 并汇报剩余额度

服务器 刻意不包含的东西

  • 没有实盘下单。 服务器对你的策略和数据是只读的;不接券商。实盘是另一回事。
  • 没有行情拉取。 OHLCV 你自己带来。服务器不从交易所或数据商拉字节——数据来源与回测对象由你掌控。
  • 调用之间没有状态。 每次 backtest_pine 都是全新容器。没有持久缓存,也没有共享会话。

这是刻意的范围边界:表面可审计,故障模式简单。

到这里会变得好玩的手动苦活

几件手工做很别扭、在这种模型里很自然的事:

  • 「把止损收紧再跑一遍。」 模型改 Pine 里的一个数,再调 backtest_pine,对比 Sharpe。你厌烦为止。
  • 「换成最近 30 天而不是 7 天。」 指向另一个 CSV,模型重跑。不必在筛选 UI 里爬。
  • 「这里参数敏感度怎样?」 对一个输入扫区间,收集 Sharpe,打印小 Markdown 表。迭代交给模型。
  • 「跟另一份策略比一比。」 两次 backtest_pine,并排读报告。

不需要新基础设施。模型 + 四个工具 + 你的话就够了。

动手试

包是开源的。服务器小到 坐下来一遍读完就能审计线路,如果你想搞清楚线上到底发了什么,很适合。