Advertisement

金融量化 — 配对交易策略 (Pair Trading)

阅读量:

配对交易是一种量化投资策略,允许投资者在严格无风险套利的基础上,略微放松100%无风险要求,同时套利机会增加100%以上。其核心在于寻找市场中具有均值回归特性的资产对,通过计算价差的均值和标准差,设定阈值进行买卖交易。该策略分为统计套利和股票配对交易两大类。统计套利通过历史数据统计分析,结合资产基本面,指导交易;股票配对交易则基于资产间的相关性和均值回归特性,通过距离法、协整法和时间序列法等方法寻找交易标的。Python实现中,主要涉及数据准备、策略开发和回测分析,包括计算收益、绘制收益曲线以及评估风险。然而,该策略面临spread不回归、做空限制、回归系数需重新平衡以及交易成本等问题。

1. 配对交易策略

1.1、引言

在量化投资领域中,由于严格的无风险套利机会极为稀少且收益率微乎其微,实际操作中完全消除风险几乎是不可能的。因此,如果有一种方法能够稍微放松100%无风险的要求,比如容忍5%的风险水平,同时却能够让套利机会显著增加,那岂不是一个值得考虑的方案?今天,我们将重点介绍一种创新的方法——配对交易。

1.2、统计套利

1.2.1 定义

统计套利主要基于对历史数据进行系统的统计分析,以估计目标统计量的分布,并结合股票的基本面数据,用于指导套利交易。

1.2.2 评价

统计套利相较于无风险套利而言,带来了额外的风险,但也提供了诱人的风险溢价回报,即能够获取更多套利机会。然而,它本质上存在一个局限性,即其建立的基础是历史数据,只能反映历史信息,而用于预测未来时往往难以完全吻合。

1.2.3 例子

统计套利的原理其实用下面这张图就可以解释:

当小狗与老头一起行走时,其运动轨迹无规律,然而两者之间的距离范围从零到绳子的长度,并且这种状态具有稳定 maintained state。

老头小狗走路时随机的,但老头和小狗的中间距离是0到绳子的长度, 具备稳定性

我们现在把这个场景应用到市场上,以股票为例:

股票A、B: 价格——Random Walk;

资产A和资产B的差价——此外,其他类型的线性组合的时间序列也表现出稳定性特征。

假设我们找到了两个股票A和B的序列,它们的价差经过统计学上的Cointegration检验显示具有稳定性(例如,Adfuller检验结果)。我们计算了该时间序列的均值和标准差,从而确定了一个稳定阀值区域。当价格偏离该区域时,我们采取买入或卖出的交易策略,等待其回归至该区域后平仓。

举例说明,过去6个月内,A 股票与 B 股票的价差序列为平稳序列,其均值为10,标准差为2。我们设定阀域区间为1.5个标准差,其平稳区间计算为7至13。

当 A-B > 13 时,我们买入 B , 卖出 A;

当 A-B < 7 时,我们买入 A , 卖出 B 。

等到回归到平稳区间平仓。

1.3 股票配对交易

1.3.1 定义

股票配对交易属于统计套利的重要组成部分之一。其主要目标是通过寻找市场中历史走势相似的股票进行配对,当价格差异显著(超出历史均值)时,进行高卖低买以实现套利。

1.3.2 主要方法

i.距离法

定义:距离法通过回溯时间区间进行标准化处理。接着,在2范数下计算n只股票之间的配对距离,计算结果为SSD。选取SSD最小的前20对股票作为投资标的,在随后的6个月内,以2倍标准差作为止盈止损的阈值,进行统计套利策略。当距离回归均值时,平仓。6个月后,更新投资标的并继续进行套利。

评 价:标的选择标准中隐含着其无法实现最大利润,因为每对的收益与其价差(SSD)成正比;此外,高相关性不能推断存在协整关系,因此均值回复无法得到保证。

改 进:(a) 只在同一行业内选择标的;

(b)使用 Pearson 相关系数度量期内相关性。

ii.协整法

前 提: 不平稳的经济时间序列的线性组合可能实现平稳。

在这里插入图片描述

Engle-Granger 方法:通过对数价格进行 OLS 回归,对残差序列进行 ADF 检验,其中误差修正模型基于 Johansen 方法。若检验确认存在协整关系,则可推断股票 A、B 间存在长期均衡关系,使得残差序列具有均值回归特性。评 价: 该模型较为单一,仅适用于两种股票且时间限制在两年以内,单笔收益的最大化并不能保证整体收益的最大化。改 进建议: 在进行协整检验之前,建议首先对股票进行距离筛选,以提高模型的适用性和有效性。

iii.时间序列法

定 义: 假定价差为具有均值回归特性的马尔科夫链,伴随着高斯噪声。

在这里插入图片描述

该方法具有显著的优越性,主要体现在其精准捕捉到了配对交易的核心特征——均值回复性。该模型具有连续性特征,从而具备预测能力,而其易处理性则使得通过卡尔曼滤波方法可以有效地获得最小均方误差(MSE)的参数估计。在实际应用中,价差计算应采用价格自然对数的差异,以消除量纲差异带来的影响。该模型的理论要求较为严格,实际应用中难以完全满足,尤其是在金融资产数据方面,现实中往往不完全符合Ornstein-Uhlenbeck过程的假设。

2. python 实现

Pair trading 策略 - 考虑时间序列平稳性

2.1 数据准备 & 回测准备

复制代码
    import pandas as pd
    import numpy as np
    import tushare as ts
    import seaborn
    from matplotlib import pyplot as plt
    plt.style.use('seaborn')
    %matplotlib inline
复制代码
    data1 = ts.get_k_data('600199', '2013-06-01', '2014-12-31')[['date','close']]
    data2 = ts.get_k_data('600702', '2013-06-01', '2014-12-31')['close']
    data.set_index('date',inplace = True)
    data.columns = stocks_pair
    data.head()
在这里插入图片描述
复制代码
    data3.plot(figsize=(8,6));
在这里插入图片描述

2.2 策略开发思路

复制代码
    data3.corr()  # 协方差矩阵
在这里插入图片描述
复制代码
    # 可视化看相关关系
    plt.figure(figsize =(10,8))
    plt.title('Stock Correlation')
    plt.plot(data['000568'], data['000858'], '.');
    plt.xlabel('000568')
    plt.ylabel('000858')
    data.dropna(inplace = True)
在这里插入图片描述
复制代码
    [slope, intercept] = np.polyfit(data.iloc[:,0], data.iloc[:,1], 1).round(2)    #   斜率和截距  
    slope,intercept
复制代码
    data['spread'] = data.iloc[:,1] - (data.iloc[:,0]*slope + intercept)
复制代码
    data.head()
在这里插入图片描述
复制代码
    data['zscore'] = (data['spread'] - data['spread'].mean())/data['spread'].std()
在这里插入图片描述
复制代码
    data3['zscore'].plot(figsize = (10,8),title = 'Z-score')
    plt.axhline(1.5)
    plt.axhline(0)
    plt.axhline(-1.5)
在这里插入图片描述

产生交易信号

复制代码
    data['position_1'] = np.where(data['zscore'] > 1.5, 1, np.nan)
    data['position_1'] = np.where(data['zscore'] < -1.5, -1, data['position_1'])
    data['position_1'] = np.where(abs(data['zscore']) < 0.5, 0, data['position_1'])
    
    data['position_1'] = data['position_1'].fillna(method = 'ffill')
    
    data['position_1'].plot(ylim=[-1.1, 1.1], figsize=(10, 6),title = 'Trading Signal_Uptrade')
在这里插入图片描述
复制代码
    data['position_2'] = -np.sign(data['position_1'])
    data['position_2'].plot(ylim=[-1.1, 1.1], figsize=(10, 6),title = 'Trading Signal_Downtrade')

2.3 计算策略年化收益并可视化

复制代码
    data['returns_1'] = np.log(data['600199'] / data['600199'].shift(1))
    data['returns_2'] = np.log(data['600702'] / data['600702'].shift(1))
    data['strategy'] = 0.5*(data['position_1'].shift(1) * data['returns_1']) +0.5*(data['position_2'].shift(1) * data['returns_2'])
    data[['returns_1','returns_2','strategy']].dropna().cumsum().apply(np.exp).plot(figsize=(10, 8),title = 'Strategy_Backtesting')
在这里插入图片描述
复制代码
    # 计算年化收益率
    data3[['returns_1','returns_2','strategy']].dropna().mean()
复制代码
    returns_1   -0.073915
    returns_2   -0.017554
    strategy     0.105002
    dtype: float64
复制代码
    # 计算年化风险
    data3[['returns_1','returns_2','strategy']].dropna().std() * 252 ** 0.5
复制代码
    returns_1    0.300306
    returns_2    0.280425
    strategy     0.068639
    dtype: float64
复制代码
    # 策略累积收益率
    data3['cumret'] = data3['strategy'].dropna().cumsum().apply(np.exp)
    # 策略累积最大值
    data3['cummax'] = data3['cumret'].cummax()
    # 算回撤序列
    drawdown = (data3['cummax'] - data3['cumret'])
    # 算最大回撤
    drawdown.max()
复制代码
038159777097367176

策略的思考

  1. 对多只ETF进行配对交易,是很多实盘量化基金的交易策略;

策略的风险和问题:

在市场结构发生重大变化时,过去历史回归得出的Spread可能在市场结构变化时出现不回归的风险。 由于中国市场的做空限制,部分做空收益无法实现。 回归系数的计算需要定期调整以保持其有效性。 该策略忽略了交易成本和其他潜在成本因素。

全部评论 (0)

还没有任何评论哟~