Strategy indicators
()
| 525 | line_width=8, line_alpha=1, line_dash='dotted') |
| 526 | |
| 527 | def _plot_indicators(): |
| 528 | """Strategy indicators""" |
| 529 | |
| 530 | def _too_many_dims(value): |
| 531 | assert value.ndim >= 2 |
| 532 | if value.ndim > 2: |
| 533 | warnings.warn(f"Can't plot indicators with >2D ('{value.name}')", |
| 534 | stacklevel=5) |
| 535 | return True |
| 536 | return False |
| 537 | |
| 538 | class LegendStr(str): |
| 539 | # The legend string is such a string that only matches |
| 540 | # itself if it's the exact same object. This ensures |
| 541 | # legend items are listed separately even when they have the |
| 542 | # same string contents. Otherwise, Bokeh would always consider |
| 543 | # equal strings as one and the same legend item. |
| 544 | def __eq__(self, other): |
| 545 | return self is other |
| 546 | |
| 547 | ohlc_colors = colorgen() |
| 548 | indicator_figs = [] |
| 549 | |
| 550 | for i, value in enumerate(indicators): |
| 551 | value = np.atleast_2d(value) |
| 552 | if _too_many_dims(value): |
| 553 | continue |
| 554 | |
| 555 | # Use .get()! A user might have assigned a Strategy.data-evolved |
| 556 | # _Array without Strategy.I() |
| 557 | is_overlay = value._opts.get('overlay') |
| 558 | is_scatter = value._opts.get('scatter') |
| 559 | is_muted = not value._opts.get('plot') |
| 560 | |
| 561 | # is overlay => show muted, hide legend item. non-overlay => don't show at all |
| 562 | if is_muted and not is_overlay: |
| 563 | continue |
| 564 | |
| 565 | if is_overlay: |
| 566 | fig = fig_ohlc |
| 567 | else: |
| 568 | fig = new_indicator_figure() |
| 569 | indicator_figs.append(fig) |
| 570 | tooltips = [] |
| 571 | colors = value._opts['color'] |
| 572 | colors = colors and cycle(_as_list(colors)) or ( |
| 573 | cycle([next(ohlc_colors)]) if is_overlay else colorgen()) |
| 574 | |
| 575 | if isinstance(value.name, str): |
| 576 | tooltip_label = value.name |
| 577 | legend_labels = [LegendStr(value.name)] * len(value) |
| 578 | else: |
| 579 | tooltip_label = ", ".join(value.name) |
| 580 | legend_labels = [LegendStr(item) for item in value.name] |
| 581 | |
| 582 | for j, arr in enumerate(value): |
| 583 | color = next(colors) |
| 584 | source_name = f'{legend_labels[j]}_{i}_{j}' |
no test coverage detected