okaa

量化交易核心策略之最优配对交易

本内容基于论文《最优配对交易》,策略是基于相互间的走势相近的股票对,当两者间的差价偏离均值时,我们认为他们的关系会回归长期的均值,根据策略进行交易,以便从这一回归行为中获利。

标准的例子是同一行业中的一对高度相关的股票。配对交易策略仅仅依赖于证券对之间的相对关系,而不是市场的整体走势,它是一种市场的中性的策略。

论文中作者开发了一个假设股票间对数价差符合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()
退出移动版