以 OHLC 值作为工具提示 or/and 标签的散景烛台图

Bokeh Candlestick Chart with OHLCV values as tooltip or/and lable

如何在像这样的 Bokeh 烛台图表上获得工具提示:

or/and 像这样的标签:


目前绘制图表的代码如下:

import pandas as pd
import numpy as  np
from bokeh.plotting import figure, output_notebook, show
from bokeh.models import LinearAxis, Range1d, Segment, Legend
from bokeh.models.formatters import NumeralTickFormatter, DatetimeTickFormatter
from bokeh.palettes import Category20
output_notebook()

def init_chart(name):
  # Tools Selections:
  TOOLS = "pan,xwheel_zoom,box_zoom,crosshair,undo,redo,reset,save"

  p = figure(x_axis_type="datetime", tools=TOOLS, 
             title = name)
  p.add_layout(Legend(click_policy="hide", orientation='horizontal', spacing=20), 'below')
  p.sizing_mode = 'scale_both'

  return p

def init_price_volume_chart(p, df):
  RED = Category20[7][6]
  GREEN = Category20[5][4]

  inc = df.Close > df.Open
  dec = df.Open > df.Close
  w = 12*60*60*1000 # half day in ms

  p.x_range = Range1d(df.index[0], df.index[-1])
  p.xaxis[0].formatter = DatetimeTickFormatter(months="%b %Y", days="%d %b %Y")
  p.xaxis.axis_label = 'Date'
  p.xaxis.major_label_orientation = 3.1415/4
  p.xaxis.ticker.desired_num_ticks = 40

  # left y axis
  low, high  = df.Low.min(), df.High.max()
  p.y_range = Range1d(low * 0.9, high * 1.1)
  p.yaxis.axis_label = 'Price'
  p.yaxis[0].formatter = NumeralTickFormatter(format="0,0.00")
  p.segment(df.index, df.High, df.index, df.Low, color=GREEN, legend_label='Candlestick')
  p.vbar(df.index[inc], w, df.Open[inc], df.Close[inc], 
        fill_color=GREEN, line_color=GREEN, legend_label='Candlestick')
  p.vbar(df.index[dec], w, df.Open[dec], df.Close[dec], 
        fill_color=RED, line_color=RED, legend_label='Candlestick')

  # right y axis
  p.extra_y_ranges.update({'two':  Range1d(0, 1.1*df.Volume.max())})
  p.add_layout(LinearAxis(y_range_name='two', axis_label='Volume' ), 'right')
  p.yaxis[1].formatter = NumeralTickFormatter(format="0a")
  p.vbar(df.index[inc], w, df.Volume[inc], [0]*inc.sum(), alpha=0.5, level='underlay', 
        fill_color=GREEN, line_color=GREEN,
        legend_label='Volume', y_range_name='two')
  p.vbar(df.index[dec], w, df.Volume[dec], [0]*dec.sum(), alpha=0.5, level='underlay', 
        fill_color=RED, line_color=RED,
        legend_label='Volume', y_range_name='two')
  
  return p

您的散景烛台由两个字形组成:vbarsegment。在下面的代码中,vbar 上只有一个工具提示,但您也可以将它添加到 segment(为 Bokeh v2.1.1 制作的代码)我还省略了不相关的代码以使代码看起来更简单.

import pandas as pd
from bokeh.plotting import figure, output_notebook, show
from bokeh.models import Legend, HoverTool, ColumnDataSource
from bokeh.palettes import Category20
from datetime import datetime, timedelta
output_notebook()

df = pd.DataFrame({"index": [datetime(2017,1,1) + timedelta(days=x) for x in range(0,3)], "Open": [3, 2, 3], "Low": [2, 0.5, 2.5], "High": [5, 3, 4.5], "Close": [4, 1, 4.5], "Volume": [10000, 20000, 10000]})
df_red = df.loc[(df['Open'] >= df['Close'])]
df_green = df.loc[(df['Close'] >= df['Open'])]

source = ColumnDataSource(df)
source_red = ColumnDataSource(df_red)
source_green = ColumnDataSource(df_green)

RED = Category20[7][6]
GREEN = Category20[5][4]
w = 12*60*60*1000

def init_chart(name):
    # Tools Selections:
    TOOLS = "pan,xwheel_zoom,box_zoom,crosshair,undo,redo,reset,save"        
    p = figure(x_axis_type="datetime", tools=TOOLS, title = name, plot_width = 1200, plot_height=500)
    p.add_layout(Legend(click_policy="hide", orientation='horizontal', spacing=20), 'below')
    p.sizing_mode = 'scale_both'
    return p

p = init_chart('Plot1')
  
segmnts_green = p.segment('index', 'High', 'index', 'Low', color=GREEN, source=source_green, legend_label='Up')
segmnts_red = p.segment('index', 'High', 'index', 'Low', color=RED, source=source_red, legend_label='Down')
vbars_green = p.vbar('index', w, 'Open', 'Close', source=source_green, fill_color=GREEN, line_color=GREEN, legend_label='Up')
vbars_red = p.vbar('index', w, 'Close', 'Open', source=source_red, fill_color=RED, line_color=RED, legend_label='Down')

tooltips=[('open', '@Open'),('close', '@Close'), ('low', '@Low'), ('high', '@High')]
red_hover = HoverTool(renderers=[vbars_red], tooltips=tooltips)
p.add_tools(red_hover)
green_hover = HoverTool(renderers=[vbars_green], tooltips=tooltips)
p.add_tools(green_hover)

show(p)

结果: