【量化课堂】基于协整的搬砖策略


导语:配对交易(Pairs Trading)是通过一买一卖的手段来赚取两只股票走势的差价的投资策略。本文介绍如何通过协整关系实现配对交易,以及在缺乏卖空机制情况下的搬砖策略。

查看详细回测与源码,以及更好的阅读体验请移步原文: https://www.joinquant.com/post/1810?f=xq

作者:Haozun,肖睿
编辑:宏观经济算命师

本文由JoinQuant量化课堂推出,难度为进阶下,理解深度为level-0。

阅读本文需要掌握协整(level-0)的知识。协整:https://www.joinquant.com/post/1731?f=xq

配对交易
相信很多同学都了解过 Pairs Trading,即配对交易策略。其基本原理就是找出两只走势相关的股票。这两只股票的价格差距从长期来看在一个固定的水平内波动,如果价差暂时性的超过或低于这个水平,就买多价格偏低的股票,卖空价格偏高的股票。等到价差恢复正常水平时,进行平仓操作,赚取这一过程中价差变化所产生的利润。

使用这个策略的关键就是“必须找到一对价格走势高度相关的股票”,而高度相关在这里意味着在长期来看有一个稳定的价差,这就要用到协整关系的检验。

在量化课堂介绍协整关系的文章里,我们知道如果用 Xt 和 Yt 代表两支股票价格的时间序列,并且发现它们存在协整关系,那么便存在实数 a 和 b,并且线性组合 Zt=aXt−bYt 是一个(弱)平稳的序列。如果 Zt 的值较往常相比变得偏高,那么根据弱平稳性质,Zt 将回归均值,这时,应该买入 b 份 Y 并卖出 a 份 X,并在 Zt 回归时赚取差价。反之,如果 Zt 走势偏低,那么应该买入 a 份 X 卖出 b 份 Y,等待 Zt上涨。所以,要使用配对交易,必须找到一对协整相关的股票。

这里要提醒读者,无论是原始的 Pairs Trading 策略,还是本篇的搬砖策略,在寻找股票对时,数据上的检验都只是辅助手段。我们首先要做的还是在基本面的角度进行分析,分析公司的主营业务,产品链,业内地位等。在此基础上,我们才会对有可能具有协整关系的股票进行数据上的检验。这是非常重要的。

协整关系的检验
我们想使用协整的特性进行配对交易,那么要怎么样发现协整关系呢?

在 Python 的 Statsmodels 包中,有直接用于协整关系检验的函数 coint,该函数包含于 statsmodels.tsa.stattools 中。

首先,我们构造一个读取股票价格,判断协整关系的函数。该函数返回的两个值分别为协整性检验的 p 值矩阵以及所有传入的参数中协整性较强的股票对。我们不需要在意 p 值具体是什么,可以这么理解它: p 值越低,协整关系就越强;p 值低于 0.05 时,协整关系便非常强。

import numpy as np
import pandas as pd
import statsmodels.api as sm
import seaborn as sns

# 输入是一DataFrame,每一列是一支股票在每一日的价格
def find_cointegrated_pairs(dataframe):
    #         得到DataFrame长度
    n = dataframe.shape[1]
    # 初始化p值矩阵
    pvalue_matrix = np.ones((n, n))
    #         抽取列的名称
    keys = dataframe.keys()
    # 初始化强协整组
    pairs = []
    #         对于每一个i
    for i in range(n):
        # 对于大于i的j
        for j in range(i+1, n):
            #         获取相应的两只股票的价格Series
            stock1 = dataframe[keys[i]]
            stock2 = dataframe[keys[j]]
            # 分析它们的协整关系
            result = sm.tsa.stattools.coint(stock1, stock2)
            #         取出并记录p值
            pvalue = result[1]
            pvalue_matrix[i, j] = pvalue
            # 如果p值小于0.05
            if pvalue < 0.05:
                #         记录股票对和相应的p值
                pairs.append((keys[i], keys[j], pvalue))
    # 返回结果
    return pvalue_matrix, pairs

其次,我们挑选10只银行股,认为它们是业务较为相似,在基本面上具有较强联系的股票,使用上面构建的函数对它们进行协整关系的检验。在得到结果后,用热力图画出各个股票对之间的 p 值,较为直观地看出他们之间的关系。

我们的测试区间为2014年1月1日至2015年1月1日。热力图画出的是 11 减去 p 值,因此颜色越红的地方表示 p 值越低。

(代码请到原文查看,雪球代码支持有问题)
JoinQuant聚宽
可以看出,上述10只股票中有5对具有较为显著的协整性关系的股票对(红色表示协整关系显著)。我们选择使用其中 p 值最低(0.01060.0106)的工商银行(601398.XSHG)和中国银行(601988.XSHG)这一对股票来进行研究。首先调取工商银行和中国银行的历史股价,画出两只股票的价格走势。

(代码请到原文查看,雪球代码支持有问题)
JoinQuant聚宽
接下来,我们用这两支股票的价格来进行一次OLS线性回归,以此算出它们是以什么线性组合的系数构成平稳序列的。

x = stock_df1
y = stock_df2
X = sm.add_constant(x)
result = (sm.OLS(y,X)).fit()
print(result.summary())
JoinQuant聚宽
系数是 0.99380.9938,画出数据和拟合线。

(代码请到原文查看,雪球代码支持有问题)JoinQuant聚宽
设中国银行的股价为 Y,工商银行为 X,回归拟合的结果是
Y=−0.7248+0.9938⋅X
也就是说 Y−0.9938⋅X是平稳序列。

依照这个比例,我们画出它们价差的平稳序列。可以看出,虽然价差上下波动,但都会回归中间的均值。

(代码请到原文查看,雪球代码支持有问题)JoinQuant聚宽

买卖时机的判断
这里,我们先介绍一下 z-score。z-score 是对时间序列偏离其均值程度的衡量,表示时间序列偏离了其均值多少倍的标准差。首先,我们定义一个函数来计算 z-score:
一个序列在时间 t 的 z-score,是它在时间 t 的值,减去序列的均值,再除以序列的标准差后得到的值。

def zscore(series):
    return (series - series.mean()) / np.std(series)

对于工商银行与中国银行的平稳线性组合,用上面的函数计算 z-score 并绘出图。

(代码请到原文查看,雪球代码支持有问题)JoinQuant聚宽
我们认为,当两这个序列的 z-score 突破 1 或者 −1 时,说明两支股票的价差脱离了统计概念中的合理区间,如果它们的协整关系能够保持,那么它们的价差应该收敛。所以,在发现上述序列突破 1 或 −1 时,应该按照比例买多一支股票并做空另外一支,从而赚取之后收敛的差价。

结合上图,当 z-score 突破上方红线时,说明工商银行的价格相对于中国银行高估,因此我们买入 1 份中国银行并卖空 0.9938 份工商银行(系数根据前面的线性回归得出),并当 z-score 回归于 0 时清仓获利。如果 z-score 突破下方绿线的话,反方向操作即可

中国式 Pairs Trading 策略:搬砖
标准的配对交易策略是通过一买一卖的行为来对冲掉系统性风险,从而以较低的风险赚取到持续的利润。但目前A股市场是不允许进行直接卖空操作的。融券的渠道我等散户又搞不定。因此,我们对原始的配对交易进行修改,只进行做多操作,不进行做空操作。这种操作被形象的成为“搬砖”。其目标不是追求绝对收益,而是追求收益率比一直持有一个股票的高。

在选定一组协整关系为 aX−bY 的股票后,我们有以下策略:
∙∙ 选定比例 p 和 q,初始仓位为 p% 的 X 和 q% 的 Y。选定测试 z-score 天数的参数 test_daystest_days。

∙∙ 每天执行:
- 计算两支股票的线性组合序列 aX−bY 在过去 test_daystest_days 的标准差和均值,以此计算 z-score。

- 如果当天 z-score 高出 1,则将仓位调整为全仓 Y。如果当天 z-score 小于 −1,则将仓位调整为全仓 X。

- 如果上一交易日处于全仓一支股票的状态,并且今日 z-score 回归 0 点,则调整回至 p% 和 q% 的比例。

在之前章节中我们通过分析发现,工商银行和中国银行在2014年全年有着非常强的协整关系,但我们不能再14年进行回测,因为这样等同于使用未来函数(比如文章最后的回测),因此我们在2015至2016的区间内进行回测。使用的参数是 p%=50%,q%=50%,test_days=120。

由于没有对冲机制,所以不能依靠绝对收益评估策略的效益,而要用它和配对的两支股票对比。如果分别跑赢了两支股票,那么说明该策略是有效的。

首先是和工商银行的对比,我们的策略完全跑赢了这支股票。
JoinQuant聚宽
其次是和中国银行的对比,虽然前半年被工商银行拖了后腿,但后半年还是稳稳地跑赢了。
JoinQuant聚宽
本策略全程满仓,持有股票只限于以上两支。通过判断两支股票的相对强度进行仓位调整,最后收益胜过了其中的任何一支,效果是非常显著的。

策略的应用
搬砖的策略能跑赢个股,但也只能跑赢个股,所以若想投入使用并赚取稳定收益,还要结合其他策略一起使用。比如,使用基本面或者技术面的思路来判断银行指数在未来一段时间中的走势。如果趋势乐观,则可以在指数成分股中选取两支具有协整性质的个股进行搬砖。如果趋势不乐观,则空仓对待。这样,通过搬砖,在其他策略之上产生更多的超额收益

代码说明书与变量说明书
函数说明书
JoinQuant聚宽
全局变量说明书
JoinQuant聚宽

本文由JoinQuant量化课堂推出,版权归JoinQuant所有,商业转载请联系我们获得授权,非商业转载请注明出处。

查看详细回测与源码,以及更好的阅读体验请移步原文: https://www.joinquant.com/post/1810?f=xq

@量化钢铁侠 @今日话题 @量化小王子 @价值趋势技术派 @云蒙 @持有封基 @非完全进化体 @阿狸 @童思侃 @Stevevai1983 @Janu68 @qs_cn @一只特立独行的猪 @william_hsu @庚白星君 @那年帝流浆 @辛无疾 @forestgumpgg @漩涡鸣人NARUTO 

为了便于策略与代码的交流,量化课堂加入了代码说明书与变量说明书,大家觉得怎么样?
欢迎各位朋友随意交流讨论,提出宝贵的建议,让我们和您一起进步。
喜欢的不要忘了转发和关注哦。


雪球对代码的支持有问题,对代码有需求的朋友,请移步原文查看吧。
雪球转发:57回复:95喜欢:455

精彩评论

pippy 2016-07-28 12:38

代码才不是冷冰冰的。代码里有尊严、信仰、感情、没有实现的梦想还有被剁成肉泥的内脏。

价值趋势技术派 2016-07-28 15:53

全市场,单策略,多参数,遗传进化。
估计我们的大方向是一致的。
以后表跟我抢钱

干干 2016-07-28 17:25

女人这可怕,咬定的东西就不松口了。

JoinQuant聚宽 2016-07-28 16:33

The whole reason that we perform a cointegration test before applying this strategy is so that we know the linear combination of stock prices is covariance stationary, hence we have reasons to believe that the average does not change.

JoinQuant聚宽 2016-07-28 11:57

恩,量化这东西门槛太高。我们虽然尽可能的降低计算机的门槛,但目前还是要编程,就算以后可模块化拖拽式编程,数学以及交易思想是避不开的,必须自己学。毕竟股市如战场,无常势,无定法,想要一劳永逸的绝对方法论,至少我目前觉得还是太难。但量化交易的好处是,将交易的策略打包封装,从原来的计算,选股,择时,凡事事必躬亲的士卒,变到了对策略的创造认识评估,时势的判断预测,决定用什么策略,信什么策略,怎么改策略的指挥千军的将帅。

全部评论

miningant 02-10 21:13

挺好的搬砖技术

Tiffany_510 2016-08-19 10:17

协整配对理论是否同样适合于基金呢

少女大魔王 2016-08-14 00:11

终于有人发协整套利咯,

高毅C 2016-08-02 21:46

除权除夕对平均股价会有影响吗 是算除权前的吗

JoinQuant聚宽 2016-08-02 14:49

股息就是系统自动处理了。细节详情推荐到原文下和作者交流。

蝈蝈 2016-08-02 14:36

这个回归测试的时候,股息怎么处理的?

勺子哥 2016-08-01 09:59

好专业,学习

龙泽天下 2016-07-31 00:12

JoinQuant聚宽 2016-07-30 08:54

包含了的,y=ax+b,b=0时,y/x=a

费米基金 2016-07-30 07:04

现在用的是两支股票市值相减来看是不是稳态,有没有可能相除是稳态的情况?

1 2 3 4 5 6 7 8 9 10