파이썬 ARIMA 모델 사용법: 주가 시계열 예측부터 성능 평가까지

ARIMA의 p·d·q 의미부터 파이썬 모델 학습, 예측, MAE·RMSE 평가까지 하나의 흐름으로 정리한 자료입니다. 시간순으로 학습·테스트 데이터를 나눠야 하는 이유와 미래 정보 누수를 피하는 방법을 함께 설명했고 ARIMA 모델의 결과를 단순 기준 예측과 비교해야 하는 이유까지 확인할 수 있습니다.
앞선 글에서는 ACF와 PACF를 이용해 시계열의 자기상관 구조를 살펴봤습니다.
이제 실제 예측 모델을 만들어볼 차례입니다.
시계열 분석을 공부하다 보면 가장 자주 접하는 모델 가운데 하나가 ARIMA입니다.
그런데 ARIMA(1,1,1) 같은 코드를 그대로 복사해서 실행하는 것만으로는 충분하지 않습니다.
왜 p가 1인지, 왜 차분을 하는지, 학습 데이터와 테스트 데이터는 어떻게 나눠야 하는지, 예측값이 실제로 쓸 만한 수준인지까지 확인해야 의미 있는 분석이 됩니다.
특히 금융 시계열에서는 미래 데이터를 학습 과정에 섞어버리는 실수가 모델의 성능을 실제보다 좋아 보이게 만들 수 있습니다.
이번 글에서는 파이썬 statsmodels를 이용해 ARIMA 모델을 만들고, 주가 시계열을 학습 데이터와 테스트 데이터로 분리한 뒤 실제 예측값을 MAE와 RMSE로 평가하는 전체 과정을 살펴보겠습니다.

1. ARIMA의 p, d, q는 무엇을 의미할까?
ARIMA는 Autoregressive Integrated Moving Average의 약자입니다.
현재 statsmodels 공식 튜토리얼에서도 ARIMA를 과거 값과 과거 예측 오차를 활용해 미래 시계열 값을 예측하는 대표적인 방법으로 설명하고 있습니다.
ARIMA 모델은 보통 다음처럼 표현합니다.
ARIMA(p, d, q)
세 숫자의 의미는 다음과 같습니다.
- p는 AR, 즉 자기회귀 차수입니다. 현재 값을 설명하기 위해 몇 개의 과거 값을 사용할지를 나타냅니다.
- d는 차분 횟수입니다. 비정상 시계열을 정상적인 형태에 가깝게 만들기 위해 몇 번 차분할지를 의미합니다.
- q는 MA, 즉 이동평균 오차 차수입니다. 몇 개의 과거 예측 오차를 모델에 반영할지를 나타냅니다.
예를 들어
ARIMA(2, 1, 1)
이라면 1차 차분을 적용하고, 자기회귀 항 2개와 이동평균 오차 항 1개를 사용하는 모델로 이해할 수 있습니다.
앞선 글들과도 연결됩니다.
ADF 검정에서 정상성을 살펴본 과정은 주로 d를 판단하는 데 참고할 수 있고, ACF와 PACF는 p와 q 후보를 찾는 데 활용할 수 있습니다.
다만 ACF와 PACF만 보고 차수를 확정하기보다는 여러 후보 모델을 실제 데이터에서 비교하는 것이 좋습니다.
statsmodels의 현재 ARIMA 인터페이스 역시 order=(p, d, q) 형태로 모델의 비계절 차수를 지정하도록 되어 있습니다.
2. 주가 데이터를 학습용과 테스트용으로 나누기
먼저 필요한 라이브러리를 불러오겠습니다.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.tsa.arima.model import ARIMA
from sklearn.metrics import (
mean_absolute_error,
root_mean_squared_error
)
예제에서는 CSV 파일에 날짜와 종가가 있다고 가정합니다.
df = pd.read_csv("stock_data.csv")
df["Date"] = pd.to_datetime(df["Date"])
df = df.sort_values("Date")
df = df.set_index("Date")
series = df["Close"].dropna()
여기서 중요한 것이 학습 데이터와 테스트 데이터 분리입니다.
일반적인 머신러닝처럼 데이터를 무작위로 섞지 않고 시간 순서를 그대로 유지합니다.
예를 들어 앞쪽 80%를 학습 데이터로 사용하고 뒤쪽 20%를 테스트 데이터로 사용할 수 있습니다.
split = int(len(series) * 0.8)
train = series.iloc[:split]
test = series.iloc[split:]
print("Train:", len(train))
print("Test:", len(test))
구조를 그림으로 확인해보겠습니다.
plt.figure(figsize=(12, 5))
plt.plot(
train.index,
train,
label="Train"
)
plt.plot(
test.index,
test,
label="Test"
)
plt.legend()
plt.show()
왜 굳이 이렇게 나눌까요?
우리가 실제 미래를 예측하는 상황에서는 미래 가격을 알고 모델을 학습할 수 없기 때문입니다.
따라서 과거 구간만 사용해 모델을 만들고, 모델이 한 번도 보지 않은 이후 기간에서 성능을 측정하는 편이 실제 예측 상황에 더 가깝습니다.
여기서 한 가지 더 기억할 점이 있습니다.
80대 20이라는 비율 자체가 정답은 아닙니다.
데이터의 길이와 빈도, 시장 국면, 예측 목적에 따라 검증 기간은 달라질 수 있습니다.
3. statsmodels로 ARIMA 모델 학습하고 예측하기
앞선 ACF와 PACF 분석을 통해 (1,1,1)을 후보 모델 가운데 하나로 정했다고 가정해보겠습니다.
모델은 다음처럼 생성할 수 있습니다.
model = ARIMA(
train,
order=(1, 1, 1)
)
model_fit = model.fit()
print(model_fit.summary())
현재 statsmodels의 공식 ARIMA 튜토리얼도 ARIMA()로 모델을 정의한 뒤 fit()을 호출하는 구조를 사용합니다.
학습이 끝났다면 테스트 데이터 길이만큼 미래 값을 예측합니다.
forecast = model_fit.forecast(
steps=len(test)
)
print(forecast.head())
statsmodels의 현재 forecast()는 표본 밖의 미래 값을 지정한 step 수만큼 예측하는 기능을 제공합니다.
실제값과 예측값을 그래프로 비교해보겠습니다.
plt.figure(figsize=(12, 5))
plt.plot(
test.index,
test,
label="Actual"
)
plt.plot(
test.index,
forecast,
label="ARIMA Forecast"
)
plt.legend()
plt.show()
그래프를 보면 모델이 전체적인 움직임을 어느 정도 따라가는지 시각적으로 확인할 수 있습니다.
예측의 불확실성까지 확인하고 싶다면 get_forecast()를 활용할 수도 있습니다.
forecast_result = model_fit.get_forecast(
steps=len(test)
)
forecast_mean = forecast_result.predicted_mean
forecast_ci = forecast_result.conf_int()
이처럼 예측값 하나만 보는 것보다 예측구간을 함께 살펴보면 모델의 불확실성을 이해하는 데 도움이 됩니다.
하지만 그래프만 보고 “잘 맞는다” 또는 “틀린다”고 판단해서는 부족합니다.
숫자로 오차를 평가해볼 필요가 있습니다.
파이썬 ARIMA 모델 사용법:
주가 시계열 예측부터 성능 평가까지
4. MAE와 RMSE로 ARIMA 성능 평가하기
회귀 또는 시계열 예측에서는 실제값과 예측값의 차이를 여러 방법으로 평가할 수 있습니다.
여기서는 MAE와 RMSE를 사용해보겠습니다.
mae = mean_absolute_error(
test,
forecast
)
rmse = root_mean_squared_error(
test,
forecast
)
print("MAE:", mae)
print("RMSE:", rmse)
MAE는 Mean Absolute Error, 즉 평균절대오차입니다.
실제값과 예측값 차이의 절댓값을 평균한 값입니다.
현재 scikit-learn 공식 문서에서도 mean_absolute_error()는 실제 목표값과 예측값 사이의 평균 절대 오차를 계산하는 회귀 손실 함수로 제공됩니다. 값은 0 이상이며 작을수록 오차가 작습니다.
RMSE는 Root Mean Squared Error입니다.
오차를 제곱한 뒤 평균하고 다시 제곱근을 취합니다.
MAE
오차의 절댓값을 평균
RMSE
큰 오차에 상대적으로 더 큰 영향을 주는 평가 방식
scikit-learn에서는 root_mean_squared_error()를 별도 함수로 제공하고 있으며, 공식 문서상 이 함수는 버전 1.4에서 추가되었습니다.
여기에서 중요한 함정이 하나 있습니다.
ARIMA 모델의 MAE가 작다고 해서 바로 “예측력이 뛰어나다”고 결론 내리면 안 됩니다.
비교 대상이 필요합니다.
가장 단순한 기준 모델 가운데 하나는 마지막 관측값을 그대로 다음 값의 예측값으로 사용하는 방법입니다.
naive_forecast = np.repeat(
train.iloc[-1],
len(test)
)
naive_mae = mean_absolute_error(
test,
naive_forecast
)
naive_rmse = root_mean_squared_error(
test,
naive_forecast
)
print("ARIMA MAE:", mae)
print("Naive MAE:", naive_mae)
print("ARIMA RMSE:", rmse)
print("Naive RMSE:", naive_rmse)
이 비교가 중요한 이유는 간단합니다.
복잡한 ARIMA 모델을 사용했는데도 아주 단순한 기준 예측보다 성능이 떨어진다면 복잡한 모델을 사용할 실익이 크지 않을 수 있기 때문입니다.
특히 금융 가격 시계열에서는 단순 기준 모델이 생각보다 강한 비교 대상이 될 수 있습니다.
모델을 평가할 때는 “오차가 얼마인가?”에서 끝내지 말고 “간단한 방법보다 실제로 개선됐는가?”까지 질문하는 것이 좋습니다.
5. ARIMA 주가 예측에서 자주 놓치는 점
여기까지 코드만 보면 ARIMA를 이용한 주가 예측은 상당히 간단해 보입니다.
하지만 실제 분석에서는 몇 가지를 더 확인해야 합니다.
먼저 원본 가격을 바로 ARIMA에 넣을지, 로그가격이나 수익률을 분석할지 결정해야 합니다.
d=1을 사용하면 모델 내부에서 차분이 적용되지만 이것이 모든 데이터 문제를 자동으로 해결해주는 것은 아닙니다.
ADF 검정과 시계열 그래프를 함께 확인하는 것이 좋습니다.
두 번째는 p, d, q를 하나만 시험하고 끝내지 않는 것입니다.
예를 들어 다음처럼 여러 후보 모델을 비교할 수 있습니다.
orders = [
(1, 1, 0),
(0, 1, 1),
(1, 1, 1),
(2, 1, 1),
(1, 1, 2)
]
for order in orders:
model = ARIMA(
train,
order=order
)
result = model.fit()
print(
order,
"AIC:",
result.aic,
"BIC:",
result.bic
)
AIC와 BIC가 작은 모델은 후보를 좁히는 데 활용할 수 있습니다.
하지만 정보기준이 가장 작은 모델이 반드시 미래 테스트 구간에서 가장 작은 오차를 보인다고 단정할 수는 없습니다.
최종적으로는 표본 밖 데이터를 이용한 검증이 중요합니다.
세 번째는 한 번에 긴 미래를 예측하는 방법과 매 시점 새 데이터를 반영해 다시 예측하는 방법을 구분해야 합니다.
실제 운용에서는 새로운 데이터가 계속 들어옵니다.
따라서 더 엄격하게 평가하려면 한 시점씩 미래를 예측하고 실제값을 확인한 다음 학습 데이터에 추가하는 walk-forward 방식도 고려할 수 있습니다.
네 번째는 ARIMA 예측 결과를 투자 신호와 동일하게 생각해서는 안 됩니다.
ARIMA는 과거 시계열의 자기상관과 오차 구조를 이용하는 통계 모델입니다.
기업 실적, 금리 변화, 정책 발표, 지정학적 사건이나 예상하지 못한 뉴스까지 자동으로 이해하는 모델은 아닙니다.
이 부분이 앞으로 뉴스 감성 분석과 연결되는 지점입니다.
지금까지 시리즈의 흐름을 정리하면 다음과 같습니다.
시계열 전처리에서 결측치와 이상치를 확인하고,
ADF 검정으로 정상성을 점검한 뒤,
ACF와 PACF로 자기상관 구조를 살펴보고,
이번 글에서는 ARIMA 모델을 이용해 실제 예측과 성능 평가까지 진행했습니다.
여기까지는 대부분 ‘과거 숫자’ 중심의 분석입니다.
그렇다면 숫자로 표현되지 않은 경제 뉴스는 어떻게 분석할 수 있을까요?
다음 글에서는 **「파이썬으로 경제 뉴스 감성 분석하기: FinBERT 활용 방법」**을 통해 기사 제목과 경제 뉴스를 긍정·중립·부정 데이터로 변환하는 방법을 살펴보겠습니다.
그리고 이후에는 이 뉴스 감성 점수를 금융 시계열과 결합해 실제로 관계가 존재하는지를 검증해볼 수 있습니다.
참고 자료
statsmodels 공식 ARIMA 튜토리얼은 ARIMA의 AR·I·MA 구성과 (p,d,q) 의미, 모델 적합 과정을 실제 코드와 함께 제공하고 있습니다.
statsmodels 0.15 계열의 현재 공식 문서에서 ARIMA는 AR, MA, ARMA, ARIMA 및 계절 확장 형태 등을 지원하는 인터페이스로 제공됩니다.
scikit-learn 공식 문서는 mean_absolute_error와 root_mean_squared_error를 회귀 예측 오차를 측정하는 함수로 제공하고 있습니다.
금융소비자보호 및 개인 유의사항
본 글은 파이썬과 통계적 시계열 분석 방법을 설명하기 위한 교육 및 정보 제공 목적의 콘텐츠입니다. 특정 금융상품의 매수·매도, 투자 또는 수익을 권유하거나 보장하기 위한 내용이 아닙니다.
ARIMA를 포함한 통계적 예측 모델의 결과는 분석 기간, 데이터 빈도, 전처리 방식, 모델 차수와 검증 방법에 따라 달라질 수 있습니다. 과거 데이터에 대한 적합도 또는 테스트 결과가 향후 금융시장 움직임이나 투자 성과를 보장하지 않습니다. 실제 금융 의사결정에는 가격 데이터 외에도 다양한 위험요인과 개인의 투자 목적 등을 함께 검토할 필요가 있습니다.
금알남
댓글 0
첫 댓글을 남겨보세요.