본문 바로가기
파이썬 (투자분석용)/Plotly 및 Dash

[python, plotly] 이동평균 그리기

by amAToRoi 2022. 2. 9.
반응형

Pandas의 DataFrame(데이터프레임) 구조를 기본으로 하며, 기초 데이터는 내가 만든 사용자함수 중 GetPriceList()를 통해 획득한 주가정보이다.

0. 준비하기

마음의 준비가 제일 중요한데...

사용자함수 구조와 사용법을 전혀 모르는 python beginner의 경우에는 이 압축파일을 다운받아서 projbullmrkt.py 파일을 작업하고 있는 폴더에 복사해두고 import 해서 사용하자. 그 다음, 바로 "2. plotly로 이동평균 그리기"로 넘어가도 무방하다. 

다음의 3줄로 삼성전자의 일(day)단위 봉차트정보(시가, 고가, 저가, 종가, 거래량 등)와 이동평균 정보를 DataFrame 형태로 구할 수 있다.

import projbullmrkt as bmk
df = bmk.GetPriceList('005930') # 종목코드가 인 삼성전자 주가정보 가져오기
df = bmk.AddMA(df, 'EMA') # 지수이동평균을 추가하기
'''
>>> df
Open High Low Close ... EMA130 MACD MACD-signal MACD-Hist
005930 ...
1990-01-03 44000 45000 43200 44800 ... 44800.000000 0.000000 0.000000 0.000000
1990-01-04 45000 45800 44800 45300 ... 45051.923077 2.243590 1.146724 1.096866
1990-01-05 45000 45300 44300 44300 ... 44797.416225 -3.063850 -0.319631 -2.744218
1990-01-06 44800 45000 44500 44500 ... 44721.337574 -4.292888 -1.380125 -2.912763
1990-01-08 44500 44900 44000 44000 ... 44572.597179 -8.678635 -2.972395 -5.706240
... ... ... ... ... ... ... ... ... ...
2022-02-09 74300 74700 74000 74700 ... 75722.009121 -173.000289 -310.116380 137.116091
2022-02-10 75600 75800 74700 75400 ... 75717.092951 -172.969655 -304.153479 131.183824
2022-02-11 75000 75500 74600 74900 ... 75704.618249 -181.613750 -298.825665 117.211914
2022-02-14 74400 74500 73100 73700 ... 75674.013391 -210.779531 -294.997572 84.218041
2022-02-15 74100 74200 73500 73800 ... 75645.402499 -236.700897 -292.462934 55.762037
[8349 rows x 14 columns]
# MACD 도 추가해둔 코드라서, MACD 관련 컬럼을 확인할 수 있다
# 지수이동평균(EMA) 관련 컬럼은 아래와 같다.
EMA5 EMA20 EMA45 EMA60 EMA120 EMA130
005930
1990-01-03 44800.000000 44800.000000 44800.000000 44800.000000 44800.000000 44800.000000
1990-01-04 45100.000000 45062.500000 45055.555556 45054.166667 45052.083333 45051.923077
1990-01-05 44721.052632 44782.514571 44792.429230 44794.352375 44797.199139 44797.416225
1990-01-06 44629.230769 44700.956983 44714.377536 44717.044687 44721.031627 44721.337574
1990-01-08 44387.677725 44531.401453 44558.526278 44563.918544 44571.978705 44572.597179
... ... ... ... ... ... ...
2022-02-09 73857.116894 74976.693359 75568.698060 75549.008831 75697.791570 75722.009121
2022-02-10 74371.411263 75017.008278 75561.363362 75544.123296 75692.869395 75717.092951
2022-02-11 74547.607508 75005.864632 75532.608433 75523.004499 75679.764116 75704.618249
2022-02-14 74265.071672 74881.496572 75452.929805 75463.233860 75647.040742 75674.013391
2022-02-15 74143.381115 74788.020708 75385.411118 75411.980291 75618.164035 75646.929217
[8349 rows x 6 columns]

반대로, 최소한 사용자함수 구조와 사용법을 겨~우 아는 "나" 이상의 수준이라면, 이 포스트에서 rolling과 ewm 메소드를 확인해보고 오자. 물론, 엄청 단순하기 때문에 몰라도 관계없다.

 

1. rolling과 ewm으로 이동평균 데이터 추가하기

데이터 처리전체 소스를 먼저 살짝 보고 다음으로 넘어갈까? (개간단)

import pandas as pd
df = pd.read_csv('https://tistory1.daumcdn.net/tistory/2670941/skin/images/sec_stockprice_amatoroi.c
sv')
df.set_index('005930', inplace=True)
df['SMA005'] = df['Close'].rolling(5, min_periods=5).mean()
df['SMA020'] = df['Close'].rolling(20, min_periods=20).mean()
df['SMA060'] = df['Close'].rolling(60, min_periods=60).mean()
df['SMA120'] = df['Close'].rolling(120, min_periods=120).mean()
df['EMA005'] = df['Close'].ewm(span=5, min_periods=5).mean()
df['EMA020'] = df['Close'].ewm(span=20, min_periods=20).mean()
df['EMA060'] = df['Close'].ewm(span=60, min_periods=60).mean()
df['EMA120'] = df['Close'].ewm(span=120, min_periods=120).mean()

101. 기초 주가데이터

이동평균을 그리기 위해서는 최소한 종가(close) 정보가 필요하다. 주가정보는 네이버에서 스크래핑했으며, 주가정보를 스크래핑하는 방법이 궁금하면 아래의 포스트에서 확인하기 바란다.

 

[python, plotly] 캔들(candlestick) 차트 그리기

★ 프로젝트: Bull Market으로 만들고 있는 사용자 함수 중, GetPriceList( ) 를 활용하여 Plotly 의 Candlestick 차트를 그리는 법을 설명하는 포스트로 GetPriceList()에 대해 정리하고 설명하는 것을 목적함 ☆.

amatoroi.tistory.com

기준 주가 데이터는 Pandas DataFrame 구조로 일자별 해당일의 종가에 해당하며, 다음의 코드를 통해 기초 데이터를 준비할 수 있다. 위 스크래핑 방법으로 네이버금융 홈페이지에서 줏어온 주가정보를 가공한 것이다.

import pandas as pd
df = pd.read_csv('https://tistory1.daumcdn.net/tistory/2670941/skin/images/sec_stockprice_amatoroi.csv')
df.set_index('005930', inplace=True)
>>> df
Close
005930
2020-02-10 59700
2020-02-11 59900
2020-02-12 60500
2020-02-13 60700
2020-02-14 61800
... ...
2022-02-09 74700
2022-02-10 75400
2022-02-11 74900
2022-02-14 73700
2022-02-15 73800
[500 rows x 1 columns]

 

이제, rolling 메소드와 ewm 메소드로 이동평균정보를 추가할 차례인데, pandas의 이들 메소드에 대해서는 아래 포스트를 확인하기 바란다.

 

[Pandas] rolling과 ewm으로 이동평균 구하기

Pandas의 rolling 및 ewm 메소드로 차트 분석에서도 사용되는 이동평균을 구해보자. 이동평균에 대해 잘 모르겠다면, 비록, 차트 분석에 맞추어 설명하였지만 이 포스트를 참조하기 바란다. 0. Data 준

amatoroi.tistory.com

 

102. rolling으로 단순이동평균 추가하기

단순이동평균을 구하기 위해서는 종가정보에 rolling 메소드만 적용하면 된다. 아주 간단하다.

df.rolling(5, min_periods=5).mean()
>>>
Close
005930
2020-02-10 NaN
2020-02-11 NaN
2020-02-12 NaN
2020-02-13 NaN
2020-02-14 60520.0
... ...
2022-02-09 73700.0
2022-02-10 74120.0
2022-02-11 74300.0
2022-02-14 74440.0
2022-02-15 74500.0
[500 rows x 1 columns]

5일 평균일 경우에는 5라고... 20일 평균이면? 20이라고 바꿔주면 끝이다.

 

103. ewm으로 지수이동평균 추가하기

지수이동평균도 단순이동평균과 마찬가지이다. ewm 메소드만 적용하면 된다.

df.ewm(span=5, min_periods=5).mean()
>>>
Close
005930
2020-02-10 NaN
2020-02-11 NaN
2020-02-12 NaN
2020-02-13 NaN
2020-02-14 60921.327014
... ...
2022-02-09 73857.116894
2022-02-10 74371.411263
2022-02-11 74547.607508
2022-02-14 74265.071672
2022-02-15 74110.047782
[500 rows x 1 columns]

 

참고: min_periods를 삽입하지 않아도 둘 모두 평균값을 계산해서 제공한다. NaN 데이터가 갖는 데이터 분석의 위험요소를 고려하면, min_periods 조건을 삽입하지 않거나, 사전/사후, 데이터 정제 과정이 필요할 것이다.

 

2. plotly로 이동평균 그리기

plotly에서 가장 손쉽게 사용할 수 있으며, 흔히 시각화 수요가 큰 그래프 오브젝트는 scatter이다. 여기서도 그래프를 그리기 위해 scatter를 사용한다. 또한, plotly 관련 포스트에서 매번 언급하지만,

★ Hint : plotly의 graph_objects는 python의 dict 타입으로, data와 layout를 선언해주면 대부분이 해결된다.

 

데이터셋을 위 2번에서 만들었다고 가정하고, plotly로 시각화하기 위한 코드만 기술하였다. 각 라인에 대한 설명은 코드블럭의 주석을 참고하면 충분하리라 판단한다. 코드 내 ⑦번에 대한 설명만 추가하자면, 이동평균은 주가 차트에 겹쳐 그리는 것이 가장 보기가 좋으므로 겹쳐그리기 위해 주가차트가 포함된 data에 주가차트와 동일한 x축으로 y값만 달리하여 20일, 60일, 120일 이동평균을 추가하였다.

import plotly.graph_objects as go # ① plotly의 graph_objects를 불러오자
dict_of_stock = dict({ # ② dict 타입으로 data를 정의한다(layout은 plotly 기본값으로 넣자)
"data": [
# 종가기준 기본 주가차트
{
"type":"scatter", # ③ 그래프 타입은 scatter 이다.
"x":df.index.to_list(), # ④ x 축은 날짜
"y":df.loc[:,'Close'].to_list(), # ⑤ y 축은 종가
"name":"삼성전자" # ⑥ 그래프 이름은 "삼성전자"로 지정했다.
}
# 지수이동평균 (20일)
,{ # ⑦
"type":"scatter",
"x":df.index.to_list(),
"y":df.loc[:,'EMA020'].to_list(),
"name":"20일평균"
}
# 지수이동평균 (60일)
,{
"type":"scatter",
"x":df.index.to_list(),
"y":df.loc[:,'EMA060'].to_list(),
"name":"60일평균"
}
# 지수이동평균 (120일)
,{
"type":"scatter",
"x":df.index.to_list(),
"y":df.loc[:,'EMA120'].to_list(),
"name":"120일평균"
}
]
})
fig = go.Figure(dict_of_stock)
fig.show()

 

3. 전체코드 및 결과물

전체코드보기
더보기
import pandas as pd
df = pd.read_csv('https://tistory1.daumcdn.net/tistory/2670941/skin/images/sec_stockprice_amatoroi.csv')
df.set_index('005930', inplace=True)
df['SMA005'] = df['Close'].rolling(5, min_periods=5).mean()
df['SMA020'] = df['Close'].rolling(20, min_periods=20).mean()
df['SMA060'] = df['Close'].rolling(60, min_periods=60).mean()
df['SMA120'] = df['Close'].rolling(120, min_periods=120).mean()
df['EMA005'] = df['Close'].ewm(span=5, min_periods=5).mean()
df['EMA020'] = df['Close'].ewm(span=20, min_periods=20).mean()
df['EMA060'] = df['Close'].ewm(span=60, min_periods=60).mean()
df['EMA120'] = df['Close'].ewm(span=120, min_periods=120).mean()
import plotly.graph_objects as go
dict_of_stock = dict({
"data": [
# 종가기준 기본 주가차트
{
"type":"scatter",
"x":df.index.to_list(),
"y":df.loc[:,'Close'].to_list(),
"name":"삼성전자"
},
# 지수이동평균 (20일)
{
"type":"scatter",
"x":df.index.to_list(),
"y":df.loc[:,'EMA020'].to_list(),
"name":"20일평균"
},
# 지수이동평균 (60일)
{
"type":"scatter",
"x":df.index.to_list(),
"y":df.loc[:,'EMA060'].to_list(),
"name":"60일평균"
},
# 지수이동평균 (120일)
{
"type":"scatter",
"x":df.index.to_list(),
"y":df.loc[:,'EMA120'].to_list(),
"name":"120일평균"
}
]
})
fig = go.Figure(dict_of_stock)
fig.show()
Apr 2020Jul 2020Oct 2020Jan 2021Apr 2021Jul 2021Oct 2021Jan 202240k50k60k70k80k90k
삼성전자20일평균60일평균120일평균
반응형

댓글