728x90
반응형

시계열 분석 주식 데이터_주가 예측

https://mzero.tistory.com/146 에 이어서

 

[시계열 분석] 주가예측 / 시계열 데이터 분석 / ARIMA 모델

시계열 분석 주식 데이터_주가 예측 ''' 기본 라이브러리 ''' import datetime import matplotlib.pyplot as plt import platform from matplotlib import font_manager, rc ''' 마이너스 기호 및 한글 설정 ''' ### 마이너스 기호 사

mzero.tistory.com

 

Best Model을 이용해서 잔차 확인

📍 잔차 : 실제값과 예측값과의 차이
📍 잔차 검정 : 정상성, 정규성 등을 만족하는지 확인하는 검정
📍 검정하는 함수 : summary(), plot_diagnostics()
  • summary()

 

확인해야할 사항

Heteroskedasticity (H) : 값이 작을수록 정규분표

P>|z| : p-value 값으로 유의미한지, 아닌지 판단

 

 

 

 

 

 

 

 

 

 

  • plot_diagnostics()
    model.plot_diagnostics(figsize=(16, 8))
    plt.show()

 

3번 그래프 : 빨간색 추세선과 비슷하게 흘러가는 것이 좋음

4번 그래프 : 0을 기점으로 모두 포함 되어 있어서 정상성을 띔, 차수의 첫번 째는 계산이 안되기 때문에 0은 빠짐

 

정상성을 띄지만, 정규분포는 낮다

 

 

 

ARIMA 모델 훈련 및 테스트하기

  • 훈련 및 테스트 데이터 = 9 : 1 로 분리
    - 시계열 데이터는 train_test_split()함수를 사용하지 않는다.
    -연속성을 띄는 데이터의 특성상, 데이터를 앞/뒤의 비율로 분리한다.
    train_data = data[:int(len(data) * 0.9)]
    test_data = data[int(len(data) * 0.9):]
    
    train_data.shape, test_data.shape​


  • auto_arima : 모델 설정 및 Best Model 추출
    - auto_arima는 훈련과 동시에 베스트 모델을 생성해 준다.
    model_fit = pm.auto_arima(
        y=train_data,
        d=n_diffs,
        start_p=0, max_p=3,
        start_q=0, max_q=3,
        m=1, seasonal=False,
        stepwise=True,
        trace=True
    )​


Best Model을 이용하여 예측(Predict)하기

📍 시계열에서 예측 용어 : forecast라고 칭한다.
📍 예측 결과 : 예측데이터, 상한가(상한 바운드), 하한가(하한 바운드)
📍 결과 시각화 : 기존값과 예측값이 연결된 시각화
📍 수행방법 : forecast 함수 생성 후 predict 수행 > 예측결과 반환

 

  • 함수 생성하기
    import numpy as np
    
    """향후 예측
     - model : Best Model
     - n : 예측하려는 향후 기간 (디폴트로 1을 지정했음)
    """
    def forecast_n_step(model, n=1):
        ### 예측하기
        # - n_periods : 예측기간 (day일단위)
        # - return_conf_int : 신뢰구간 반환여부
        # - fc : 예측결과(y_pred)
        # - conf_int : 신뢰구간
        fc, conf_int = model.predict(n_periods=n, return_conf_int=True)
        
        # print(fc, conf_int)
        ### 반환값은 리스트형태로 변환해서 전달
        return (
            fc.tolist()[0:n],
            # asarray : 배열로 바꾸는 함수 / tolist : 리스트로 바꾸는 함수
            np.asarray(conf_int).tolist()[0:n]
        )

    """함수 생성하기"""
    import pandas as pd
    
    def forecast(len, model, index, data=None) :
        ### 결과값을 담아서 반환할 변수
        y_pred = []
        pred_upper = []
        pred_lower = []
    
        ###데이터(data)가 있는 경우
        if data is not None :
            for new_data in data :
                ### 예측하기 : 반복수행을 위해 함수로 생성
                fc, conf = forecast_n_step(model)
    
                ### 예측결과 리스트에 담기
                y_pred.append(fc[0])
    
                ### 상한가
                pred_upper.append(conf[0][1])
    
                ### 하한가
                pred_lower.append(conf[0][0])
    
                ### 시계열에서는 데이터별로 Model을 갱신함
                model.update(new_data)
                
        
        ###데이터(data)가 없는 경우
        else : 
            for i in range(len):
                fc, conf = forecast_n_step(model)
                
                ### 예측결과 리스트에 담기
                y_pred.append(fc[0])
    
                ### 상한가
                pred_upper.append(conf[0][1])
    
                ### 하한가
                pred_lower.append(conf[0][0])
    
                ### 시계열에서는 데이터별로 Model을 갱신함
                model.update(fc[0])
            
    
        ### 결과값에 대해서는 시리즈 타입으로
        return pd.Series(y_pred, index=index), pred_upper, pred_lower
        # return "", "", ""
  • 함수 호출하기
    '''
    함수 호출하기
     - fc : 예측결과
     - upper : 상한가
     - lower : 하한가
    '''
    
    fc, upper, lower = forecast(len(test_data), model_fit,
                               test_data.index, data=test_data)
    fc, upper, lower


  • 상한가와 하한가의 리스트 타입 데이터를 날짜를 인덱스로 하는 시리즈 타입으로 변환하기
     - 추후 시각화 시 결과값의 인덱스와 매핑하여 그리기 위함

    lower_series = pd.Series(lower, index=test_data.index)
    upper_series = pd.Series(upper, index=test_data.index)
    
    lower_series, upper_series​


  • 전체 시각화
    - 훈련데이터 및 테스트데이터 시각화
    plt.figure(figsize=(20, 6))
    plt.title("시계열 분석 결과 시각화")
    
    ### 훈련데이터 그리기
    plt.plot(train_data, label="train_data")
    
    ### 테스트 데이터 그리기
    plt.plot(test_data, label="test_data(예측 전 실제값)", c="b")
    
    ### 테스트데이터로 예측한 결과 그리기
    plt.plot(fc, label="예측결과", c="r")
    
    ### 상한가(상한 바운드) 하한가(하한 바운드) 그리기
    plt.fill_between(lower_series.index, lower_series,
                    upper_series, alpha=.9, color="k")
    
    plt.legend()
    plt.show()​

모델 성능 평가

from sklearn.metrics import mean_absolute_error, mean_squared_error
import math
  • 평균제곱오차(MSE)
    mse =  mean_squared_error(np.exp(test_data), np.exp(fc))
    mse​


  • 평균절대오차(MAE)
    mae =  mean_absolute_error(np.exp(test_data), np.exp(fc))
    mae​


  • RMSE(Root Mean Squared Error)
    - 예측값과 실제값 간의 거리를 나타내는 지표
    - 값이 작을 수록 모델의 성능이 좋다고 해석 
    rmse = math.sqrt(mean_squared_error(np.exp(test_data), np.exp(fc)))
    rmse​


  • MAPE(Mean Absolute Percentage Error)
    - 예측값과 실제값 간의 백분율 오차 평균
    mape = np.mean(np.abs(np.exp(fc) - np.exp(test_data)) / np.abs(np.exp(test_data)))
    mape * 100​


한국 증권거래소(KRX)의 주식거래일을 기준으로 1년 후 예측하기

  • 사용 라이브러리 
     - 한국증권거래소(KRX)의 주식거래일자에 대한 데이터 수집을 위한 라이브러리
     - 설치 필요 : pip install exchange_calendars
    import exchange_calendars as ecals​
  • 주식 거래일자 수집하기
    ### 원본 인덱스의 마지막 인덱스 일자 이후부터 1년치에 대한 거래일자 수집
    # 거래 시작일
    start = "2022-11-01"
    # 거래 종료일
    end = "2023-10-31"
    
    ### 한국증권거래소(KRX) code 값 : XKRX
    k = ecals.get_calendar("XKRX")
    k​


  • 시작 및 종료 기간 동안의 거래일 정보 가지고 오기 
    df =pd.DataFrame(k.schedule.loc[start:end])
    df



  • open 컬럼을 사용하기 위해 날짜 정보를 리스트에 추가하기
    date_list = []
    for i in df["open"] :
        date_list.append(i.strftime("%Y-%m-%d"))
        # print(i.strftime("%Y-%m-%d"))
    
    ### DatetimeIndex 형태로 변환하기
    date_index = pd.DatetimeIndex(date_list)
    date_index


  • 1년 후 주가 예측하기
    fc2, upper2, lower2 =forecast(len(date_index), model_fit, date_index)
    fc2


  • 상한가와 하한가의 리스트 타입 데이터를 날짜를 인덱스로 하는 시리즈 타입으로 변환하기
    - 추후 시각화 시 결과값의 인덱스와 매핑하여 그리기 위함
    lower2_series = pd.Series(lower2, index=date_index)
    upper2_series = pd.Series(upper2, index=date_index)
    
    lower2_series, upper2_series​
  • 훈련데이터 및 테스트데이터 시각화
    plt.figure(figsize=(20, 6))
    plt.title("[1년 후] 시계열 분석 결과 시각화")
    
    ### 훈련데이터 그리기
    plt.plot(train_data, label="train_data")
    
    ### 테스트 데이터 그리기
    plt.plot(test_data, label="test_data(예측 전 실제값)", c="b")
    
    ### 테스트데이터로 예측한 결과 그리기
    plt.plot(fc, label="예측결과", c="r")
    
    ### 1년 후 주가 예측 그리기
    plt.plot(fc2, label="1년 후 예측결과", c="g")
    
    ### 테스트 데이터 예측 > 상한가(상한 바운드) 하한가(하한 바운드) 그리기
    plt.fill_between(lower_series.index, lower_series,
                    upper_series, alpha=.9, color="k")
    
    ### 1년 후 예측 > 상한가(상한 바운드) 하한가(하한 바운드) 그리기
    plt.fill_between(lower2_series.index, lower2_series,
                    upper2_series, alpha=.9, color="k")
    
    plt.legend(loc="upper left")
    plt.show()
728x90
반응형

+ Recent posts