From 6b03a1b7c12ddbfacf38122a8aaf414f5102b93b Mon Sep 17 00:00:00 2001 From: Azaya <99359668+Azaya89@users.noreply.github.com> Date: Tue, 11 Feb 2025 18:33:44 +0100 Subject: [PATCH] Set OHLC x-axis tooltip to datetime format (#1493) --- hvplot/converter.py | 14 ++++++-- hvplot/tests/plotting/testohlc.py | 59 +++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/hvplot/converter.py b/hvplot/converter.py index 155efad2e..83e34930f 100644 --- a/hvplot/converter.py +++ b/hvplot/converter.py @@ -2630,15 +2630,25 @@ def ohlc(self, x=None, y=None, data=None): seg_cur_opts, seg_compat_opts = self._get_compat_opts('Segments') tools = seg_cur_opts.pop('tools', []) if 'hover' in tools: + x_data = data[x] if x in data.columns else data.index + if pd.api.types.is_datetime64_any_dtype(x_data): + # %F %T: strftime code for %Y-%m-%d %H:%M:%S. + # See https://man7.org/linux/man-pages/man3/strftime.3.html + x_tooltip = f'@{x}{{%F %T}}' + formatter = {f'@{x}': 'datetime'} + else: + x_tooltip = f'@{x}' + formatter = {} tools[tools.index('hover')] = HoverTool( + formatters=formatter, tooltips=[ - (x, f'@{x}'), + (x, x_tooltip), ('Open', f'@{o}'), ('High', f'@{h}'), ('Low', f'@{l}'), ('Close', f'@{c}'), ] - + [(hc, f'@{hc}') for hc in vdims[4:]] + + [(hc, f'@{hc}') for hc in vdims[4:]], ) seg_cur_opts['tools'] = tools seg_cur_opts['color'] = self.kwds.get('line_color', 'black') diff --git a/hvplot/tests/plotting/testohlc.py b/hvplot/tests/plotting/testohlc.py index 5cdb9a570..2eb3e5fc7 100644 --- a/hvplot/tests/plotting/testohlc.py +++ b/hvplot/tests/plotting/testohlc.py @@ -32,3 +32,62 @@ def test_ohlc_hover_cols_all(): tooltips = segments.opts.get('plot').kwargs['tools'][0].tooltips assert len(tooltips) == len(df.columns) + 1 assert tooltips[-1] == ('Volume', '@Volume') + + +def test_ohlc_date_tooltip_format(): + plot = df.hvplot.ohlc(y=ohlc_cols) + segments = plot.Segments.I + hover_tool = segments.opts.get('plot').kwargs['tools'][0] + tooltips = hover_tool.tooltips + x_label, x_tooltip = tooltips[0] + assert '{%F %T}' in x_tooltip + formatter_key = '@' + x_label + formatter = hover_tool.formatters + assert formatter[formatter_key] == 'datetime' + + +def test_ohlc_non_datetime_x_axis(): + 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=[1, 2, 3], + ) + + ohlc_cols = ['Open', 'High', 'Low', 'Close'] + + plot = df.hvplot.ohlc(y=ohlc_cols) + segments = plot.Segments.I + hover_tool = segments.opts.get('plot').kwargs['tools'][0] + tooltips = hover_tool.tooltips + x_label, x_tooltip = tooltips[0] + assert '{%F}' not in x_tooltip + formatter_key = '@' + x_label + assert formatter_key not in hover_tool.formatters + + +def test_ohlc_non_index_date_col(): + df = pd.DataFrame( + { + 'Date': [ + pd.Timestamp('2022-08-01'), + pd.Timestamp('2022-08-03'), + pd.Timestamp('2022-08-04'), + ], + '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], + }, + ) + plot = df.hvplot.ohlc(hover_cols='all', use_index=False) + segments = plot.Segments.I + hover_tool = segments.opts.get('plot').kwargs['tools'][0] + tooltips = hover_tool.tooltips + assert len(tooltips) == len(df.columns) + assert tooltips[0] == ('Date', '@Date{%F %T}')