삶의 공유

[Python 금융] 알고리즘 트레이딩 - 단순이동평균전략 본문

Data Scientist/Python

[Python 금융] 알고리즘 트레이딩 - 단순이동평균전략

dkrehd 2023. 7. 31. 21:59
728x90
반응형

안녕하세요 

 

Python 으로 하는 금융 데이터 분석 내용으로 알고리즘 트레이딩 그 중에서도 단순 이동 평균 전략에 대한 소개와 예시를 통해 같이 공부하는 내용을 소개해드리고자 합니다.

 

 

단순 이동 평균 전략

 

 

단순 이동 평균 전략은 무엇을까요? 제목만 놓고 보면 이동선 평균을 활용한 전략일 거 같은데,,? 라는 감이 살짝 오시나요?

자세히 한번 알아보겠습니다.

 

이동평균선은 가장 기본적으로 사용되는 기술적 분석 지표로, 일정 기간 동안의 가격 평균을 보여 줍니다. 차트를 해석할 때 잡음(noise)을 줄여줌으로써 추세를 보다 명확하게 파악하는 데 도움이 되고, 후행성 지표이기 때문에 미래를 예측하기보다는 현재 상태를 확인하고 분석하는 해석 지표로 사용하는 것이 일반적입니다.

 

이러한 이동평균선은 장기와 단기로 나누어 전략을 수립하는데 아래의 그림과 같이

 

(a) 단기 이동평균선이 장기 이동평균선을 깨고 올라가면 매수

(b) 단기 이동평균선이 장기 이동평균선을 깨고 내려오면 매도 

 

입니다.

 

출처: https://wikidocs.net/4582

 

 

위의 전략을 파이썬 코드로 나타내 보도록 하겠습니다.

 

 

1.  EDA & 데이터 시각화

 

 

데이터는 2010~ 2019년까지의 유로 환율 데이터를 활용 할 예정입니다. 

import pandas as pd
data = pd.DataFrame(raw['EUR='])
data.rename(columns={'EUR=':'price'}, inplace = True)
data.info()

 

총 2516개의 데이터가 있고, null 값이 없는 것을 확인 할 수 있습니다.

 

데이터가 어떤 형태로 되어있는지 확인해보겠습니다.

data.head()

 

 

index로 날짜, column은 price 하나만 있는 것을 볼 수 있습니다.

 

자 이제 이동평균선의 데이터를 구해보도록 하겠습니다. 바로 rolling이라는 함수를 이용합니다.

 

data['SMA1'] = data['price'].rolling(42).mean() # 42일간의 SMA값으로 열을 생성. 처음 41개는 NaN이다
data['SMA2'] = data['price'].rolling(252).mean() # 252일간의 SMA값으로 열을 생성. 처음 251개는 NaN이다
data.tail()

 

rolling 함수에 대해 좀 더 자세히 알아보겠습니다. 아래 이미지는 

df['PageViews'].rolling(3).max()

이 코드에 대한 예시 이미지라고 보시면 되는데요, 순서대로 3개(= rolling(3)) 씩 의 최대값(max())을 리턴하고 최초의 2개 데이터는 NaN으로 처리 된 상태로 하나의 시리즈 데이터를 만들게 됩니다. 

출처 : https://datascienceparichay.com/

 

 

이제 위에서 전처리한 데이터를 시각화를 통해 나타내어 어떻게 분포가 되어 있는 지 확인해보도록 하겠습니다.

 

%matplotlib inline
import matplotlib.pyplot as plt
from pylab import mpl
plt.style.use('seaborn')
mpl.rcParams['savefig.dpi'] = 300
mpl.rcParams['font.family'] = 'serif'

data.plot(title='EUR.USD | 42 & 252 days SMAs', figsize=(10,6))

 

 

그리고 2번째로는 우리의 Position에 대해서도 시각화를 나타내보겠습니다. 위에서 말씀드린대로,

 

(a) 단기 이동평균선이 장기 이동평균선을 깨고 올라가면 매수 = 1

(b) 단기 이동평균선이 장기 이동평균선을 깨고 내려오면 매도  = -1

 

이 전략을 코드로 나타내기 위해서는 numpy의 .where함수를 활용 합니다. if 문이랑 비슷하다고 보시면 되는데 표현식 (data['SMA1'] > data['SMA2'])이 참 이면 첫번째(1)을 반환하고, 거짓 이면 -1을 반환한다는 의미입니다.

import numpy as np
data['position'] = np.where(data['SMA1'] > data['SMA2'],1,-1) #np.where()는 표현식이 참(True)인 경우 +1 생성 거짓(False)인 경우 -1을 생성하게 된다.
data.dropna(inplace=True)

이것을 시각화하여 표현 하면 아래와 같이 나타내지게 됩니다.

data['position'].plot(ylim=[-1.1, 1.1], title='Market Positioning', figsize=(10,6));

 

반응형

 

2.  전략 시뮬레이션 및 백테스팅

자 이제 전략을 수립 하였고, 그에 맞는 포지션 데이터도 처리하였으니 이제 해당 결과가 어느정도 성과가 있는지 계산해보도록 하겠습니다.

 

data['returns'] = np.log(data['price'] / data['price'].shift(1))
data['returns'].hist(bins=35, figsize=(10,6))

로그 수익률의 분포를 보면 아래와 같이 분포 되어있는 것을 볼 수 있습니다. 0을 기준으로 좌우 대칭 형태로 퍼져 있는 것을 볼 수 있습니다.

 

※ 로그 수익률을 사용하는 이유에 대해서는 하기 포스팅 참고 부탁드립니다.

https://wg-cy.tistory.com/150

 

자동매매 개발 관련 로그 수익률 사용 이유

안녕하세요 ~ 오늘은 자동 매매 개발 관련 공부를 하다가 로그 수익률을 사용하는 이유에 대해 포스팅을 해보려고 합니다. 금융 분야에서 수익률을 계산할 때 주로 로그 수익률을 사용합니다.

wg-cy.tistory.com

 

자 이제 저희 position별 데이터 기준으로 전략의 성과를 확인해볼까요?

와 단순이동평균선 전략은 28%의 수익를 내어 시장 수익률 대비 훨씬높은 성과를 내는 것을 확인 할 수 있었습니다.

data['strategy'] = data['position'].shift(1) * data['returns']
data[['returns','strategy']].sum().apply(np.exp) # 지수 함수를 로그 수익 합계에 적용해 총 성과를 계산

 

그래프를 통해 성과를 눈으로 확인해보도록 하겠습니다.

 

data[['returns','strategy']].cumsum().apply(np.exp).plot(figsize=(10, 6))

 

연 평균 수익은 아래와 같이 구할 수 있습니다.

 

np.exp(data[['returns','strategy']].mean()*252) - 1 # 연 평균 수익 (로그)

 

지금까지 단순이동평균 전략에 대해 파이썬으로 구현해보는 방법에 대해 알아보았는데, 어떠셨나요?

 

도움이 되셨길 바라며 이만 포스팅을 마치도록 하겠습니다.

 

 

 

반응형