在財務領域有許多用來預測時間序列的計量模型,像是AR、ARMA、ARIMA、ARCH、GARCH…。但使用這些模型通常都需要很多嚴謹的假設檢定和繁複的轉換方式。也因此比較少人使用這些模型。這些模型背後有許多理論,像是非定態的時間序列轉換成定態的時間序列。此次的目的就是希望可以善加利用這些統計理論結合pytorch來增加訓練模型的精準度。
因此,我從當中選擇一個最簡單、好懂的AR模型作為對比,來比較看看,LSTM和AR哪種表現比較優異。
一般的回歸式
\[ y_{i} = \alpha + \beta_{0}X_{1i} + \beta_{1}X_{2i}...\\ \]
自回歸模型
\[ y_{t+1} = \alpha + \beta_{0}y_{t} + \beta_{1}y_{t-1} + \beta_{2}y_{t-2} ... \]
import requests import json url = '''https://www.twse.com.tw/exchangeReport/FMTQIK ?response=json&date=20211213''' r = requests.get(url) rawJson = r.json()
日期 | TWII | 成交金額 | 成交股數 | 成交筆數 | 漲跌點數 |
---|---|---|---|---|---|
2011-01-03 | 9025.3 | 1.49701e+11 | 6.66862e+09 | 1.29521e+06 | 52.8 |
2011-01-04 | 8997.19 | 1.62515e+11 | 7.00041e+09 | 1.41335e+06 | -28.11 |
2011-01-05 | 8846.31 | 1.80318e+11 | 7.66616e+09 | 1.50807e+06 | -150.88 |
2011-01-06 | 8883.21 | 1.39196e+11 | 5.88292e+09 | 1.153e+06 | 36.9 |
2011-01-07 | 8782.72 | 1.59552e+11 | 6.30132e+09 | 1.24305e+06 | -100.49 |
均值回歸(Mean Reversion)
指當某數值偏離平均值(Mean),其後數值將會傾向回歸平均值。
- 報酬率、對數報酬率
\[ \frac{P_{1} - P_{0}}{P_{0}} \space or\space \ln(\frac{P_{1}}{P_{0}}) \]- 差分法
\[ P_{1} - P_{0} \]
Date | t | t-1 | t-2 | t-3 | t-4 |
---|---|---|---|---|---|
2011-01-04 | -0.00311944 | nan | nan | nan | nan |
2011-01-05 | -0.0169119 | -0.00311944 | nan | nan | nan |
2011-01-06 | 0.00416256 | -0.0169119 | -0.00311944 | nan | nan |
2011-01-07 | -0.0113768 | 0.00416256 | -0.0169119 | -0.00311944 | nan |
2011-01-10 | 0.00399532 | -0.0113768 | 0.00416256 | -0.0169119 | -0.00311944 |
2011-01-11 | 0.0127872 | 0.00399532 | -0.0113768 | 0.00416256 | -0.0169119 |
2011-01-12 | 0.00375943 | 0.0127872 | 0.00399532 | -0.0113768 | 0.00416256 |
2011-01-13 | 0.00117945 | 0.00375943 | 0.0127872 | 0.00399532 | -0.0113768 |
2011-01-14 | -0.000342098 | 0.00117945 | 0.00375943 | 0.0127872 | 0.00399532 |
class logReturn: def __init__(self): pass def fit(self, df, windows:int=0): self.df = copy.deepcopy(df) self.windows = windows self.transformR() self.rollingWindow() def transformR(self): self.lr = np.log(self.df/self.df.shift(1)) return self def backwardR(self, logR, pred:bool=False): if pred: return np.exp(logR) * self.df[self.windows:].shift(1) else: return np.exp(logR) * self.df.shift(1) def rollingWindow(self): rolling = len(self.lr) - self.windows self.rollingX = np.array([self.lr[i: i+self.windows] for i in range(rolling)]) self.rollingY = np.array([self.lr[i+self.windows] for i in range(rolling)]) return self
windows=10 LR = logReturn() LR.fit(df.close, windows=windows)
LR.lr # 純粹的對數報酬率 x, y = LR.rollingX, LR.rollingY # 使用Rolling-Window後
# 純粹的對數報酬率返回 pd.DataFrame( { 'True': df.close.values, 'Backward': LR.backwardR(LR.lr).values } ) # 預測值返回,因為使用 Rolling-Window 前幾個row會刪除 pd.DataFrame( { 'Pred': outputs, 'Pred-Backward': LR.backwardR(outputs, pred=True) } )
對Rolling Window生成的Features取平方, 次方, 對數…來增加一些多樣性
原本的資料包含成交股數, 成交筆數, 漲跌點數的欄位,使用Talib生成技術指標
diff = df["漲跌點數"].shift(1) volume = df["成交股數"].shift(1) records = df["成交筆數"].shift(1) df['MOM_volume'] = talib.MOM(volume, timeperiod=5) df['MOM_records'] = talib.MOM(records, timeperiod=5) df['MOM_diff'] = talib.MOM(diff, timeperiod=5) df['RSI_volume'] = talib.RSI(volume,timeperiod=5) df['RSI_records'] = talib.RSI(records,timeperiod=5) df['RSI_diff'] = talib.RSI(diff,timeperiod=5) df['willR'] = talib.WILLR(volume, records, diff, timeperiod=5) df['CCI'] = talib.CCI(volume, records, diff, timeperiod=5)
- AR(Autoregressive, 自迴歸模型)
用過去的y值作為預測值的Features。- Rolling-Window
Window代表過去幾日的值作為Features.
e.g. windows=10, 過去10日的值當作預測第11日時的Features。- Talib
生成技術指標的套件。- log-return(對數報酬率)
在做量化投資時常用來計算報酬率的一種方式,具有良好的可加性。