更多精彩内容,欢迎关注公众号:数量技术宅。想要获取本期分享的完整策略代码,请加技术宅微信:sljsz01
价差计算的“误区”我们在测试两个或多个金融资产相互运算产生的策略信号时,免不了需要涉及将不同的价格时间序列,按照时间轴进行对齐,套利策略就是其中之一。然而,大部分介绍套利策略、统计套利类的文章,对于价差序列的生成计算,处理的十分简单,基本就是两个时间序列相减。对于较为低频的信号,这样处理问题不大,但在中高频的信号领域,直接相减,会存在着一定的问题。
这是因为,对于不同资产的价格序列,存在着交易所推送时间、以及到达时间的差异。即使我们回测时看到的两个Tick的时间戳是完全相同的,在实盘服务器接收推送行情的时候,也是按照先、后顺序达到的。我们在实际交易中发现,比如上海期货交易所某个品种的不同到期交割月的合约,交易所在切片数据的推送不是同时进行的,而是按照交割月的顺序推送的,例如按照RB2010、RB2101、RB2015,类似这样的先后顺序来进行推送的,其他品种也是如此,而对于同一个500ms的切片时间内,收到RB2010、RB2101、RB2015的Tick数据的时间戳,却是相同的。
再比如数字货币的跨交易所套利,两个交易所即使在相同时间发送的Tick数据,由于交易所服务器物理位置不同造成的传输时间不同,到达我们策略信号计算服务器的时间大概率也会不同。
一个典型的价格到达频率不同的例子如果说行情数据到达时间有先后,直接相减计算价差会有一定的“滞后”或“未来函数”问题的话,价格到达频率不同,则根本就无法直接相减计算价差了。总之,我们需要一套更贴近实际交易的价差计算方式。
我们来看一个价格到达频率不同的例子,即两个品种数据的推送频率是不一样的。如果我们需要对股指期货、股票ETF进行期现套利策略的设计,以IC与中证500ETF的数据为例,计算期现套利的价差。
IC股指期货的Tick数据,我们的数据源是Wind,IC对应的中金所,它的行情推送频率是每1秒2笔数据,Level1免费行情推送的是1档盘口,即只有买1、卖1的数据,数据时间是股指期货的交易时间:9:29-15:00。我们来看一下IC的Tick数据样例。
再来看中证500ETF的数据,同样来源于Wind,500ETF行情数据的推送频率相比较IC要低很多,每3秒会有1笔数据,Level1免费行情有5档的盘口,即买1到买5、卖1到卖5,数据推送时间:9:15-15:00,包含股票的集合竞价时间段。我们来看一下500ETF的Tick数据样例。
巧用Pandas的Merge函数对于这样推送频率有差异、时间轴也有差异的数据,计算价差,我们就需要根据时间轴来进行合成。Python Pandas库的Merge函数,正好符合我们所需要的功能。我们简要介绍一下Merge函数。
pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,left_index=False, right_index=False, sort=True,suffixes=('x', 'y'), copy=True, indicator=False,validate=None)
我们在做数据合成的时候,最常用到的是前4组参数:
left: 拼接的左侧DataFrame对象
right: 拼接的右侧DataFrame对象
on: 要加入的列或索引级别名称。 必须在左侧和右侧DataFrame对象中找到,对于金融时间序列,一般来说是时间轴
how: One of ‘left’, ‘right’, ‘outer’, ‘inner’,默认inner。inner是取交集,outer取并集。比如left:[‘A’,‘B’,‘C’];right[’'A,‘C’,‘D’];inner取交集的话,left中出现的A会和right中出现的买一个A进行匹配拼接,如果没有是B,在right中没有匹配到,则会丢失。'outer’取并集,出现的A会进行一一匹配,没有同时出现的会将缺失的部分添加缺失值。