从研究到实盘:走出 Pyodide
直觉
本网站用 Pyodide 在浏览器里跑回测,是为了零门槛学习。但真正要把策略上线,你必须离开这个沙盒:拿到真实行情、对接券商 API、处理延迟和部分成交、24 小时监控、并在真金白银上控制风险。研究与实盘之间隔着一条沟——回测里的「假设」在实盘里全是「成本」。这一节是工程指南:怎么把一个跑通的回测,一步步变成稳健运行的实盘策略。
研究与实盘的落差
| 维度 | 研究(本站 Pyodide) | 实盘 |
|---|---|---|
| 数据 | 内置合成 CSV、无延迟 | 实时行情、有延迟、偶尔缺失/错误 |
| 成交价 | 假设按收盘/开盘成交 | 滑点、价差冲击、部分成交、拒单 |
| 成本 | 固定 cost_bps | 佣金 + 交易所费 + 滑点 + 隔夜利息 |
| 状态 | 无状态、可重跑 | 持仓、挂单、资金必须精确持久化 |
| 时间 | 一次性向量化 | 事件驱动、逐 tick 决策 |
「人话」解释:为什么实盘 PnL 几乎总是低于回测?
回测默认「信号一出、按理想价全量成交」,现实里每一项假设都要打折:你看到的行情有延迟、你的单子会冲击价格、大单会部分成交剩下挂在簿子里、网络/系统可能断连。这些「摩擦」叠加,常常吃掉回测里相当一部分 Alpha。实盘工程的本质,就是把回测里被忽略的每一项摩擦,逐个量化、逐个控制。所以业内行话:先证明策略能在「加了真实摩擦的回测」里活下来,再谈上线。
实盘事件循环骨架
脱离 Pyodide 后,策略通常跑成一个事件驱动循环(而非向量化):每来一条行情/定时器,重新计算信号、决定是否调仓、下单、记录成交。下面是一个最小骨架(本地 Python,非浏览器):
# 伪代码骨架: 研究 → 实盘 的事件循环
position = load_state() # 从磁盘恢复持仓/资金(必须持久化!)
for event in market_data_stream(): # 实时行情或定时器
signal = compute_signal(event) # 复用研究阶段的信号函数
target = size_position(signal) # 仓位管理(凯利/波动率目标)
if target != position:
order = build_order(target - position)
fill = broker.submit(order) # 对接券商 API, 处理部分成交/拒单
log_trade(fill); position = apply_fill(fill)
save_state(position) # 落盘, 防断连丢状态
monitor_risk(position) # 实时风控: VaR/回撤/敞口超限即平仓
可运行案例:迷你「纸面交易」事件引擎
用事件驱动方式(逐日、按昨日信号在今日开盘成交)在 SPY 合成数据上跑一遍,输出成交记录与期末净值——这就是回测引擎与实盘循环的共同骨架。
import numpy as np
import pandas as pd
df = pd.read_csv('/data/spy_daily.csv', parse_dates=['date']).set_index('date')
fast = df['adj_close'].rolling(10).mean(); slow = df['adj_close'].rolling(30).mean()
sig = (fast > slow).astype(float).shift(1).fillna(0).values # 昨日信号, 今日开盘执行
opens, closes = df['open'].values, df['adj_close'].values
eq, pos, trades = 1.0, 0.0, []
for i in range(1, len(df)):
tgt = sig[i]
if tgt != pos: # 事件: 需调仓
eq -= abs(tgt - pos) * 2e-4 * eq # 按规模扣成本
pos = tgt
trades.append((df.index[i].date(), '多' if tgt > 0 else '空/平'))
eq *= (1 + pos * (closes[i] / opens[i] - 1)) # 今日开盘→收盘
print(f"成交次数 = {len(trades)} 期末净值 = {eq:.3f}")
print("前 5 笔成交:", [(str(d), a) for d, a in trades[:5]])
print("\n骨架要点: 逐事件决策 → 下单 → 记录 → 持久化持仓 → 实时风控。")
print("上线前务必在'加了真实摩擦的回测'里验证, 再纸面交易, 再小仓位放量。")
上线检查清单
- 摩擦回测:把佣金、滑点、冲击、延迟都加进去再验,夏普还正才考虑下一步;
- 纸面交易:用实时(但虚拟)数据跑 2–4 周,对比「实盘信号 vs 回测信号」是否一致;
- 小仓位放量:先用极小资金实盘,逐步加仓,观察 PnL 是否贴合纸面结果;
- 监控与熔断:实时盯 VaR/回撤/敞口,超限自动减仓或停机;记录所有成交以便复盘。
小结
- 实盘 = 在「真实摩擦」(延迟、滑点、部分成交、断连)下运行事件驱动循环;
- 持仓/资金必须持久化,风控必须实时且可自动熔断;
- 路径:摩擦回测 → 纸面交易 → 小仓位放量——任何一步不达标都不要往下走。