vn.py量化社区
By Traders, For Traders.
Member
avatar
加入于:
帖子: 21
声望: 5

刚刚接触差价交易,最近研究了一下VNPY的差价交易模块,这里整理一下思路,新手可以参考。
如果有写的不对的地方,大佬指正一下哈。

首先来解释一下差价交易。
简单的例子:
你们王家坝村,有一个卫生纸厂,主要生产厕所用的卷纸。
产品物美价廉,垄断全球。
镇上的交易所都开始卖起了卫生纸期货,代码Z。
你家二姨就在厂里做包装工,天天加班,仓库都堆满了发往全球的产品。

结果川普抽风了,想搞点事,宣布美国人一周只能拉一次。。。

好了,依你的智商,肯定知道这妥妥的利空啊!
做空,就是干!

万万没想到,印度阿三半夜突然宣布上厕所必须用纸了。。。
一夜之间来了个十几亿的茅坑需求。。。

哦豁,爆仓了。。。

在你万分沮丧的时候,突然收到大表哥的消息,要请你去他们赵家村撸串。。。
说是做期货发财了

这就奇怪了,这大表哥小学毕业就去村里的木浆厂砍树了啊,怎么还能把期货玩飞起?
原来,你大表哥看到你们村的纸厂天天来催木浆原料送货,就做多了几手木浆(M)的期货。
国际新闻都看不懂的大表哥,就这么蒙对了。。。你说气人不

感觉被啪啪打脸的你,冷静分析,发现卫生纸(Z),和木浆(M)的走势几乎一模一样。

木浆作为卫生纸的主要原材料,两者相关性非常明显。

假设以最简单的模型,一吨卫生纸需要两吨木浆。
生产工艺简单,所以其他主要成本就是人工了。
问问你家二姨,发现已经多年没有涨过工资了,所以人工成本基本就是恒定了

因此,卫生纸和木浆之间的差价,理论上就是恒定了

做一个简单的差价合约 ZM
ZM = Z - 2M

把Z和M的价格数据拉出来算算,ZM基本就是在100到300之间来回摆动。

看到了了么,这特么不就是震荡行情么!

高抛低吸!就是干!

策略已经很明显了,
价格到了100就给我多,到了200平他
价格到了300就给我空,到了200平他

管他川普拉不拉,阿三屁屁用什么擦。。。
单边再怎么波动,差价最终都是要回归的嘛

接下来就是具体操盘了
1:首先你需要自己手动合成一个差价合约ZM
2:当价格到到达指定价位,需要开仓做多ZM或者做空ZM
市场上没有合成好的ZM给你买卖,所有你要自己转换成对应的Z和M来交易。
3:价格回到正常价位,你需要平仓出场
同样你需要转换成Z和M的合约来做平仓交易
由于价格波动频繁,你一个人肯定是搞不定了,于是找来了基友,
铁蛋帮你做Z的交易,狗剩帮你做M的交易
你就专门合成ZM

来个情景再现:
Z价格为1000
M价格为451

ZM = Z - 2M = 92
低于了100
此时你发出指令:ZM,做多,10手
铁蛋率先出手,撸他10手的Z 多单,
接着,狗剩开始撸20手的M空单。

一顿操作猛如虎,妥妥的锁住了10手ZM合约。
就算川普要求老百姓一年拉一次,Z价格暴跌,M合约上的空单也能妥妥的补回来。

ZM价格到200后,再同时平掉Z和M即可。

这样ZM 1000个点的利润就到手了,稳稳的幸福有没有!

同理可以对ZM做空操作


接下来聊一下VNPY里具体的差价模块是怎么操作的

首先看一下差价模块的目录结构:
ui/widget.py
strategies/basic_spread_strategy.py
base.py
engine.py
temple.py
algo.py

ui部分就不多讲了
聊一下具体的交易逻辑
以上面的例子做对比

首先是ZM差价合约的合成,这里要用到base.py下的两个类:LegData和SpreadData
LegData实际上就是差价合约中的某一个单合约,比如例子中的Z
里面主要是单一合约的买卖价格,量,以及仓位信息
主要是给后面的SpreadData用

SpreadData就是我们手动合成的新合约了,例子中对应的就是ZM
这个是需要在用户在UI里创建的,界面上“创建价差”。
价差名称:这个是后面交易价差合约要用到的合约代码,比如Z&M
主动腿:例子中的Z就是所谓的主动腿
每条腿信息:本地代码:就是vtsymbol,比如螺纹钢:rb1910.shfe
价格乘数:主动腿 Z就是1, 被动腿 M 就是 -2
交易乘数:主动腿 Z就是1, 被动腿 M 就是 -2

对SpreadData的管理是通过engine.py中的SpreadDataEngine类
创建完SpreadData后,有行情的情况下,会看到UI上会实时更新价差的数据。
这里就是SpreadDataEngine中的process_tick_event,在收到单条腿的tick信息后。
会将tick信息写到LegData中,同时发出EVENT_SPREAD_DATA消息。
ui中的SpreadDataMoniter会收到EVENT_SPREAD_DATA来更新界面
同时SpreadStrategyEngine和SpreadAlgoEngine也会收到,在后续的交易逻辑中会用到

有了ZM的SpreadData,就可以开始做差价交易了
上面的简单策略,100买,300卖
就是strategies/basic_spread_strategy.py中BasicSpreadStrategy

几个参数, buy_price,做多的价位,这里就是100, short_price,做空的价位这里就是300, sell_price和cover_price就是平多平空的位置,这里是200

比较重要的接口是on_spread_data(),这里其实可以理解为针对SpreadData的on_tick,
其触发逻辑是:SpreadDataEngine/process_tick_event->SpreadDataEngine/put_data_event(EVENT_SPREAD_DATA)->SpreadStrategyEngine/process_spread_data_event->BasicSpreadStrategy/on_spread_data

启动策略后,一开始spread_pos是0,策略会创建一个buy_algo和一个sell_algo
algo(算法)是价差交易中比较特别的地方,算法负责了具体的单合约买卖操作
可以把算法理解成你的基友铁蛋和狗剩,他们来负责了具体的买卖

engine.py中的SpreadAlgoEngine具体管理了所有的Algo
当前版本中的所有algo都是用SpreadTakerAlgo
具体的买卖操作就在SpreadTakerAlgo 的on_tick中实现的
其调用逻辑为:SpreadAlgoEngine/process_tick_event -> SpreadAlgoTemplate/update_tick -> SpreadTakerAlgo/on_tick

我们以上面的例子做多来解释一下里面的执行逻辑
价差到92,你决定做 ZM 10手多单
on_tick收到数据后,走到:Direction.LONG下的take_active_leg()
在take_active_leg中:
之前没有过成交,spread_volume_left就是10
假设这时候spread可以交易的volume大于10,可以交易的spread_order_volume就是10
如果spread可以交易的volume小于10,要取小的值,否则,交易会出现瘸腿的情况,差价交易中如果瘸腿风险非常大。
spread的ask_volume和bid_volume的计算也比较繁琐,具体参考SpreadData中的calculate_price方法

再通过SpreadData中的calculate_leg_volume计算出具体某一条腿(实际单合约)具体的手数
在这个例子中,Z的交易乘数是1,计算出的Z就是10。而M交易乘数是2,对应的单合约就是20手

最后通过send_leg_order() 发出实际的交易指令到交易所

on_order收到订单事件后,逻辑会进入hedge_passive_legs()
这个就是进入了被动腿的追单逻辑,也就是传说中的对冲,类似狗剩后面做了20手M的空单。
对冲逻辑类似之前的主动腿发单,要注意的就,被动腿要发的单量是根据主动腿成交量来的。

被动腿成交后,就完成了一次对ZM价差合约的做多操作。

价差交易里面比较繁琐的是价差合约的价格计算和volume计算,以及各个腿之间的algo协调。
后面整理了再写写。
上面有什么写得不对的地方,大家多多指正

感谢vnpy作者开源的系统
我是群里的上海-老麦,大家到群里多多交流

祝大家都发财!

Member
avatar
加入于:
帖子: 35
声望: 2

这个非常棒。

Administrator
avatar
加入于:
帖子: 4214
声望: 241

WOW,给你加个精!最后图片好像看不到,请检查下哈~

Member
avatar
加入于:
帖子: 144
声望: 3

感谢,
非常好的入门教程。

Member
avatar
加入于:
帖子: 21
声望: 5

用Python的交易员 wrote:

WOW,给你加个精!最后图片好像看不到,请检查下哈~

之前发的是processon上的脑图,好像不行,我直接上传图片也失败了
其实很乱,也没多少参考价值,以后再发吧

等陈老板的价差回测功能哈:)

Member
avatar
加入于:
帖子: 186
声望: 23

好贴

Member
avatar
加入于:
帖子: 8
声望: 0

好贴,强烈支持,决定好好撸一帖

Member
avatar
加入于:
帖子: 7
声望: 0

讲解的通俗。谢谢

© 2015-2019 上海韦纳软件科技有限公司
备案服务号:沪ICP备18006526号-3