#!/usr/bin/env python # coding: utf-8 # # Interactive auto-scaling candlestick plot in Jupyter Notebook with Bokeh # In[1]: from bokeh.io import output_notebook, show from bokeh.plotting import figure from bokeh.models import CustomJS, ColumnDataSource output_notebook() from functools import partial # Set some figure defaults figure = partial(figure, plot_width=800, plot_height=500, responsive=False, tools="pan,wheel_zoom,box_zoom,undo,redo,reset,crosshair,save", active_drag='pan', active_scroll='wheel_zoom') # In[2]: def candlestick_plot(df): fig = figure(x_axis_type='datetime') inc = df.Close > df.Open dec = ~inc width_ms = dict(day=86400, hour=3600, minute=60, second=1)[df.index.resolution] * 1000 * .85 fig.segment(df.index, df.High, df.index, df.Low, color="black") fig.vbar(df.index[inc], width_ms, df.Open[inc], df.Close[inc], fill_color="lime", line_color="black") fig.vbar(df.index[dec], width_ms, df.Open[dec], df.Close[dec], fill_color="tomato", line_color="black") source = ColumnDataSource(dict(index=df.index, x=df.Close)) fig.x_range.callback = CustomJS(args=dict(y_range=fig.y_range, source=source), code=''' clearTimeout(window._autoscale_timeout); var index = source.data.index, x = source.data.x, start = cb_obj.start, end = cb_obj.end, min = 1e10, max = -1; for (var i=0; i < index.length; ++i) { if (start <= index[i] && index[i] <= end) { max = Math.max(x[i], max); min = Math.min(x[i], min); } } var pad = (max - min) * .05; window._autoscale_timeout = setTimeout(function() { y_range.start = min - pad; y_range.end = max + pad; }, 50); ''') show(fig) # In[3]: import pandas_datareader.data as web GOOG = web.DataReader('GOOG', 'google', '2015', '2018') GOOG.head() # In[4]: candlestick_plot(GOOG)