backtrader.bokeh.tabs.analyzer 源代码

#!/usr/bin/env python
"""
Analyzer tab.

Displays results of all analyzers.
"""

from ..tab import BokehTab

try:
    from bokeh.layouts import column
    from bokeh.models import ColumnDataSource, DataTable, TableColumn
    from bokeh.models.widgets import Div

    BOKEH_AVAILABLE = True
except ImportError:
    BOKEH_AVAILABLE = False


[文档] class AnalyzerTab(BokehTab): """Analyzer tab. Displays analysis results of all analyzers in the strategy. """ def _is_useable(self): """Check if useable. Useable when strategy has analyzers. """ if not BOKEH_AVAILABLE: return False strategy = self.strategy if strategy is None: return False return len(getattr(strategy, "analyzers", [])) > 0 def _get_panel(self): """Get panel content. Returns: tuple: (widget, title) """ strategy = self.strategy scheme = self.scheme # Create analyzer results display widgets = [] for analyzer in strategy.analyzers: analyzer_name = analyzer.__class__.__name__ # Get analysis results try: analysis = analyzer.get_analysis() except Exception: analysis = {} # Create title title_div = Div( text=f'<h3 style="color: {scheme.text_color if scheme else "#333"};">{analyzer_name}</h3>', sizing_mode="stretch_width", ) widgets.append(title_div) # Convert analysis results to table data data = self._flatten_analysis(analysis) if data: source = ColumnDataSource( data={"key": list(data.keys()), "value": [str(v) for v in data.values()]} ) columns = [ TableColumn(field="key", title="Metric"), TableColumn(field="value", title="Value"), ] table = DataTable( source=source, columns=columns, width=400, height=min(len(data) * 25 + 30, 300), index_position=None, ) widgets.append(table) else: empty_div = Div(text="<p>No data available</p>") widgets.append(empty_div) content = column(*widgets, sizing_mode="stretch_width") return content, "Analyzers" def _flatten_analysis(self, analysis, prefix=""): """Flatten nested analysis results. Args: analysis: Analysis result dictionary prefix: Key prefix Returns: dict: Flattened dictionary """ result = {} if isinstance(analysis, dict): for key, value in analysis.items(): new_key = f"{prefix}.{key}" if prefix else str(key) if isinstance(value, dict): result.update(self._flatten_analysis(value, new_key)) else: result[new_key] = value else: result[prefix or "value"] = analysis return result