投資組合分析1(ZTEHK VA ZTEA)方法2(OLS+adfuller)
阿新 • • 發佈:2019-01-02
思路: 輸入投資組合序列–>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;序列趨近中軌撤資離場.