주가 분석 연구를 하게 되면 차트를 통해 시각화해야하는 경우가 많다.
그러나 캔들 차트는 구현이 까다로워서 대중적으로 사용되지는 않았었는데, FinaceDataReader 라이브러리에
차트 기능이 추가되어 간편하게 차트 시각화가 가능해졌다.


직접 사용해 본 결과, 코드 한줄로도 간단한 캔들 차트가 완성되어 무척 신기했다. 그러나 각 캔들의 정확한 날짜를
알기 위해서는 줌 인 기능을 통해 엄청 크게 확대한 후 눈으로 짐작해야해서 매우 불편했다.
따라서 가격 캔들과 거래량 봉에 마우스를 갖다대면 날짜와 가격을 알 수 있도록 코드를 커스터마이징 했다.
코드는 다음과 같으며 깃허브에도 공유할 예정이다.
사용하기 위해서는 FDR의 chart.plot 함수를 재정의 하거나 아래 코드의 함수를 자신만의 이름으로 바꿔서 사용하면 된다.
def get_width(df):
mindate = min(df.index)
maxdate = max(df.index)
width = 0.8 #vbar의 가로폭 0.8 로 설정
return width * (maxdate-mindate).total_seconds()*1000 / len(df.index)
def chart_plot(df,start=None,end=None,volume=False,ma_lines=[5,20,60]):
try:
from bokeh.plotting import figure, gridplot
from bokeh.models import NumeralTickFormatter, DatetimeTickFormatter, Span
from bokeh.io import output_notebook, show, export_png
from bokeh.palettes import d3
except ModuleNotFoundError as e:
raise ModuleNotFoundError(bokeh_install_msg)
for n in ma_lines: # 이동평균 계산
df[f'MA_{n}'] = df.Close.rolling(window=n).mean()
inc = df.Close > df.Open
dec = df.Open > df.Close
##############
df['date_'] = df.index
# plot price OHLC candles
x = np.arange(len(df))
width = 940
height = 680 # 그래프 전체 높이 설정
if volume == True:
height = int(height - height * 0.3) # 거래량 비중 0.3
TOOLTIPS = [
("index", "$index"),
("y", "$y{0.0})"),
("date", "$x{%F}"),
]
pp = figure(plot_width=width,
plot_height=height,
x_range=Range1d(start=df.index[0], end=df.index[-1]),
y_range=(df.Low.min(), df.High.max()),
title='',
y_axis_label='',
tools=[PanTool(), WheelZoomTool(), BoxZoomTool(),SaveTool(), ResetTool(), HelpTool(),
HoverTool(formatters={'$x':'datetime'})],
tooltips=TOOLTIPS)
pp.segment(df.index[inc], df.High[inc], df.index[inc], df.Low[inc], color='red')
pp.segment(df.index[dec], df.High[dec], df.index[dec], df.Low[dec], color='blue')
pp.vbar(df.index[inc], get_width(df), df.Open[inc], df.Close[inc], fill_color='red', line_color='red')
pp.vbar(df.index[dec], get_width(df), df.Open[dec], df.Close[dec], fill_color='blue', line_color='blue')
pp.yaxis[0].formatter = NumeralTickFormatter(format='0,0')
if volume == True:
pp.xaxis.visible = False
else:
x_labels = {i: dt.strftime('%Y-%m-%d') for i,dt in enumerate(df.index)}
x_labels.update({len(df): ''})
pp.xaxis.major_label_overrides = x_labels
pp.xaxis.formatter=DatetimeTickFormatter(hours=["%H:%M"], days=["%Y-%m-%d"])
pp.xaxis.major_label_orientation = np.pi / 5
source = ColumnDataSource(data = {i:df[i] for i in df.columns})
for ix,n in enumerate(ma_lines):
pal = d3['Category10'][10]
pp.line(df.index, df[f'MA_{n}'], line_color=pal[ix % len(pal)],legend_label=f'MA_{n}')
# plot volume
if volume == True:
inc = df.Volume.diff() >= 0
dec = df.Volume.diff() < 0
height = int(height * 0.3)
pv = figure(plot_width= width, plot_height=height, x_range = pp.x_range,
tools= [HoverTool(formatters={'$x':'datetime'})],tooltips=TOOLTIPS)
pv.vbar(df.index[inc], get_width(df), df.Volume[inc], fill_color='red', line_color="black")
pv.vbar(df.index[dec], get_width(df), df.Volume[dec], fill_color='blue', line_color="black")
pv.yaxis[0].formatter = NumeralTickFormatter(format='0,0')
x_labels = {i: dt.strftime('%Y-%m-%d') for i,dt in enumerate(df.index)}
x_labels.update({len(df): ''})
pv.xaxis.major_label_overrides = x_labels
pv.xaxis.formatter=DatetimeTickFormatter(hours=["%H:%M"], days=["%Y-%m-%d"])
pv.xaxis.major_label_orientation = np.pi / 5
pv.y_range.range_padding = 0
# 가격(pp)과 거래량(pv) 함께 그리기
p = gridplot([[pp], [pv]])
else:
p = gridplot([[pp]])
output_notebook()
show(p)

수정한 코드를 통해서 함수를 실행하면 캔들에 마우스를 갖다 댈 경우 해당 캔들의 날짜가 보이도록 하였고,
차트에 거래량을 함께 볼지 말지, 이동평균으로 쓰고싶은 값을 한번에 입력받아 표시하도록 수정하였다.
'공부 > 퀀트' 카테고리의 다른 글
주가 예측 연구의 종류 정리 1 (0) | 2022.01.13 |
---|---|
파이썬을 이용해 급등 종목 추출하기 (0) | 2022.01.07 |
퀀트란? (0) | 2022.01.07 |