vnpy/docs/spread_trading.md
2019-10-10 23:45:50 +08:00

14 KiB
Raw Blame History

价差交易模块

价差交易与CTA有比较大的不同

  • CTA主要是针对单标的品种盈利主要靠肥尾部分特点是低胜率高盈亏比。

  • 价差交易针对的是关联程度高的品种,实现方式可以是期现套利、跨期套利、跨市套利、跨品种套利。从另一个角度来看,价差交易的标的物是价差,价差的统计特征是均值回归,即围绕某个数值上下波动。因此出现黑天鹅的概率要远远少于单标的品种,其盈利主要靠尖峰部分。

 

根据品种相关程度不同,价差交易所适用的领域也有所不同:

  • 相关程度100%也就是说交易的是同一样商品区别仅仅是所处的市场不同。举个例子比特币在火币的价格是8500美元在币安是8495美元这样完全可以从币安以8495美元买入并且在火币以8500美元卖出赚取5美元的无风险利润。因此类似这种无风险套利拼的是低延时属于高频交易领域。需要投入大量精力在托管机房、海底光缆、网卡设计等方面。

  • 相关程度高的品种,如期货的近期合约和远期合约,可以做日内交易。简单的可以设置固定阈值,如价差<买入阈值,买入价差(买入主动腿,并且卖出被动退完成对冲);价差>卖出阈值,卖出价差(卖出主动腿,并且买入被动腿完成对冲)。若价差并不严格的遵守均值回归;或者在大周期上价差发生较大的偏离,但是在小周期上围绕着均值上下波动;这两类可以使用布林带通道实现套利,如价差>布林带通道上轨,卖出价差;价差<布林带下轨,买入价差。

  • 相关程度价高品种,如产业链相关的期货品种,可以做基本面套利。基本面套利更要求投资者主动挖掘有用信息,如参与实地调研,或者使用无人机加上图形识别技术监控品种的实际库存状况;通过对基本面信息的分析与处理,然后在单个方向去交易价差,即在高位卖出价差,在均值位平仓离场。由于价差基本面套利的持仓周期可以从几周到几个月,所以对执行的要求不高,更偏重于基本面信息的挖掘和处理。

 

模块构成

价差交易模块主要由6部分构成如下图

  • base定义了价差交易模块中用到的一些基础设置如主动腿/被动腿合约数据结构,以及由主动腿和被动腿合成的价差数据结构。

  • template包含了价差算法模板和价差交易策略模板。

  • strategies: 官方提供的价差交易策略示例如basic_spread_strategy实现了只要设置好固定的阈值buy、sell、short、cover即可实现自动化交易。

  • algo: 定义了主动对价成交算法:为了规避交易所设置挂撤单次数的上限,通用做法是牺牲点差来保证成交率。并且价差交易也要求在主动腿完成交易后,被动腿要立刻跟上完成对冲。

  • engine定义了父类价差引擎并且继承于父类的价差数据引擎、价差算法引擎、价差策略引擎。

  • ui基于PyQt5的GUI图形应用。

 

基本操作

打开价差交易界面

打开VN Trader先连接上交易接口如BITMEX然后在菜单栏中点击【功能】->【价差交易】进入价差交易界面。

 

总体来说价差交易界面可分成2部分

  • 交易部分:在创建好价差合约后,可以调用价差策略实现自动交易,也可以手动交易来调整仓位。
  • 监控部分:可以查看实时价差合约行情信息,价差策略和价差算法执行情况,日志组件也会输出相关信息。

 

创建价差合约

1 寻找可组成价差的合约:

  • 回到VN Trader在菜单栏中点击【帮助】-> 【查询合约】按钮,弹出合约查询界面;
  • 在界面中找到我们用于价差交易的合约;
  • 在BITMEX的示例中我们主要通过比特币期货的跨期套利来展示即交易XBTUSD比特币期货永续合约和XBTZ19比特币期货19年12月到期合约

 

2 构建价差合约

  • 点击【价差创建】按钮,会弹出创建价差界面;
  • 在界面中,【价差名称】指的是用户定义的价差合约名称;
  • 【主动腿代码】是在下面的【腿】选项中,通过【本地代码】来找到的主动腿。一般来说,价差交易原则上是主动腿完成交易后,立刻用被动腿进行对冲,故主动腿一般选择较为不活跃的合约,价格乘数和交易乘数均为正;被动腿一般选择较为活跃的合约,价格乘数和交易乘数均为负;
  • 【腿】包含构建价差合约的主动腿与被动腿,它们由【本地代码】,【价格乘数】,【交易乘数】组成;
  • 在BITMEX的比特币期货跨期套利示例中其价格乘数和交易乘数均为11即价差= XBTZ19 - XBTUSD买入1手价差等于买入1手XBTZ19同时卖出1手XBTUSD完成对冲。
  • 设置好价差合约的参数后,点击下方的【创建价差】按钮。

注意:在多条腿并且期货合约规模不等时,构建价差会相对困难一些,如构建虚拟钢厂套利所用到的价差合约:

  • 螺纹钢生产技艺是16吨铁矿石加上5吨焦炭练成10吨螺纹钢。
  • 基于价格乘数的价差spread = 1* RB - 1.6*I - 0.5*O。
  • 但是由于螺纹是10吨/手铁矿石和焦炭都是100吨/手所以他们交易乘数是11010
  • 故基于最大公约数规则其实际交易手数关系是每买入100手螺纹钢1000吨需要卖出16手铁矿石1600吨和5手焦炭500吨完成对冲。

 

3监控价差合约

  • 创建好xbt价差后【日志】组件会输出相关信息
  • 【价差】组件也实时价差合约的行情信息价差合约由base.py的SpreadData类来负责
  • 在xbt价差的示例中【买价】= 1*XBTZ19买一价 - 1*XBTUSD卖一价
  • 【买量】= minXBTZ19买一量XBTUSD卖一量取最小值用于保证各合约能均能成交
  • 【卖价】= 1*XBTZ19卖一价 - 1*XBTUSD买一价
  • 【卖量】= minXBTZ19卖一量XBTUSD买一量

 

手动交易

假设当前xbt价差合约买价为330和卖价为340并且在大周期上价差围绕0上下波动。

价差交易的盈利在于高抛低吸,即在低位,如-500买入xbt价差合约在高位如+500卖出xbt价差合约平仓获利离场。由于不能立刻成交所以其默认执行算法SpreadTaker主动对价成交算法会每隔一段时间进行委托操作一般是以超价的限价单的形式发出委托。

下面通过2个例子分别是发出委托立即成交和发出委托等待成交来具体介绍手动交易的操作情况

1发出委托立即成交

  • 目标价差合约价格的350
  • 我们以超价5美金的形式及355的价位发出买入限价单
  • 由于限价单355价位高于当前卖价340所以委托立刻成交。

 

2成交委托监控

  • 【日志】组件显示发出买入xbt价差合约的顺序是发出XBTZ19多头委托 -> XBTZ19委托成交 -> 发出XBTUSD空头委托 -> XBTUSD委托成交。价差交易必须遵循的逻辑是主动腿成交后才去用被动腿来对冲头寸并且对冲必须尽可能即使。这也为什么一般被动腿选择较为活跃合约的原因。

  • 【价差】组件显示买入1手xbt价差合约成交后【净仓】从0变成1实际上VN Trader【持仓】组件显示XBTZ19合约多头持仓1手XBTUSD合约空头持仓1手。

  • 【算法】组件显示本次委托SpreadTaker算法执行情况成交数量1手委托状态是完全成交。

 

3发出委托等待成交

  • 以-500的价位发出限价买入指令由于当前买价卖价分别位于330和340所以委托状态是“未成交”。仅当卖价低于-500时才出发该限价单已超价5美金即-495去主动成交。
  • 【日志】组件显示本次算法即SpreadTaker_000004已经启动但由于价格没有触发到目标价位算法在循环读秒中处于等待状态
  • 【算法】组件显示其委托状态为"未成交"要结束算法只需鼠标双击【SpreadTaker_000004】单元格即可。

 

4撤销委托

鼠标双击完【SpreadTaker_000004】单元格后在【日志】组件可以看到算法已经停止【算法】组件显示委托状态由“未成交”变成”已撤单“。

 

自动交易

目前vnpy官方只提供一个价差策略BasicSpreadStrategy策略逻辑相对简单即设置4个目标价位

  • 在价差合约的价格低位买入开仓BUY然后在接近均值时候卖出平仓SELL
  • 在合约价格高位卖出开仓SHORT然后在价格走低接近均值买入平仓COVER

 

BasicSpreadStrategy策略继承于SpreadStrategyTemplate其策略逻辑主要在on_spread_data()函数上。执行逻辑是先检测仓位:

  • 若无仓位分别发出买入开仓和卖出开仓委托然后检测若存在平仓委托调用stop_algo()函数撤销;
  • 若持有多头仓位,先发出卖出平仓委托,然后检测若存在买入开仓委托,撤单处理;
  • 若持有空头仓位,先发出买入平仓委托,然后检测若存在卖出开仓委托,撤单处理。
    def on_spread_data(self):
        """
        Callback when spread price is updated.
        """
        self.spread_pos = self.get_spread_pos()

        # No position
        if not self.spread_pos:
            # Start open algos
            if not self.buy_algoid:
                self.buy_algoid = self.start_long_algo(
                    self.buy_price, self.max_pos, self.payup, self.interval
                )

            if not self.short_algoid:
                self.short_algoid = self.start_short_algo(
                    self.short_price, self.max_pos, self.payup, self.interval
                )

            # Stop close algos
            if self.sell_algoid:
                self.stop_algo(self.sell_algoid)

            if self.cover_algoid:
                self.stop_algo(self.cover_algoid)

        # Long position
        elif self.spread_pos > 0:
            # Start sell close algo
            if not self.sell_algoid:
                self.sell_algoid = self.start_short_algo(
                    self.sell_price, self.spread_pos, self.payup, self.interval
                )

            # Stop buy open algo
            if self.buy_algoid:
                self.stop_algo(self.buy_algoid)

        # Short position
        elif self.spread_pos < 0:
            # Start cover close algo
            if not self.cover_algoid:
                self.cover_algoid = self.start_long_algo(
                    self.cover_price, abs(
                        self.spread_pos), self.payup, self.interval
                )

            # Stop short open algo
            if self.short_algoid:
                self.stop_algo(self.short_algoid)

        self.put_event()

由此可见BasicSpreadStrategy策略逻辑是基于预先设置好的阈值来发出委托只能处理相对简单的均值回归情况若价差均值并不是围绕某个固定数值波动或者它能够持续走出趋势就需要更加复杂的策略如价差的布林带策略等等。这些更加个性化的策略用户可以基于SpreadStrategyTemplate策略模板自己实现。

现在展示价差交易模块如何基于现有策略去创建策略实例来实现自动交易。由于其用法与CTA策略模块一样故用户迁移成交较低。

1添加策略实例

  • 先选择使用的策略BasicSpreadStrategy
  • 点击【添加策略】按钮,在弹出的界面中写入相关参数;
  • 【strategy_name】为用户自定义的策略实例名称这里是xbt_arb
  • 【spread_name】为用于交易的价差合约这里是xbt
  • 【buy_price】为买入开仓阈值这里是-500即当价格跌破-500时执行委托
  • 【sell_price】为卖出平仓阈值这里是-200即当价格回升到-200时执行委托
  • 【short_price】为卖出开仓阈值这里是500即当价格上涨到500时执行委托
  • 【cover_price】为买入平仓阈值这里是200即当价格下跌到200时执行委托
  • 【max_pos】为主动腿委托数量
  • 【payup】为超价的数值;
  • 【interval】为时间间隔即每隔一段时间会发出委托
  • 最后,点击【添加】按钮完成策略实例的创建。

 

2启动策略

  • 创建好策略实例后,在【策略】组件会显示该策略;
  • 依次点击【初始化】和【启动】按钮后,在【日志】组件中可以看到相关信息的输出;
  • 【算法】组件显示xbt_arb策略调用SpreadTaker算法分别在-500和500的位子上挂上买入和卖出委托
  • 由于实际价格没有达到这2个阈值故委托一直挂着其委托状态为"未成交"。

 

最后,若要停止策略,点击【停止】按钮即可;【编辑】按钮用于修改策略参数;【移除】按钮用于移除该策略。