【Mquant】7:構(gòu)建價差套利(三) ——空間誤差校正模型

1. 上節(jié)回顧

【Mquant】6:構(gòu)建價差套利(二)上節(jié)帶領(lǐng)大家編寫了統(tǒng)計套利均值回歸的程序,通過歷史回測發(fā)現(xiàn)還不能進(jìn)入實(shí)盤交易狀態(tài),原因出現(xiàn)在手續(xù)費(fèi)率上,由于加密市場手續(xù)費(fèi)率較高,我們選擇國內(nèi)期貨市場,一般期貨市場手續(xù)費(fèi)率可以達(dá)到萬分之一,個別品種手續(xù)費(fèi)率可以達(dá)到萬分之0.1。這節(jié)內(nèi)容,我們圍繞期貨產(chǎn)品中的純堿來做統(tǒng)計套利。純堿一手交易所收取3.5元手續(xù)費(fèi),期貨公司在這個基礎(chǔ)上收取+1分的開戶手續(xù)費(fèi)也就是一手3.51元。

2. 純堿價差套利

純堿價差套利是一種商品套利策略,涉及到純堿市場中不同地區(qū)或不同時間點(diǎn)的價格差異。純堿是一種廣泛用于工業(yè)和化工生產(chǎn)的堿性物質(zhì),其價格受到供需關(guān)系、運(yùn)輸成本、市場地區(qū)等因素的影響。

純堿價差套利的基本原理是在不同市場或時間點(diǎn)購買低價的純堿,然后在高價的市場或時間點(diǎn)出售,從價格差異中獲得利潤。這種套利策略依賴于市場價格的波動以及供需不平衡的情況,因此需要及時準(zhǔn)確地識別價格差異和執(zhí)行交易。建議在實(shí)施任何套利策略之前,咨詢專業(yè)人士或金融顧問,以獲得適當(dāng)?shù)慕ㄗh和指導(dǎo)。

鄭商所倉單交割相關(guān)規(guī)定:
http://www.czce.com.cn/cn/flfg/zcjywgz/pzxz/webinfo/2023/05/1685047755429516.htm

【Mquant】5:構(gòu)建價差套利(一) 中:我們描述了價差走勢曲線,從圖中可以很清晰的看出在某一段時間內(nèi),兩個合約價差比較平穩(wěn),如2023年10月1日到10月10日,在2023年10月22日后,價差走了一波上漲趨勢,對于這種非平穩(wěn)的時間序列,我們就很難去做價差均值回歸策略。于是在【Mquant】6:構(gòu)建價差套利(二)中我們通過價格波動率指標(biāo)去選擇交易品種,并且構(gòu)建了一個布林帶交易策略,但是受到手續(xù)費(fèi)和價差的影響,實(shí)際策略并不能賺錢。這節(jié)內(nèi)容我們深入探討“平穩(wěn)性”這個概念,帶領(lǐng)讀者通過協(xié)整性分析,找到一組資產(chǎn)的價格在長期內(nèi)存在穩(wěn)定的線性關(guān)系,來優(yōu)化交易策略。

在這里插入圖片描述

3. 什么是協(xié)整性分析

用學(xué)術(shù)的話講:協(xié)整性分析是一種用于檢驗(yàn)非平穩(wěn)時間序列之間是否存在穩(wěn)定關(guān)系的方法。它可以幫助我們確定變量之間的長期均衡關(guān)系,以及是否存在偽回歸的情況。

通俗來說:還是以上面比特幣的價差圖來看,我們期望的價差是時間區(qū)域1,整體走勢非常平穩(wěn),沒什么太大振幅,并且不希望出現(xiàn)這種異常數(shù)據(jù)點(diǎn),像時間區(qū)域2這種上升趨勢很明顯走勢沒有一點(diǎn)回歸的就被認(rèn)為是非平穩(wěn)序列。那有沒有一種方式可以將這個走勢通過一個數(shù)學(xué)模型來擬合成類似時間區(qū)域1的走勢圖呢?答案是:可能有!這就需要用到協(xié)整性分析了,如果通過這個分析,我們就可以建立VECM(向量誤差修正模型)來擬合數(shù)據(jù)了。

在這里插入圖片描述

協(xié)整性分析可以幫助我們理解變量之間的因果關(guān)系,以及它們之間的長期均衡關(guān)系。通過協(xié)整性分析,我們可以避免在非平穩(wěn)序列上進(jìn)行回歸分析時出現(xiàn)偽回歸的情況。常用的協(xié)整性分析方法包括Engle-Granger方法和Johansen方法。Engle-Granger方法是一種兩步法,首先通過單位根檢驗(yàn)確定變量是否是非平穩(wěn)的,然后通過回歸分析檢驗(yàn)殘差是否是平穩(wěn)的。Johansen方法是一種多步法,它可以同時檢驗(yàn)多個變量之間的協(xié)整關(guān)系。本文就不給大家羅列具體的數(shù)學(xué)公式了,這些公式在網(wǎng)上也可以查的到,直接給大家上代碼。

4. 通過協(xié)整性檢驗(yàn)

進(jìn)行協(xié)整性測試通常需要以下步驟:

  1. 選擇需要進(jìn)行協(xié)整性測試的兩個時間序列。
  2. 對兩個時間序列進(jìn)行單位根檢驗(yàn)(Unit Root Test),以確定它們是否平穩(wěn)。常用的單位根檢驗(yàn)方法包括ADF檢驗(yàn)(Augmented Dickey-Fuller Test)和KPSS檢驗(yàn)(Kwiatkowski-Phillips-Schmidt-Shin Test)等。
  3. 如果兩個時間序列都不是平穩(wěn)的,則需要對它們進(jìn)行差分,直到差分后的序列成為平穩(wěn)序列。
  4. 對差分后的序列進(jìn)行協(xié)整性檢驗(yàn)。常用的協(xié)整性檢驗(yàn)方法包括Johansen協(xié)整性檢驗(yàn)(Johansen Cointegration Test)和Engle-Granger協(xié)整性檢驗(yàn)(Engle-Granger Cointegration Test)等。
  5. 如果兩個時間序列之間存在協(xié)整性,則可以使用空間誤差校正模型(ECM)對其進(jìn)行建模和分析。
    下面,我們將使用Python的Pandas中的協(xié)整性測試方法來進(jìn)行示范。
import pandas as pd
from statsmodels.tsa.stattools import adfuller, kpss

# 準(zhǔn)備數(shù)據(jù)
data = pd.read_csv('data.csv')  # 從CSV文件中讀取數(shù)據(jù),確保包含所有相關(guān)時間序列
data = data.iloc[:1000,:]   # 選擇前1000個數(shù)據(jù)做擬合適用后續(xù)200個數(shù)據(jù)

result_A_adf = adfuller(data['SA401'])
result_B_adf = adfuller(data['SA405'])
result_A_kpss = kpss(data['SA401'])
result_B_kpss = kpss(data['SA405'])

print('ADF Test - Stock A: p-value =', result_A_adf[1])
print('ADF Test - Stock B: p-value =', result_B_adf[1])
print('KPSS Test - Stock A: p-value =', result_A_kpss[1])
print('KPSS Test - Stock B: p-value =', result_B_kpss[1])
在這里插入圖片描述

如果p-value小于0.05,則可以拒絕原假設(shè),即SA401、SA405是平穩(wěn)的。如果p-value大于等于0.05,則不能拒絕原假設(shè),即SA401、SA405可能是非平穩(wěn)的。

我們可以看到輸出結(jié)果中的p-value均小于0.05,因此我們可以認(rèn)定SA401、SA405均為非平穩(wěn)序列:

為了使SA401、SA405成為平穩(wěn)序列,我們需要對它們進(jìn)行差分。我們可以使用Pandas的diff函數(shù)對其進(jìn)行一階差分:

df = data[["SA401","SA405"]]
df_diff = df.diff().dropna()

result_diff_A_adf = adfuller(df_diff['SA401'])
result_diff_B_adf = adfuller(df_diff['SA405'])
result_diff_A_kpss = kpss(df_diff['SA401'])
result_diff_B_kpss = kpss(df_diff['SA405'])

print('ADF Test (Diff) - Stock A: p-value =', result_diff_A_adf[1])
print('ADF Test (Diff) - Stock B: p-value =', result_diff_B_adf[1])
print('KPSS Test (Diff) - Stock A: p-value =', result_diff_A_kpss[1])
print('KPSS Test (Diff) - Stock B: p-value =', result_diff_B_kpss[1])
在這里插入圖片描述

我們可以看到輸出結(jié)果中的p-value均小于0.05,因此我們可以認(rèn)定差分后的SA401、SA405均為平穩(wěn)序列:

from statsmodels.tsa.stattools import coint

result_coint = coint(df_diff['SA401'], df_diff['SA405'])
print('Cointegration Test - p-value =', result_coint[1])

我們可以得到協(xié)整性檢驗(yàn)的輸出結(jié)果如下:

Cointegration Test - p-value = 0.0

由于p-value小于0.05,因此我們可以認(rèn)為SA401、SA405之間存在協(xié)整性。

5. 空間誤差校正模型(VECM)

空間誤差校正模型(Spatial Error Correction Model, SECM)是一種同時考慮時間和空間依賴性的模型,用于分析具有空間相關(guān)性的時間序列數(shù)據(jù)。SECM可以用來研究時間序列變量之間的協(xié)整關(guān)系,并糾正由于空間相關(guān)性引起的模型偏誤。

SECM的基本形式如下:

y_t = α + βx_t + λu_t + ε_t

其中,y_t是因變量的時間序列,x_t是自變量的時間序列,u_t是協(xié)整關(guān)系的誤差項(xiàng),ε_t是空間相關(guān)誤差項(xiàng)。α、β和λ是模型的參數(shù)。

from statsmodels.tsa.vector_ar.vecm import VECM

# 擬合空間誤差校正模型
model = VECM(df_diff, k_ar_diff=1, coint_rank=1)
model_fit = model.fit()

# 獲取模型的參數(shù)
alpha = model_fit.alpha
beta = model_fit.beta

# 獲取誤差修正向量(ECV)
ecv = model_fit.resid

# 打印模型參數(shù)和誤差修正向量
print('Alpha (α):')
print(alpha)
print('Beta (β):')
print(beta)
print('Error Correction Vector (ECV):')
print(ecv)
errors = []
# 根據(jù)模型參數(shù)和誤差修正向量確定交易信號
for i in range(len(df_diff[2:])):
    error = df_diff.iloc[i,0] - alpha[0] - beta[0] * df_diff.iloc[i,0] - beta[1] * df_diff.iloc[i,1] - ecv[i]
    error = error[0]-error[1]
    errors.append(error)
    
import matplotlib.pyplot as plt
plt.plot([i for i in range(len(errors))],errors)
在這里插入圖片描述

6. 構(gòu)建交易策略

統(tǒng)計套利的交易策略一般包括三個信號:當(dāng)價差偏離均值達(dá)到一定標(biāo)準(zhǔn)差幅度時,建倉交易;當(dāng)其偏離回復(fù)到一定程度時平倉獲利了結(jié);同時為了防止配對股票原長期均衡關(guān)系實(shí)際已經(jīng)破壞的事實(shí),價差將不會回復(fù)到均值區(qū)間,因此需要進(jìn)行風(fēng)險控制,即當(dāng)偏離超過一定標(biāo)準(zhǔn)差幅度時,止損離場。

對于交易觸發(fā)信號的確立,有不同的方法?!俺S玫慕灰撞呗匀缦拢寒?dāng) mspread 的絕對值大于 b 倍標(biāo)準(zhǔn)差時,建倉交易;當(dāng) mspread 的絕對值縮小到 a 倍標(biāo)準(zhǔn)差時平倉;當(dāng) mspread 的絕對值擴(kuò)大到 c 倍標(biāo)準(zhǔn)差時強(qiáng)制平倉離場。這里,a<b<c,a,b,c 常用的固定組合值有(0,1,2),(0,0.75,2)和(1,2,3)等。”除此之外,還有比較激進(jìn)的交易策略,比如海龜交易策略,到了止損位置,不僅不止損還繼續(xù)加倉。

# 計算目標(biāo)倉位
target = 0
target_data = []

for ix, spread in enumerate(errors):
    # 沒有倉位
    if not target:
        if spread >= np.std(errors)*1:
            target = -1
        elif spread <= -np.std(errors)*1:
            target = 1
    # 多頭倉位
    elif target > 0:
        if spread <= np.mean(errors):
            target = 0
    # 空頭倉位
    else:
        if spread >= np.mean(errors):
            target = 0
    # 記錄目標(biāo)倉位
    target_data.append(target)
df = pd.DataFrame()
df["spread"] = errors
df["target"] = target_data
# 計算倉位
df["pos"] = df["target"].shift(1)
# 未扣除手續(xù)費(fèi)和滑點(diǎn)
# 計算盈虧
df["change"] = df["spread"].diff()
df["pnl"] = df["change"] * df["pos"]
df["balance"] = df["pnl"].cumsum()
df["balance"].plot()
在這里插入圖片描述

7 總結(jié)

對于金融時間序列,往往會出現(xiàn)明顯的集群現(xiàn)象。因此這類數(shù)據(jù)利用時變標(biāo)準(zhǔn)差確定交易時機(jī)更合理,它可以更好的挖掘價差序列自回歸殘差的特性,從而使得統(tǒng)計套利的觸發(fā)信號更加精準(zhǔn)。所以統(tǒng)計套利經(jīng)常選用GARCH 模型進(jìn)行具體的統(tǒng)計套利策略研究。具體交易策略可以選擇,在價差(Spread)較小(由 GARCH 模型提供合理價差)的情況建倉,在價差(Spread)較大的情況下(由
GARCH 模型提供合理價差) 強(qiáng)制平倉止損,在價差(Spread)回歸 0 的時候平倉套利。

本文由mdnice多平臺發(fā)布

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容