From 0581c550e0f654fd683f6fce8fa4db2b7db859cf Mon Sep 17 00:00:00 2001 From: Zeel Patel Date: Sat, 22 May 2021 19:30:20 -0700 Subject: [PATCH 01/17] Auto-scale Y-axis for indicators when zooming #356 --- backtesting/_plotting.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/backtesting/_plotting.py b/backtesting/_plotting.py index bec6757a..1b01d385 100644 --- a/backtesting/_plotting.py +++ b/backtesting/_plotting.py @@ -523,6 +523,12 @@ def __eq__(self, other): colors = colors and cycle(_as_list(colors)) or ( cycle([next(ohlc_colors)]) if is_overlay else colorgen()) legend_label = LegendStr(value.name) + + indicator_max=value.df.max(axis='columns') + indicator_min=value.df.min(axis='columns') + source.add(indicator_max, f'indicator_{j}_range_max') + source.add(indicator_min,f'indicator_{j}_range_min') + for j, arr in enumerate(value, 1): color = next(colors) source_name = f'{legend_label}_{i}_{j}' @@ -609,6 +615,12 @@ def __eq__(self, other): source=source) if plot_volume: custom_js_args.update(volume_range=fig_volume.y_range) + + indicator_ranges = {} + for idx,indicator in enumerate(indicator_figs): + indicator_range_key = f'indicator_{idx}_range' + indicator_ranges.update({indicator_range_key:indicator.y_range}) + custom_js_args.update({'indicator_ranges':indicator_ranges}) fig_ohlc.x_range.js_on_change('end', CustomJS(args=custom_js_args, code=_AUTOSCALE_JS_CALLBACK)) From 779258895bc8f6836d9b5483b03244c9d156222f Mon Sep 17 00:00:00 2001 From: Zeel Patel Date: Sat, 22 May 2021 19:31:43 -0700 Subject: [PATCH 02/17] Auto-scale Y-axis for indicators when zooming #356 --- backtesting/autoscale_cb.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/backtesting/autoscale_cb.js b/backtesting/autoscale_cb.js index da888ecf..63135615 100644 --- a/backtesting/autoscale_cb.js +++ b/backtesting/autoscale_cb.js @@ -31,5 +31,18 @@ window._bt_autoscale_timeout = setTimeout(function () { max = Math.max.apply(null, source.data['Volume'].slice(i, j)); _bt_scale_range(volume_range, 0, max * 1.03, false); } + + if(indicator_ranges){ + let keys = Object.keys(indicator_ranges); + for(var count=0;count Date: Sat, 22 May 2021 19:36:10 -0700 Subject: [PATCH 03/17] Auto-scale Y-axis for indicators when zooming #356 --- backtesting/_plotting.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backtesting/_plotting.py b/backtesting/_plotting.py index 1b01d385..85c3a251 100644 --- a/backtesting/_plotting.py +++ b/backtesting/_plotting.py @@ -526,8 +526,8 @@ def __eq__(self, other): indicator_max=value.df.max(axis='columns') indicator_min=value.df.min(axis='columns') - source.add(indicator_max, f'indicator_{j}_range_max') - source.add(indicator_min,f'indicator_{j}_range_min') + source.add(indicator_max, f'indicator_{i}_range_max') + source.add(indicator_min,f'indicator_{i}_range_min') for j, arr in enumerate(value, 1): color = next(colors) From c0dcbbedced95f08b61d9789b09a0b316cbbd99a Mon Sep 17 00:00:00 2001 From: Zeel Patel Date: Sat, 22 May 2021 20:19:37 -0700 Subject: [PATCH 04/17] Auto-scale Y-axis for indicators when zooming #356 --- backtesting/_plotting.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/backtesting/_plotting.py b/backtesting/_plotting.py index 85c3a251..86c1697a 100644 --- a/backtesting/_plotting.py +++ b/backtesting/_plotting.py @@ -523,12 +523,10 @@ def __eq__(self, other): colors = colors and cycle(_as_list(colors)) or ( cycle([next(ohlc_colors)]) if is_overlay else colorgen()) legend_label = LegendStr(value.name) - indicator_max=value.df.max(axis='columns') indicator_min=value.df.min(axis='columns') source.add(indicator_max, f'indicator_{i}_range_max') - source.add(indicator_min,f'indicator_{i}_range_min') - + source.add(indicator_min, f'indicator_{i}_range_min') for j, arr in enumerate(value, 1): color = next(colors) source_name = f'{legend_label}_{i}_{j}' @@ -619,9 +617,8 @@ def __eq__(self, other): indicator_ranges = {} for idx,indicator in enumerate(indicator_figs): indicator_range_key = f'indicator_{idx}_range' - indicator_ranges.update({indicator_range_key:indicator.y_range}) - custom_js_args.update({'indicator_ranges':indicator_ranges}) - + indicator_ranges.update({indicator_range_key: indicator.y_range}) + custom_js_args.update({'indicator_ranges': indicator_ranges}) fig_ohlc.x_range.js_on_change('end', CustomJS(args=custom_js_args, code=_AUTOSCALE_JS_CALLBACK)) From 6b1c436a459d46d9a5e25f07ab232377004f69cf Mon Sep 17 00:00:00 2001 From: Zeel Patel Date: Sat, 22 May 2021 20:23:02 -0700 Subject: [PATCH 05/17] Auto-scale Y-axis for indicators when zooming #356 --- backtesting/_plotting.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/backtesting/_plotting.py b/backtesting/_plotting.py index 86c1697a..e22358b0 100644 --- a/backtesting/_plotting.py +++ b/backtesting/_plotting.py @@ -523,8 +523,8 @@ def __eq__(self, other): colors = colors and cycle(_as_list(colors)) or ( cycle([next(ohlc_colors)]) if is_overlay else colorgen()) legend_label = LegendStr(value.name) - indicator_max=value.df.max(axis='columns') - indicator_min=value.df.min(axis='columns') + indicator_max = value.df.max(axis = 'columns') + indicator_min = value.df.min(axis = 'columns') source.add(indicator_max, f'indicator_{i}_range_max') source.add(indicator_min, f'indicator_{i}_range_min') for j, arr in enumerate(value, 1): @@ -612,10 +612,9 @@ def __eq__(self, other): custom_js_args = dict(ohlc_range=fig_ohlc.y_range, source=source) if plot_volume: - custom_js_args.update(volume_range=fig_volume.y_range) - + custom_js_args.update(volume_range=fig_volume.y_range) indicator_ranges = {} - for idx,indicator in enumerate(indicator_figs): + for idx, indicator in enumerate(indicator_figs): indicator_range_key = f'indicator_{idx}_range' indicator_ranges.update({indicator_range_key: indicator.y_range}) custom_js_args.update({'indicator_ranges': indicator_ranges}) From bf03b63503d28a568b80a440c018e4dc1432f91a Mon Sep 17 00:00:00 2001 From: Zeel Patel Date: Sat, 22 May 2021 20:34:29 -0700 Subject: [PATCH 06/17] Auto-scale Y-axis for indicators when zooming #356 --- backtesting/_plotting.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backtesting/_plotting.py b/backtesting/_plotting.py index e22358b0..424dd18a 100644 --- a/backtesting/_plotting.py +++ b/backtesting/_plotting.py @@ -523,8 +523,8 @@ def __eq__(self, other): colors = colors and cycle(_as_list(colors)) or ( cycle([next(ohlc_colors)]) if is_overlay else colorgen()) legend_label = LegendStr(value.name) - indicator_max = value.df.max(axis = 'columns') - indicator_min = value.df.min(axis = 'columns') + indicator_max = value.df.max(axis='columns') + indicator_min = value.df.min(axis='columns') source.add(indicator_max, f'indicator_{i}_range_max') source.add(indicator_min, f'indicator_{i}_range_min') for j, arr in enumerate(value, 1): @@ -612,7 +612,7 @@ def __eq__(self, other): custom_js_args = dict(ohlc_range=fig_ohlc.y_range, source=source) if plot_volume: - custom_js_args.update(volume_range=fig_volume.y_range) + custom_js_args.update(volume_range=fig_volume.y_range) indicator_ranges = {} for idx, indicator in enumerate(indicator_figs): indicator_range_key = f'indicator_{idx}_range' From 5ca9a59ccb37f90fc8230b2ede1af4bbdf2dcd48 Mon Sep 17 00:00:00 2001 From: Zeel Patel Date: Sun, 13 Jun 2021 00:06:36 -0700 Subject: [PATCH 07/17] Auto-scale Y-axis for Profit/Loss chart when zooming kernc#356 --- backtesting/_plotting.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/backtesting/_plotting.py b/backtesting/_plotting.py index 424dd18a..0ecd0d45 100644 --- a/backtesting/_plotting.py +++ b/backtesting/_plotting.py @@ -588,7 +588,8 @@ def __eq__(self, other): figs_above_ohlc.append(_plot_drawdown_section()) if plot_pl: - figs_above_ohlc.append(_plot_pl_section()) + fig_pl = _plot_pl_section() + figs_above_ohlc.append(fig_pl) if plot_volume: fig_volume = _plot_volume_section() @@ -611,6 +612,8 @@ def __eq__(self, other): custom_js_args = dict(ohlc_range=fig_ohlc.y_range, source=source) + if plot_pl: + custom_js_args.update(pl_range=fig_pl.y_range) if plot_volume: custom_js_args.update(volume_range=fig_volume.y_range) indicator_ranges = {} From ab17cbf7ef674e6b9be542a516e17f2b7a071246 Mon Sep 17 00:00:00 2001 From: Zeel Patel Date: Sun, 13 Jun 2021 12:00:52 -0700 Subject: [PATCH 08/17] Auto-scale Y-axis for PL chart when zooming kernc#356 --- backtesting/_plotting.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backtesting/_plotting.py b/backtesting/_plotting.py index 0ecd0d45..d2724858 100644 --- a/backtesting/_plotting.py +++ b/backtesting/_plotting.py @@ -391,6 +391,9 @@ def _plot_pl_section(): returns_short = np.where(trades['Size'] < 0, trades['ReturnPct'], np.nan) size = trades['Size'].abs() size = np.interp(size, (size.min(), size.max()), (8, 20)) + ohlcv_index_trade_close_arr = np.empty(source.data['index'][-1]+1,dtype=float) + ohlcv_index_trade_close_arr[trade_source.data['index']] = trades['ReturnPct'] + source.add(ohlcv_index_trade_close_arr,'return_pct') trade_source.add(returns_long, 'returns_long') trade_source.add(returns_short, 'returns_short') trade_source.add(size, 'marker_size') From 44a0200e02aa44e437b42b5a74e3cf8a0d0b0ea4 Mon Sep 17 00:00:00 2001 From: Zeel Patel Date: Sun, 13 Jun 2021 12:03:00 -0700 Subject: [PATCH 09/17] Add auto scaling of y-axis for PL chart kernc#356 --- backtesting/autoscale_cb.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backtesting/autoscale_cb.js b/backtesting/autoscale_cb.js index 63135615..9ed3784c 100644 --- a/backtesting/autoscale_cb.js +++ b/backtesting/autoscale_cb.js @@ -27,6 +27,14 @@ window._bt_autoscale_timeout = setTimeout(function () { min = Math.min.apply(null, source.data['ohlc_low'].slice(i, j)); _bt_scale_range(ohlc_range, min, max, true); + if (pl_range) { + max = Math.max.apply(null, source.data['return_pct'].slice(i, j)); + min = Math.min.apply(null, source.data['return_pct'].slice(i, j)); + if(min && max){ + _bt_scale_range(pl_range, min, max, true); + } + } + if (volume_range) { max = Math.max.apply(null, source.data['Volume'].slice(i, j)); _bt_scale_range(volume_range, 0, max * 1.03, false); From 307e4ffb654698a5274588f71c8fc518ceb60dc8 Mon Sep 17 00:00:00 2001 From: Zeel Patel Date: Sun, 13 Jun 2021 12:05:26 -0700 Subject: [PATCH 10/17] Add whitespace after , to fix lint issue kernc#356 --- backtesting/_plotting.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backtesting/_plotting.py b/backtesting/_plotting.py index d2724858..c6195777 100644 --- a/backtesting/_plotting.py +++ b/backtesting/_plotting.py @@ -391,9 +391,9 @@ def _plot_pl_section(): returns_short = np.where(trades['Size'] < 0, trades['ReturnPct'], np.nan) size = trades['Size'].abs() size = np.interp(size, (size.min(), size.max()), (8, 20)) - ohlcv_index_trade_close_arr = np.empty(source.data['index'][-1]+1,dtype=float) + ohlcv_index_trade_close_arr = np.empty(source.data['index'][-1]+1, dtype=float) ohlcv_index_trade_close_arr[trade_source.data['index']] = trades['ReturnPct'] - source.add(ohlcv_index_trade_close_arr,'return_pct') + source.add(ohlcv_index_trade_close_arr, 'return_pct') trade_source.add(returns_long, 'returns_long') trade_source.add(returns_short, 'returns_short') trade_source.add(size, 'marker_size') From 97712c7b91ab5fe9520010a669b5e1aabe9e62fc Mon Sep 17 00:00:00 2001 From: Zeel Patel Date: Sun, 13 Jun 2021 12:20:08 -0700 Subject: [PATCH 11/17] Fixing build error by adding [:] kernc#356 --- backtesting/_plotting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backtesting/_plotting.py b/backtesting/_plotting.py index c6195777..e6c52058 100644 --- a/backtesting/_plotting.py +++ b/backtesting/_plotting.py @@ -392,7 +392,7 @@ def _plot_pl_section(): size = trades['Size'].abs() size = np.interp(size, (size.min(), size.max()), (8, 20)) ohlcv_index_trade_close_arr = np.empty(source.data['index'][-1]+1, dtype=float) - ohlcv_index_trade_close_arr[trade_source.data['index']] = trades['ReturnPct'] + ohlcv_index_trade_close_arr[trade_source.data['index'][:]] = trades['ReturnPct'] source.add(ohlcv_index_trade_close_arr, 'return_pct') trade_source.add(returns_long, 'returns_long') trade_source.add(returns_short, 'returns_short') From 14943964415e9fb1007403ba56802cbe7548c513 Mon Sep 17 00:00:00 2001 From: Zeel Patel Date: Sun, 13 Jun 2021 13:36:17 -0700 Subject: [PATCH 12/17] Remove y-axis scaling logic for PnL graph kernc#356 --- backtesting/_plotting.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/backtesting/_plotting.py b/backtesting/_plotting.py index e6c52058..0ecd0d45 100644 --- a/backtesting/_plotting.py +++ b/backtesting/_plotting.py @@ -391,9 +391,6 @@ def _plot_pl_section(): returns_short = np.where(trades['Size'] < 0, trades['ReturnPct'], np.nan) size = trades['Size'].abs() size = np.interp(size, (size.min(), size.max()), (8, 20)) - ohlcv_index_trade_close_arr = np.empty(source.data['index'][-1]+1, dtype=float) - ohlcv_index_trade_close_arr[trade_source.data['index'][:]] = trades['ReturnPct'] - source.add(ohlcv_index_trade_close_arr, 'return_pct') trade_source.add(returns_long, 'returns_long') trade_source.add(returns_short, 'returns_short') trade_source.add(size, 'marker_size') From 95e03f8b61ca1491008f4befb655d97521eefe6f Mon Sep 17 00:00:00 2001 From: Zeel Patel Date: Sun, 13 Jun 2021 13:36:50 -0700 Subject: [PATCH 13/17] Remove y-axis scaling logic for PnL graph kernc#356 --- backtesting/autoscale_cb.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/backtesting/autoscale_cb.js b/backtesting/autoscale_cb.js index 9ed3784c..63135615 100644 --- a/backtesting/autoscale_cb.js +++ b/backtesting/autoscale_cb.js @@ -27,14 +27,6 @@ window._bt_autoscale_timeout = setTimeout(function () { min = Math.min.apply(null, source.data['ohlc_low'].slice(i, j)); _bt_scale_range(ohlc_range, min, max, true); - if (pl_range) { - max = Math.max.apply(null, source.data['return_pct'].slice(i, j)); - min = Math.min.apply(null, source.data['return_pct'].slice(i, j)); - if(min && max){ - _bt_scale_range(pl_range, min, max, true); - } - } - if (volume_range) { max = Math.max.apply(null, source.data['Volume'].slice(i, j)); _bt_scale_range(volume_range, 0, max * 1.03, false); From 50fd012deaec983604d4a9c99eb40ee1d75aa35b Mon Sep 17 00:00:00 2001 From: Zeel Patel Date: Sat, 22 May 2021 19:30:20 -0700 Subject: [PATCH 14/17] Auto-scale Y-axis for indicators when zooming #356 --- backtesting/_plotting.py | 15 +++++++++++++-- backtesting/autoscale_cb.js | 13 +++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/backtesting/_plotting.py b/backtesting/_plotting.py index bec6757a..0ecd0d45 100644 --- a/backtesting/_plotting.py +++ b/backtesting/_plotting.py @@ -523,6 +523,10 @@ def __eq__(self, other): colors = colors and cycle(_as_list(colors)) or ( cycle([next(ohlc_colors)]) if is_overlay else colorgen()) legend_label = LegendStr(value.name) + indicator_max = value.df.max(axis='columns') + indicator_min = value.df.min(axis='columns') + source.add(indicator_max, f'indicator_{i}_range_max') + source.add(indicator_min, f'indicator_{i}_range_min') for j, arr in enumerate(value, 1): color = next(colors) source_name = f'{legend_label}_{i}_{j}' @@ -584,7 +588,8 @@ def __eq__(self, other): figs_above_ohlc.append(_plot_drawdown_section()) if plot_pl: - figs_above_ohlc.append(_plot_pl_section()) + fig_pl = _plot_pl_section() + figs_above_ohlc.append(fig_pl) if plot_volume: fig_volume = _plot_volume_section() @@ -607,9 +612,15 @@ def __eq__(self, other): custom_js_args = dict(ohlc_range=fig_ohlc.y_range, source=source) + if plot_pl: + custom_js_args.update(pl_range=fig_pl.y_range) if plot_volume: custom_js_args.update(volume_range=fig_volume.y_range) - + indicator_ranges = {} + for idx, indicator in enumerate(indicator_figs): + indicator_range_key = f'indicator_{idx}_range' + indicator_ranges.update({indicator_range_key: indicator.y_range}) + custom_js_args.update({'indicator_ranges': indicator_ranges}) fig_ohlc.x_range.js_on_change('end', CustomJS(args=custom_js_args, code=_AUTOSCALE_JS_CALLBACK)) diff --git a/backtesting/autoscale_cb.js b/backtesting/autoscale_cb.js index da888ecf..63135615 100644 --- a/backtesting/autoscale_cb.js +++ b/backtesting/autoscale_cb.js @@ -31,5 +31,18 @@ window._bt_autoscale_timeout = setTimeout(function () { max = Math.max.apply(null, source.data['Volume'].slice(i, j)); _bt_scale_range(volume_range, 0, max * 1.03, false); } + + if(indicator_ranges){ + let keys = Object.keys(indicator_ranges); + for(var count=0;count Date: Thu, 17 Jun 2021 15:42:58 -0700 Subject: [PATCH 15/17] Fix indicator index mapping kernc#356 --- backtesting/_plotting.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/backtesting/_plotting.py b/backtesting/_plotting.py index 0ecd0d45..32f88ad4 100644 --- a/backtesting/_plotting.py +++ b/backtesting/_plotting.py @@ -502,6 +502,7 @@ def __eq__(self, other): ohlc_colors = colorgen() indicator_figs = [] + non_overlay_indicator_idxs = [] for i, value in enumerate(indicators): value = np.atleast_2d(value) @@ -518,6 +519,7 @@ def __eq__(self, other): else: fig = new_indicator_figure() indicator_figs.append(fig) + non_overlay_indicator_idxs.append(i) tooltips = [] colors = value._opts['color'] colors = colors and cycle(_as_list(colors)) or ( @@ -574,7 +576,7 @@ def __eq__(self, other): # have the legend only contain text without the glyph if len(value) == 1: fig.legend.glyph_width = 0 - return indicator_figs + return (indicator_figs, non_overlay_indicator_idxs) # Construct figure ... @@ -600,9 +602,10 @@ def __eq__(self, other): ohlc_bars = _plot_ohlc() _plot_ohlc_trades() - indicator_figs = _plot_indicators() + indicator_figs, non_overlay_indicator_idxs = _plot_indicators() if reverse_indicators: indicator_figs = indicator_figs[::-1] + non_overlay_indicator_idxs = non_overlay_indicator_idxs[::-1] figs_below_ohlc.extend(indicator_figs) set_tooltips(fig_ohlc, ohlc_tooltips, vline=True, renderers=[ohlc_bars]) @@ -617,9 +620,9 @@ def __eq__(self, other): if plot_volume: custom_js_args.update(volume_range=fig_volume.y_range) indicator_ranges = {} - for idx, indicator in enumerate(indicator_figs): - indicator_range_key = f'indicator_{idx}_range' - indicator_ranges.update({indicator_range_key: indicator.y_range}) + for idx,(indicator,indicator_idx) in enumerate(zip(indicator_figs, non_overlay_indicator_idxs)): + indicator_range_key = f'indicator_{indicator_idx}_range' + indicator_ranges.update({indicator_range_key:indicator.y_range}) custom_js_args.update({'indicator_ranges': indicator_ranges}) fig_ohlc.x_range.js_on_change('end', CustomJS(args=custom_js_args, code=_AUTOSCALE_JS_CALLBACK)) From 453dd7bf75dcb2b0a832c1745fcf1ba8de133124 Mon Sep 17 00:00:00 2001 From: Zeel Patel Date: Thu, 17 Jun 2021 15:45:19 -0700 Subject: [PATCH 16/17] Fix lint issues kernc#356 --- backtesting/_plotting.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backtesting/_plotting.py b/backtesting/_plotting.py index 32f88ad4..68f609b3 100644 --- a/backtesting/_plotting.py +++ b/backtesting/_plotting.py @@ -620,9 +620,9 @@ def __eq__(self, other): if plot_volume: custom_js_args.update(volume_range=fig_volume.y_range) indicator_ranges = {} - for idx,(indicator,indicator_idx) in enumerate(zip(indicator_figs, non_overlay_indicator_idxs)): + for idx, (indicator, indicator_idx) in enumerate(zip(indicator_figs, non_overlay_indicator_idxs)): indicator_range_key = f'indicator_{indicator_idx}_range' - indicator_ranges.update({indicator_range_key:indicator.y_range}) + indicator_ranges.update({indicator_range_key: indicator.y_range}) custom_js_args.update({'indicator_ranges': indicator_ranges}) fig_ohlc.x_range.js_on_change('end', CustomJS(args=custom_js_args, code=_AUTOSCALE_JS_CALLBACK)) From 9baed4e338dee7201be2bb93b280303db928c18b Mon Sep 17 00:00:00 2001 From: Zeel Patel Date: Thu, 17 Jun 2021 15:55:47 -0700 Subject: [PATCH 17/17] Fix flake8 formatting issue kernc#356 --- backtesting/_plotting.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backtesting/_plotting.py b/backtesting/_plotting.py index 68f609b3..aa6768cc 100644 --- a/backtesting/_plotting.py +++ b/backtesting/_plotting.py @@ -620,7 +620,8 @@ def __eq__(self, other): if plot_volume: custom_js_args.update(volume_range=fig_volume.y_range) indicator_ranges = {} - for idx, (indicator, indicator_idx) in enumerate(zip(indicator_figs, non_overlay_indicator_idxs)): + for idx, (indicator, + indicator_idx) in enumerate(zip(indicator_figs, non_overlay_indicator_idxs)): indicator_range_key = f'indicator_{indicator_idx}_range' indicator_ranges.update({indicator_range_key: indicator.y_range}) custom_js_args.update({'indicator_ranges': indicator_ranges})