* 본 포스트는 개인연구/학습 기록 용도로 작성되고 있습니다.
[Python] 모멘텀 전략 주식 거래 Basic
By MK on July 21, 2019
모멘텀 전략이란 자산 가격의 흐름이 최근 추세를 유지하려는 경향이 있다.
는 가설을 기반으로 하는 전략이다.
최근 수익률이 좋았던 주식을 사고 그렇지 않은 주식을 피하거나, 팔거나, 공매도한다.
모멘텀을 측정하는 방법에는 여러가지가 있지만, 기본적으로는 과거 특정 기간 동안의 가격 변동을 활용한다.
아래 예에서 모멘텀은 과거 90일간의 주가 흐름과 방향성의 회귀분석 R^2 값에 의해 계산되고 그 결과의 기울기(slope)를 분석한다.
필요한 라이브러리
from datetime import datetime
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
plt.rcParams["figure.figsize"] = (10, 6) # (w, h)
plt.ioff()
종가데이터는 FinanceDataReader
를 사용하였다.
pip install -U finance-datareader
import FinanceDataReader as fdr
fdr.__version__
자세한 내용은 가이드 페이지 참고 https://financedata.github.io/posts/finance-data-reader-users-guide.html
1. 종가데이터 가져오기
우선 tickers라는 리스트 변수에 구하고자하는 주식 종목들을 넣어둔다. stocks에는 tickers의 종가데이터를 넣는다.
# 한국거래소 상장종목 전체
df_krx = fdr.StockListing('KRX')
print(df_krx.head())
Symbol | Name | Sector | Industry |
---|---|---|---|
001250 | GS글로벌 | 상품 종합 도매업 | 수출입업(시멘트,철강금속,전기전자,섬유,기계화학),상품중개,광업,채석업/하수처리 서… |
082740 | HSD엔진 | 일반 목적용 기계 제조업 | 대형선박용엔진,내연발전엔진 |
001390 | KG케미칼 | 기초 화학물질 제조업 | 콘크리트혼화제, 비료, 친환경농자재, 수처리제 |
011070 | LG이노텍 | 전자부품 제조업 | 기타 전자부품 제조업 |
010060 | OCI | 기초 화학물질 제조업 | 타르제품,카본블랙,무수프탈산,농약원제,석탄화학제품,정밀화학제품,플라스틱창호재 제조,판매 |
종목 셋팅하기
# 10개의 종목을 추출한다.
tickers = df_krx.Symbol[:10]
# 원하는 종목을 셋팅할 수도 있다.
# tickers = ['005930','079160','068270']
print(tickers)
0 | 001250 |
1 | 082740 |
2 | 001390 |
3 | 011070 |
4 | 010060 |
5 | 001740 |
6 | 096770 |
7 | 011810 |
8 | 024070 |
9 | 011420 |
종가 가져오기
stocks = pd.DataFrame()
for ticker in tickers:
# 종가데이터를 가져온다.
data_temp = fdr.DataReader(ticker, '20140101','20190630')
data_temp = data_temp[['Close']]
# 항목명을 종목명으로 교체
# list형태로 전환
stock_nm = []
stock_nm.append(ticker)
data_temp.columns = stock_nm
# concat 옆으로 이어 붙이기
stocks = pd.concat([stocks,data_temp],axis=1)
print(stocks.head())
Date | 001250 | 082740 | 001390 | 011070 | 024070 | 011420 | |
---|---|---|---|---|---|---|---|
2014-01-02 | 6272 | 5912 | 16550 | 83100 | 4805 | 1940 | |
2014-01-03 | 6286 | 5766 | 17000 | 83600 | 4805 | 1990 | |
2014-01-06 | 6229 | 5731 | 17400 | 82900 | 4800 | 2000 | |
2014-01-07 | 6279 | 5836 | 17100 | 83700 | 4756 | 2020 |
# 과거 데이터순으로 정렬한다(날짜 오름차순(DataReader default))
stocks = stocks.sort_index(ascending=True)
2. 모멘텀 함수 생성
아래에서 우리는 원하는 종목(tikers)들의 데이터를 stocks에서 꺼내서 모멘텀을 구할 것이다.
모멘텀을 계산하는 함수 코드이다.
from scipy.stats import linregress
def momentum(closes):
returns = np.log(closes)
x = np.arange(len(returns))
slope, _, rvalue, _, _ = linregress(x, returns)
return ((1 + slope) ** 252) * (rvalue ** 2) # annualize slope and multiply by R^2
momentums = stocks.copy(deep=True)
for ticker in tickers:
momentums[ticker] = stocks[ticker].rolling(90).apply(momentum, raw=False)
3. 결과 확인
모멘텀이 최대치인 5개 종목을 추출 한다.
plt.figure(figsize=(12, 9)) plt.xlabel(‘Days’) plt.ylabel(‘Stock Price’)
** 모멘텀값이 최고인 5개 종목 **
bests = momentums.max().sort_values(ascending=False).index[:5]
for best in bests:
end = momentums[best].index.get_loc(momentums[best].idxmax()) # 모멘텀이 최고인 시점
rets = np.log(stocks[best].iloc[end - 90 : end]) # 모멘텀이 최고시점 이전 90일간의 log 종가
x = np.arange(len(rets))
slope, intercept, r_value, p_value, std_err = linregress(x, rets) # 회귀함수
try:
# 주가 그래프
plt.plot(np.arange(180), stocks[best][end-90:end+90]) # 모멘텀 최고 시점 전후 90일 총 180일의 주가
# 모멘텀 그래프
plt.plot(x, np.e ** (intercept + slope*x)) # 회귀함수 결과
except:
# 모멘텀 최고 시점의 전후 90 데이터가 부제하여 그래프 오류 날 수 있음.-> 그릴수 없는 종목은 skip
# 5개가 모두 그려지지 않았다면 수집 데이터 기간을 늘려보기
continue
위 그래프는 90일간의 모멘텀을 잘 따른 5개의 종목을 보여준다.
포트폴리오 전략 활용
20일간의 주가 범위를 ATR20(Average True Range)라고 하고 Risk Factor를 10 basis point 라고 한다.
우리는 각 주식의 ATR이 미래에도 비슷하다고 가정하면 각 주식이 우리 포트폴리오의 10 basis points (0.1%), 즉 0.1 %의 일일 영향을 미칠 것으로 기대할 수 있다. 포트폴리오 내에서 해당 종목의 비중을 아래와 같이 적용한다면, 종목 위험에 기반한 포트폴리오 조정이 가능하다.
Size = AccountValue×RiskFactor / ATR20