[Python pandas] 차수(order) m인 단순이동평균 구하기 (simple moving average with order m)
Python 분석과 프로그래밍/Python 데이터 전처리 2019. 12. 25. 18:01이번 포스팅에서는
(1) Yahoo Finace에서 'Apple' 회사의 2019년도 주가 데이터를 가져오기
(2) 주식 종가로 5일, 10일, 20일 단순이동평균(Simple Moving Average) 구하기
(3) 종가, 5일/10일/20일 이동평균을 seaborn을 이용해서 시각화하기
를 차례대로 해보겠습니다.
(1) Yahoo Finace에서 'Apple' 회사의 2019년도 주가 데이터를 가져오기 |
Yahoo Finance 사이트에서 쉽게 주가 데이터를 다운로드 받는 방법 중의 하나는 yfinance library를 설치해서 download() 함수를 이용하는 것입니다. Jupyter Notebook의 Cell에서 바로 !pip install yfinance 명령어로 라이브러리를 설치하고 import 해서 download() 함수로 Apple('AAPL')의 2019-01-01 ~ 2019-12-24' 일까지의 주가 데이터를 다운로드하였습니다.
# Install yfinance package. !pip install yfinance
# Import yfinance import yfinance as yf
# Get the data for the stock Apple by specifying the stock ticker, start date, and end date aapl = yf.download('AAPL','2019-01-01','2019-12-25') Requirement already satisfied: yfinance in /Users/ihongdon/anaconda3/envs/py3.6_tf2.0/lib/python3.6/site-packages (0.1.52)
Requirement already satisfied: multitasking>=0.0.7 in /Users/ihongdon/anaconda3/envs/py3.6_tf2.0/lib/python3.6/site-packages (from yfinance) (0.0.9)
Requirement already satisfied: numpy>=1.15 in /Users/ihongdon/anaconda3/envs/py3.6_tf2.0/lib/python3.6/site-packages (from yfinance) (1.17.3)
Requirement already satisfied: pandas>=0.24 in /Users/ihongdon/anaconda3/envs/py3.6_tf2.0/lib/python3.6/site-packages (from yfinance) (0.25.3)
Requirement already satisfied: requests>=2.20 in /Users/ihongdon/anaconda3/envs/py3.6_tf2.0/lib/python3.6/site-packages (from yfinance) (2.22.0)
Requirement already satisfied: pytz>=2017.2 in /Users/ihongdon/anaconda3/envs/py3.6_tf2.0/lib/python3.6/site-packages (from pandas>=0.24->yfinance) (2019.3)
Requirement already satisfied: python-dateutil>=2.6.1 in /Users/ihongdon/anaconda3/envs/py3.6_tf2.0/lib/python3.6/site-packages (from pandas>=0.24->yfinance) (2.8.1)
Requirement already satisfied: certifi>=2017.4.17 in /Users/ihongdon/anaconda3/envs/py3.6_tf2.0/lib/python3.6/site-packages (from requests>=2.20->yfinance) (2019.11.28)
Requirement already satisfied: idna<2.9,>=2.5 in /Users/ihongdon/anaconda3/envs/py3.6_tf2.0/lib/python3.6/site-packages (from requests>=2.20->yfinance) (2.8)
Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /Users/ihongdon/anaconda3/envs/py3.6_tf2.0/lib/python3.6/site-packages (from requests>=2.20->yfinance) (1.25.7)
Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /Users/ihongdon/anaconda3/envs/py3.6_tf2.0/lib/python3.6/site-packages (from requests>=2.20->yfinance) (3.0.4)
Requirement already satisfied: six>=1.5 in /Users/ihongdon/anaconda3/envs/py3.6_tf2.0/lib/python3.6/site-packages (from python-dateutil>=2.6.1->pandas>=0.24->yfinance) (1.13.0)
[*********************100%***********************] 1 of 1 completed aapl.head() [Out]:
|
(2) 주식 종가(Close)로 5일, 10일, 20일 이동평균 구하기 |
Apple 회사의 주식 데이터 중에서 '종가(Close)'를 대상으로 이동평균을 구해보겠습니다.
aapl.Close[:10] [Out]: Date
2018-12-31 157.740005
2019-01-02 157.919998
2019-01-03 142.190002
2019-01-04 148.259995
2019-01-07 147.929993
2019-01-08 150.750000
2019-01-09 153.309998
2019-01-10 153.800003
2019-01-11 152.289993
2019-01-14 150.000000
Name: Close, dtype: float64
|
이동평균은 시계열 데이터 내의 잡음(noise)을 제거하는 데이터 전처리, 혹은 계절성이 존재하는 시계열 데이터에서 계절성 부분을 빼고 장기 추세 요인(trend factor)나 중기 순환/주기 요인(cycle factor)를 보려고 할 때 많이 사용합니다. 시계열 데이터 예측(forecasting)에도 사용하구요.
이동평균은 가중치를 고려 안하는 (즉, 모든 값의 가중치가 같다고 가정하는) 단순이동평균(Simple Moving Average, SMA)과, 가중치를 부여하는 가중이동평균(Weighted Moving Average, WMA)가 있는데요, 이번 포스팅에서는 단순이동평균(SMA)에 대해서 다룹니다.
차수(order) m 인 단순이동평균(Simple Moving Average with Order m) 은 다시 중심이동평균(Centered Moving Average)와 추적이동평균(Trailing Moving Average)로 구분할 수 있습니다 (아래의 개념 비교 이미지를 참고하세요). 이번 포스팅에서는 python pandas에서 사용하고 있는 추적이동평균 개념으로 window 5일, 10일, 15일의 단순이동평균을 계산해 보았습니다.
이동평균을 구하는 두 가지 방법으로, for loop 반복문과 numpy.mean() 을 이용하는 수작업 방법과, pandas 라이브러리의 rolling(window=m).mean() 함수를 이용하는 좀더 편리한 방법을 소개하겠습니다.
(2-1) for loop 반복문과 numpy.mean() 을 이용한 5일 이동평균 구하기
import numpy as np for i in range(0, 6): stock_close_5days = aapl.Close[i:(i+5)] sma_5d = np.mean(stock_close_5days) print('SMA(5 Days Window) of', aapl.Close.index[i+4].date(), ':', sma_5d)
|
(2-2) pandas 의 rolling(window=5).mean() 함수를 이용한 5일 이동평균 구하기
차수 m인 이동평균(trailing moving average)을 구하면 처음 시작부분에 m-1 개의 결측값이 발생합니다.
import pandas as pd sma_5d = aapl.Close.rolling(window=5).mean() sma_5d[:10]
|
이제 pandas에서 이동평균 구하는 rolling() 함수를 알았으니, 차수(order, window)가 5일, 10일, 20일인 단순 추적 이동평균(simple trailing moving average)을 구해보겠습니다.
# simple trailing moving average with window 5 days/ 10 days/ 20 days df_sma = pd.DataFrame({ 'close': aapl.Close , 'sma_5d': aapl.Close.rolling(window=5).mean() , 'sma_10d': aapl.Close.rolling(window=10).mean() , 'sma_20d': aapl.Close.rolling(window=20).mean() })
# top first 25 rows df_sma[:25] [Out]:
|
(3) 종가, 5일/10일/15일 이동평균을 seaborn을 이용해서 시각화하기 |
trailing moving average 이동평균을 구하면 차수 m-1 만큼의 결측값(NaN) 이 생깁니다. 시각화를 위해서 결측값이 있는 행은 삭제하도록 하겠습니다.
df_sma.dropna(axis=0, inplace=True) df_sma.head(10) [Out]:
|
Matplotlib 을 이용해서 '종가(Close)', '5일 이동평균', '10일 이동평균', '20일 이동평균' 선 그래프를 그려보겠습니다.
# line plot with moving average of 5 window, 10 window, 20 window import matplotlib.pyplot as plt plt.figure(figsize=(15, 10)) plt.plot(df_sma.index, df_sma.close, 'y-', label='close_price') plt.plot(df_sma.index, df_sma.sma_5d, 'b-', label='sma_5d') plt.plot(df_sma.index, df_sma.sma_10d, 'r-', label='sma_10d') plt.plot(df_sma.index, df_sma.sma_20d, 'g-', label='sma_20d') plt.legend() plt.show() |
위의 1년치 시계열 그래프가 서로 겹쳐보여서 잘 구분이 안되네요. 그래서 2월달의 20개 관측치만 선택해서 다시 시계열 선 그래프를 그려보겠습니다.
아래의 그래프에서 확인할 수 있는 바와 같이, 이동평균 값은 원래의 주식 종가(Close) 값보다 후행적으로 쫓아가고(trailing) 있습니다. 그리고 차수(order, rolling window)가 클 수록 후행적으로 쫒아가는 정도가 더 느림을 알 수 있습니다.
plt.figure(figsize=(15, 10)) plt.plot(df_sma.index[:20], df_sma.close[:20], 'yo-', label='close_price') plt.plot(df_sma.index[:20], df_sma.sma_5d[:20], 'bo-', label='sma_5d') plt.plot(df_sma.index[:20], df_sma.sma_10d[:20], 'ro-', label='sma_10d') plt.plot(df_sma.index[:20], df_sma.sma_20d[:20], 'go-', label='sma_20d') plt.legend() plt.show()
|
많은 도움이 되었기를 바랍니다.
이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. :-)