1. 程式人生 > >投資組合分析1(ZTEHK VA ZTEA)方法2(OLS+adfuller)

投資組合分析1(ZTEHK VA ZTEA)方法2(OLS+adfuller)

思路: 輸入投資組合序列–>OLS線性迴歸–>取殘差–>ADF-Test(判斷殘差序列穩定性)–>否,元組合不具備協整關係
|
V
是,套利

分別從tushare和yahoo獲取zte a股和zte港股的資料:

import pandas_datareader.data as web
import datetime
import fix_yahoo_finance as yf
import pandas as pd
import tushare as ts
import statsmodels.api as sm#for ols

yf.pdr_override()
#開啟已有檔案,拿到最新記錄時間最為資料抓取開始時間,注意沒有engine ='python'會報錯
#data=pd.read_csv(r'C:\Users\yi\Desktop\Study\量化交易\ztehk.csv',sep=',',engine ='python')
#此時dmax為str,需將其轉為datetime
#start=pd.to_datetime(data['Date']).max()+datetime.timedelta(days=1)
start='2015-06-01'
end=str(datetime.date.today())
ztehk=web.get_data_yahoo('0763.HK',start,end)

#獲取的ztehk為dataframe格式,可以直接儲存為CSV
#ztehk.to_csv(r'C:\Users\yi\Desktop\Study\量化交易\ztehk.csv',index=True,sep=',',mode='a', header=False)
#獲取的ztesz資料
pro = ts.pro_api()
api=ts.pro_api('416626394789e89bcb3ad6f62ca0c8cb332b49fa2ac9156cb7aa6fc6')
ztesz = ts.pro_bar(pro_api=api, ts_code='000063.SZ', adj='qfq', start_date=start.replace('-',''), end_date=end.replace('-',''))

根據日期排序,擷取閉市價維度:

#資料整理,取各自的EOD close
ztesz_eod=ztesz.sort_index().rename(columns={'close':'ztesz_eod'}).loc[:,'ztesz_eod']
ztehk_eod=ztehk.sort_index().rename(columns={'Adj Close':'ztehk_eod'}).loc[:,'ztehk_eod'] 

yahoo給的資料index是datetime格式,而tushare給的是str格式,需要做格式轉換:

#迴圈獲取ztehk_eod.index,轉換為與tushare index相同格式的str
import numpy as np
i=0
reind=[]
for i in range(0,len(ztehk_eod.index)):
    reind.append(str(ztehk_eod.index[i]).split()[0].replace('-',''))
    i+=1

將新的時間列表插入原df,並將其設為index,drop原來的index

ztehk_eod_new=pd.DataFrame({'date_old':ztehk_eod.index,'ztehk_close':ztehk_eod.values,'date':reind}).set_index('date').drop('date_old',axis=1)

為了與ztehk格式保持一致,將ztesz由原來的series轉換為df

ztesz_eod_new=pd.DataFrame({'ztesz_close':ztesz_eod})

將兩組資料合併為一個新的df

zte=pd.DataFrame()
for t in ztehk_eod_new.index:
    if t in ztesz_eod_new.index:
        zte_sz_eod=ztesz_eod_new.loc[t,'ztesz_close']
        zte_hk_eod=ztehk_eod_new.loc[t,'ztehk_close']
        zte=zte.append(pd.DataFrame({'ztesz':[zte_sz_eod],'ztehk':[zte_hk_eod],'date':t}))
        #print(ztehk_eod,ztesz_eod)
        
zte1=zte.set_index('date')      

用OLS對兩組資料進行線性迴歸,獲取迴歸方程殘差並畫出

ols_result = sm.OLS(zte1.iloc[:,0], zte1.iloc[:,1]).fit()
ols_result.resid.plot()

在這裡插入圖片描述用ADF-Test檢驗殘差的平穩性:

from statsmodels.tsa.stattools import adfuller
def testStationarity(data):
    adftest = adfuller(data)
    result = pd.Series(adftest[0:4], index=['Test Statistic','p-value','Lags Used','Number of Observations Used'])
    for key,value in adftest[4].items():
        result['Critical Value (%s)'%key] = value
    return result
result=testStationarity(ols_result.resid)
result
import pprint
pprint.pprint(result)
Test Statistic                  -4.005821
p-value                          0.001380
Lags Used                        7.000000
Number of Observations Used    756.000000
Critical Value (1%)             -3.439029
Critical Value (5%)             -2.865371
Critical Value (10%)            -2.568810
dtype: float64

test值小於cv-5%,認為殘差為平穩序列;
計算兩組資料差值,並將其正態化:

#定義差價正態化函式
import matplotlib.pyplot as plt
def zscore(series):
    trans=(series - series.mean()) / np.std(series)
    return trans
zscore(zte1.iloc[:,0]-zte1.iloc[:,1]).plot(figsize=(20,7))
plt.axhline(zscore(zte1.iloc[:,0]-zte1.iloc[:,1]).mean(), color='black')
plt.axhline(1.0, color='red', linestyle='--')
plt.axhline(-1.0, color='green', linestyle='--')
plt.title('ztesz-ztehk')

在這裡插入圖片描述可以看到兩組股票的eod差值正態化序列在±1箱體波動,投資策略可以設為當序列突破上軌,做空ztesz,做多ztehk, 當序列突破下軌,做多ztesz,做空ztehk;序列趨近中軌撤資離場.