backtrader.bokeh.tabs.metadata 源代码

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

Displays metadata info for strategy and backtest.
"""

import datetime

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 MetadataTab(BokehTab): """Metadata tab. Displays metadata info for strategy, data, indicators, etc. """ def _is_useable(self): """Metadata tab is always useable.""" return BOKEH_AVAILABLE def _get_panel(self): """Get panel content. Returns: tuple: (widget, title) """ strategy = self.strategy scheme = self.scheme text_color = scheme.text_color if scheme else "#333" widgets = [] # Basic info widgets.append( Div( text=f'<h3 style="color: {text_color};">Backtest Metadata</h3>', sizing_mode="stretch_width", ) ) metadata = {} # Time info metadata["Generated"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") if strategy is not None: # Strategy info metadata["Strategy"] = strategy.__class__.__name__ # Data info if hasattr(strategy, "datas") and strategy.datas: metadata["Data Feeds"] = len(strategy.datas) # Data range data = strategy.datas[0] if hasattr(data, "datetime") and len(data) > 0: try: # Get start and end dates start_dt = data.datetime.date(0) if hasattr(data.datetime, "date"): end_dt = data.datetime.date(-1) if len(data) > 1 else start_dt else: end_dt = start_dt metadata["Start Date"] = str(start_dt) metadata["End Date"] = str(end_dt) metadata["Total Bars"] = len(data) except Exception: pass # Indicator info if hasattr(strategy, "_lineiterators"): ind_count = len(strategy._lineiterators.get(1, [])) # IndType = 1 obs_count = len(strategy._lineiterators.get(2, [])) # ObsType = 2 metadata["Indicators"] = ind_count metadata["Observers"] = obs_count # Analyzer info if hasattr(strategy, "analyzers"): metadata["Analyzers"] = len(strategy.analyzers) # Broker info if hasattr(strategy, "broker"): broker = strategy.broker try: metadata["Final Value"] = f"{broker.getvalue():.2f}" metadata["Final Cash"] = f"{broker.getcash():.2f}" except Exception: pass # Create table if metadata: source = ColumnDataSource( data={ "property": list(metadata.keys()), "value": [str(v) for v in metadata.values()], } ) columns = [ TableColumn(field="property", title="Property"), TableColumn(field="value", title="Value"), ] table = DataTable( source=source, columns=columns, width=400, height=min(len(metadata) * 25 + 30, 400), index_position=None, ) widgets.append(table) # Indicator list if strategy is not None and hasattr(strategy, "_lineiterators"): indicators = strategy._lineiterators.get(1, []) if indicators: widgets.append( Div( text=f'<h3 style="color: {text_color};">Indicators</h3>', sizing_mode="stretch_width", ) ) ind_data = [] for ind in indicators: ind_data.append( { "name": ind.__class__.__name__, "lines": ", ".join(getattr(ind.lines, "_getlinealiases", lambda: [])()), } ) if ind_data: source = ColumnDataSource( data={ "name": [d["name"] for d in ind_data], "lines": [d["lines"] for d in ind_data], } ) columns = [ TableColumn(field="name", title="Indicator"), TableColumn(field="lines", title="Lines"), ] table = DataTable( source=source, columns=columns, width=400, height=min(len(ind_data) * 25 + 30, 200), index_position=None, ) widgets.append(table) content = column(*widgets, sizing_mode="stretch_width") return content, "Metadata"