本内容基于论文《最优配对交易》,策略是基于相互间的走势相近的股票对,当两者间的差价偏离均值时,我们认为他们的关系会回归长期的均值,根据策略进行交易,以便从这一回归行为中获利。
标准的例子是同一行业中的一对高度相关的股票。配对交易策略仅仅依赖于证券对之间的相对关系,而不是市场的整体走势,它是一种市场的中性的策略。
论文中作者开发了一个假设股票间对数价差符合OU过程的模型。OU过程是一个平稳的高斯-马尔可夫过程,其数学期望为0且指数函数为核函数。将动态投资组合优化问题转化为随机控制问题。假设投资者可以基于价差进行交易或者将资金放入无风险资产中,他们能够为将资产净值作为控制目标的控制问题找到一个解析解。
通过代码测试了上海贝岭和士兰微最近300个交易日的数据,通过策略可以获得3倍收益。(仅为理论参考)
但是,在回测中国银行和中国建设银行的历史数据上,效果并不理想。
可以优化的地方很多,希望得到更多的意见。
这是中国银行和建设银行策略组合的收益曲线,可以说是悬崖是回撤。
import pandas as pd
import numpy as np
from math import exp
import matplotlib.pyplot as plt
df2 = pd.read_csv(
filepath_or_buffer=r'C:\Users\kongx\Desktop\KONG_QUANT\Data\stock\sh600171.csv',
encoding='gbk',
sep=',',
# 该参数代表跳过数据文件的的第1行不读入
skiprows=1,
# parse_dates=['交易日期'],
# index_col=['交易日期'],
)
df1 = pd.read_csv(
filepath_or_buffer=r'C:\Users\kongx\Desktop\KONG_QUANT\Data\stock\sh600460.csv',
encoding='gbk',
sep=',',
# 该参数代表跳过数据文件的的第1行不读入
skiprows=1,
# parse_dates=['交易日期'],
# index_col=['交易日期'],
)
data1 = df1.tail(300)
data2 = df2.tail(300)
data1 = data1.iloc[:, 5].values
data2 = data2.iloc[:, 5].values
print(data1)
print(data2)
S_data = np.log(data2)
X_data = np.log(data1) - np.log(data2)
'''
真实回测前,需预设一些参数:
'''
N = 60
T = 1
r = -100
V_list = [1]
for i in range(N, len(data1) - 1): # 滚动窗口计算参数估计值
m = (S_data[i] - S_data[i - N]) / N
SS = (np.power((pd.Series(S_data[i - N:i + 1]) - pd.Series(S_data[i - N:i + 1]).shift(1)), 2)[1:].sum() - 2 * m * (
S_data[i] - S_data[i - N]) + N * m ** 2) / N
p = 1 / (N * np.power(X_data[i - N:i], 2).sum() - X_data[i - N:i].sum() ** 2) * (
N * (pd.Series(X_data[i - N:i + 1]) * pd.Series(X_data[i - N:i + 1]))[1:].sum() - (
X_data[i] - X_data[i - N]) * X_data[i - N:i].sum() - np.power(X_data[i - N:i].sum(), 2))
if p<0:
p=-p
q = (X_data[i] - X_data[i - N] + X_data[i - N:i].sum() * (1 - p)) / N
VV = 1 / N * (X_data[i] ** 2 - X_data[i - N] ** 2 + (1 + p ** 2) * np.power(X_data[i - N:i], 2).sum() -
2 * p * (pd.Series(X_data[i - N:i + 1]) * pd.Series(X_data[i - N:i + 1]))[1:].sum() - N * q)
if VV<0:
VV=-VV
C = 1 / (N * VV ** 0.5 * SS ** 0.5) * (
(pd.Series(X_data[i - N:i + 1]) * (pd.Series(S_data[i - N:i + 1]) - pd.Series(S_data[i - N:i + 1]).shift(1)))[
1:].sum() - p * (pd.Series(X_data[i - N:i + 1]) * (
pd.Series(S_data[i - N:i + 1]).shift(-1) - pd.Series(S_data[i - N:i + 1])))[:-1].sum() - m * (
X_data[i] - X_data[i - N]) - m * (1 - p) * pd.Series(X_data[i - N:i]).sum())
std_ = (SS / 1) ** 0.5
u_ = m / 1 + 0.5 * std_ ** 2
k_ = -(np.log(p) / 1)
theta_ = q / (1 - p)
eta_ = (2 * k_ * VV / (1 - p ** 2)) ** 0.5
rho_ = k_ * C * (VV ** 0.5) * (SS ** 0.5) / (eta_ * theta_ * (1 - p))
beta_t = 1 / (
2 * eta_ ** 2 * (1 - 101 ** 0.5 - (1 + 101 ** 0.5) * exp(2 * k_ * (T - 0) / (101 ** 0.5)))) * (
-100 * 101 ** 0.5 * (eta_ ** 2 + 2 * rho_ * std_* eta_) * (
(1 - exp(2 * k_ * (T - 0 ) / (101 ** 0.5))) ** 2) + 100 * (
eta_ ** 2 + 2 * rho_ * std_ * eta_ + 2 * k_*theta_) * (
1 - exp(2 * k_ * (T - 0) / (101 ** 0.5))))
alpha_t=k_ * (1 - 101 ** 0.5) / (2 * eta_ ** 2) * (1 + 2 * 101 ** 0.5 / (
1 - 101 ** 0.5 - (1 + 101 ** 0.5) * exp(2 * k_ * (T - 0 ) / (101 ** 0.5))))
h_t=1 / 101 * (beta_t + 2 * X_data[i] * alpha_t - k_ * (X_data[i] - theta_) / (eta_ ** 2) + rho_ * std_ / eta_ + 0.5)
dV_t = V_list[-1] * (
h_t * (data1[i + 1] - data1[i]) / data1[i] - h_t * (data2[i + 1] - data2[i]) / data2[i])
V_list.append(V_list[-1] + dV_t)
'''第一幅图为价差曲线'''
pd.Series(X_data).plot()
plt.show()
'''第二幅图为收益曲线'''
pd.Series(V_list).plot()
plt.show()