1. 우선주와 보통주의 괴리율 계산¶
In [1]:
from datetime import datetime # 오늘날짜 가져올때 사용
import FinanceDataReader as fdr
df_krx = fdr.StockListing('KRX')
df_krx['Name'] = df_krx['Name'].str.strip()
In [2]:
#### 우선주 목록 만들기
exception = ['미래에셋대우', '연우', '이오플로우']
ps_list = [s for s in df_krx['Name'] if (s.endswith('우') | s.endswith('우B')) & (s not in exception)]
df_ps = df_krx.loc[df_krx['Name'].isin(ps_list), ['Symbol', 'Market', 'Name']]
import re
# '~우'로 끝나는 종목은 '우' 앞자리 까지만 가져옴
df_ps.loc[df_ps['Name'].str.endswith('우'), '보통주명'] = df_ps['Name'].str[:-1]
# '~우B'로 끝나는 종목은 '우B' 앞자리 까지만 가져옴
df_ps.loc[df_ps['Name'].str.endswith('우B'), '보통주명'] = df_ps['Name'].str[:-2]
# 정규표현식으로 숫자만 제거
df_ps['보통주명'] = df_ps['보통주명'].map(lambda s: re.sub('\d+', '', s)).str.strip()
# 우선주에서 본주의 이름이 축약되어 있는 예외 케이스 수정
df_ps.loc[df_ps['보통주명']=='남선알미', '보통주명'] = '남선알미늄'
df_ps.loc[df_ps['보통주명']=='삼성중공', '보통주명'] = '삼성중공업'
df_ps.loc[df_ps['보통주명']=='코리아써', '보통주명'] = '코리아써키트'
In [3]:
#### 우선주와 보통주 매핑
import pandas as pd
df_krx = df_krx[['Symbol', 'Name', 'Sector']].rename(columns={'Symbol':'보통주_ticker', 'Name':'보통주명'})
df_ps = pd.merge(df_ps.rename(columns={'Symbol':'우선주_ticker', 'Name':'우선주명'}), df_krx, how='left', on='보통주명')
df_ps.head()
Out[3]:
In [4]:
#### 가격 데이터 가져오기
date = '20210618'
for idx in range(len(df_ps)):
try:
df_ps.loc[idx, '우선주_가격'] = fdr.DataReader(symbol=df_ps.loc[idx, '우선주_ticker'], start=date, end=date)['Close'].iat[0]
except:
df_ps.loc[idx, '우선주_가격'] = 0
try:
df_ps.loc[idx, '보통주_가격'] = fdr.DataReader(symbol=df_ps.loc[idx, '보통주_ticker'], start=date, end=date)['Close'].iat[0]
except:
df_ps.loc[idx, '보통주_가격'] = 0
In [5]:
#### 가격이 안들어간 케이스가 있는지 확인
df_ps[(df_ps['우선주_가격']==0) | (df_ps['보통주_가격']==0)]
Out[5]:
In [6]:
# 괴리율 = 1 - 우선주가격/보통주가격
df_ps['괴리율'] = round(1 - df_ps['우선주_가격']/df_ps['보통주_가격'], 4)*100
df_ps = df_ps[['우선주_ticker', '우선주명', '보통주_ticker', '보통주명', '우선주_가격', '보통주_가격', '괴리율']]
df_ps = df_ps.sort_values('괴리율', ascending=False).reset_index(drop=True)
In [7]:
df_ps.head(20)
Out[7]:
- 괴리율 TOP 20 구성종목은 지난주와 차이가 없음 - 지난주 목록
- 두산퓨얼셀과 아모레퍼시픽의 순위가 바뀌었는데 두산퓨얼셀 주가가 크게 올랐기 때문임
2. 괴리율이 큰 종목의 2021년 주가 추이¶
- 여기서는 주가 데이터를 가져올 때 pykrx 패키지를 사용하는데 FinanceDatareader를 사용해도 무방함
- [python] pykrx로 주가 데이터 가져오기
- [python] 볼린저 밴드(Bollinger bands) - (1) 볼린저밴드 그리기
- [python] 볼린저 밴드(Bollinger bands) - (2) %b와 밴드폭(BandWidth)
- [python] 볼린저 밴드(Bollinger Bands) - (3) MFI(현금흐름지표)
In [9]:
import FinanceDataReader as fdr
fdr.DataReader(symbol='051900', start=date, end=date)
Out[9]:
In [10]:
from pykrx import stock
stock.get_market_ohlcv_by_date(fromdate=date, todate=date, ticker='051900')
Out[10]:
In [11]:
from pykrx import stock
import pandas as pd
from datetime import datetime # 오늘날짜 가져올때 사용
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors # 색상표
# 한글폰트 설정, 그래프 마이너스 표시 설정
import matplotlib
from matplotlib import font_manager, rc
import platform
if platform.system() == 'Windows':
# 윈도우인 경우
font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()
rc('font', family=font_name)
else:
# Mac 인 경우
rc('font', family='AppleGothic')
matplotlib.rcParams['axes.unicode_minus'] = False
def bollinger(stock_nm, fromdate, todate):
import matplotlib
stock_list = pd.DataFrame({'종목코드':stock.get_market_ticker_list(market="ALL")})
stock_list['종목명'] = stock_list['종목코드'].map(lambda x: stock.get_market_ticker_name(x))
# 두산중공업의 2020년 이후 주가 데이터 가져오기
stock_nm = stock_nm
ticker = stock_list.loc[stock_list['종목명']==stock_nm, '종목코드']
df = stock.get_market_ohlcv_by_date(fromdate=fromdate, todate=todate, ticker=ticker)
# 10일(거래일 기준으로 2주 동안) 기준의 현금흐름지표를 구하는 코드
df['TP'] = (df['고가']+df['저가']+df['종가'])/3
df['PMF'] = 0
df['NMF'] = 0
for i in range(len(df['종가'])-1):
# 당일의 중심가격이 전일의 중심가격보다 크면 긍정적 현금흐름
if df['TP'].values[i] < df['TP'].values[i+1]:
df['PMF'].values[i+1] = df['TP'].values[i+1]*df['거래량'].values[i+1]
df['NMF'].values[i+1] = 0
# 당일의 중심가격이 전일의 중심가격보다 작거나 같으면 부정적 현금흐름
else:
df['NMF'].values[i+1] = df['TP'].values[i+1]*df['거래량'].values[i+1]
df['PMF'].values[i+1] = 0
df['MFR'] = df['PMF'].rolling(window=10).sum()/df['NMF'].rolling(window=10).sum()
df['MFI10'] = 100 - 100/(1+df['MFR'])
df = df.assign(이동평균=df['종가'].rolling(window=20).mean(),
표준편차=df['종가'].rolling(window=20).std())
df = df.assign(상단밴드=df['이동평균'] + df['표준편차']*2,
하단밴드=df['이동평균'] - df['표준편차']*2)
df = df.assign(PB=(df['종가']-df['하단밴드']) / (df['상단밴드']-df['하단밴드']),
밴드폭=(df['상단밴드']-df['하단밴드'])/df['이동평균'])
df = df[19:]
tab_cols = mcolors.TABLEAU_COLORS
plt.figure(figsize=(10, 5))
plt.plot(df.index, df['종가'], color=tab_cols['tab:gray'], linewidth=1, label='종가')
plt.plot(df.index, df['상단밴드'], color=tab_cols['tab:red'], linestyle='dashed', linewidth=1, label='상단밴드')
plt.plot(df.index, df['이동평균'], color=tab_cols['tab:green'], linestyle='dashed', linewidth=1, label='20일 이동평균')
plt.plot(df.index, df['하단밴드'], color=tab_cols['tab:blue'], linestyle='dashed', linewidth=1, label='하단밴드')
plt.title(f'{stock_nm}의 볼린저 밴드(20일, 2 표준편차)')
for i in range(df.shape[0]):
if df['PB'].values[i] > 0.8 and df['MFI10'].values[i] > 80:
plt.plot(df.index.values[i], df['종가'].values[i], 'r^')
elif df['PB'].values[i] < 0.2 and df['MFI10'].values[i] < 20:
plt.plot(df.index.values[i], df['종가'].values[i], 'bv')
plt.legend(loc='best')
plt.xticks(rotation=90, ha='right')
ax=plt.gca()
ax.xaxis.set_major_locator(matplotlib.ticker.MultipleLocator(7));
- 파란색 화살표는 추세추종 기법에서의 매도신호, 빨간색 화살표는 추세추종 기법에서의 매수신호
두산퓨얼셀¶
In [28]:
bollinger(stock_nm='두산퓨얼셀', fromdate="20210101", todate=datetime.today().strftime("%Y%m%d"))
In [30]:
bollinger(stock_nm='두산퓨얼셀1우', fromdate="20210101", todate=datetime.today().strftime("%Y%m%d"))
- 지난주부터 두산퓨얼셀1우에서 추세추종기법 기준 매수신호가 지속적으로 발생하고 있음
LG생활건강¶
In [13]:
bollinger(stock_nm='LG생활건강', fromdate="20210101", todate=datetime.today().strftime("%Y%m%d"))
In [14]:
bollinger(stock_nm='LG생활건강우', fromdate="20210101", todate=datetime.today().strftime("%Y%m%d"))
아모레G¶
In [17]:
bollinger(stock_nm='아모레G', fromdate="20210101", todate=datetime.today().strftime("%Y%m%d"))
In [18]:
bollinger(stock_nm='아모레G우', fromdate="20210101", todate=datetime.today().strftime("%Y%m%d"))
현대차¶
In [19]:
bollinger(stock_nm='현대차', fromdate="20210101", todate=datetime.today().strftime("%Y%m%d"))
In [20]:
bollinger(stock_nm='현대차우', fromdate="20210101", todate=datetime.today().strftime("%Y%m%d"))
In [21]:
bollinger(stock_nm='현대차2우B', fromdate="20210101", todate=datetime.today().strftime("%Y%m%d"))
In [22]:
bollinger(stock_nm='현대차3우B', fromdate="20210101", todate=datetime.today().strftime("%Y%m%d"))
코오롱인더¶
In [26]:
bollinger(stock_nm='코오롱인더', fromdate="20210101", todate=datetime.today().strftime("%Y%m%d"))
In [27]:
bollinger(stock_nm='코오롱인더우', fromdate="20210101", todate=datetime.today().strftime("%Y%m%d"))