LoginSignup
3
1

More than 1 year has passed since last update.

Plotlyのローソク足描画が遅いのでBokehを採用した話

Last updated at Posted at 2022-04-21

output.gif

ローソク足チャートをPlotlyで書くと、少ないコード量でインタラクティブなグラフができて、素晴らしいのですが、10年分のデータくらいで我慢できないくらい描画が遅くなっていました。
Backtesting.pyで出力するグラフだと全然固まらないのでいいなーと思っていたら、内部でBokehを使っていたので、bokehでローソク足を書いてみました。
コード量は多くなるのですが、作りたいグラフを作れたので、Bokehもいいぞって思いました。

以下のローソク足は、pandasのDataFrameでデータを渡しており、dateで指定したところに帯をつけます。

from bokeh.plotting import figure, save, output_file
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, CDSView, CustomJS
from bokeh.models import BooleanFilter, HoverTool, Span
from bokeh.events import DoubleTap

def make_one_chart(df, date):
    source = ColumnDataSource(data=df)

    # 陽線と陰線はそれぞれに色の異なる四角を描画するため
    # どちらもデータをフィルターしたViewを用意する
    inc = df.Close >= df.Open
    view_inc = CDSView(source=source, filters=[BooleanFilter(inc)])
    dec = df.Open > df.Close
    view_dec = CDSView(source=source, filters=[BooleanFilter(dec)])
    w = 12 * 60 * 60 * 1000  # half day in ms

    TOOLS = "pan,box_zoom,ywheel_zoom,crosshair"

    p = figure(
        height=200,
        x_axis_type="datetime",
        tools=TOOLS,
    )
    p.grid.grid_line_alpha = 0.3

    # 一番下のレイヤーなので最初に記述
    p.add_layout(
        Span(
            location=date,
            dimension='height',
            line_color='red',
            line_dash='solid',
            line_alpha=0.1,
            line_width=10,
        )
    )

    p.segment(
        'Date', 'High', 'Date', 'Low',
        color="black", source=source, line_width=2,
    )
    p.vbar(
        'Date', w, 'Open', 'Close',
        fill_color="red", line_color="black",
        source=source, view=view_inc
    )
    p.vbar(
        'Date', w, 'Open', 'Close',
        fill_color="blue", line_color="black",
        source=source, view=view_dec
    )

    # 出来高用のグラフ
    p2 = figure(
        height=100,
        x_axis_type="datetime",
        max_width=600,
        x_range=p.x_range,
        tools=p.tools,
    )
    p2.vbar(x='Date', top='Volume', width=1, fill_color='black', source=source)
    p2.js_on_event(DoubleTap, CustomJS(args=dict(p=p), code='p.reset.emit()'))

    return column(p, p2)

おおよそこんな感じの記述でトップのようなグラフができます。(ホバー情報は少し調整している)
なかなか書きやすくていい感じです。

上記関数を以下のように使います。

from backtesting.test import GOOG
from datetime import datetime as dt

GOOG.index.name = 'Date'
date = dt(2013, 2, 28)
p = make_one_chart(GOOG, date)
output_file('google.html')
save(p)
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1