PineForge 脱离 TradingView 离线回测 Pine Script:一个 Docker 镜像,相同输入,相同交易。
为什么要离线?
浏览器回测很适合在图表上反复调试。当下一步要为策略投入资金时,就该用离线回测:你需要审计轨迹,需要每次提交都过 CI 门禁,也需要两个月前的结果今天仍能逐笔复现。
离线跑批给你浏览器端工具做不到的能力:结果是确定的 —— 相同的脚本、数据和镜像版本得到相同的交易。你可以固定镜像版本、把报告提交到仓库、在不同提交之间比对交易列表,并在 CI 中以无界面方式跑完全部流程。输入的 CSV 属于你,引擎在本地运行,报告还会记录其生成来源的指纹。
具体来说:固定镜像版本,两个月前的提交今天仍能得到相同的交易列表;使用你自己的数据,从交易所 K 线到用 tick 数据自行合成的 K 线都可以,只要是 OHLCV;CI 检查在出现回归时让构建失败;策略就是一个文件,不绑定任何单一平台。
如果你分享结果只能靠截图 —— 说明你缺的就是这层离线运行时。
怎么离线回测 Pine Script
PineForge 把 PineScript v6 转译为原生 C++,用一个 Docker 镜像在你的机器上运行。
三个步骤。镜像只需拉取一次,之后一切都离线运行。
第 1 步 —— 拉取运行时
只需一个镜像:ghcr.io/pineforge-4pass/pineforge-release。无需 pip 安装、无需密钥、无需注册:转译、编译和回测全部在镜像内离线完成。镜像中的引擎采用 Apache-2.0 许可;内置的转译器个人交易免费。
第 2 步 —— 把你的 Pine 转译成 C++
以仅转译模式运行镜像,它会在本地把你的 PineScript v6 转成一份完整的 C++ 源文件。回测时不会运行任何 Pine 解释器:镜像会把 C++ 编译为原生代码。
docker run --rm --network=none \
-e PINEFORGE_TRANSPILE_ONLY=1 \
-v "$(pwd)/my_strategy.pine":/in/strategy.pine:ro \
ghcr.io/pineforge-4pass/pineforge-release:1.10.0 > strategy.cpp第 3 步 —— 回测
把你的 OHLCV CSV 放在生成的 C++ 旁边一起挂载,然后运行镜像。CSV 需要表头 timestamp,open,high,low,close,volume,时间戳为 UNIX 毫秒。引擎逐根 K 线执行策略,并把 JSON 报告写到 stdout。你也可以跳过第 2 步:改为挂载 strategy.pine,镜像会先完成转译。
docker run --rm --network=none \
-v "$(pwd)/strategy.cpp":/in/strategy.cpp:ro \
-v "$(pwd)/ohlcv.csv":/in/ohlcv.csv:ro \
ghcr.io/pineforge-4pass/pineforge-release:1.10.0 > report.jsonJSON 报告包含:汇总块(总交易笔数、盈利和亏损笔数、胜率、净盈亏、最大回撤);完整交易列表(入场和出场时间、价格、数量、盈亏及 K 线索引);盈利因子、夏普比率、索提诺比率等指标;权益曲线;以及本次运行背后的引擎、转译器、输入参数和数据的指纹(无法计算时为 null)。
没有 GUI、没有二次登录、没有等图表加载 —— 能跑 Docker,就能批量离线验证。
能喂什么数据
一句话:能序列化成 OHLCV 的都行;我们不绑行情商。
- 交易所加密资产。REST/WebSocket 抓原始成交 → 聚合成任意周期 CSV → 与实盘相同的 venue + symbol 组合验收。
- 由逐笔数据合成的 K 线。如果你用逐笔成交或订单簿数据合成 K 线,以 OHLCV 格式传入即可。引擎不关心 K 线从何而来。
- 其他序列。引擎只读取 timestamp、open、high、low、close 和 volume 这几列,多余的列会被忽略。情绪评分或链上指标,只有编码进这几列才能参与回测。
画廊中的 312 套策略均来自公开测试集,每套都对照 TradingView 自己的导出数据评级。在引擎 main 分支上,测试集检查锁定其中 311 套为优秀:交易笔数相同,第 90 百分位的价格偏差在 0.01% 以内、盈亏偏差在 1% 以内;其中 7 套策略的 trail_* 出场按生产阈值评级,出场价和盈亏的限值更宽。剩下的 1 套是已声明的异常。对于优秀评级,当 TradingView 在完全相同的时间、价格和方向上显示两个或以上不同的入场 Signals 时,引擎也在该处显示相同数量的独立入场(独立入场识别)。