@@ -422,64 +422,62 @@ class LegendStr(str):
422422 # legend items are listed separately even when they have the
423423 # same string contents. Otherwise, Bokeh would always consider
424424 # equal strings as one and the same legend item.
425- # This also prevents legend items named the same as some
426- # ColumnDataSource's column to be replaced with that column's
427- # values.
428425 def __eq__ (self , other ):
429426 return self is other
430427
431428 ohlc_colors = colorgen ()
432429
433- for value in indicators :
430+ for i , value in enumerate ( indicators ) :
434431 value = np .atleast_2d (value )
435432
436433 # Use .get()! A user might have assigned a Strategy.data-evolved
437434 # _Array without Strategy.I()
438435 if not value ._opts .get ('plot' ) or _too_many_dims (value ):
439436 continue
440437
438+ is_overlay = value ._opts ['overlay' ]
439+ is_scatter = value ._opts ['scatter' ]
440+ if is_overlay :
441+ fig = fig_ohlc
442+ else :
443+ fig = new_indicator_figure ()
444+ figs_below_ohlc .append (fig )
441445 tooltips = []
442-
443- # Overlay indicators on the OHLC figure
444- if value ._opts ['overlay' ]:
445- color = value ._opts ['color' ]
446- color = color and _as_list (color )[0 ] or next (ohlc_colors )
447- legend = LegendStr (value .name )
448- for i , arr in enumerate (value ):
449- source_name = '{}_{}' .format (value .name , i )
450- source .add (arr , source_name )
451- if value ._opts .get ('scatter' ):
452- fig_ohlc .scatter (
446+ colors = value ._opts ['color' ]
447+ colors = colors and cycle ([_as_list (colors )[0 ]]) or (
448+ cycle ([next (ohlc_colors )]) if is_overlay else colorgen ())
449+ legend_label = LegendStr (value .name )
450+ for j , arr in enumerate (value , 1 ):
451+ color = next (colors )
452+ source_name = '{}_{}_{}' .format (legend_label , i , j )
453+ if arr .dtype == bool :
454+ arr = arr .astype (int )
455+ source .add (arr , source_name )
456+ tooltips .append ('@{{{}}}{{0,0.0[0000]}}' .format (source_name ))
457+ if is_overlay :
458+ ohlc_extreme_values [source_name ] = arr
459+ if is_scatter :
460+ fig .scatter (
453461 'index' , source_name , source = source ,
454- color = color , line_color = 'black' , fill_alpha = .8 ,
455- marker = 'circle' , radius = bar_width / 2 * 1.5 , legend_label = legend )
462+ legend_label = legend_label , color = color ,
463+ line_color = 'black' , fill_alpha = .8 ,
464+ marker = 'circle' , radius = bar_width / 2 * 1.5 )
456465 else :
457- fig_ohlc .line (
466+ fig .line (
458467 'index' , source_name , source = source ,
459- line_width = 1.3 , line_color = color , legend_label = legend )
460- ohlc_extreme_values [source_name ] = arr
461- tooltips .append ('@{{{}}}{{0,0.0[0000]}}' .format (source_name ))
462- ohlc_tooltips .append ((value .name , NBSP .join (tooltips )))
463- else :
464- # Standalone indicator sections at the bottom
465- color = value ._opts ['color' ]
466- color = color and cycle (_as_list (color )) or colorgen ()
467- fig = new_indicator_figure ()
468- for i , arr in enumerate (value , 1 ):
469- legend = '{}-{}' .format (value .name , i ) if len (value ) > 1 else value .name
470- name = legend + '_' # Otherwise fig.line(legend=) is interpreted as col of source # noqa: E501
471- tooltips .append ('@{{{}}}' .format (name ))
472- source .add (arr .astype (int if arr .dtype == bool else float ), name )
473- if value ._opts .get ('scatter' ):
468+ legend_label = legend_label , line_color = color ,
469+ line_width = 1.3 )
470+ else :
471+ if is_scatter :
474472 r = fig .scatter (
475- 'index' , name , source = source , color = next ( color ) ,
476- marker = 'circle' , radius = bar_width / 2 * .9 ,
477- legend_label = LegendStr ( legend ) )
473+ 'index' , source_name , source = source ,
474+ legend_label = LegendStr ( legend_label ), color = color ,
475+ marker = 'circle' , radius = bar_width / 2 * .9 )
478476 else :
479477 r = fig .line (
480- 'index' , name , source = source , line_color = next ( color ) ,
481- line_width = 1.3 , legend_label = LegendStr (legend ))
482-
478+ 'index' , source_name , source = source ,
479+ legend_label = LegendStr (legend_label ), line_color = color ,
480+ line_width = 1.3 )
483481 # Add dashed centerline just because
484482 mean = float (pd .Series (arr ).mean ())
485483 if not np .isnan (mean ) and (abs (mean ) < .1 or
@@ -488,16 +486,15 @@ def __eq__(self, other):
488486 fig .add_layout (Span (location = float (mean ), dimension = 'width' ,
489487 line_color = '#666666' , line_dash = 'dashed' ,
490488 line_width = .5 ))
491-
492- set_tooltips (fig , [(value .name , NBSP .join (tooltips ))], vline = True , renderers = [r ])
493-
489+ if is_overlay :
490+ ohlc_tooltips .append ((legend_label , NBSP .join (tooltips )))
491+ else :
492+ set_tooltips (fig , [(legend_label , NBSP .join (tooltips ))], vline = True , renderers = [r ])
494493 # If the sole indicator line on this figure,
495494 # have the legend only contain text without the glyph
496495 if len (value ) == 1 :
497496 fig .legend .glyph_width = 0
498497
499- figs_below_ohlc .append (fig )
500-
501498 # Construct figure ...
502499
503500 if plot_equity :
0 commit comments