量化投资实战(三)之配对交易策略--最短距离法

点赞、关注再看,养成良好习惯
Life is short, U need Python
量化投资实战系列,不断更新中


1. 初识配对交易策略

配对交易(Pairing Trading)是指八十年代中期华尔街著名投行Morgan Stanley的数量交易员Nunzio Tartaglia成立的一个数量分析团队提出的一种市场中性投资策略,其成员主要是物理学家、数学家、以及计算机学家。

Ganapathy Vidyamurthy[1]在《Pairs Trading: Quantitative Methods and Analysis》一书中定义配对交易为两种类型:一是基于统计套利的配对交易,二是基于风险套利(并购套利)的配对交易。

基于风险套利的配对交易策略是一种相当复杂的交易策略,它包括两种基本类型:债务重组和收购兼并。在换股并购中,风险套利者通常做多被收购公司的股票,同时做空收购公司的股票;在现金并购中,风险套利者寻求收购价格与目标公司价格之间的差异。

基于统计套利的配对交易策略是一种市场中性策略,具体的说,是指从市场上找出历史股价走势相近的股票进行配对,当配对的股票价格差偏离历史均值时,则做空股价较高的股票同时买进股价较低的股票,等待他们回归到长期均衡关系,由此赚取两股票价格收敛的报酬。

中国银行与浦发银行在2014年—2015年的价格走势曲线(如下图所示),其价格走势基本相同,可以构建配对交易策略。

在这里插入图片描述

2. 配对交易的思想

配对交易 的思想最早起源于20世纪20年代,华尔街交易员 Jesse Lauriston Livermore 在投资实战中采用的姐妹对(Sister Stocks)交易策略。他发现两只同行业内业务相似的股票,其价格波动趋势有某种规律,即两者的价差会构成一种均衡关系。若在两只股票价格偏离较大时建仓,价差回复时平仓,便会赚取价差由发散至收敛带来的收益。

随着数理金融学和计算机技术的不断发展,到了20世纪80年代,配对交易策略在华尔街得到巨大关注。1985年,华尔街投资银行摩根士丹利(Morgan Stanley)的天体物理学家 努齐奥·塔塔里亚(Nunzio Tartaglia)组建了一个由著名物理学家、计算机学家和数学家构成的数量化分析团队,该团队以数学模型计算股票买卖组合,并开发计算机自动交易程序,在当时华尔街投资实战中大获成功。该程序运用的买卖组合策略即是配对交易策略,与传统的主观技术分析不同,摩根士丹利的交易程序对于股票对的选择、交易参数的设定与交易规则的制定,都采取量化分析的手段并由计算机程序自动完成,自此以后,这种量化投资策略逐渐广为人知并流传开来。时至今日,配对交易己经衍生出众多模型和交易规则,并为各种避险基金和股票投资者使用。

有关配对交易的学术研究也不胜枚举。Gatev,Goetzmann 和Rouwenhorst[2](1999)采用最小距离法寻找历史价格最近的20组股票对,计算其标准化股票价格差序列,进场交易策略是标准价差超过2倍标准差,运用买低卖高的策略,年化收益率可达11%以上;Vidyamurthy[1](2004)把协整理论运用到配对交易的股票对选择中,并将平稳性作为配对好坏的判别准侧,从股票基本面或历史资料挑选出潜在具有协整关系之配对股票;崔方达和吴亮[3](2011)以上证50指数成分股为样本,运用最小距离法进行配对交易,最终得出配对交易与市场风险无关并可获利。

3. 配对交易的步骤

配对交易策略 的时期分为 形成期(Formation Period)和 交易期(Trading Period)。在形成期挑选历史走势存在规律的股票对,并制定交易策略;在交易期模拟开仓平仓交易,而后计算收益。在整个配对交易策略过程中,具体需要考虑如下问题:

(1)如何挑选进行配对的股票?

(2)挑选好股票对以后,如何制定交易策略?开仓点如何设置?

(3)开仓时,两只股票如何进行多空仓配比?

3.1 股票对的选择(最小距离法)

配对交易的第一步是在形成期中寻找历史价差走势大致稳定的股票对。截止2020年底,中国沪深两市共计不低于4000只股票,若完全两两配对,则一共可以配出不低于7998000个股票对。因此,从这样的股票对中寻找出历史价差走势稳定的股票对,势必耗费大量计算资源。其中可行的方法就是进一步将市场划分为多个子空间(即寻找特定的板块)分别进行检索。

(1)行业内匹配:选取行业公司规模相近的股票进行配对(比如,选取银行板块或者券商板块进行两两配对)。

(2)产业链匹配*:将同一产业链内(比如,某一产品制造公司与其上游配件生产公司或下游产品销售公司)的上市公司股票进行两两配对。

(3)财务管理匹配*:挑选上市公司市盈率、市净率、负债率等相近的股票进行配对。

为了客观地衡量两只股票价格之间的距离, 需要对股票价格序列进行标准化处理。假设 p t i ( t = 0 , 1 , ⋯   , T ) p_{t}^{i}(t=0,1, \cdots, T) pti(t=0,1,,T) 表示股票 i i i 在第 t t t 天的价格。则股票 i i i 在第 t t t 天的单期收益率表示为:

p t i = p t i − p t − 1 i p t − 1 i ( t = 1 , 2 , ⋯   , T ) p_{t}^{i}=\frac{p_{t}^{i}-p_{t-1}^{i}}{p_{t-1}^{i}}(t=1,2, \cdots, T) pti=pt1iptipt1i(t=1,2,,T)

假设有股票 X \mathrm{X} X Y \mathrm{Y} Y , 对应的价格分别为 p t X p_{t}^{X} ptX p t Y p_{t}^{Y} ptY , 则二者之间的标准化价格偏差之平方和为:

S S D X , Y = ∑ t = 1 T ( p t X − p t Y ) 2 S S D_{X, Y}=\sum_{t=1}^{T}\left(p_{t}^{X}-p_{t}^{Y}\right)^{2} SSDX,Y=t=1T(ptXptY)2

3.2 配对交易策略的制定(最小距离法)

首先,对挑选出的股票对计算形成期(Formation Period)内标准化的价格序列差 p t X − p t Y p_{t}^{X}-p_{t}^{Y} ptXptY 的平均值 μ \mu μ 和标准差 σ \sigma σ。然后,选定交易期(Trading Period)进行交易。

Gatev等学者运用最小距离法选出股票对,设定交易信号触发点为 ,交易期的适用期限为6个月。当交易期超过6个月以后,重新设定形成期和选取股票对。

当交易期的标准化价差又回复到均值 μ \mu μ 附近时,反向操作平仓,从而赚取价差收益。具体步骤如下:

(1)在形成期(Formation Period)中计算资产X与资产Y标准化价格序列差,并求出价差的平均值和标准差,并设定开仓、平仓条件。

(2)设定交易期(Trading Period)时间,选取交易期数据,寻找配对交易开仓和平仓位点。当价差上穿线时,反向开仓;当价差线回复到均线附近时,进行平仓;当价差线下穿时,正向开仓;当价差线再次回复到均线附近时,进行平仓。

4. 最短距离法之Python实战

4.1 股票对的选取

(1)计算上证50板块两两配对股票之间的距离,提取距离最小的前五组

# 导入包(三剑客)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 中文设置
plt.rcParams['font.sans-serif'] = ['SimHei']  
# 负号显示
plt.rcParams['axes.unicode_minus'] = False  
# 读取数据
sh = pd.read_csv('sh50.csv',index_col='Trddt')  
sh.index = pd.to_datetime(sh.index)
sh.head()

在这里插入图片描述

# 定义形成期
formStart = '2014-01-01'
formEnd = '2014-12-31'

# 提取形成期数据
sh_form = sh[formStart:formEnd]

# 构造SSD距离函数(累计收益率偏差)
def SSD(priceX,priceY): 
    returnX = (priceX - priceX.shift(1)) / priceX.shift(1)[1:]    # 计算 X 收益率
    returnY = (priceY - priceY.shift(1)) / priceY.shift(1)[1:]    # 计算 Y 收益率
    standardX = (returnX + 1).cumprod()                           
    standardY = (returnY + 1).cumprod()
    SSD = np.sum((standardX - standardY) ** 2)                   # 计算累计收益率偏差 
    return(SSD) 


# 计算上证50板块两两配对股票之间的距离
lst = list(sh_form.columns)
d = dict()
for i in range(len(lst)):
    for j in range(i+1,len(lst)):
        P_zhonghang_f = sh_form[lst[i]]
        P_pufa_f = sh_form[lst[j]]
        dis = SSD(P_zhonghang_f,P_pufa_f)
        d[lst[i]+'-'+lst[j]] = dis
        
# 按照‘值’排序,并挑出前5个最小距离股票对
d_sort = sorted(d.items(),key=lambda x:x[1])
d_sort[:5]
  • 结论(前5组配对)
    • 600015-601166:华夏银行–兴业银行
    • 601288-601398:农业银行–工商银行
    • 600050-601288:中国联通–农业银行
    • 601166-601288:兴业银行–农业银行
    • 601398-601857:工商银行–中国石油

(2)提取形成期 华夏银行--兴业银行 数据

# 提取华夏银行(600015)和兴业银行(601166)股票的收盘价格数据
P_huaxia_f = sh_form['600015']
P_xingye_f = sh_form['601166']

# 合并数据形成DataFrame数据
pair_form = pd.concat([P_huaxia_f,P_xingye_f],axis =1,join='outer')
pair_form.head(3) 

(3)形成期股票对数据的可视化分析(价格、收益率和累计收益率)

# 股票对收盘价格历史走势图 
plt.figure(figsize=(10,4))
ax = plt.subplot()
ax.plot(pair_form['600015'], label='华夏银行')
ax.plot(pair_form['601166'], label='兴业银行')
plt.title('华夏银行 vs 兴业银行(收盘价)',fontsize=15)
ax.set_xlabel('日期', fontsize=14)
ax.set_ylabel('收盘价', fontsize=14)
ax.legend()
plt.show()

在这里插入图片描述

# 计算股票对收益率
return_huaxia = (P_huaxia_f - P_huaxia_f.shift(1)) / P_huaxia_f.shift(1)[1:]    
return_xingye = (P_xingye_f - P_xingye_f.shift(1)) /P_xingye_f.shift(1)[1:]   

# 股票对收益率价格历史走势图
plt.figure(figsize=(10,4))
ax = plt.subplot()
ax.plot(return_huaxia, label='华夏银行')
ax.plot(return_xingye, label='兴业银行')
plt.title('华夏银行 vs 兴业银行(收益率)',fontsize=15)
ax.set_xlabel('日期', fontsize=14)
ax.set_ylabel('收益率', fontsize=14)
ax.legend()
plt.show()

在这里插入图片描述

# 计算股票对的累计收益率
cum_return_huaxia = (1 + return_huaxia).cumprod()     
cum_return_xingye = (1 + return_xingye).cumprod()

# 股票对累计收益率历史走势图
plt.figure(figsize=(10,4))
ax = plt.subplot()
ax.plot(cum_return_huaxia, label='华夏银行')
ax.plot(cum_return_xingye, label='兴业银行')
plt.title('华夏银行 vs 兴业银行(累计收益率)',fontsize=15)
ax.set_xlabel('日期', fontsize=14)
ax.set_ylabel('累计收益率', fontsize=14)
ax.legend()
plt.show()

在这里插入图片描述

4.2 配对交易策略的制定

(1)在 形成期 中计算价格序列差 SSD-pair,价差序列的平均值 meanSSD-pair 和标准差 sdSSD-pair,并设定开仓、平仓条件。

# 华夏银行标准化价格
standard_huaxia = (1 + return_huaxia).cumprod()
# 兴业银行标准化价格
standard_xingye = (1 + return_xingye).cumprod()

# 计算华夏银行与兴业银行标准化价格序列的价差 
SSD_pair = standard_xingye - standard_huaxia 

############  (1.1)计算形成期标准化价格差序列的均值和方差   ############
meanSSD_pair = np.mean(SSD_pair)
sdSSD_pair = np.std(SSD_pair)
print('配对股票序列的均值 =', meanSSD_pair)
print('配对股票序列的标准差 =', sdSSD_pair)

############ (1.2)设置交易期交易信号触发点:mu +/- 1.5sigma   ############
thresholdUp = meanSSD_pair + 1.5 * sdSSD_pair
thresholdDown = meanSSD_pair - 1.5 * sdSSD_pair
print([thresholdDown,thresholdUp])

# 可视化
plt.figure(figsize=(10,6))
SSD_pair.plot()
plt.title('华夏银行与兴业银行标准化价差序列(形成期)',loc='center',fontsize=16) 
plt.axhline(y=meanSSD_pair,color='black')
plt.axhline(y=thresholdUp,color='green')
plt.axhline(y=thresholdDown,color='green') 
plt.show()

在这里插入图片描述
(2)设定交易期时间,选取交易期数据,寻找配对交易开仓和平仓位点。

  • 当价差上穿 μ + 1.5 σ \mu + 1.5\sigma μ+1.5σ 线时,反向开仓,当价差线回复到均线附近(可以给出阈值进行度量)时,进行平仓。
  • 当价差线下穿 μ − 1.5 σ \mu - 1.5\sigma μ1.5σ 线时正向开仓,当价差线再次回复到均线附近时平仓。
详见资源包!

在这里插入图片描述

结论:如图所示,价差序列多在1.2倍标准差范围内,从2015年1月1日至2015年6月30日,价差序列向上突破1.2倍标准差线1次,向下突破1.2倍标准差线6次以上,共有6次以上开仓机会,且价差序列比较稳定,开仓后均有平仓机会。当然,该股票对在交易期的走势不是很理想,相信熟悉中国股市的人都知道2015年股市的与众不同!

4.3 构建PairTrading类

详见资源包!

4.4 配对交易策略的回测

接下来,运用华夏银行和兴业银行股票的交易数据自行设计配对交易策略,具体有如下4个步骤:

(1) 在形成期内,计算中国银行和浦发银行两只股票价差序列的平均值( μ \mu μ)和标准差( σ \sigma σ)。

(2) 在交易期内,设定 $ \mu \pm 1.5\sigma$ 为开仓阈值、 $ \mu \pm 0.2\sigma$ 为平仓阈值,将 $ \mu \pm 3.0\sigma$ 为止损阈值,具体交易规则如下:

  • 当价差上穿 $ \mu + 1.5\sigma$ 时,做空配对股票,反向建仓(即卖出浦发银行,买入中国银行,二者资金比值为 β \beta β);
  • 当价差下穿 $ \mu + 0.2\sigma$ 时,反向平仓;
  • 当价差下穿 $ \mu - 1.5\sigma$ 时,做多配对股票,正向建仓(即买入浦发银行,卖出中国银行,二者资金比值为 β \beta β);
  • 当价差上穿 $ \mu - 0.2\sigma$ 时,正向平仓;
  • 当价差突破 $ \mu \pm 3.0\sigma$ 时,及时止损。

(3) 配对交易策略绩效评价

详见资源包!
account.iloc[:, [1,2,3,4]].plot(style=['--','--','-',':'], color=['red','blue','yellow','green'],figsize=(10,6))
plt.title('配对交易账户',loc='center', fontsize=16) 
plt.show()

在这里插入图片描述
上图曲线中,ShareY表示标的(兴业银行)的配对仓位(正表示买入,负表示卖出,0表示不持仓),ShareX表示标的(华夏银行)的配对仓位,Cash表示现金变化(初始资金为2000元),Cash表示资产变化。观察交易仓位曲线图可知,一方面,该时间段内配对交易信号触发4次交易(交易次数不多,读者可以结合自己的数据遍历寻找最优的阈值,本案例仅仅是主观选取的阈值);另一方面,配对资产整体呈现下降趋势,这与主观选取阈值以及选取标的的时间段有关(事实上,2015年中国股市属于异常情况,不适合配对交易,而属于单边走势)。

5. 展望

下一步,博主将继续探讨配对交易策略的其他方法(协整模型法和随机价差法),敬请期待中!

6. 参考资料

  • 蔡立耑. 量化投资以Python为工具[M]. 北京:电子工业出版社,2017.
  • PyQuant. 量化投资基础[M]. 北京:科学出版社,2024.

7. 资源包下载

  • 链接:https://pan.baidu.com/s/1RVCRuF-7y2_uBOPp5-r5pQ
  • 提取码:1234

  • 写作不易,切勿白剽
  • 博友们的点赞关注就是对博主坚持写作的最大鼓励
  • 持续更新,未完待续…
  • 20
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PyQuant

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值