vnpy 股票交易如何实现自动化下单
摘要:
vnpy 股票交易自动化下单的核心在于事件引擎驱动与网关适配。通过掌握策略模板编写、实盘风控设置与数据回测要点,散户也能用开源工具搭建自己的交易系统。理解订单生命周期与滑点控制,是避免实盘踩坑的关键。

为什么用 vnpy 做股票交易
很多散户以为量化交易是机构专利,其实开源工具已经把门槛降得很低。vnpy 就是一个用 Python 写的量化交易框架,它把行情接收、策略信号、订单执行这些环节都打包好了。你不需要从零开始对接券商接口,也不用自己造轮子管理订单状态。股票交易和期货交易在 vnpy 里共用同一套事件引擎,区别主要在于网关和交易规则。股票是 T+1、有涨跌停限制,期货是 T+0、保证金交易。理解这个差异,才能把 vnpy 用对地方。
事件引擎到底在干什么
vnpy 的核心是一个事件驱动引擎。你可以把它想象成一个快递分拣中心:行情数据到了,分拣中心贴个行情事件的标签扔给策略;策略算完发出买卖信号,分拣中心再贴个信号事件的标签扔给订单执行模块;订单成交了,又扔回给策略更新持仓。整个过程是异步的,策略不需要死等行情,也不会因为下单慢而卡住。股票交易里 tick 数据频率不高,但集合竞价和开盘瞬间数据量很大,事件引擎能帮你把行情接收和逻辑处理拆开,避免丢包。

写一个股票策略需要改哪几个地方
打开 vnpy 的策略模板,你会看到几个必须实现的函数。on_init 里做初始化,比如设置均线周期;on_tick 接收实时行情,股票用 tick 数据算信号就够;on_bar 接收 K 线,适合做分钟级或日线级策略;on_order 和 on_trade 处理订单和成交回报。股票交易最常踩的坑是仓位管理。期货可以开空仓,股票只能先买后卖,所以策略里要加一个判断:当前持仓可用数量够不够卖。另外股票有最小交易单位 100 股,下单数量必须取整到 100 的倍数,不然柜台直接拒单。
网关选择与实盘对接
vnpy 支持多种券商网关,常见的有中泰 XTP、华鑫奇点、东方证券 OST 等。选网关看两点:一是券商是否提供 API 权限,二是网关是否稳定。很多券商对量化接口有资金门槛,五十万到一百万不等,小资金散户可以先跑模拟盘或者用文件单模式。模拟盘用 vnpy 的仿真网关就行,行情用其他数据源补上。实盘对接时要注意股票交易的佣金和印花税,策略回测必须把这些成本算进去,否则回测曲线很漂亮,实盘一跑就亏。
回测和实盘的差距在哪里
股票回测最容易忽略的是涨跌停无法成交。回测引擎默认按收盘价成交,但实盘遇到一字涨停板,买单根本排不进去。vnpy 的回测模块可以加载历史 tick 数据,但大多数散户拿不到完整的 tick 历史。一个折中办法是用分钟线回测,在信号触发时检查当天最高价和最低价是否触及涨跌停。另一个差距是滑点,股票盘口薄的时候,大单砸下去价格会跳好几个价位。回测里设置千分之二的滑点比较贴近实盘。还有 T+1 限制,当天买的股票当天不能卖,回测引擎里要加一个持仓冻结逻辑,不然会算出虚假的收益。
风控模块怎么设置才不爆仓
股票交易虽然不像期货那样容易爆仓,但满仓一只股票遇到黑天鹅照样腰斩。vnpy 的风控模块可以设置单笔最大委托金额、单日最大交易次数、单只股票最大持仓比例。建议把单只股票持仓上限设在总资金的百分之二十以内,单日亏损超过百分之三就暂停策略。股票没有保证金追缴,但券商的融资融券账户有平仓线,如果用融资额度交易,风控要更严。另外股票停牌期间策略收不到行情,订单会一直挂着,风控里要加一个超时撤单逻辑,比如订单挂出去三十秒没成交就撤掉重发。
一个最简单的双均线股票策略代码演示
下面这段代码演示了在 vnpy 里写一个双均线策略的核心逻辑,只做多不做空,每次交易一百股整数倍。
from vnpy_ctastrategy import CtaTemplate, BarGenerator, ArrayManager
class DoubleMaStrategy(CtaTemplate):
author = "trader"
fast_window = 10
slow_window = 30
parameters = ["fast_window", "slow_window"]
variables = ["fast_ma0", "slow_ma0", "pos"]
def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
super().__init__(cta_engine, strategy_name, vt_symbol, setting)
self.bg = BarGenerator(self.on_bar)
self.am = ArrayManager()
self.fast_ma0 = 0.0
self.slow_ma0 = 0.0
def on_init(self):
self.write_log("策略初始化")
self.load_bar(10)
def on_tick(self, tick):
self.bg.update_tick(tick)
def on_bar(self, bar):
am = self.am
am.update_bar(bar)
if not am.inited:
return
fast_ma = am.sma(self.fast_window, array=True)
slow_ma = am.sma(self.slow_window, array=True)
self.fast_ma0 = fast_ma[-1]
self.slow_ma0 = slow_ma[-1]
cross_over = fast_ma[-1] > slow_ma[-1] and fast_ma[-2] <= slow_ma[-2]
cross_below = fast_ma[-1] < slow_ma[-1] and fast_ma[-2] >= slow_ma[-2]
if cross_over and self.pos == 0:
volume = 100
self.buy(bar.close_price, volume)
elif cross_below and self.pos > 0:
self.sell(bar.close_price, abs(self.pos))
self.put_event()
这段代码里 buy 和 sell 发出的是限价单,股票交易用限价单比市价单安全,市价单在流动性差的时候成交价会很离谱。注意 volume 固定一百股,实盘里可以根据资金量动态计算,但一定要取整到一百的倍数。
股票和期货在 vnpy 里的配置差异
股票交易不需要设置保证金率和合约乘数,但需要设置股票池和涨跌停价。期货策略里的 on_bar 通常用分钟线,股票策略用日线或五分钟线更多。股票没有夜盘,交易时间集中在上午九点半到十一点半,下午一点到三点,策略里要做时间过滤,非交易时段不响应信号。期货的 short 函数在股票里不能用,股票做空需要融券,普通账户只能先买后卖。用 vnpy 做股票交易,把这几条规则守住了,实盘就不会出大乱子。
声明
转载声明:欢迎分享本文,转载请注明出处!
点击复制: