きっかけ
Botterになるためにまずはチャートを描けるようにならなくてはいけないと思いました。
最初、Plotlyでやってたんだけど、有料っていうのを見かけたので、Bokehにシフト
環境
- Windows 10 Pro 21H1
- Python 3.9.7
- Jupyter Notebook 6.4.5
- Pandas 1.3.4
- Bokeh 2.4.1
コード
from math import pi
import pandas as pd
from bokeh.plotting import figure, show, output_file
from bokeh.sampledata.stocks import MSFT
df = pd.DataFrame(MSFT)
df["date"] = pd.to_datetime(df["date"])
mids = (df.open + df.close)/2
spans = abs(df.close-df.open)
inc = df.close > df.open
dec = ~inc
# 日時表示用のフォーマットを設定(日足と分足に分岐
xaxis_dt_format = '%Y-%m-%d'
if df.iloc[0]['date'].hour > 0:
xaxis_dt_format = '%Y-%m-%d_%H:%M:%S'
# チャートの初期設定
p = figure(sizing_mode="stretch_both",
tools=TOOLS,
x_axis_type="linear", # linearを指定しないと、土日が空くチャートになる。
plot_width=1000,
toolbar_location="left")
# Colour scheme for increasing and descending candles
# 色はなんとなくTradingViewに合わせた
INCREASING_COLOR = '#26a69a'
DECREASING_COLOR = '#ef5350'
width = 0.5
# 陽線と陰線のデータをまとめちゃう
inc_source = ColumnDataSource(data=dict(
x1=df.index[inc],
top1=df.open[inc],
bottom1=df.close[inc],
high1=df.high[inc],
low1=df.low[inc],
Date1=df.date[inc]
))
dec_source = ColumnDataSource(data=dict(
x2=df.index[dec],
top2=df.open[dec],
bottom2=df.close[dec],
high2=df.high[dec],
low2=df.low[dec],
Date2=df.date[dec]
))
w = 12*60*60*1000 # half day in ms 半日をミリ秒に?
TOOLS = "pan,wheel_zoom,box_zoom,crosshair,reset,save"
p.title = "MSFT Candlestick"
p.xaxis.major_label_orientation = pi/4 # X軸のラベルを開店
p.grid.grid_line_alpha=0.3
p.yaxis[0].formatter = NumeralTickFormatter(format="5.3f") # y軸のフォーマット
# Plot candles #ローソク足を描いていく
# High and low
p.segment(x0='x1', y0='high1', x1='x1', y1='low1', source=inc_source, color=INCREASING_COLOR)
p.segment(x0='x2', y0='high2', x1='x2', y1='low2', source=dec_source, color=DECREASING_COLOR)
# Open and close
r1 = p.vbar(x='x1', width=width, top='top1', bottom='bottom1', source=inc_source,
fill_color=INCREASING_COLOR, line_color=INCREASING_COLOR)
r2 = p.vbar(x='x2', width=width, top='top2', bottom='bottom2', source=dec_source,
fill_color=DECREASING_COLOR, line_color=DECREASING_COLOR)
# Add date labels to x axis
p.xaxis.major_label_overrides = {
i: date.strftime(xaxis_dt_format) for i, date in enumerate(pd.to_datetime(df.date))
}
# Set up the hover tooltip to display some useful data
p.add_tools(HoverTool(
renderers=[r1],
tooltips=[
("Open", "$@top1"),
("High", "$@high1"),
("Low", "$@low1"),
("Close", "$@bottom1"),
("Date", "@Date1{" + xaxis_dt_format + "}"),
],
formatters={
'@Date1': 'datetime',
},
mode='vline', # 縦線に相当する値を表示
# mode='mouse', # マウスポインタを合わせたときに表示
))
p.add_tools(HoverTool(
renderers=[r2],
tooltips=[
("Open", "$@top2"),
("High", "$@high2"),
("Low", "$@low2"),
("Close", "$@bottom2"),
("Date", "@Date2{" + xaxis_dt_format + "}")
],
formatters={
'@Date2': 'datetime',
},
mode='vline', # 縦線に相当する値を表示
# mode='mouse', # マウスポインタを合わせたときに表示
))
#output_file("candlestick.html", title="candlestick.py example")
# 出力先をノートブックに設定
output_notebook()
show(p) # open a browser
結果
補足
bokeh.sampledata.stocksは、事前にダウンロードしないといけないです。
下記を事前に実行しておくと、データ落としといてくれます。
import bokeh.sampledata
bokeh.sampledata.download()
今後の予定
移動平均線とか出してみたいと思っている。
参考