1912 字
10 分钟
《量化交易入门》第 10 章:实盘落地——模拟盘、API 与自动化下单

《量化交易入门》第 10 章:实盘落地——模拟盘、API 与自动化下单#

到上一章为止,你的策略已经过了两关:回测有效、扣费后仍有效。很多人在这里直接开户充钱,然后亏得莫名其妙。这一章讲回测和实盘之间那段最容易翻车的路,要过三座桥:模拟盘、交易接口、自动下单的保险。

10.1 第一座桥:模拟盘(纸面交易)#

模拟盘就是用实时的真实行情、虚拟的钱,让策略跑起来。国内几乎所有券商 App 都自带”模拟炒股”,量化框架(如 vnpy、backtrader 的 live 模式)也支持模拟账户。

为什么回测漂亮还必须先跑模拟?因为回测和实盘之间藏着三个回测永远看不见的坑:

  1. 未来函数在实时中无处藏身。 回测里你可能不小心用了收盘时才知道的数据在盘中下单,历史曲线毫无破绽;实时运行时,数据只能一根一根地来,这类错误立刻暴露;
  2. 成交是被撮合出来的,不是假设出来的。 回测里写”按 10.00 元成交”,实盘中你的限价单可能根本排不上队,或只成交一半;
  3. 你自己。 第一次看着程序自动花钱,手会不会抖、想不想手动干预,只有实盘模拟能给你答案。

建议模拟盘至少跑一个完整的调仓周期(月频策略就跑一个月以上),把每一笔预期信号和实际成交记下来对账。

10.2 第二座桥:交易 API 长什么样#

程序化交易靠的是券商提供的 API(应用程序接口),本质上就是一组可以用代码调用的功能。无论哪家券商,都逃不开三类接口:

  • 行情接口:订阅实时报价和 K 线,策略的数据来源;
  • 交易接口:下单、撤单、改单,是唯一会动真钱的部分;
  • 账户接口:查询资金、持仓、当日委托和成交。

一段典型的下单代码,骨架长这样(仅示意,各券商函数名不同):

# 伪代码:真实下单流程的骨架
order_id = api.buy(code="600000", price=10.00, volume=1000) # 发单
while True:
order = api.query_order(order_id) # 轮询委托状态
if order.status in ("filled", "cancelled"):
break
api.cancel_order(order_id) # 超时未成交可撤单

现实中个人直接接券商柜台的门槛较高,多数人走的是 QMT、Ptrade 这类券商量化终端,或支持 API 的加密货币交易所。无论用哪个,先用官方文档里的模拟环境跑通,再碰实盘。

10.3 动手写:一个最小模拟券商#

光说不练不过瘾。下面用 Python 实现一个”模拟券商”:它接收买卖指令,用你给定的价格撮合成交,管理现金和持仓,并自动扣减手续费(费率接上一章的设定)。不依赖任何第三方库,可以直接运行:

class PaperBroker:
def __init__(self, cash, commission_rate=0.00025,
stamp_tax=0.0005, slippage=0.001):
self.cash = cash # 可用现金
self.positions = {} # 股票代码 -> 持股数
self.rate = commission_rate
self.stamp = stamp_tax
self.slip = slippage
def _fee(self, amount, is_buy):
commission = max(amount * self.rate, 5) # 最低 5 元
tax = 0 if is_buy else amount * self.stamp
return commission + tax
def buy(self, code, price, shares):
fill_price = price * (1 + self.slip) # 买入滑点:买贵一点
amount = fill_price * shares
cost = amount + self._fee(amount, True)
if cost > self.cash:
print("现金不足,买单被拒绝")
return
self.cash -= cost
self.positions[code] = self.positions.get(code, 0) + shares
print(f"买入 {code} {shares} 股,成交价 {fill_price:.2f},"
f"花费 {cost:.2f}")
def sell(self, code, price, shares):
held = self.positions.get(code, 0)
if shares > held:
print("持仓不足,卖单被拒绝")
return
fill_price = price * (1 - self.slip) # 卖出滑点:卖便宜一点
amount = fill_price * shares
net = amount - self._fee(amount, False)
self.cash += net
self.positions[code] = held - shares
print(f"卖出 {code} {shares} 股,成交价 {fill_price:.2f},"
f"到手 {net:.2f}")
def equity(self, prices):
"""prices:当前各股票价格的字典,算总市值"""
market = sum(prices[c] * n for c, n in self.positions.items())
return self.cash + market
# 跑一段完整流程:10 万本金,买入、持有、卖出、结算
b = PaperBroker(100000)
b.buy("600000", price=10.00, shares=5000)
b.sell("600000", price=10.50, shares=5000)
print("期末总资产:", round(b.equity({"600000": 10.50}), 2), "元")

运行结果:

买入 600000 5000 股,成交价 10.01,花费 50062.51
卖出 600000 5000 股,成交价 10.49,到手 52408.16
期末总资产: 102345.65 元

股价明明从 10.00 涨到 10.50,账面涨幅 5%,但扣掉双边滑点、佣金和印花税后,总资产只涨了约 2.3%。把这个类里的手动调用换成实时行情驱动的策略信号,它就是一个最小的自动化交易内核——而这中间所有数字,都和真钱账户一一对应。

10.4 第三座桥:自动化下单的四道保险#

程序能自动花钱,是力量也是深渊。上线自动交易前,请务必装好这四道保险:

  1. 仓位硬上限:在代码里写死单只股票和总仓位上限,超过就拒单。永远不要让程序有权限一把梭哈;
  2. 一键停止开关(Kill Switch):一个最简单的命令或按钮,立刻停止一切新开仓。程序失控、网络异常、行情源抽风时,你的手指要能一秒钟掐断它;
  3. 防重复下单:每笔委托带唯一编号,发单前先查询当日委托,避免网络重试时同一信号连下三次单——这类事故在新手身上真实地反复发生;
  4. 断线保护:行情或交易连接断开时,默认动作是”停止交易并告警”,而不是”用旧数据继续下单”。

此外,所有实盘程序都要写日志:什么时间、收到什么信号、下了什么单、成交没有,逐条落盘。出事复盘时,日志是你唯一的现场。

10.5 实盘起步:小到你能睡着觉#

模拟盘稳定盈利一个周期后,实盘请用一笔小到亏光也不影响生活的钱开始,比如几千元。这个阶段的目标不是赚钱,而是验证三件事:接口是否稳定、对账是否对得上、你自己能不能睡着觉。

等小额实盘跑满两三个月、每笔账都清清楚楚、心态不再随程序起伏,再逐步加仓。量化里最贵的学费,从来都交给了”跳过这一步”的人。

10.6 这一章你该记住的#

  1. 回测→实盘必过三桥:模拟盘、交易 API、自动化保险;
  2. 模拟盘暴露未来函数、真实撮合和你自己的心态问题;
  3. API 三类接口:行情、交易、账户,交易接口是唯一动钱的;
  4. 自动下单四道保险:仓位上限、急停开关、防重复、断线保护,外加完整日志;
  5. 实盘从亏光也无所谓的小钱开始,先验证系统,再谈赚钱。

能自动交易了,你手里就有了一台不知疲倦、严格执行规则的机器。但机器的好坏,取决于喂给它的”判断”。下一章:机器学习入门:过拟合与模型陷阱,我们聊聊当策略不满足于均线和因子、开始让算法自己从数据里”学规律”时,那些闪闪发光的高收益预测,为什么大多是陷阱,以及普通人该怎么避坑。


📚 《量化交易入门》系列:零基础小白向量化交易,每章一个主题 + 可运行 Python 示例。第 10 章已读,下一章《机器学习入门:过拟合与模型陷阱》明天见。

《量化交易入门》第 10 章:实盘落地——模拟盘、API 与自动化下单
https://021028.xyz/posts/default/140/
作者
021028
发布于
2026-10-14
许可协议
CC BY-NC-SA 4.0