How to add data into hover in Hvplot (bokeh) candlestick without missing-date gaps

110 views Asked by At

I have an simple example, run in jupyter notebook:

  • hvplot.ohlc without missing-date gaps
  • wanted to fix Hover (add Date in the right format, and add Volume info)

packages:

python 3.12
bokeh 3.3.2
hvplot 0.9.0
holoviews 1.18.1

import pandas as pd
import hvplot.pandas

data = pd.DataFrame({
        "Open": [100.00, 101.25, 102.75],
        "High": [104.10, 105.50, 110.00],
        "Low": [94.00, 97.10, 99.20],
        "Close": [101.15, 99.70, 109.50],
        "Volume": [10012, 5000, 18000],
    }, index=[pd.Timestamp("2022-08-01"), pd.Timestamp("2022-08-03"), pd.Timestamp("2022-08-04")])

df = pd.DataFrame(data)
# remove datetime gaps
df = df.reset_index(names="Date")
df['Idx'] = pd.RangeIndex(0, df.shape[0], 1)

# fix hover ------
from bokeh.models import HoverTool

hover = HoverTool(
    tooltips=[
        ('Date', '@Date{%Y-%m-%d}'),
        ('Open', '@Open{0.00}'),
        ('High', '@High{0.00}'),
        ('Low', '@Low{0.00}'),
        ('Close', '@Close{0.00}'),
        ('Volume', '@Volume{0}'),
    ],
    formatters={'@Date': 'datetime'},
    mode='vline'
)
# fix hover ------

ohlc_cols = ["Open", "High", "Low", "Close"]
ohlc = df.hvplot.ohlc(x='Idx', y=ohlc_cols, hover_cols=["Date", *ohlc_cols, "Volume"], tools=[hover])

# fix x tick labels ------
import holoviews as hv
from bokeh.io import show

fig = hv.render(ohlc)
fig.xaxis.major_label_overrides = {
    i: dt.strftime("%b %d") for i, dt in enumerate(df['Date'])
}
# fix x tick labels ------

show(fig)

But the output is: enter image description here

1

There are 1 answers

3
mosc9575 On BEST ANSWER

The solution, or more a workaround, is to manupilate the ColumnDataSource of the first renderer in the bokeh figure.

You can do so b adding the line below:

fig.renderers[0].data_source.data['Volume'] = df['Volume'].values

Explanation

To understand why the line above is the solution, I want to explain, what df.hvplot.ohlc() does.

This function creates a bokeh figure with 2 renderers, the first rederer is for all whiskers, which gets the HoverTool, and the seconde renderer draws the boxes. The DataFrame is converted to a ColumnsDataSource in the inside. The ColumnsDataSources don't have any information about the "Volume", because only used columns used by the whiskers and boxes are stored inside the ColumnDataSource. The HoverTool can't find information for the Volumne, so it prints ???. But we can extend the source by this information.

Minimal Example

I adapted your example, because I think it is simpler, but the downside is, that there is one empty date.

import pandas as pd
import hvplot.pandas
import holoviews as hv
from bokeh.io import show
from bokeh.models import HoverTool

df= pd.DataFrame({
        "Open": [100.00, 101.25, 102.75],
        "High": [104.10, 105.50, 110.00],
        "Low": [94.00, 97.10, 99.20],
        "Close": [101.15, 99.70, 109.50],
        "Volume": [10012, 5000, 18000],
    },
    index=[pd.Timestamp("2022-08-01"), pd.Timestamp("2022-08-03"), pd.Timestamp("2022-08-04")]
)
df.index.name = "Date"

fig = hv.render(ohlc)
# add missing values to the source for the HoverTool
fig.renderers[0].data_source.data['Volume'] = df['Volume'].values
show(fig)

Output

ohlc plot with extra data for HoverTool