단순회귀모형을 이용한 주가 예측

2020. 7. 13. 22:38금융 데이터 분석

반응형

앞의 글(https://direction-f.tistory.com/6)에서 어떻게 하면 주가 데이터를 수집할지에 대해서 정리하였습니다.  이번에는 수집한 데이터를 활용하는 방법에 대해서 정리하도록 하겠습니다. 먼저 기본적인 모형인 단순회귀모형을 이용하여 주가를 예측하는 모델을 구성해보겠습니다. 

사실 단순회귀모형은 주가를 예측하는데 탁월한 예측력을 제공해주는 모형은 아닙니다. 왜냐하면 주가는 변동성이 심해, 올라갔다 내려갔다를 반복하는데, 회귀모형은 이러한 변동성을 잡아내기 어렵기 때문입니다. 그래서 정확한 예측을 위해선 변동성을 일부 반영 할 수 있는 ARIMA/ARIMAX같은 시계열 모형이나, RNN/LSTM과 같은 딥러닝 모형이 활발히 적용되고 있습니다.

그럼에도 불구하고, 전문적인 분석모델링을 하는 것이 아니라 실무에서 단순히 "시장의 크기"나 "매출"에 대해 시간에 따른 추세를 볼 때와 같이 대략적인 추정치를 산정하기에 접근하기 좋은 방법이기 때문에 오히려 실용적이고 강력한 방법이라고 생각합니다. 

 

[단순회귀모형]

회귀분석에서도 다양한 복잡한 모형들이 존재합니다. 단순회귀모형은 독립변수와 종속변수간의 선형적 관계를 추정하고 이를 이용하여 관계를 설명하거나 예측을 하는 모형입니다. 예를 들어 Y= αX+β라는 함수가 있다고 가정해 보면 X가 독립변수가 되고 X값에 따라 값이 변하는 Y는 종속변수가 됩니다.

여기서 단순회귀모형은 적절한 α, β값을 추정하는 것입니다. α, β를 추정하는 방법은 예측값과 실제값이 최소화 되도록 하는 α, β를 구하는 것입니다. 예를 들어 아래 표와 같이 자료가 주어졌다고 가정해보겠습니다.

X Y_예측값1 (α:1, β:1) Y_예측값2 (α:2, β:0) Y_실제값
1 2 2 2
2 3 4 4
3 4 6 6
4 5 7 8


해당 자료는
α가 2이고 β가0일 때 실제값과 예측값의 오차가 최소값(0)을 가집니다. 이 처럼 실제값과 예측값이 최소가 되는 α,β를 찾게 됩니다.

이제 이러한 단순회귀모형을 바탕으로 주가를 추정해보도록 하겠습니다.

먼저 필요한 모듈을 Import하고 수집한 데이터를 불러오도록 하겠습니다.(2018.07.13~2020.07.10 삼성전자 주가 데이터)

import statsmodels.api as sm
import statsmodels.formula.api as smf
import numpy as np
import pandas as pd
import os
import matplotlib.pyplot as plt
os.chdir(".../stock_price")

data = pd.read_csv("samsung.csv")
data.head()
  날짜 종가 전일비 시가 고가 저가 거래량
0 2020.07.10 52700.0 100.0 53100.0 53200.0 52300.0 13646439.0
1 2020.07.09 52800.0 200.0 53200.0 53600.0 52800.0 17054850.0
2 2020.07.08 53000.0 400.0 53600.0 53900.0 52900.0 19664652.0
3 2020.07.07 53400.0 1600.0 55800.0 55900.0 53400.0 30760032.0
4 2020.07.06 55000.0 1400.0 54000.0 55000.0 53800.0 19856623.0

저희는 이번 예측을 위해서 종가만을 활용하도록 하겠습니다. 추가적으로 회귀분석의 독립변수로써 시간을 활용하기 위해 time 이라는 Column을 추가적으로 만들도록 하겠습니다. 이 때 시간은 데이터의 시작일이 1이 되고 하루가 지나면서 계속 1씩 더해지도록 하겠습니다. 마지막으로 우리는 총 491일 데이터가 있는데 시작일 부터 400일까지는 Train 데이터로 401일부터 491일까지는 Test 데이터로 구성하겠습니다.

data["time"]=data.sort_index(ascending=False).index+1
data.rename(columns ={"종가":"Close"}, inplace =True) ## 이름 변경

train_data =data.loc[data.time <= 400][["Close", "time"]]
print(len(train_data))
test_data =data.loc[data.time > 400][["Close", "time"]]
print(len(test_data))

이제 Python에서 제공하는 statsmodels 모듈을 활용하여 회귀분석을 수행하겠습니다.

Close_tr = train_data["Close"]
time_tr = train_data["time"]
time_tr = sm.add_constant(time_tr)
mod = sm.OLS(Close_tr, time_tr)
res = mod.fit()
print(res.summary())

위의 결과 출력해보시면 보면 시간과 주가의 관계가 상당히 유의하게 나옴을 확인 할 수 있습니다.(P>|t|가 0.05보다 작으면 해당 독립변수가 유의함을 뜻함) 추가적으로 Train 데이터를 이용하여 실제값과 예측값의 추세를 확인해 보겠습니다.

train_result=res.predict(time_tr)
plt.plot(train_data["time"], train_result, label = "Predict")
plt.plot(train_data["time"], Close_tr, label = "Real")
plt.xlabel("time")
plt.ylabel("Close")
plt.legend()
plt.title("Real vs Predict")
plt.show()

꽤 추세를 잘 설명하고 있는 것으로 볼 수 있을 것 같습니다.

그럼 이제 만든 모형을 가지고 최근 90일의 데이터를 예측해보도록 하겠습니다.

Close_test = test_data["Close"]
time_test = test_data["time"]
time_test = sm.add_constant(time_test)

test_result=res.predict(time_test)
plt.plot(test_result, label = "Predict")
plt.plot(Close_test, label = "Real")
plt.xlabel("time")
plt.ylabel("Close")
plt.legend()
plt.title("Real vs Predict")
plt.show()

추세는 얼추 비슷하게 나온 것으로 볼 수 있을까요? 하지만 선형 모형이기 때문에 전혀 변동성을 반영하지 못하고 있는 것을 볼 수 있습니다. 하지만 간단히 추세를 확인하는데 있어 꽤 효과적으로 적용될 수 있다는 것도 확인 할 수 있을 것 같습니다.

 

반응형