backtrader.bokeh.tabs.config 源代码

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

Displays configuration info for strategy and data.
"""

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 ConfigTab(BokehTab): """Configuration tab. Displays strategy parameters, data configuration and other info. """ def _is_useable(self): """Config tab is always useable.""" return BOKEH_AVAILABLE def _get_panel(self): """Get panel content. Returns: tuple: (widget, title) """ strategy = self.strategy scheme = self.scheme widgets = [] text_color = scheme.text_color if scheme else "#333" # Strategy parameters if strategy is not None: # Strategy name strategy_name = strategy.__class__.__name__ widgets.append( Div( text=f'<h3 style="color: {text_color};">Strategy: {strategy_name}</h3>', sizing_mode="stretch_width", ) ) # Strategy parameters params = {} if hasattr(strategy, "params"): for name in dir(strategy.params): if not name.startswith("_"): try: value = getattr(strategy.params, name) if not callable(value): params[name] = value except Exception: pass if params: source = ColumnDataSource( data={ "parameter": list(params.keys()), "value": [str(v) for v in params.values()], } ) columns = [ TableColumn(field="parameter", title="Parameter"), TableColumn(field="value", title="Value"), ] table = DataTable( source=source, columns=columns, width=400, height=min(len(params) * 25 + 30, 300), index_position=None, ) widgets.append(table) # Data source info if hasattr(strategy, "datas") and strategy.datas: widgets.append( Div( text=f'<h3 style="color: {text_color};">Data Feeds</h3>', sizing_mode="stretch_width", ) ) data_info = [] for i, data in enumerate(strategy.datas): name = data._name if hasattr(data, "_name") else f"Data{i}" length = len(data) if hasattr(data, "__len__") else "N/A" data_info.append( { "name": name, "length": str(length), "timeframe": str( getattr(data._timeframe, "name", "N/A") if hasattr(data, "_timeframe") else "N/A" ), } ) if data_info: source = ColumnDataSource( data={ "name": [d["name"] for d in data_info], "length": [d["length"] for d in data_info], "timeframe": [d["timeframe"] for d in data_info], } ) columns = [ TableColumn(field="name", title="Name"), TableColumn(field="length", title="Length"), TableColumn(field="timeframe", title="Timeframe"), ] table = DataTable( source=source, columns=columns, width=400, height=min(len(data_info) * 25 + 30, 200), index_position=None, ) widgets.append(table) if not widgets: widgets.append(Div(text="<p>No configuration available</p>")) content = column(*widgets, sizing_mode="stretch_width") return content, "Config"