[python] 이동평균선 만들기
파이썬을 이용한 이동평균선 만들기
단순 이동 평균 (MA 혹은 SMA: Simple Moving Average)
단순 이동 평균 (SMA)은 최근 가격을 더한 다음 해당 수치를 계산 평균의 기간 수로 나누어 계산 한 산술 이동 평균입니다. 예를 들어, 여러 기간 동안 유가 증권의 종가를 더한 다음 이 합계를 동일한 기간 수로 나눌 수 있습니다. 단기 평균은 기본 증권의 가격 변동에 빠르게 반응하는 반면 장기 평균은 반응 속도가 느립니다.
소스코드
import pandas as pd
class MovingAverage():
def __init__(self):
super().__init__()
def cal_sma(self):
data = [
['2023-12-18', 208500, 212000, 207000],
['2023-12-19', 209000, 212500, 207500],
..........
['2024-01-17', 186000, 197000, 186000],
['2024-01-18', 186700, 188700, 184400],
]
df = pd.DataFrame(data)
df.columns = ['Date', 'Close', 'High', 'Low']
# 5일선
df['ma_5'] = df['Close'].rolling(5).mean()
## 20일선
df['ma_20'] = df['Close'].rolling(20).mean()
if __name__ == "__main__":
print(__name__)
cal = MovingAverage()
cal.cal_sma()
결과
Date Close High Low ma_5 ma_20
0 2023-12-18 208500 212000 207000 NaN NaN
1 2023-12-19 209000 212500 207500 NaN NaN
2 2023-12-20 209000 213500 209000 NaN NaN
3 2023-12-21 207000 210000 205000 NaN NaN
4 2023-12-22 178500 208500 177000 202400.0 NaN
5 2023-12-26 181200 185800 180700 196940.0 NaN
6 2023-12-27 189400 190500 182100 193020.0 NaN
7 2023-12-28 193600 194800 187200 189940.0 NaN
8 2024-01-02 195800 197900 191400 187700.0 NaN
9 2024-01-03 194800 199200 194100 190960.0 NaN
10 2024-01-04 200500 202500 192300 194820.0 NaN
11 2024-01-05 201500 211000 199100 197240.0 NaN
12 2024-01-08 201000 202000 196800 198720.0 NaN
13 2024-01-09 206500 208500 202000 200860.0 NaN
14 2024-01-10 203000 208000 199400 202500.0 NaN
15 2024-01-11 201000 205500 201000 202600.0 NaN
16 2024-01-12 201500 202500 199100 202600.0 NaN
17 2024-01-15 204000 206000 200500 203200.0 NaN
18 2024-01-16 195000 204000 195000 200900.0 NaN
19 2024-01-17 186000 197000 186000 197500.0 198340.0
20 2024-01-18 186700 188700 184400 194640.0 197250.0
지수 이동 평균 (EMA : Exponetial Moving Average)
보다 최근의 값에 가중치를 두면서 이동평균을 계산하는 방법입니다.
금일의 지수이동평균 = (금일 종가 * EP) + (전일의 지수 이동평균 * (1 - EP))
EP(평활 계수 : Exponential Percentage) = 2 / (기간 + 1)
소스코드
def cal_ema(self):
..........
# 5일선
df['ema_5'] = df['Close'].ewm(5).mean()
## 20일선
df['ema_20'] = df['Close'].ewm(20).mean()
결과
Date Close High Low ema_5 ema_20
0 2023-12-18 208500 212000 207000 208500.000000 208500.000000
1 2023-12-19 209000 212500 207500 208772.727273 208756.097561
2 2023-12-20 209000 213500 209000 208862.637363 208841.395718
3 2023-12-21 207000 210000 205000 208263.040238 208346.828688
4 2023-12-22 178500 208500 177000 199969.576435 201781.242754
5 2023-12-26 181200 185800 180700 195266.143534 197919.467194
6 2023-12-27 189400 190500 182100 193909.969724 196517.245505
7 2023-12-28 193600 194800 187200 193842.652199 196087.377395
8 2024-01-02 195800 197900 191400 194247.300356 196048.871539
9 2024-01-03 194800 199200 194100 194357.159892 195894.838608
10 2024-01-04 200500 202500 192300 195540.187938 196422.848394
11 2024-01-05 201500 211000 199100 196658.968651 196968.402405
12 2024-01-08 201000 202000 196800 197457.067268 197377.151745
13 2024-01-09 206500 208500 202000 199091.525025 198254.891119
14 2024-01-10 203000 208000 199400 199788.152453 198690.276495
15 2024-01-11 201000 205500 201000 200001.676087 198893.245995
16 2024-01-12 201500 202500 199100 200263.183738 199113.452512
17 2024-01-15 204000 206000 200500 200910.292525 199511.572206
18 2024-01-16 195000 204000 195000 199893.414614 199156.038787
19 2024-01-17 186000 197000 186000 197515.828427 198150.634417
20 2024-01-18 186700 188700 184400 195673.136289 197300.058313
가중 이동 평균 (WMA: Weighted Moving Average)
현재에 가까운 가격 데이터가 과거의 가격 데이터보다 더 중요하다는 전제로 합니다.
선형 가중 이동평균(Linearly Weighted Moving Average)을 보면 동일한 값 1(4일 전) 2(3일 전) 3(2일 전) 4(1일 전) 5(금일)의 가격이라면 금일의 종가에 가중치를 부여하여 11 + 22 + 33 + 44 + 5*5 = 55
계산에서 사용된 값 (1 + 2 + 3 + 4 + 5 = 15)
55 / 15 = 3.67을 5개의 값의 평균으로 사용하는 것입니다.
WMA의 문제점은 여전히 이용한 기간 값의 가격 데이터만을 평균으로 반영하기 때문에 실제로는 잘 사용되지 않습니다.
소스코드
def cal_wma(self):
..........
# 5일선
weights = np.arange(1, 6)
df['wma_5'] = df['Close'].rolling(5).apply(lambda prices: np.dot(prices, weights) / weights.sum(), raw=True)
# 20일선
weights = np.arange(1, 21)
df['wma_20'] = df['Close'].rolling(20).apply(lambda prices: np.dot(prices, weights) / weights.sum(), raw=True)
결과
Date Close High Low wma_5 wma_20
0 2023-12-18 208500 212000 207000 NaN NaN
1 2023-12-19 209000 212500 207500 NaN NaN
2 2023-12-20 209000 213500 209000 NaN NaN
3 2023-12-21 207000 210000 205000 NaN NaN
4 2023-12-22 178500 208500 177000 198266.666667 NaN
5 2023-12-26 181200 185800 180700 191200.000000 NaN
6 2023-12-27 189400 190500 182100 188686.666667 NaN
7 2023-12-28 193600 194800 187200 188880.000000 NaN
8 2024-01-02 195800 197900 191400 190833.333333 NaN
9 2024-01-03 194800 199200 194100 193200.000000 NaN
10 2024-01-04 200500 202500 192300 196380.000000 NaN
11 2024-01-05 201500 211000 199100 198606.666667 NaN
12 2024-01-08 201000 202000 196800 199860.000000 NaN
13 2024-01-09 206500 208500 202000 202453.333333 NaN
14 2024-01-10 203000 208000 199400 203166.666667 NaN
15 2024-01-11 201000 205500 201000 202666.666667 NaN
16 2024-01-12 201500 202500 199100 202300.000000 NaN
17 2024-01-15 204000 206000 200500 202766.666667 NaN
18 2024-01-16 195000 204000 195000 200033.333333 NaN
19 2024-01-17 186000 197000 186000 195066.666667 197890.476190
20 2024-01-18 186700 188700 184400 191466.666667 196781.904762