ARIMA 모델과 온라인 매체를 이용하여 S&P 500 과 Nasdaq 의 전망을 예측하는 모델을 만들어볼까 한다.
시장은 많은 요소들이 영향을 끼치기 때문에 완벽하게 예측하는 것은 불가능에 가깝다. 하지만 모든건 확률 싸움인 만큼, 정확도를 조금이라도 더 올릴 수 있는 파라미터들을 찾아서 예측 해 볼 수 있다면 시장을 상대로 조금 더 높은 승률을 가져갈 수 있을것이다. 세부적인것들을 보기 전에 시장의 trend 를 알아보기 위해 Nasdaq 을 예측하는 모델을 먼저 만들어 볼까한다.
시장은 세부적으로는 셀 수 없이 많은 영향을 받지만, 크게는 두가지 영향을 받는다:
1. Endogenous factors (technical factor)
2. Exogenous factors
간략히 설명하자면
1. 내부적인 요소 2. 외부적인 요소 로 설명할 수 있을것이다. 내부적인 요소는 일별시세 (주별, 월별), order book, 거래량등을 이용하여 시장을 예측하는것을 뜻하고. 외부적인 요소는 그 외의 데이터들이 기대하지 못한 방향으로 시장에 영향을 주는것을 말한다. (예: 분기별 실적, customer supply shock, macro data release) 내부적인 요소는 가설을 세우고 유의미하게 영향을 미치는 parameter 들을 찾은 후 Arima 모델에 넣어 줄 것이고, 외부적인 요소는 Machine Learning을 이용하여 인터넷 기사들, sns등을 crawling 한 후 부정적인 단어나 긍정적인 단어를 학습시키는 text-mining 기법을 이용하여 ARIMAX 모델을 만들 계획이다.
Data Mining => Dickey-Fuller Test for stationary => Granger Causality => Text-mining => ARIMAX
<가설>
H1: COVID-19 확진자 수는 시장에 유의미하게 부정적인 영향을 끼친다
위 가설을 증명하기 위해 경제/통계학에서 접할수 있는 Granger Causality Test를 통해 코로나 확진자 수가 유의미하게 영향을 끼치는지 살펴볼 것이다.
1. 먼저 코로나 확진자수와 SP500지수 데이터를 사용하였다. 데이터는 WHO와 Investing.com에서 어렵지않게 구할수 있었다. (차후 VIX 지수로 test 예정)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime
COVID = pd.read_csv("../us.csv")
SP500 = pd.read_csv("../US500.csv")
왼쪽은 2020년 1월부터 미국 코로나 확진자수를 집계해놓은 데이터이고 오른쪽은 2020년 7월부터 약 1년간 SP500지수의 데이터를 집계해 놓은것이다. 코로나 바이러스와 SP500지수가 Granger cause를 하였는지 알아보기 위해 두 데이터를 날짜로 먼저 묶어본다. 날짜로 묶기전에 서로 날짜 format이 다르니 format 을 맞춰준 후 날짜별로 데이터를 합쳐보겠다.
print("COVID date type: {}, SP date type: {}".format(type(COVID['date'][0]), type(SP500['Date'][0])))
# output: COVID date type: <class 'str'>, SP date type: <class 'str'>
## Date Format 맞추기
COVID["date"] = pd.to_datetime(COVID.date, format = "%Y-%m-%d")
SP500["date"] = pd.to_datetime(SP500.Date, format = "%b %d, %Y") ## Price object -> numeric (Price가 data type이 object 라서 쉼표를 지우고 numeric으로 변경)
SP500.replace(',', '', regex=True, inplace=True)
SP500['Price'] = SP500['Price'].apply(pd.to_numeric, errors='coerce')
result = pd.merge(COVID, SP500, how='inner', on='date')
result = result[['date', 'cases', 'Price']]
이제 데이터 준비는 끝낫으니 테스트를 하기전에 Granger Causality는 시계열 데이터가 stationary 하다는 전제조건이 붙는다.
데이터가 stationary 인지 non-stationary 인지 구별하기위해 제일 널리 사용되는 Dickey-Fuller test 를 이용하여 테스트 해보겠다.
Null hypothesis: 시계열 데이터가 non-stationary하다
Alternative hypothesis: 시계열 데이터가 stationary 하다
P-value: 0.05
from statsmodels.tsa.stattools import adfuller
def adf_test(df):
result = adfuller(df.values)
print('ADF Statistics: %f' % result[0])
print('p-value: %f' % result[1])
print('Critical values:')
for key, value in result[4].items():
print('\t%s: %.3f' % (key, value)) adf_test(result['cases'])
# P-value < 0.05 in order to reject the null
"""
ADF Statistics: -0.733331 p-value: 0.837926 Critical values: 1%: -3.455
5%: -2.872 10%: -2.572 """ adf_test(result['Price'])
"""
ADF Statistics: -0.896332 p-value: 0.789178 Critical values: 1%: -3.453
5%: -2.872 10%: -2.572
"""
P-value 가 0.05 이상이라 null hypothesis 를 reject 하지 못하였다. 데이터는 non-stationary 하고 stationary 하게 바꾸기 위해 difference method를 사용해보았다.
result_diff = result.diff().dropna()
result_diff
difference method 를 사용하여 데이터가 stationary 하게 만들어주었다. (I of Price = 1 , I of cases = 2)
이제 VAR을 이용하여 lag order을 정해보겠다.
from statsmodels.tsa.api import VAR
model = VAR(result_diff[['cases_2','Price']])
for i in [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]:
result = model.fit(i)
print('Lag Order =', i)
print('AIC : ', result.aic)
print('BIC : ', result.bic)
print('FPE : ', result.fpe)
print('HQIC: ', result.hqic, '\n')
Lag를 정하기 위해선 주로 AIC가 제일 낮은 숫자를 선택한다. 위의 경우에는 7이다.
<작성중>
'3. 심화 학습 (Advanced Topics) > 연구실' 카테고리의 다른 글
간단한 BERT 모델을 이용하여 GPT 챗봇 성능 높이기 (1) | 2023.11.23 |
---|---|
[논문분석] 딥러닝을 이용하여 불규칙적인 시계열 예측 모델 만들기 (LSTNet) (0) | 2023.01.17 |
시계열 분석에서 예측 모델의 구축 및 Stacking을 위한 베이지안 회귀 분석 방법 (2/2) - 구현 (0) | 2022.02.28 |
시계열 분석에서 예측 모델의 구축 및 Stacking을 위한 베이지안 회귀 분석 방법 (1/2) - 설명 (0) | 2022.02.16 |
4가지 온라인 매체를 이용하여 유가 예측하기 (0) | 2021.08.06 |
댓글