88 lines
3.1 KiB
Python
Raw Normal View History

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import statsmodels.api as sm
import numpy as np
import quantcommon
def print_graph(values):
plt.rc('font', family='Malgun Gothic')
g = sns.relplot(data=values,
x='날짜',
y='종가',
col='종목코드',
col_wrap=5,
kind='line',
facet_kws={
'sharey': False,
'sharex': True
})
g.set(xticklabels=[])
g.set(xlabel=None)
g.set(ylabel=None)
g.fig.set_figwidth(15)
g.fig.set_figheight(8)
plt.subplots_adjust(wspace=0.5, hspace=0.2)
plt.show()
# strategy/momentum에 구현
# 모멘텀 포트폴리오. 최근 12개월 수익률이 높은 주식
def get_momentum_top(count):
qc = quantcommon.QuantCommon()
ticker_list = qc.get_ticker_list()
price_list = qc.get_price_list(interval_month=12)
price_pivot = price_list.pivot(index='날짜', columns='종목코드', values='종가')
# 가격 테이블에서 (가장 끝 행 / 가장 첫 행)으로 각 종목의 12개월 수익률을 구함
ret_list = pd.DataFrame(data=(price_pivot.iloc[-1] / price_pivot.iloc[0]) - 1,
columns=['return'])
data_bind = ticker_list[['종목코드', '종목명']].merge(ret_list, how='left', on='종목코드')
# 12개월 수익률 열 순위를 구함. 지표가 높을 수록 좋으니 ascending=False
momentum_rank = data_bind['return'].rank(axis=0, ascending=False)
# 모멘텀만 가지고 순위 측정
price_momentum = price_list[price_list['종목코드'].isin(
data_bind.loc[momentum_rank <= count, '종목코드'])]
# 해당 종목들(모멘텀 상위 count 개)의 가격 그래프 확인
# print_graph(price_momentum)
# k-ratio(모멘텀의 꾸준함 지표)
# pct_change() 함수로 각 종목의 수익률 계산하고 수익률이 곗나되지 않는 첫 번째 행은 제외
ret = price_pivot.pct_change().iloc[1:]
# 로그 누적 수익률 계산
ret_cum = np.log(1 + ret).cumsum()
# x축은 기간
x = np.array(range(len(ret)))
k_ratio = {}
for i in range(0, len(ticker_list)):
ticker = data_bind.loc[i, '종목코드']
try:
y = ret_cum.loc[:, price_pivot.columns == ticker]
reg = sm.OLS(y, x).fit()
res = float(reg.params / reg.bse)
except:
res = np.nan
k_ratio[ticker] = res
k_ratio_bind = pd.DataFrame.from_dict(k_ratio, orient='index').reset_index()
k_ratio_bind.columns = ['종목코드', 'K_ratio']
k_ratio_bind.head()
data_bind = data_bind.merge(k_ratio_bind, how='left', on='종목코드')
k_ratio_rank = data_bind['K_ratio'].rank(axis=0, ascending=False)
momentum_top = data_bind[k_ratio_rank <= count]
k_ratio_momentum = price_list[price_list['종목코드'].isin(data_bind.loc[k_ratio_rank <= count, '종목코드'])]
print_graph(k_ratio_momentum)
return momentum_top
if __name__ == '__main__':
print(get_momentum_top(20))