CAP02 에서 주식 벡테스팅 라이브러리인 Finterstella 에 관한 간단한 소개와 사용법을 했다. 이번 포스트는 Finterstella를 이용한 첫 번째 기술적 투자 전략, Moving Average Convergence Divergence (MACD)이다. CAP01에서 소개한 이동평균선 (MA)을 이용한 전략이다. 한 가지 다른 점은 기본적인 MA가 아닌 지수 이동 평균선 (EMA)을 이용한다는 것이다. EMA는 MA와 다르게 현재에 가까운 값일수록 가중치를 부여한다. 자세한 설명은 investopedia link를 참조하겠다. https://www.investopedia.com/ask/answers/122314/what-exponential-moving-average-ema-formula-and-how-ema-calculated.asp
How Is the Exponential Moving Average (EMA) Formula Calculated?
Calculating exponential moving averages (EMAs) and constructing moving average ribbons from them helps traders and analysts spot market trends.
www.investopedia.com
!pip install finterstellar import finterstellar as fs
이제 시작해보겠다. 라이브러리를 설치하고 import 한다
def get_data(stock,start,end): df = fs.get_price(stock,start_date=start,end_date=end) fs.draw_chart(df,right=stock) return df df = get_data('SBUX','2020-01-01','2021-10-23')
주식 데이터를 가져오는 get_data 함수를 정의하고, 스타벅스 2020-01-01부터 2021-10-23까지 종가를 불러와보겠다.
dataframe을 확인하면 위와 같이 날짜를 index로 하고 SBUX 칼럼에 가격 데이터가 들어가 있다.
이제 MACD 전략을 설명하겠다.
- MACD = EMA(short) - EMA(Long)
- MACD signal = EMA(MACD,9)
- MACD oscillator = MACD - MACD signal
MACD 란 짧은 EMA에서 긴 EMA를 뺀 것이다. 이 값이 양수이면 현재 상승추세임을 의미하고 하락이면 하락 추세임을 의미한다. MACD signal 은 MACD를 다시 9일 EMA로 스무딩 한 것이다. MACD oscillator는 MACD에서 MACD signal을 뺀 값이다. 우린 MACD oscillator 가 양수이면 매수, 음수이면 매도하는 전략을 사용할 것이다. 지금 강력하게 오르고있는 것은 계속 오를것이다, 내리고 있는것은 내릴 것이다로 가정하는 것이므로 기본적으로 추세에 배팅하는 모멘텀 전략인셈이다. 아래 그림을 보면 좀 더 이해가 편하다.
fs.macd(df)
Finterstella 내부에 이미 macd 함수가 내장되어있어서, 위와 같은 코드 한 줄로 macd 값을 가져올 수 있다. EMA(short), EMA(Long), Signal(term)의 기본 세팅은 12,26,9 일이다. MACD가 만들어진 시점이 주6일제라서 그런것이다. https://money.stackexchange.com/questions/22461/rationale-behind-using-12-26-and-9-to-calculate-macd
fs.draw_chart(df,right=['macd','macd_signal','macd_oscillator'])
fs.draw_chart를 이용해서 macd, macd_signal, macd_oscillator를 그려봤다. 초록색이 양수이면 long 음수이면 short하는 게 우리의 전략이다. 이제 전략을 만들어보자!
fs.indicator_to_signal(df, factor='macd_oscillator',buy=0,sell=0) df
fs.indicator_to_signal로 buy/sell trading signal을 만들 수 있다. factor는 macd_oscillator 고되고, buy sell을 각각 0으로 세팅하면, 기본적으로 양수는 long 음수는 short을 하게 된다.
dataframe을 확인해보면 trade 란 칼럼이 새로 생긴 것을 볼 수 있다. zero 면 hold buy는 long sell 은 short를 뜻한다.
fs.position(df) fs.draw_chart(df, right='position_chart',left='macd_oscillator')
이제 트레이딩 signal에 따른 주식 보유 상태 (position)을 산출한다. 말로 하면 헷갈리니 포지션 차트와 macd_oscillator를 한 번에 시각화해보겠다.
주가가 요동쳐서 그런지 트레이딩을 참 많이 했다. Position 차트는 단순 1,0의 값만 가지며(오른쪽 axis) 1 이면 보유 상태, 0 이면 보유하지 않은 상태로 볼 수 있다. 여기서 조금 헷갈리는 게 있다. 만약 한 주씩 Long Long Long Short을 했다면 마지막 short에서는 가진 주식을 다 파는가?? 내 생각엔 1주만 팔 것 같은데 이것은 좀 더 찾아보겠다. (혹시 알고 계신 분 있으면 댓글 부탁합니다^^)
fs.evaluate(df,cost=.001) # cost: 매매비용 fs.performance(df,rf_rate=.01) # rf_rate: 무위험이자율 fs.draw_trade_results(df)
마지막으로 해당 전략을 평가해보겠다.
- fs.evaluate 함수로 dataframe 안에 각종 평가 지표 칼럼을 집어넣는다. (cost 에는 매매비용 % 를 넣는다)
- fs.performance로 성과지표 요약을 출력할 수 있다. (rf_rate는 무위험 이자 % 를 넣는다)
- fs.draw_trade_results로 수익률을 시각화할 수 있다.
- CAGR: 3.43% 연평균 수익률이 3.43%이다. 물가보단 높다...
- Accumulated return: 6.27% 투자 기간 동안 누적 수익률이다.
- Average return: 0.30% 건별 수익률을 0.3%이다.
- Benchmark return : 28.20% 개별종목일 경우 buy and hold 수익률을 뜻한다. MACD의 4배가 넘는다.
- Number of trades: 20 트레이딩 횟수이다
- Number of win: 8 트레이딩 중에 수익이 난 경우이다
- Hit ratio: 40.00% win/number of trade
- Investment period: 1.8 yrs
- Sharpe ratio: 0.09 샤프지수 (https://www.investopedia.com/terms/s/sharperatio.asp)
- MDD: -16.54% 최대 낙폭이다
- Benchmark MDD: -39.91% 벤치마크 최대 낙폭이다
누적 6.27%를 먹었고, 벤치마크 MDD 보다 적은 MDD를 보였다. 하지만 buy and hold 가 4배 잘 나온 거를 보면 뭔가 좀 아쉬워 보인다.
개별 주 말고 미국 시장 전체를 대표하는 S&P 지수에 같은 전략을 적용하면 어떨까? 현실적으로 모든 종목을 매수하지는 못하니, SPY라는 S&P 지수를 따라 하는 ETF를 가져와서 시뮬레이션해보겠다.
df = get_data('SPY','2020-01-01','2021-10-23') fs.macd(df) fs.indicator_to_signal(df, factor='macd_oscillator',buy=0,sell=0) fs.position(df) fs.draw_chart(df, right='position_chart',left='macd_oscillator') fs.evaluate(df,cost=.001) fs.performance(df,rf_rate=.01) fs.draw_trade_results(df)
지금까지 모든 코드를 한 블록에 써보았다.
- CAGR: 11.37%
- Accumulated return: 21.46%
- Average return: 0.80%
- Benchmark return : 39.48%
- Number of trades: 22
- Number of win: 10
- Hit ratio: 45.45%
- Investment period: 1.8 yrs
- Sharpe ratio: 0.62
- MDD: -11.22%
- Benchmark MDD: -34.10%
생각보다 나쁘진 않다? 벤치마킹보다 MDD 방어도 잘한다. 그렇다면 코로나 이전도 해보자. 2018-01 - 2020-01까지 결과이다.
- CAGR: 5.84%
- Accumulated return: 11.98%
- Average return: 0.52%
- Benchmark return : 19.75%
- Number of trades: 22
- Number of win: 10
- Hit ratio: 45.45%
- Investment period: 2.0 yrs
- Sharpe ratio: 0.49
- MDD: -10.10%
- Benchmark MDD: -20.18%
이번에도 나쁘진 않다. 신기하게도 이렇게 차트만 보고 투자하는 전략이 S&P에 대해서 어느 정도의 수익을 보장해준다. 개인적인 해석을 덧붙인다면 개별주의 경우 회사에 관한 이슈가 주가에 영향을 많이 미치기 때문에 단순히 가격 데이터만 보고 투자를 하는것에는 무리가 있어보인다. 하지만 여러 주식이 합쳐져 한 나라의 경제 지표를 대변하는 S&P 등의 Index 일 경우에는 글로벌한 이슈를 제외하면 어느정도 추세라는게 존재하고, 기술적 전략을 잘 쓰면 가능하지 않을까 라는 기대를 해본다. 시장은 완벽히 효율적이지는 않지만 큰 수의법칙에서는 어느정도는 효율적이다 라고 생각해보았다.
*Referece
http://www.kyobobook.co.kr/product/detailViewKor.laf?ejkGb=KOR&mallGb=KOR&barcode=9791162244753#N)
미국 주식으로 시작하는 슬기로운 퀀트투자 - 교보문고
주린이+코알못도 파이썬으로 쉽게 따라 하는 퀀트투자 레시피 | 필요한 것은 이 책과 컴퓨터 1대뿐! 퀀트머신으로 따라 하며 배우는 미국 주식 퀀트투자 방법 이 책은 프로그래밍 학습 경험이 없
www.kyobobook.co.kr
'투자' 카테고리의 다른 글
퀀트킹 백테스터01 마법공식 백테스팅 (1) | 2022.01.10 |
---|---|
Python05 기술적투자04 Envelope 전략 (0) | 2021.12.03 |
Python04 기술적투자03 RSI 전략 (4) | 2021.10.31 |
Python02 기술적투자01 라이브러리 소개 (0) | 2021.10.22 |
Python01 Financial data reader 와 pandas 를 이용한 이동평균선 구하기 (0) | 2021.07.23 |