ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

VeighNa Elite 价差套利(SpreadTrading)实战指南:从价差合约构建到 EliteSpreadStrategyTemplate 策略开发

VeighNa Elite 价差套利(SpreadTrading)实战指南:从价差合约构建到 EliteSpreadStrategyTemplate 策略开发 VeighNa Elite 价差套利SpreadTrading实战指南从价差合约构建到 EliteSpreadStrategyTemplate 策略开发【免费下载链接】vnpy基于Python的开源量化交易平台开发框架项目地址: https://gitcode.com/vnpy/vnpy导读本文基于 VeighNa Elite 版文档 docs/elite/strategy/elite_spreadtrading.md 编写系统讲解 VeighNa Elite Trader 中 SpreadTrading 价差套利模块的完整使用链路如何创建多合约价差、如何通过三种执行算法Taker/Maker/Exchange完成半自动算法交易以及如何基于专业价差策略模板 EliteSpreadStrategyTemplate 开发全自动价差策略。读完本文你将掌握价差合约的构建与监控、算法交易的启动与停止、策略实例的全生命周期管理以及一套可直接运行的策略开发范式。SpreadTrading 是 vnpy 生态中用于多合约价差套利的功能模块社区版文档见 docs/community/app/spread_trading.mdVeighNa Elite 版在社区版基础上增加了专业价差策略模板EliteSpreadStrategyTemplate与三种价差执行算法用户可以通过 UI 界面便捷创建灵活的价差合约、完成半自动算法交易和全自动策略交易。模块主要优势SpreadTrading 模块不仅提供了Taker见价下单、Maker报价做市以及Exchange交易所价差三种价差执行算法支持还提供了专业价差策略模板EliteSpreadStrategyTemplate以实现更加强大的价差策略开发。算法的职责是完成价差组合的多腿执行主动腿下单 被动腿对冲策略的职责则是基于价差行情生成信号并调度算法二者分工明确。启动模块SpreadTrading 模块需要在启动之前通过 VeighNa Elite Trader 登录界面下方的【策略应用】标签页加载加载成功后下次启动无需重复操作加载应用的具体操作见 docs/elite/info/elite_trader.md 中加载应用一节。启动登录 VeighNa Elite Trader 后启动模块之前请先连接交易接口。看到 VeighNa Elite Trader 主界面【日志】栏输出合约信息查询成功之后再启动模块如果在合约信息查询成功之前打开模块可能会导致价差的价格跳动取值为零进而在委托成交之后引发底层报错。请注意IB 接口因为登录时无法自动获取所有的合约信息只有在用户手动订阅行情时才能获取。因此需要在主界面上先行手动订阅合约行情再启动模块。成功连接交易接口后在菜单栏中点击【功能】- 【套利价差交易】或者点击左侧按钮栏的价差交易图标即可进入套利价差交易模块的 UI 界面。模块界面主要包含【交易】、【价差创建】、【移除价差】、【算法】、【价差】、【日志】以及右下角的【策略】监控组件。策略文件目录对于用户自行开发的策略需要放到 VeighNa Elite Trader 运行时目录下的strategies目录中才能被识别加载。具体的运行时目录路径可以在 VeighNa Elite Trader 主界面顶部的标题栏查看。对于在 Windows 上默认安装的用户来说放置策略的 strategies 目录路径通常为C:\Users\Administrator\strategies其中 Administrator 为当前登录 Windows 的系统用户名。创建价差合约查询合约在创建价差合约前用户可以通过【查询合约】功能寻找可以组成价差的合约不支持交易所套利合约在 VeighNa Elite Trader 菜单栏中点击【帮助】- 【查询合约】按钮弹出合约查询界面在界面中找到可用于组成价差交易的合约本文档以豆油期货的跨期套利来展示即交易 y2309.DCE豆油期货 23 年 9 月到期合约和 y2401.DCE豆油期货 24 年 1 月到期合约。构建价差合约在价差交易的界面左侧点击【价差创建】按钮弹出创建价差界面。价差交易模块支持灵活的价差计算公式例如 A/B、A-B*C 等同时允许引入不参与交易的定价腿满足复杂境内外套利价差需要考虑汇率和税率等因素的需求。在创建价差合约时需要配置相关参数各参数要求如下价差名称用户定义的价差合约名称价差名称不能重名主动腿代码价差盘口价格满足条件时先发出的那条腿的本地代码。格式为 vt_symbol合约代码 交易所名称必须是下面的腿选项中的一项最小交易量最小交易手数价格公式价差合约的计算公式支持任何 Python 内置数学函数注意其中的变量只能是 A、B、C、D、E不需要都用【A、B、C、D、E】包含构建价差合约的主动腿与被动腿也可以引入不参与交易的定价腿由合约代码、交易方向、交易乘数组成合约代码为公式中的变量所对应的合约本地代码vt_symbol一般来说价差交易原则上是主动腿完成交易后立刻用被动腿进行对冲故主动腿一般选择较为不活跃的合约价格乘数和交易乘数均为正被动腿一般选择较为活跃的合约价格乘数和交易乘数均为负图形界面选择【卖出】交易乘数填写正数jupyter 回测两者皆传负数不用的变量留空即可设置好价差合约的参数后点击下方的【创建价差】按钮即可成功创建价差合约。在豆油期货跨期套利示例中其价格乘数和交易乘数均为 1:1即价差 y2401 - y2309买入 1 手价差等于买入 1 手 y2401同时卖出 1 手 y2309 完成对冲。请注意在多条腿并且期货合约规模不等时构建价差合约会相对困难一些如构建虚拟钢厂套利所用到的价差合约时计算公式如下螺纹钢生产技艺是 16 吨铁矿石加上 5 吨焦炭练成 10 吨螺纹钢。基于价格乘数的价差 spread 1*RB - 1.6*I - 0.5*J。但是由于螺纹是 10 吨/手铁矿石和焦炭都是 100 吨/手所以他们交易乘数是 1:10:10故基于最大公约数规则其实际交易手数关系是每买入 100 手螺纹钢1000 吨需要卖出 16 手铁矿石1600 吨和 5 手焦炭500 吨完成对冲。监控价差合约价差合约创建完毕监控界面中的【日志】栏会输出价差创建成功【价差】栏也会展示价差合约的实时行情。在豆油期货价差交易示例中【价差】组件的各字段含义如下所示买价y2401 买一价 - y2309 卖一价买量min(y2401 买一量, y2309 卖一量)取最小值用于保证各合约能均能成交卖价y2401 卖一价 - y2309 买一价卖量min(y2401 卖一量, y2309 买一量)移除价差合约在价差交易的界面左侧点击【移除价差】按钮弹出移除价差界面。选择好要移除的价差合约之后点击【移除】按钮即可成功移除价差合约。【日志】组件输出价差移除成功。半自动算法交易用户可以通过模块界面左上角【交易】组件选择算法目前支持三种算法进行半自动算法交易算法列表对应本文算法介绍一节的 SpreadTakerAlgo、SpreadMakerAlgo 与 SpreadExchangeAlgo。填写参数时请注意开平只有启动 Exchange 算法在【开仓】和【平仓】中选择其他大多数时候选择【净仓】股指合约用【锁仓】。下面通过 2 个 SpreadTakerAlgo主动对价成交算法的例子分别是发出委托立即成交和发出委托等待成交来介绍手动交易的操作情况启动算法立即成交超价目标价差合约价格为 -70以 -60 的价位启动做多算法超价算法会立即发出委托并成交。由于限价单-60价位高于当前卖价-72 附近委托立刻成交。此时各监控组件状态如下日志组件买入价差合约的顺序是发出主动腿多头委托 - 主动腿委托成交 - 发出被动腿空头委托 - 被动腿委托成交。价差交易必须遵循的逻辑是主动腿成交后才去用被动腿来对冲头寸并且对冲必须尽可能及时。这也是为什么一般被动腿会选择较为活跃合约的原因。价差组件买入价差合约成交后净仓从 0 变成 1底层【持仓】组件显示主动腿合约多头持仓、被动腿合约空头持仓。算法组件本次 SpreadTaker 算法执行情况成交数量 1 手委托状态是【全部成交】。启动算法等待成交限价以 -80 的价位启动做多算法由于当前买价卖价分别位于 -76 和 -72所以委托状态显示【未成交】。此时算法已启动但由于价格没有触发到目标价位算法在循环读秒中处于等待状态仅当卖价低于 -80 时才触发该限价单并以超价的方式去主动成交。停止运行中的算法鼠标双击需要停止算法的单元格即可结束该算法。此时【日志】组件输出算法已停止【算法】组件显示委托状态由【未成交】变成【已撤销】。全自动策略交易添加策略用户可以基于编写好的价差策略模板类来创建不同的策略实例对象。在左侧的下拉框中选择要交易的策略名称如 MeanReversionStrategy。请注意显示的策略名称是策略类驼峰式命名的名字而不是策略文件下划线模式命名的名字。选择好策略类之后点击【添加策略】会弹出添加策略对话框。在创建策略实例时需要配置相关参数各参数要求如下实例名称用户自定义的策略实例名称策略实例名称不能重名价差名称用于交易的价差合约一定要是价差组件可以查询到的价差合约参数设置显示的参数名称是在策略中使用 Parameter 辅助类定义的参数默认数值为策略里的参数的默认值参数名后面 括号中显示的是该参数的数据类型在填写参数时应遵循相应的数据类型。其中class str是字符串、class int是整数、class float是浮点数请注意如果某个参数可能会调整至有小数位的数值而默认参数值是整数比如 1。请在编写策略时把默认参数值设为浮点数比如 1.0。否则策略会默认该项参数为整数在后续【编辑】策略实例参数时会只允许填进整数。以 MeanReversionStrategy 为例该策略的参数设置如下ma_window均线窗口entry_range入场范围fixed_volume固定交易数量payup各条腿委托时基于对价盘口的加点interval限价单多少秒不成交则撤销重挂参数配置完成后点击【添加】按钮则开始创建策略实例。创建成功后可在右下角的策略监控组件中看到该策略实例。策略监控组件顶部显示的是策略实例名、价差名、策略类名以及策略作者名在策略里定义的 author。顶部按钮用于控制和管理策略实例第一行表格显示了策略内部的参数信息参数名需要写在策略的 parameters 列表中图形界面才会显示第二行表格则显示了策略运行过程中的变量信息变量名需要写在策略的 variables 列表中图形界面才会显示。【inited】字段表示当前策略的初始化状态是否已经完成了历史数据回放【trading】字段表示策略当前是否能够开始交易。从上图可观察到此时该策略实例的【inited】和【trading】状态都为【False】。说明该策略实例还没有初始化也还不能发出交易信号。策略实例创建成功后该策略实例的配置信息会被保存到 .vntrader 文件夹下的 spread_trading_strategy.json 文件中。管理策略初始化策略实例创建成功后就可以对该实例进行初始化了。点击该策略实例下的【初始化】按钮若初始化成功该策略实例的【inited】状态已经为【True】说明该策略实例已经调用过 load_bar 函数加载历史数据并完成初始化了。【trading】状态还是为【False】说明此时该策略实例还不能开始自动交易。启动策略实例初始化成功【inited】状态为【True】时才能启动该策略的自动交易功能。点击该策略实例下的【启动】按钮即可启动该策略实例。成功启动后【日志】组件则会输出相应信息请注意策略启动并不代表算法启动算法启动状态取决于策略逻辑。此时【策略】组件中【trading】字段从【False】变为【True】。停止若要停止策略点击策略实例下的【停止】按钮即可停止该策略实例的自动交易。【日志】组件输出策略停止【策略】组件中【trading】字段从【True】变为【False】。停止策略时策略引擎会先停止策略启动的所有算法撤销所有未成交委托然后再停止策略实例的自动交易。若停止策略时仍有未停止的算法可以在【日志】组件观察到算法已停止的输出【算法】组件中对应算法状态也会变为【已撤销】。编辑如果创建策略实例之后想要编辑某个策略实例的参数若已启动策略需要先点击策略实例下的【停止】按钮停止策略可以点击该策略实例下的【编辑】按钮会弹出参数编辑对话框以供修改策略参数。编辑完策略参数之后点击下方的【确定】按钮相应的修改会立即更新在参数表格中。但是策略实例的交易合约代码无法修改同时修改完后也不会重新执行初始化操作。也请注意此时修改的只是 .vntrader 文件夹下 spread_trading_strategy.json 文件中该策略实例的参数值并没有修改原策略文件下的参数。若盘中编辑后想要再次启动策略点击策略实例下的【启动】按钮即可再次启动该策略实例。移除如果创建策略实例之后想要移除某个策略实例若已启动策略需要先点击策略实例下的【停止】按钮停止策略可以点击该策略实例下的【移除】按钮。移除成功后图形界面右下角的策略监控组件中将不会再显示该策略实例的信息。此时 .vntrader 文件夹下的 spread_trading_strategy.json 文件也移除了该策略实例的配置信息。批量操作在策略经过充分测试实盘运行较为稳定不需要经常进行调整的情况下如果有多个需要运行的价差策略实例可以使用界面左下角的【全部初始化】、【全部启动】和【全部停止】功能来执行盘前批量初始化、启动策略实例以及盘后批量停止策略实例的操作。价差交易策略模板价差交易策略模板提供了信号生成和委托管理功能用户可以基于模板自行开发策略。用户自行开发的策略可以放在用户运行文件夹下的 strategies 文件夹内。请注意策略文件命名采用下划线模式如 mean_reversion_strategy.py而策略类命名采用驼峰式如 MeanReversionStrategy。自建策略的类名不要与示例策略的类名重合否则会出现策略类互相覆盖的错误情况。EliteSpreadStrategyTemplateVeighNa Elite Trader 的价差套利模块提供了 EliteSpreadStrategyTemplate 专业价差套利策略模板实现更强大的价差策略开发。下面通过 MeanReversionStrategy 策略示例来展示策略开发的具体步骤。在基于 EliteSpreadStrategyTemplate 编写策略逻辑之前需要在策略文件的顶部载入需要用到的内部组件如下方代码所示from vnpy.trader.utility import BarGenerator, ArrayManager from elite_spreadtrading import ( SpreadStrategyTemplate, SpreadAlgoTemplate, AlgoType, AlgoOffset, Variable, Parameter, SpreadData, OrderData, TradeData, TickData, BarData )其中SpreadStrategyTemplate 是 VeighNa Elite Trader 提供的价差交易策略模板SpreadAlgoTemplate 是价差算法模板AlgoType 和 AlgoOffset 是用来配置算法交易模式的算法类型和算法开平选项Parameter 是储存策略参数的数据容器Variable 是储存策略变量的数据容器SpreadData、OrderData、TickData、TradeData 和 BarData 是储存对应信息的数据容器BarGenerator 是 K 线生成模块ArrayManager 是 K 线时间序列管理模块策略参数与变量在策略类的下方可以设置策略的作者author参数parameters以及变量variables如下方代码所示author 用Python的交易员 ma_window: int Parameter(60) entry_range: int Parameter(20) fixed_volume: int Parameter(10) payup: int Parameter(10) interval: int Parameter(5) spread_pos: float Variable(0.0) ma_value: float Variable(0.0)虽然策略的参数和变量都从属于策略类但策略参数是固定的由交易员从外部指定而策略变量则在交易的过程中随着策略的状态变化所以策略变量一开始只需要初始化为对应的基础类型。例如整数设为 0浮点数设为 0.0。如果需要价差套利交易模块引擎在运行过程中将策略参数和变量显示在 UI 界面上并在数据刷新、停止策略时保存其数值则需在创建策略类的时候创建对应的参数和变量实例。请注意Parameter 容器和 Variable 容器只能接受参数或变量以 str、int、float 和 bool 四种数据类型传入。策略的回调函数SpreadStrategyTemplate 中以 on 开头的函数称为回调函数在编写策略的过程中能够用来接收价差行情或者接收状态更新。回调函数的作用是当某一个事件发生的时候策略里的这类函数会被价差交易策略引擎自动调用无需在策略中主动操作。回调函数按其功能可分为以下三类策略实例状态控制所有策略都需要on_init入参无出参无初始化策略时 on_init 函数会被调用在此处通常会实现的功能逻辑包括实例化 K 线数据合成组件BarGenerator通过时间切片将 Tick 数据合成 1 分钟 K 线数据。如有需求还可合成更长的时间周期数据。实例化 K 线时间序列缓存组件ArrayManager基于 K 线数据将其转化为便于向量化计算的时间序列数据结构并在内部支持使用 talib 库来计算相应的技术指标。ArrayManager 的默认长度为 100如需调整 ArrayManager 的长度可传入 size 参数进行调整size 不能小于计算指标的周期长度。对价差算法交易模式进行配置AlgoType枚举值值TAKERtakerMAKERmakerEXCHANGEexchangeAlgoOffset枚举值值LOCK锁仓NET净仓OPEN开仓CLOSE平仓完成上述组件初始化后再调用 load_bar 函数加载历史数据如下方代码所示def on_init(self): Callback when strategy is inited. self.bg BarGenerator(self.on_spread_bar) self.am ArrayManager(self.ma_window 10) # 价差算法交易模式配置 self.algo_type: AlgoType AlgoType.TAKER self.algo_offset: AlgoOffset AlgoOffset.NET self.write_log(策略初始化) self.load_bar(10)请注意如果是基于 Tick 数据回测请在此处调用 load_tick 函数。策略初始化时策略的 inited 和 trading 状态都为【False】此时只是调用 ArrayManager 计算并缓存相关的计算指标不能发出交易信号。调用完 on_init 函数之后策略的 inited 状态才变为【True】策略初始化才完成。on_start入参无出参无启动策略时 on_start 函数会被调用默认写法是调用 write_log 函数输出策略启动日志如下方代码所示def on_start(self): Callback when strategy is started. self.write_log(策略启动)调用策略的 on_start 函数启动策略后策略的 trading 状态变为【True】此时策略才能够启动价差交易算法。on_stop入参无出参无停止策略时 on_stop 函数会被调用默认写法是调用 write_log 函数输出策略停止日志如下方代码所示def on_stop(self): Callback when strategy is stopped. self.write_log(策略停止) self.put_event()调用策略的 on_stop 函数停止策略后策略的 trading 状态变为【False】此时策略就不再允许启动价差交易算法了。接收数据、计算指标、发出交易信号on_spread_data入参无出参无当价差数据更新的时候 on_spread_data 函数会被调用因本次示例策略类 MeanReversionStrategy 不是基于 on_spread_data 交易故不作示例讲解。MeanReversionStrategy 的写法是先调用 get_spread_tick 获取价差 Tick 数据然后推进 on_spread_tick 函数中如下方代码所示def on_spread_data(self): Callback when spread price is updated. tick self.get_spread_tick() self.on_spread_tick(tick)on_spread_tick入参tick: TickData出参无on_spread_tick 函数通常由用户在 on_spread_data 下发起调用通常的用法是通过 BarGenerator 的 update_tick 函数把收到的 Tick 数据推进前面创建的 bg 实例中以便合成 1 分钟的 K 线如下方代码所示def on_spread_tick(self, tick: TickData): Callback when new spread tick data is generated. self.bg.update_tick(tick)on_spread_bar入参bar: BarData出参无当 BarGenerator 完成 1 分钟 K 线合成时实盘时默认推进来的是基于 Tick 合成的一分钟的 K 线回测时则取决于选择参数时填入的 K 线数据频率on_spread_bar 函数就会被调用。如果策略基于 on_spread_bar 推进来的 K 线交易那么请把交易请求类函数都写在 on_spread_bar 函数下。示例策略类 MeanReversionStrategy 是通过 1 分钟 K 线数据回报来生成信号的一共有三部分如下方代码所示def on_spread_bar(self, bar: BarData): Callback when spread bar data is generated. self.stop_all_algos() self.am.update_bar(bar) if not self.am.inited: return self.ma_value self.am.sma(self.ma_window) if not self.spread_pos: if bar.close_price self.ma_value self.entry_range: self.start_short_algo( bar.close_price - 10, self.fixed_volume, payupself.payup, intervalself.interval, algo_typeself.algo_type, algo_offsetself.algo_offset ) elif bar.close_price self.ma_value - self.entry_range: self.start_long_algo( bar.close_price 10, self.fixed_volume, payupself.payup, intervalself.interval, algo_typeself.algo_type, algo_offsetself.algo_offset ) elif self.spread_pos 0: if bar.close_price self.ma_value: self.start_long_algo( bar.close_price 10, abs(self.spread_pos), payupself.payup, intervalself.interval, algo_typeself.algo_type, algo_offsetself.algo_offset ) else: if bar.close_price self.ma_value: self.start_short_algo( bar.close_price - 10, abs(self.spread_pos), payupself.payup, intervalself.interval, algo_typeself.algo_type, algo_offsetself.algo_offset ) self.put_event()清空未成交委托为了防止之前下的单子在上 1 分钟没有成交但是下 1 分钟可能已经调整了价格就用 stop_all_algos() 方法立刻撤销之前未成交的所有委托保证策略在当前这 1 分钟开始时的整个状态是清晰和唯一的计算策略信号指标基于最新的 1 分钟价差 K 线数据来计算相应的技术指标如均线等。首先获取 ArrayManager 对象然后将收到的 K 线推送进去检查 ArrayManager 的初始化状态如果还没初始化成功就直接返回没有必要去进行后续的交易相关的逻辑判断。因为很多技术指标计算对最少 K 线数量有要求如果数量不够的话计算出来的指标会出现错误或无意义。反之如果没有 return就可以开始计算技术指标了启动价差执行算法通过持仓的判断以及结合均线指标挂出委托同时设置离场点。请注意启动算法时如果不传 algo_type 和 algo_offset则分别默认为 taker 和 净仓启动 Maker 算法时不要忘记传入 active_quote_range 和 active_max_volume 参数只有启动 Exchange 算法时algoOffset 才在 AlgoOffset.OPEN 和 AlgoOffset.CLOSE 中选择如果需要在图形界面刷新显示的策略状态数值请不要忘记调用 put_event() 函数。委托状态更新以下函数在策略中几乎都可以直接 pass其具体逻辑应用交给回测/实盘引擎负责。on_spread_pos入参无出参无收到持有仓位更新时 on_spread_pos 函数会被调用。与 CTA 策略模块访问策略逻辑持仓不同价差交易模块访问的是账户底层持仓。所以默认写法是通过调用 get_spread_pos 函数获取价差持仓以供策略进行逻辑判断如下方代码所示def on_spread_pos(self): Callback when spread position is updated. self.spread_pos self.get_spread_pos() self.put_event()on_spread_algo入参algo: SpreadAlgoTemplate出参无收到算法状态更新时 on_spread_algo 函数会被调用。on_order入参order: OrderData出参无收到策略委托回报时 on_order 函数会被调用只有通过策略发出委托才能收到该函数回调通过策略启动算法进行委托收不到该函数回调。on_trade入参trade: TradeData出参无收到策略成交回报时 on_trade 函数会被调用只有通过策略发出委托才能收到该函数回调通过策略启动算法进行委托收不到该函数回调。主动函数start_long_algo入参price: float, volume: float, payup: int None, interval: int None, algo_type: AlgoType AlgoType.TAKER, algo_offset: AlgoOffset AlgoOffset.NET, active_quote_range: int None, active_max_volume: int None出参algoid: strstart_short_algo入参price: float, volume: float, payup: int None, interval: int None, algo_type: AlgoType AlgoType.TAKER, algo_offset: AlgoOffset AlgoOffset.NET, active_quote_range: int None, active_max_volume: int None出参algoid: str与 CTA 策略模块不同价差交易的示例策略都是通过调用 start_long_algo/start_short_algo 函数针对价差组合而不是 buy/sell/short/cover 函数针对单一合约来发出委托的。在价差交易模块中算法负责价差交易的执行策略负责价差算法的调度。价差算法将价差交易简化为了普通委托封装掉了所有主动腿下单和被动腿对冲的细节。以下方 start_long_algo 函数的代码为例可以看到价格和数量是必填的参数超价的数值、时间间隔、算法类型、算法开平、maker 挂单范围阈值、maker 单笔委托量最大值等参数都是选填。也可以看到函数内部收到传进来的参数之后就调用了 SpreadStrategyTemplate 里的 start_algo 函数来发单因为是 long 指令则自动把方向填成了 LONGdef start_long_algo( self, price: float, volume: float, payup: int None, interval: int None, algo_type: AlgoType AlgoType.TAKER, algo_offset: AlgoOffset AlgoOffset.NET, active_quote_range: int None, active_max_volume: int None ) - str: return self.start_algo( Direction.LONG, price, volume, payup, interval, algo_type, algo_offset, active_quote_range, active_max_volume )start_algo入参direction: Direction, price: float, volume: float, payup: int None, interval: int None, algo_type: AlgoType AlgoType.TAKER, algo_offset: AlgoOffset AlgoOffset.NET, active_quote_range: int None, active_max_volume: int None出参algoid: strstart_algo 函数是价差策略引擎调用的启动新的价差交易算法的函数。一般在策略编写的时候不需要单独调用通过 start_long_algo/start_short_algo 函数发送委托即可。请注意要在策略启动之后也就是策略的 trading 状态变为【True】之后才能发出交易委托。如果策略的 Trading 状态为【False】时调用了该函数只会返回 若启动算法时少传参或传错参算法会启动失败并输出相关日志信息。stop_algo入参algoid: str出参无stop_all_algos入参无出参无stop_algo 和 stop_all_algos 都是负责停止价差算法的交易请求类函数。stop_algo 是停止策略内指定的价差算法stop_all_algos 是停止策略所有的活动价差算法。请注意要在策略启动之后也就是策略的 trading 状态变为【True】之后才能撤单。buy买入开仓DirectionLONGOffsetOPENsell卖出平仓DirectionSHORTOffsetCLOSEshort卖出开仓DirectionSHORTOffsetOPENcover买入平仓DirectionLONGOffsetCLOSE入参vt_symbol: str, price: float, volume: float, lock: bool False出参vt_orderids: List[vt_orderid] / 无buy/sell/short/cover 都是策略内部的负责针对特定的单一合约发出底层交易委托的请求类函数。策略可以通过这些函数给价差策略引擎发送交易信号来达到下单的目的。以下方 buy 函数的代码为例可以看到本地代码、价格和数量是必填的参数锁仓转换则默认为 False。也可以看到函数内部收到传进来的参数之后就调用了 SpreadStrategyTemplate 里的 send_order 函数来发单因为是 buy 指令则自动把方向填成了 LONG开平填成了 OPEN如果 lock 设置为 True那么该笔订单则会进行锁仓委托转换在有今仓的情况下如果想平仓则会先平掉所有的昨仓然后剩下的部分都进行反向开仓来代替平今仓以避免平今的手续费惩罚。def buy(self, vt_symbol: str, price: float, volume: float, lock: bool False) - List[str]: return self.send_order(vt_symbol, price, volume, Direction.LONG, Offset.OPEN, lock)send_order入参vt_symbol: str, price: float, volume: float, direction: Direction, offset: Offset, lock: bool False出参vt_orderids / []send_order 函数是价差策略引擎调用的针对特定合约而不是价差发送委托的函数。一般在策略编写的时候不需要单独调用通过 buy/sell/short/cover 函数发送委托即可。请注意要在策略启动之后也就是策略的 trading 状态变为【True】之后才能发出交易委托。如果策略的 Trading 状态为【False】时调用了该函数只会返回 []。cancel_order入参vt_orderid: str出参无cancel_all入参无出参无cancel_order 和 cancel_all 都是负责撤单的交易请求类函数。cancel_order 是撤掉策略内指定的活动委托cancel_all 是撤掉策略所有的活动委托。请注意要在策略启动之后也就是策略的 trading 状态变为【True】之后才能撤单。功能函数以下为委托交易以外的功能函数put_event入参无出参无在策略中调用 put_event 函数可以通知图形界面刷新策略状态相关显示。请注意要策略初始化完成inited 状态变为【True】之后才能刷新界面。write_log入参msg: str出参无在策略中调用 write_log 函数可以进行指定内容的日志输出。get_engine_type入参无出参engine_type: EngineType在策略里调用 get_engine_type 函数可以获取策略引擎类型。get_spread_tick入参无出参tick: TickData在策略里调用 get_spread_tick 函数可以获取价差 Tick 数据。get_spread_pos入参无出参spread_pos: float在策略里调用 get_spread_pos 函数可以获取价差净持仓数据。get_leg_tick入参vt_symbol: str出参leg.tick: TickData / None在策略里调用 get_leg_tick 函数可以获取特定合约的 Tick 数据。get_leg_pos入参vt_symbol: str, direction: Direction Direction.NET出参leg.net_pos: float / leg.long_pos: float / leg.short_pos: float / None在策略里调用 get_leg_pos 函数可以获取特定合约的持仓数据用于处理瘸腿后的细粒度调整。send_email入参msg: str出参无配置好邮箱相关信息之后配置方法详见 docs/elite/info/elite_trader.md 中全局配置的邮件部分在策略中调用 send_email 函数可以发送指定内容的邮件到自己的邮箱。请注意要策略初始化完成inited 状态变为【True】之后才能发送邮件。load_bar入参days: int, interval: Interval Interval.MINUTE, callback: Callable None出参无在策略中调用 load_bar 函数可以在策略初始化时加载价差 K 线数据。如下方代码所示load_bar 函数调用时默认加载的天数是 10频率是一分钟对应也就是加载 10 天的 1 分钟 K 线数据建议加载的天数宁可多一些也不要太少。加载时会先依次尝试通过交易接口、数据服务、数据库获取历史数据直到获取历史数据或返回空。请注意回测期内每条腿的 K 线数据1 分钟最佳若有某条腿缺失一段则所有腿的这一段数据都会被弃用。def load_bar( self, days: int, interval: Interval Interval.MINUTE, callback: Callable None, ): Load historical bar data for initializing strategy. if not callback: callback self.on_spread_bar self.strategy_engine.load_bar(self.spread, days, interval, callback)load_tick入参days: int出参无价差 Tick 数据来源首先需要在 SpreadTrading 模块中创建配置好价差后通过 DataRecorder 模块来进行 Tick 录制本地代码填入 xx-spread.LOCAL其中 xx-spread 为用户定义的价差名称LOCAL 为固定交易所后缀代表本地生成。在策略中调用 load_tick 函数可以在策略初始化时去数据库加载录制好的价差 Tick 盘口数据。算法介绍价差套利模块都是通过价差算法来执行价差交易从而将相对复杂的多条腿交易执行简化为面向价差组合的普通委托封装掉所有主动腿下单和被动腿对冲的细节。算法检查函数is_active检查算法是否结束is_order_finished检查委托是否全部结束is_hedge_finished检查被动腿和主动腿是否匹配check_algo_cancelled检查算法是否被停止calculate_traded_volume计算已成交价差数量calculate_traded_price计算已成交价差均价SpreadTakerAlgo见价下单算法算法原理见价下单主动腿以对价先行下单被动腿以对价立即对冲。算法收到 tick 数据推送先检查委托是否结束再检查对冲是否结束若未结束则发起被动腿对冲。最后检查盘口是否满足条件满足条件后发出主动腿委托。算法收到委托回报若收到主动腿已结束的委托则发起被动腿对冲。超时限制到达计时时间执行委托全撤。算法优势灵活且不占用过多撤单次数。不足所有腿均需要付出盘口买卖价差的滑点成本等待主动腿对价满足条件需要比 Maker 更长的时间。SpreadMakerAlgo报价做市算法算法原理报价做市基于被动腿盘口计算主动腿最差成交价。算法收到 tick 数据推送先检查委托是否结束再检查对冲是否结束若未结束则发起被动腿对冲。然后检查新的挂单价格与当前已挂价格的差值是否超过设定的阈值如果未超过则发出主动腿委托如果超过则重挂。算法收到委托回报遭遇拒单则停止策略若收到主动腿已结束的委托则清空挂单价格记录。算法收到成交回报只关心主动腿委托若对冲未结束则发起被动腿对冲。计时时间到达到达计时时间执行委托全撤。算法优势主动腿报价挂单做市目标是赚得盘口价差的同时提高成交概率。不足虽然有设定挂单阈值限制但撤单行为比 Taker 更频繁需要仔细监控委托流量费成本。SpreadExchangeAlgo交易所价差算法算法原理基于交易所提供的价差组合来创建价差采用各条腿的行情盘口计算价差盘口最终采用交易所的价差合约进行交易执行。算法收到 tick 数据推送检查是否已发出了委托若已发出则返回。再检查价差套利合约是否生成成功并查询价差套利合约的合约信息然后发出交易所价差委托缓存委托号和价差关系最后输出日志并记录委托已经发出的状态。算法优势体验上类似单合约且免去了主动腿撤单。不足缺乏灵活性可选择合约范围有限。补充说明与社区版的关系及适用前提本文基于 VeighNa Elite 版文档展开其中介绍的价差创建/移除、策略实例管理与回调函数体系等核心操作流程与社区版 docs/community/app/spread_trading.md 一脉相承Elite 版的差异点主要体现在策略模板升级为 EliteSpreadStrategyTemplate新增 AlgoType/AlgoOffset 算法配置枚举支持 Taker/Maker/Exchange 三种算法类型与锁仓/净仓/开仓/平仓四种开平选项策略参数采用 Parameter/Variable 容器类声明并支持通过 jupyter 进行价差回测回测场景下主动腿/被动腿的乘数符号约定与图形界面相反两者皆传负数。需要说明的是vnpy 核心仓库本身以框架层代码为主SpreadTrading 应用模块位于独立的vnpy_spreadtrading扩展包中本仓库内对应功能说明文档即 docs/elite/strategy/elite_spreadtrading.md 与 docs/community/app/spread_trading.md实际使用时请确保已安装并加载对应的扩展应用。策略文件放入运行时目录的 strategies 目录后即可在【添加策略】下拉框中看到对应策略类并创建策略实例投入全自动交易。【免费下载链接】vnpy基于Python的开源量化交易平台开发框架项目地址: https://gitcode.com/vnpy/vnpy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表