* 본 포스트는 개인연구/학습 기록 용도로 작성되고 있습니다.


[Python] 모멘텀 전략 주식 거래 Basic


모멘텀 전략이란 자산 가격의 흐름이 최근 추세를 유지하려는 경향이 있다.는 가설을 기반으로 하는 전략이다.

최근 수익률이 좋았던 주식을 사고 그렇지 않은 주식을 피하거나, 팔거나, 공매도한다.

모멘텀을 측정하는 방법에는 여러가지가 있지만, 기본적으로는 과거 특정 기간 동안의 가격 변동을 활용한다.

아래 예에서 모멘텀은 과거 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

img_area

위 그래프는 90일간의 모멘텀을 잘 따른 5개의 종목을 보여준다.



포트폴리오 전략 활용
20일간의 주가 범위를 ATR20(Average True Range)라고 하고 Risk Factor를 10 basis point 라고 한다.

우리는 각 주식의 ATR이 미래에도 비슷하다고 가정하면 각 주식이 우리 포트폴리오의 10 basis points (0.1%), 즉 0.1 %의 일일 영향을 미칠 것으로 기대할 수 있다. 포트폴리오 내에서 해당 종목의 비중을 아래와 같이 적용한다면, 종목 위험에 기반한 포트폴리오 조정이 가능하다.

Size = AccountValue×RiskFactor / ATR20



Reference


Tags:


Back to blog