I have a candlestick chart that works nicely with bokeh. The only issue I have is the data is 1 minute data and chart can look a little squashed together. Is there anyway to create a small gap between the candlestick bars?
update - code
import pandas as pd
from datetime import timedelta
from bokeh.plotting import figure, ColumnDataSource
from bokeh.models.widgets import Dropdown
from bokeh.io import curdoc
from bokeh.layouts import column
from bokeh.models import BooleanFilter, CDSView, Select, Range1d, HoverTool
from bokeh.palettes import Category20
from bokeh.models.formatters import NumeralTickFormatter
from bokeh.io import output_file, show
# Define constants
W_PLOT = 1700
H_PLOT = 600
TOOLS = "pan,box_zoom,zoom_in,zoom_out,redo,undo,reset,save,crosshair"
VBAR_WIDTH = 60*60*10000
# VBAR_WIDTH = 12*60*60*1000 # half day in ms
# VBAR_WIDTH = 24*60*60*1000 # day in ms
RED = Category20[7][6]
GREEN = Category20[5][4]
def plot_test(df: pd.DataFrame,
name: str) -> None:
inc = df.price_close > df.price_open
dec = ~inc
cds = ColumnDataSource(data=df)
view_inc = CDSView(source=cds, filters=[BooleanFilter(inc)])
view_dec = CDSView(source=cds, filters=[BooleanFilter(dec)])
fig = figure(plot_width=W_PLOT, plot_height=H_PLOT,
tools=TOOLS,
x_axis_type="datetime",
title=name,
toolbar_location='above')
# Plot candles
# High and low
fig.segment(x0='time_stamp', y0='price_high',
x1='time_stamp', y1='price_low',
source=cds, view=view_inc,
color='black')
fig.segment(x0='time_stamp', y0='price_high',
x1='time_stamp', y1='price_low',
source=cds, view=view_dec,
color='black')
# Open and close
r1 = fig.vbar(x='time_stamp', width=timedelta(minutes=1),
top='price_open', bottom='price_close',
source=cds, view=view_inc,
fill_color=GREEN, line_color="black")
r2 = fig.vbar(x='time_stamp', width=timedelta(minutes=1),
top='price_open', bottom='price_close',
source=cds, view=view_dec,
fill_color=RED, line_color="black")
# let add a moving average
fig.line(x='time_stamp', y='ma_20', source=cds, legend_label='MA 20')
# entry signals
fig.triangle(x='time_stamp', y='buy', source=cds, fill_color=GREEN,
size=10)
fig.inverted_triangle(x='time_stamp', y='sell', source=cds,
fill_color=RED, size=10)
# Set up the hover tooltip to display some useful data
fig.add_tools(HoverTool(
renderers=[r1],
tooltips=[
("Open", "@price_open{0.0000}"),
("High", "@price_high{0.0000}"),
("Low", "@price_low{0.0000}"),
("Close", "@price_close{0.0000}"),
("Date", "@time_stamp{%Y-%m-%d %H:%M}"),
],
formatters={
'@time_stamp': 'datetime'
}))
fig.add_tools(HoverTool(
renderers=[r2],
tooltips=[
("Open", "@price_open{0.0000}"),
("High", "@price_high{0.0000}"),
("Low", "@price_low{0.0000}"),
("Close", "@price_close{0.0000}"),
("Date", "@time_stamp{%Y-%m-%d %H:%M}"),
],
formatters={
'@time_stamp': 'datetime'
}))
elements = list()
elements.append(fig)
curdoc().add_root(column(elements))
curdoc.title = 'Blah'
show(fig)
As pointed out my bigredot, in order to change the width of the candlestick it is done by setting the width parameter of the vbar method.
The number below is good for daily data. For higher frequency data I would reduce the '12'
VBAR_WIDTH = 126060*1000 # half day in ms