backtrader.bokeh.tabs.live 源代码

#!/usr/bin/env python
"""
Live configuration tab.
For configuration adjustments in live plotting mode.
"""

from ..tab import BokehTab

try:
    from bokeh.layouts import column
    from bokeh.models.widgets import Button, Div, Select, Slider

    BOKEH_AVAILABLE = True
except ImportError:
    BOKEH_AVAILABLE = False


[文档] class LiveTab(BokehTab): """Live configuration tab. Provides configuration options for live plotting mode: - Lookback adjustment - Auto-refresh interval - Filter options """ def _is_useable(self): """Useable in live mode.""" if not BOKEH_AVAILABLE: return False return self._client is not None def _get_panel(self): """Get panel content. Returns: tuple: (widget, title) """ scheme = self.scheme text_color = scheme.text_color if scheme else "#333" widgets = [] # Title widgets.append( Div( text=f'<h3 style="color: {text_color};">Live Plot Settings</h3>', sizing_mode="stretch_width", ) ) # Lookback settings lookback_value = getattr(self._client, "lookback", 100) if self._client else 100 lookback_slider = Slider( start=10, end=500, value=lookback_value, step=10, title="Lookback (candles)", width=300 ) def on_lookback_change(attr, old, new): if self._client is not None: self._client.lookback = new lookback_slider.on_change("value", on_lookback_change) widgets.append(lookback_slider) # Fill Gaps option fill_gaps = getattr(self._client, "fill_gaps", False) if self._client else False fill_gaps_select = Select( title="Fill Gaps", value="Yes" if fill_gaps else "No", options=["Yes", "No"], width=150 ) def on_fill_gaps_change(attr, old, new): if self._client is not None: self._client.fill_gaps = new == "Yes" fill_gaps_select.on_change("value", on_fill_gaps_change) widgets.append(fill_gaps_select) # Plot Group settings plotgroup = getattr(self._client, "plotgroup", "") if self._client else "" plotgroup_select = Select( title="Plot Group", value=plotgroup or "All", options=["All"], # Can dynamically add more options width=200, ) widgets.append(plotgroup_select) # Refresh button refresh_btn = Button(label="Refresh", button_type="primary", width=100) def on_refresh_click(): if self._client is not None: self._client.updatemodel() refresh_btn.on_click(on_refresh_click) widgets.append(refresh_btn) # Status info status_text = ( "Running" if self._client and not getattr(self._client, "_paused", True) else "Paused" ) status_div = Div( text=f'<p style="color: {text_color};">Status: <strong>{status_text}</strong></p>', sizing_mode="stretch_width", ) widgets.append(status_div) content = column(*widgets, sizing_mode="stretch_width") return content, "Live"