본문 바로가기

인공지능/딥러닝

[시계열 분석] 주식데이터 주가예측 - 주식흐름( 롤링rolling ), ARIMA 모델, AR(자기상관), MA(이동평균), 정상성/비정상성(차분), ADF 테스트(adfuller), ACF plot/PACF plot, ndiffs/auto_arima 함수

~ 목차 ~

 

 

주식데이터

 

기본 라이브러리


import datetime
import matplotlib.pyplot as plt

import platform
from matplotlib import font_manager, rc

 

 


"""마이너스 기호 및 한글 설정"""
### 마이너스 기호 사용 설정
plt.rcParams["axes.unicode_minus"] = True

### OS별 한글 설정
if platform.system() == "Windows":
    path = "c:/Windows/Fonts/malgun.ttf"
    font_name = font_manager.FontProperties(fname=path).get_name()
    rc("font", family=font_name)

### Mac인 경우
elif platform.system() == "Darwin":
    rc("font", family="Applegothic")

### 리눅스인 경우
elif platform.system() == "Linux":
    path = "/usr/share/fonts/NanumGothic.ttf"
    font_name = font_manager.FontProperties(fname=path).get_name()
    rc("font", family=font_name)

else:
    print("OS 확인이 불가능 합니다.")

 


 

10년치 주가 정보 수집하기 - datetime() 🐥

 


 * 증권사 : yahoo finance
 * 수집 증권 : 구글 주식(GOOG) 수집
 * 수집 기간 : 2012년 10월 31일 ~ 2022년 10월 31일까지 데이터
 * 증권사 제공 라이브러리 : yfinance 라이브러리를 제공하고 있음
 * 라이브러리 설치 필요 : pip install yfinance
 * import datetime
    -  . datetime.datetime(년, 월, 일, 시, 분 ) : 특정 날짜와 시간 생성

 

 

10년치 주가 정보 수집하기


import yfinance as yf

 

 

데이터 수집하기


### 시작 및 종료 기간 변수 설정
# - 날짜 타입으로 넣어야 합니다.

start = datetime.datetime(2012, 10, 31)
end = datetime.datetime(2022, 10, 31)
start, end

 

(datetime.datetime(2012, 10, 31, 0, 0), datetime.datetime(2022, 10, 31, 0, 0))

 


 

Google(GOOG)주식 가격 데이터 가져오기 - download() 🐥

 


 * Google(GOOG)주식 가격 데이터 가져오기
 - yf.download() : 해당 주식 데이터 가져오는 함
 - 첫번째 인자 : 가져올 주식(증권) 지정
 - start : 거래 시작일
 - end : 거래 종료일

 

 

Google(GOOG)주식 가격 데이터 가져오기


goog_data = yf.download("GOOG", start=start, end=end)
goog_data

 

 

GOOG 데이터

 

GOOG 주식 가격 데이터 - info()


goog_data.info()

 

GOOG 데이터 인포

 

 - Open : 시작가
 - High : 상한가
 - Low : 하한가
 - Close : 종가
 - Adj Close : 수정종가(분할, 배당, 배분, 신주 등이 발생한 경우 조정이 이루어짐)
 - Volume : 거래량

 

 

GOOG 주식 가격 데이터 - describe()


goog_data.describe()

 

GOOG describe

 


 

 

Google(GOOG)주식 가격 데이터 전처리 🐥

 

 

수정 종가 데이터만 추출하기


data = goog_data["Adj Close"]
data

 

"Adj Close"

 

 


 

주식흐름(롤링rolling) 확인하기 - rolling, 롤링🐥

 

 


 * 주식 흐름(이동)

  - 흐름 또는 이동이라고 칭하며, 롤링(rolling)이라는 명칭을 사용합니다.
  - 주식 흐름을 확인하기 위해서는 이동(rolling)평균이동(rolling) 표준편차 데이터가 필요함

 * 50일치에 대한 주식 흐름(이동 흐름) 확인하기
  - 50일치에 이동(rolling)평균과 표준편차 계산하기
  - interval = 50

  - 이동평균 계산하기 : 주식 가격의 흐름을 유연하게 보기 좋게 하기 위해서 사용,
                                     실제 가격 흐름과 이동평균값과 차이가 보이는 부분 : 변동성이 있는 부분
    rolmean = data.rolling(interval).mean()

  - 이동표준편차 계산하기 : 변동성의 흐름 데이터
    rolstd = data.rolling(interval).std()

 

 

50일치에 대한 주식 흐름(이동 흐름) 확인하기
 - 50일치에 이동(rolling)평균과 표준편차 계산하기


### 기간 설정 : 50일
interval = 50

### 이동평균 계산하기
# - 주식 가격의 흐름을 유연하게 보기 좋게 하기 위해서 사용
# - 실제 가격 흐름과 이동평균값과 차이가 보이는 부분 : 변동성이 있는 부분
rolmean = data.rolling(interval).mean()
rolmean

### 이동표준편차 계산하기 : 변동성의 흐름 데이터
rolstd = data.rolling(interval).std()
rolstd

 

rolmean, rolstd

 

 

시각화 하기

 


### 원본, 이동평균, 이동표준편차 시각화
plt.figure(figsize=(10, 6))
plt.title("실제, 이동평균, 이동표준편차 시각화")

### 실제 주식가격 그리기
plt.plot(data, color="blue", label="실제 원본 추가")

### 50일 간격의 이동평균 그리기
plt.plot(rolmean, color="red", label=f"이동평균 {interval}일 기준")

### 50일 간격의 이동표준편차 그리기
plt.plot(rolstd, color="black", label=f"아동표준편차 {interval}일 기준")

plt.xlabel("Date")
plt.ylabel("best")
plt.legend()

plt.show()

 

주식데이터 주식흐름 그래프

 

(시각화 해석)
 * 비정상성 : 평균이 일정하지 않고 오르락 내리락하는 불규칙 형태를 의미함
   - 시계열 분석 시에는 비정상성을 정상성으로 만들어서 분석을 진행합니다.
     → 정상성으로 만들기 위해 차수(d)라는 개념이 적용됨
     → 표준화(정규화) 시키는 개념과 유사함
   - 계절성을 나타내지 않는 것으로 보이며, 특징적 패턴을 보이고 있지 않음(특정 주기성이 없음)

 

 


 

 

시계열 데이터 분석 모델 → ARIMA 모델🐥

 

 


 [시계열 분석]

   - 시계열 분석에서 주로 사용되는 모델은 ARIMA 모델로,
   - 오랜 동안 사용되어온 통계학적 기술통계 모델

   - 시계열 분석은, 일반적으로 예측분석 중에서도 시간독립변수(X)로 사용하고, 
     다른 데이터 종속변수(Y)로 사용하여 예측하는 분석 방법임
 
  * ARIMA(Autoregressive Integrated Moving Average)
      : 시계열 분석(예측)에서 가장 널리 사용되는 모델 중 하나
      : 시계열 분석은 현 시점까지의 데이터를 이용해서 
       → 앞으로 어떤 패턴의 차트를 그릴지 예측하는 분석기법임

 * AR(Autoregressive) : "자기상관" 이라고 칭합니다.
   - 이전의 값이 이후의 값에 영향을 미치고 있는 상황(관계)

 * MA(Movign Average) : "이동평균" 이라고 칭합니다.
   - 특정 변수의 평균값이 지속적으로 증가하거나 감소하는 추세(추이)

 


 


[정상성(stationary)과 비정상성(Non-stationary)]

 * 정상성
   - 평균과 분산이 일정한 형태
 * 비정상성
   - 평균과 분산이 일정하지 않은 형태
   - 시간에 따라 평균 수준이 다르거나, 특징적 패턴(Trend)이나 계절성(Seasonality)에 영향을 받는 형태
   - 예시 데이터 형태 : 겨울에 난방비 증가, 여름에 아이스크림 판매량 증가 등등...
   - 비정상성 데이터는 예측 범위가 너무 다양하고 많기에, 고려해야할 특성들이 많음
   - 이에, 비정상성 데이터를 정상성으로 변환하여 분석을 진행하게 됨
   - 정상성으로 분석을 진행하며, 예측범위가 일정하게 줄어들고, 성능이 개선되는 효과를 발휘함

 


 

 


 [비정상성을 정상성으로 변환하는 방법들]

  - 평균의 정상화를 위한 차분 사용 (** 주로 사용되는 방법)
  - 분산의 안정화를 위한 로그 변환 사용
  - 제곱/제곱근 변환 사용
  - 이외 등등...
 
  * 차분 : 비정상성을 정상성으로 만들기 위해, 관측값들의 차이를 계산하여 사용하게 됨

 


 

시계열 정상성 확인하기 → ADF 테스트🐥

 

 


 [ADF 테스트(Augmented Dickey-Fuller Test)]

 - 시계열 데이터의 정상성 여부를 통계적은 정량 방법으로 검증하는 방법
 - 귀무가설 대립가설 따라 결정됨
 - 귀무(비정상성 데이터), 대립(정상성 데이터)
 
  * 귀무가설 vs 대립가설
   - 귀무가설 : 기존 연구이론
   - 대립가설 : 신규 연구이론(우리가 하고자 하는 것)
   - 귀무가설과 대립가설의 보편적 기준 → p-value < 0.05 (증감 가능)
     : p-value < 0.05 이면, 귀무가설 기각, 대립가설 채택
     : p-value > 0.05 이면, 귀무가설 채택 (연구 방향을 수정해야 함)
   - 시계열 분석에서는 정상성과 비정상성 데이터의 형태를 구분하는 용도로 사용됨
 
   - ADF 테스트 라이브러리 : statsmodels 패키지의 dfuller 라이브러리 사용
      → 설치 필요 : pip install statsmodels
   - adfuller() : ADF 검정을 수행하는 함수로, 주어진 시계열 데이터가 정상성(stationarity)을 가지는지를 확인하는 데 사용됩니다
  - ADF 결과의 1번째 값이  → p-value 값

 

 

 

ADF 테스트


"""ADF 라이브러리"""
from statsmodels.tsa.stattools import adfuller

""" 원본 (수정종가) 데이터를 이용해서 ADF 테스트 하기 """
result = adfuller(data.values)
result

data.values

 

 

result

 

data.values

 

 

p-value 추출하기


"""p-value 추출하기
 - ADF 결과의 1번째 값이  → p-value 값임"""
print(f"p-value : {result[1]}")

 

(시각화 해석)
 - p-value > 0.05 을 만족하지 않으므로,
   (p-value의 값이 0.827로 0.05보다 크므로.. → 이렇게 작성하면 안됨!!!)
 - 귀무가설을 기각할 수 없음. 즉, 유의미 하지 않음
 - 따라서, 구글 주식 데이터는 "비정상성" 데이터이며,
   정상성으로 만들기 위한 차분 처리가 필요함

 


 

차분 계산하기🐥

 

 


 [차분 계산하기]

* 1d(1차) 차분 계산하기
   - 1d(1차) : 1칸씩 이동하면서 이전과 현재의 차이값을 사용함
   - 사용함수 : diff()
   - 차분을 계산하게되면, 최초 또는 차분의 이동 거리에 따라서 Nan이 발생
       → Nan은 제거하고 사용함 
       사용함수 : dropna()

   - 2차 차분 : 2칸씩 아래로 이동하면서 이전과 현재의 차이값을 사용 

[차분의 차수 사용]
 - 1차 차분 : 일반적으로 시계열 곡선이 특정한 트랜드(패턴이 있음)를 가지고 있을 때 사용
 - 2차 차분 : 시간에 따라 들쑥 날쑥한 트랜드를 가지고 있을 때 사용 (랜덤한 들쑥 날쑥)


 

 

차분 설명 이미지1

 

 

1d(1차) 차분 계산하기


dff1 = data.diff().dropna()
dff1

 

1차 차분 계산하기

 

 

차분 결과 데이터 시각화하기


dff1.plot(figsize=(15, 5))

차분 결과 시각화

 

 

차분 결과 데이터를 이용하여 정상성 여부 확인하기


"""차분 결과 데이터를 이용하여 정상성 여부 확인하기
 - ADF 테스트하여, p-value < 0.05 확인하기
"""
result = adfuller(dff1.values)
print("p-value : %f" % result[1])

 

p-value : 0.000000

(해석)
- p-value < 0.05 를 만족하므로, 유의미 함
- 즉, 귀무가설을 기각하고 대립가설을 채택
- 시계열 분석에서는 차분 처리를 통해 정상성 데이터로 변환되었으며, 
- 이후, ARIMA 분석을 통해 진행이 가능한 것으로 증명 되었음
- 사용된 차분은 1차 차분을 수행하여 증명하였음

 

 

 


 

 

ARIMA 모델의 모수(하이퍼파라메터) 찾기🐥

 

 


 [ARIMA 모델의 모수(하이퍼파라메터)]

 * ARIMA 모델에서 사용되는 중요한 3개의 하이퍼파라메터
   - p, d, q
   - ARIMA(AR, MA, ARMA) 모델을 사용하기 위해서는 
      → AR(자기회귀모형, p), 차분(d), MA(이동평균모형, q) 값을 결정해야 함

 * 결정 방법
  1. ACF plot과 PACF plot을 통해 모수(하이퍼파라메터)를 결정할 수 있음
    - 현재 값이  → 과거 값과 어떤 관계(relationship)가 있는지를 보여주는 그래프로 확인
    
  2. pmdarima 라이브러리의 ndiffsauto_arima 함수를 사용하여 모수(하이퍼파라메터) 결정할 수 있음
    - 주로 auto_arima 함수를 사용함

 

 

 

(방법1) ACF plot과 PACF plot을 통해 모수(하이퍼파라메터)를 결정🐥

 


"""사용 라이브러리"""
from statsmodels.graphics.tsaplots import plot_acfplot_pacf

 

 

(방법1) 실제 원본 데이터를 이용해서 → ACF 및 PACF 시각화하기


"""실제 원본 데이터를 이용해서 → ACF 및 PACF 시각화하기"""
plot_acf(data)
plot_pacf(data)
plt.show()

 

ACF, PACF 시각화

 

(해석)
 * ACF plot 
   - ACF plot에서 막대그래프가 천천히 감소되는 것으로 보임
   - 이는 주식 데이터가 주기에 따라 일정하지 않은 비정상 데이터로 판단합니다.

 * PACF plot
   - 첫값을 제외한 1개 이후 파란 박스에 들어가면서, 그래프가 끊기는 것으로 보임
   - 이는 자기회귀모형(AR)의 결과값이 1개 이후인, 즉 p는 1인 값을 활용하는 것이 적절하다는 의미암
   - 이동평균(MA)의 값은 AR과의 차이값이 0이 되도록 하는 것이 일반적임
     따라서, MA는 1이 적절함을 의미함.

 

 

(방법1) 1차 차분데이터를 이용해서 → ACF 및 PACF 시각화하기


"""실제 원본 데이터를 이용해서 → ACF 및 PACF 시각화하기"""
plot_acf(dff1)
plot_pacf(dff1)
plt.show()

 

ACF 및 PACF 시각화

 

(결론)
 - AR(p)=1, d=1, MA(q)=1이 적절
 - 이때, MA(q)값은 AR - MA값을 사용하기도 합니다.(q=0)
 - 일반적으로 MA값은 AR - MA를 사용

 

 


 

 

 

(방법2) pmdarima 라이브러리의 ndiffsauto_arima 함수를 사용하여 모수(하이퍼파라메터) 결정🐥

 

 


"""사용 라이브러리
 - 라이브러리 설치 : pip install pmdarima """

import pmdarima as pm
from pmdarima.arima import ndiffs

 

 

(방법2) ndiffs 방법


"""ndiffs 방법 : 차수를 결정하는 함수
  - data : 원본 데이터
  - alpha : 차분 횟수를 결정하는데 사용할 p-value(유의수준) 기준
  - test : 차분 횟수를 결정하는데 사용할 테스트 방법 지정
           : 주로 adf 테스트 방법을 사용(kpass 테스트 방법도 있으나, 거의 사용안함)
  - max_d : 최대 차분 횟수를 제한함(이 범위 내에서 가장 적절한 차수를 결정)
"""
n_diffs = ndiffs(dataalpha=0.05, test="adf", max_d=6)
print(f"결정된 차수 : {n_diffs}")

 

 

결정된 차수 : 1

 

 

(방법2)  auto_arima 함수 사용


"""
 * auto_arima 함수 사용 : p, d, q 값을 모두 추출해 줍니다.
   - : 원본 데이터
   - d : 차분의 차수, 이를 지정하지 않으면 실행 시간이 매우 길어짐(기본값 None)
   - start_p, max_p : AR(p)를 찾기 위한 범위(start_p에서 max_p까지 수행
   - start_q, max_q : MA(q)를 찾기 위한 범위(start_q에서 max_q까지 수행
   - m : 계절적 특성이 있을 때 사용하는 매개변수(기본값 1)
   - seasonal : 계절성 특성을 있을 때 사용(기본값 True) → 차수를 의미함
                    : 계절성 특성이 있을 때 (True) → m의 값은 계절적 특성의 범위 차수 지정(보통 3)
                    : 계절성 특성이 없을 때 (False)→ m은 1을 보통 사용
   - stepwise : 최적의 모수를 찾기 위한 알고리즘을 사용할지 여부(기본값 True)
                (최적의 모수 찾기 알고리즘 : 힌드만-칸다카르 알고리즘이 적용됨)
   - trace: 결과 출력 여부(기본값 False)
"""

model = pm.auto_arima(
    y=data,
    d=1,
    start_p=0, max_p=3,
    start_q=0, max_q=3,
    m=1, seasonal=False,
    stepwise=True,
    trace=True
)

 

auto_arima&nbsp;함수

 

(해석)
 - auto_arima를 사용한 결과에서 최적의 모델은 ARIMA(1, 1, 0) 모형으로 결정됨
 - 모델이 설명력(결정력)이 좋을수록 AIC 값이 작아지고, 
 - 모델의 복잡도가 높아질수록 AIC값이 커짐
 - AIC값은 작을수록 좋음 → 그 ARIMA값이 Best model이 됨

 

 

 

 

 

728x90