@@ -422,64 +422,62 @@ class LegendStr(str):
422
422
# legend items are listed separately even when they have the
423
423
# same string contents. Otherwise, Bokeh would always consider
424
424
# 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.
428
425
def __eq__ (self , other ):
429
426
return self is other
430
427
431
428
ohlc_colors = colorgen ()
432
429
433
- for value in indicators :
430
+ for i , value in enumerate ( indicators ) :
434
431
value = np .atleast_2d (value )
435
432
436
433
# Use .get()! A user might have assigned a Strategy.data-evolved
437
434
# _Array without Strategy.I()
438
435
if not value ._opts .get ('plot' ) or _too_many_dims (value ):
439
436
continue
440
437
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 )
441
445
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 (
453
461
'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 )
456
465
else :
457
- fig_ohlc .line (
466
+ fig .line (
458
467
'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 :
474
472
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 )
478
476
else :
479
477
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 )
483
481
# Add dashed centerline just because
484
482
mean = float (pd .Series (arr ).mean ())
485
483
if not np .isnan (mean ) and (abs (mean ) < .1 or
@@ -488,16 +486,15 @@ def __eq__(self, other):
488
486
fig .add_layout (Span (location = float (mean ), dimension = 'width' ,
489
487
line_color = '#666666' , line_dash = 'dashed' ,
490
488
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 ])
494
493
# If the sole indicator line on this figure,
495
494
# have the legend only contain text without the glyph
496
495
if len (value ) == 1 :
497
496
fig .legend .glyph_width = 0
498
497
499
- figs_below_ohlc .append (fig )
500
-
501
498
# Construct figure ...
502
499
503
500
if plot_equity :
0 commit comments