694 lines
26 KiB
Python
694 lines
26 KiB
Python
"""
|
|
Bot-Enhanced Signal Layers
|
|
|
|
This module provides enhanced versions of signal layers that automatically integrate
|
|
with the bot management system, making it easier to display bot signals and trades
|
|
without manual data fetching.
|
|
"""
|
|
|
|
import pandas as pd
|
|
import plotly.graph_objects as go
|
|
from typing import Dict, Any, Optional, List, Union, Tuple
|
|
from dataclasses import dataclass
|
|
from datetime import datetime, timedelta
|
|
|
|
from .signals import (
|
|
TradingSignalLayer, TradeExecutionLayer, EnhancedSignalLayer,
|
|
SignalLayerConfig, TradeLayerConfig, SignalStyleConfig
|
|
)
|
|
from .bot_integration import (
|
|
BotFilterConfig, BotSignalLayerIntegration, bot_integration,
|
|
get_active_bot_signals, get_active_bot_trades
|
|
)
|
|
from utils.logger import get_logger
|
|
|
|
# Initialize logger
|
|
logger = get_logger()
|
|
|
|
|
|
@dataclass
|
|
class BotSignalLayerConfig(SignalLayerConfig):
|
|
"""Extended configuration for bot-integrated signal layers"""
|
|
# Bot filtering options
|
|
bot_filter: Optional[BotFilterConfig] = None
|
|
auto_fetch_data: bool = True # Automatically fetch bot data
|
|
time_window_days: int = 7 # Time window for data fetching
|
|
active_bots_only: bool = True # Only show signals from active bots
|
|
include_bot_info: bool = True # Include bot info in hover text
|
|
group_by_strategy: bool = False # Group signals by strategy
|
|
|
|
def __post_init__(self):
|
|
super().__post_init__()
|
|
if self.bot_filter is None:
|
|
self.bot_filter = BotFilterConfig(active_only=self.active_bots_only)
|
|
|
|
|
|
@dataclass
|
|
class BotTradeLayerConfig(TradeLayerConfig):
|
|
"""Extended configuration for bot-integrated trade layers"""
|
|
# Bot filtering options
|
|
bot_filter: Optional[BotFilterConfig] = None
|
|
auto_fetch_data: bool = True # Automatically fetch bot data
|
|
time_window_days: int = 7 # Time window for data fetching
|
|
active_bots_only: bool = True # Only show trades from active bots
|
|
include_bot_info: bool = True # Include bot info in hover text
|
|
group_by_strategy: bool = False # Group trades by strategy
|
|
|
|
def __post_init__(self):
|
|
super().__post_init__()
|
|
if self.bot_filter is None:
|
|
self.bot_filter = BotFilterConfig(active_only=self.active_bots_only)
|
|
|
|
|
|
class BotIntegratedSignalLayer(TradingSignalLayer):
|
|
"""
|
|
Signal layer that automatically integrates with bot management system.
|
|
"""
|
|
|
|
def __init__(self, config: BotSignalLayerConfig = None):
|
|
"""
|
|
Initialize bot-integrated signal layer.
|
|
|
|
Args:
|
|
config: Bot signal layer configuration (optional)
|
|
"""
|
|
if config is None:
|
|
config = BotSignalLayerConfig(
|
|
name="Bot Signals",
|
|
enabled=True,
|
|
signal_types=['buy', 'sell'],
|
|
confidence_threshold=0.3,
|
|
auto_fetch_data=True,
|
|
active_bots_only=True
|
|
)
|
|
|
|
# Convert to base config for parent class
|
|
base_config = SignalLayerConfig(
|
|
name=config.name,
|
|
enabled=config.enabled,
|
|
signal_types=config.signal_types,
|
|
confidence_threshold=config.confidence_threshold,
|
|
show_confidence=config.show_confidence,
|
|
marker_size=config.marker_size,
|
|
show_price_labels=config.show_price_labels,
|
|
bot_id=config.bot_id
|
|
)
|
|
|
|
super().__init__(base_config)
|
|
self.bot_config = config
|
|
self.integration = BotSignalLayerIntegration()
|
|
|
|
self.logger.info(f"Bot Enhanced Signal Layer: Initialized BotIntegratedSignalLayer: {config.name}")
|
|
|
|
def render(self, fig: go.Figure, data: pd.DataFrame, signals: pd.DataFrame = None, **kwargs) -> go.Figure:
|
|
"""
|
|
Render bot signals on the chart with automatic data fetching.
|
|
|
|
Args:
|
|
fig: Plotly figure to render onto
|
|
data: Market data (OHLCV format)
|
|
signals: Optional manual signal data (if not provided, will auto-fetch)
|
|
**kwargs: Additional rendering parameters including 'symbol' and 'timeframe'
|
|
|
|
Returns:
|
|
Updated figure with bot signal overlays
|
|
"""
|
|
try:
|
|
# Auto-fetch bot signals if not provided and auto_fetch is enabled
|
|
if signals is None and self.bot_config.auto_fetch_data:
|
|
symbol = kwargs.get('symbol')
|
|
timeframe = kwargs.get('timeframe')
|
|
|
|
if not symbol:
|
|
self.logger.warning("No symbol provided and no manual signals - cannot auto-fetch bot signals")
|
|
return fig
|
|
|
|
# Calculate time range
|
|
end_time = datetime.now()
|
|
start_time = end_time - timedelta(days=self.bot_config.time_window_days)
|
|
time_range = (start_time, end_time)
|
|
|
|
# Fetch signals from bots
|
|
signals = self.integration.get_signals_for_chart(
|
|
symbol=symbol,
|
|
timeframe=timeframe,
|
|
bot_filter=self.bot_config.bot_filter,
|
|
time_range=time_range,
|
|
signal_types=self.bot_config.signal_types,
|
|
min_confidence=self.bot_config.confidence_threshold
|
|
)
|
|
|
|
if signals.empty:
|
|
self.logger.info(f"No bot signals found for {symbol}")
|
|
return fig
|
|
|
|
self.logger.info(f"Auto-fetched {len(signals)} bot signals for {symbol}")
|
|
|
|
# Enhance signals with bot information if available
|
|
if signals is not None and not signals.empty and self.bot_config.include_bot_info:
|
|
signals = self._enhance_signals_with_bot_info(signals)
|
|
|
|
# Use parent render method
|
|
return super().render(fig, data, signals, **kwargs)
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error rendering bot-integrated signals: {e}")
|
|
# Add error annotation
|
|
fig.add_annotation(
|
|
text=f"Bot Signal Error: {str(e)}",
|
|
x=0.5, y=0.95,
|
|
xref="paper", yref="paper",
|
|
showarrow=False,
|
|
font=dict(color="red", size=10)
|
|
)
|
|
return fig
|
|
|
|
def _enhance_signals_with_bot_info(self, signals: pd.DataFrame) -> pd.DataFrame:
|
|
"""
|
|
Enhance signals with additional bot information for better visualization.
|
|
|
|
Args:
|
|
signals: Signal data
|
|
|
|
Returns:
|
|
Enhanced signal data
|
|
"""
|
|
if 'bot_name' in signals.columns and 'strategy' in signals.columns:
|
|
# Signals already enhanced
|
|
return signals
|
|
|
|
# If we have bot info columns, enhance hover text would be handled in trace creation
|
|
return signals
|
|
|
|
def create_signal_traces(self, signals: pd.DataFrame) -> List[go.Scatter]:
|
|
"""
|
|
Create enhanced signal traces with bot information.
|
|
|
|
Args:
|
|
signals: Filtered signal data
|
|
|
|
Returns:
|
|
List of enhanced Plotly traces
|
|
"""
|
|
traces = []
|
|
|
|
try:
|
|
if signals.empty:
|
|
return traces
|
|
|
|
# Group by strategy if enabled
|
|
if self.bot_config.group_by_strategy and 'strategy' in signals.columns:
|
|
for strategy in signals['strategy'].unique():
|
|
strategy_signals = signals[signals['strategy'] == strategy]
|
|
strategy_traces = self._create_strategy_traces(strategy_signals, strategy)
|
|
traces.extend(strategy_traces)
|
|
else:
|
|
# Use parent method for standard signal grouping
|
|
traces = super().create_signal_traces(signals)
|
|
|
|
# Enhance traces with bot information
|
|
if self.bot_config.include_bot_info:
|
|
traces = self._enhance_traces_with_bot_info(traces, signals)
|
|
|
|
return traces
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error creating bot signal traces: {e}")
|
|
error_trace = self.create_error_trace(f"Error displaying bot signals: {str(e)}")
|
|
return [error_trace]
|
|
|
|
def _create_strategy_traces(self, signals: pd.DataFrame, strategy: str) -> List[go.Scatter]:
|
|
"""
|
|
Create traces grouped by strategy.
|
|
|
|
Args:
|
|
signals: Signal data for specific strategy
|
|
strategy: Strategy name
|
|
|
|
Returns:
|
|
List of traces for this strategy
|
|
"""
|
|
traces = []
|
|
|
|
# Group by signal type within strategy
|
|
for signal_type in signals['signal_type'].unique():
|
|
type_signals = signals[signals['signal_type'] == signal_type]
|
|
|
|
if type_signals.empty:
|
|
continue
|
|
|
|
# Enhanced hover text with bot and strategy info
|
|
hover_text = []
|
|
for _, signal in type_signals.iterrows():
|
|
hover_parts = [
|
|
f"Signal: {signal['signal_type'].upper()}",
|
|
f"Price: ${signal['price']:.4f}",
|
|
f"Time: {signal['timestamp']}",
|
|
f"Strategy: {strategy}"
|
|
]
|
|
|
|
if 'confidence' in signal and signal['confidence'] is not None:
|
|
hover_parts.append(f"Confidence: {signal['confidence']:.1%}")
|
|
|
|
if 'bot_name' in signal and signal['bot_name']:
|
|
hover_parts.append(f"Bot: {signal['bot_name']}")
|
|
|
|
if 'bot_status' in signal and signal['bot_status']:
|
|
hover_parts.append(f"Status: {signal['bot_status']}")
|
|
|
|
hover_text.append("<br>".join(hover_parts))
|
|
|
|
# Create trace for this signal type in strategy
|
|
trace = go.Scatter(
|
|
x=type_signals['timestamp'],
|
|
y=type_signals['price'],
|
|
mode='markers',
|
|
marker=dict(
|
|
symbol=self.signal_symbols.get(signal_type, 'circle'),
|
|
size=self.config.marker_size,
|
|
color=self.signal_colors.get(signal_type, '#666666'),
|
|
line=dict(width=1, color='white'),
|
|
opacity=0.8
|
|
),
|
|
name=f"{strategy} - {signal_type.upper()}",
|
|
text=hover_text,
|
|
hoverinfo='text',
|
|
showlegend=True,
|
|
legendgroup=f"strategy_{strategy}_{signal_type}"
|
|
)
|
|
|
|
traces.append(trace)
|
|
|
|
return traces
|
|
|
|
def _enhance_traces_with_bot_info(self, traces: List[go.Scatter], signals: pd.DataFrame) -> List[go.Scatter]:
|
|
"""
|
|
Enhance existing traces with bot information.
|
|
|
|
Args:
|
|
traces: Original traces
|
|
signals: Signal data with bot info
|
|
|
|
Returns:
|
|
Enhanced traces
|
|
"""
|
|
# This would be implemented to modify hover text of existing traces
|
|
# For now, return traces as-is since bot info enhancement happens in trace creation
|
|
return traces
|
|
|
|
|
|
class BotIntegratedTradeLayer(TradeExecutionLayer):
|
|
"""
|
|
Trade layer that automatically integrates with bot management system.
|
|
"""
|
|
|
|
def __init__(self, config: BotTradeLayerConfig = None):
|
|
"""
|
|
Initialize bot-integrated trade layer.
|
|
|
|
Args:
|
|
config: Bot trade layer configuration (optional)
|
|
"""
|
|
if config is None:
|
|
config = BotTradeLayerConfig(
|
|
name="Bot Trades",
|
|
enabled=True,
|
|
show_pnl=True,
|
|
show_trade_lines=True,
|
|
auto_fetch_data=True,
|
|
active_bots_only=True
|
|
)
|
|
|
|
# Convert to base config for parent class
|
|
base_config = TradeLayerConfig(
|
|
name=config.name,
|
|
enabled=config.enabled,
|
|
show_pnl=config.show_pnl,
|
|
show_trade_lines=config.show_trade_lines,
|
|
show_quantity=config.show_quantity,
|
|
show_fees=config.show_fees,
|
|
min_pnl_display=config.min_pnl_display,
|
|
bot_id=config.bot_id,
|
|
trade_marker_size=config.trade_marker_size
|
|
)
|
|
|
|
super().__init__(base_config)
|
|
self.bot_config = config
|
|
self.integration = BotSignalLayerIntegration()
|
|
|
|
self.logger.info(f"Bot Enhanced Trade Layer: Initialized BotIntegratedTradeLayer: {config.name}")
|
|
|
|
def render(self, fig: go.Figure, data: pd.DataFrame, trades: pd.DataFrame = None, **kwargs) -> go.Figure:
|
|
"""
|
|
Render bot trades on the chart with automatic data fetching.
|
|
|
|
Args:
|
|
fig: Plotly figure to render onto
|
|
data: Market data (OHLCV format)
|
|
trades: Optional manual trade data (if not provided, will auto-fetch)
|
|
**kwargs: Additional rendering parameters including 'symbol' and 'timeframe'
|
|
|
|
Returns:
|
|
Updated figure with bot trade overlays
|
|
"""
|
|
try:
|
|
# Auto-fetch bot trades if not provided and auto_fetch is enabled
|
|
if trades is None and self.bot_config.auto_fetch_data:
|
|
symbol = kwargs.get('symbol')
|
|
timeframe = kwargs.get('timeframe')
|
|
|
|
if not symbol:
|
|
self.logger.warning("Bot Enhanced Trade Layer: No symbol provided and no manual trades - cannot auto-fetch bot trades")
|
|
return fig
|
|
|
|
# Calculate time range
|
|
end_time = datetime.now()
|
|
start_time = end_time - timedelta(days=self.bot_config.time_window_days)
|
|
time_range = (start_time, end_time)
|
|
|
|
# Fetch trades from bots
|
|
trades = self.integration.get_trades_for_chart(
|
|
symbol=symbol,
|
|
timeframe=timeframe,
|
|
bot_filter=self.bot_config.bot_filter,
|
|
time_range=time_range
|
|
)
|
|
|
|
if trades.empty:
|
|
self.logger.info(f"Bot Enhanced Trade Layer: No bot trades found for {symbol}")
|
|
return fig
|
|
|
|
self.logger.info(f"Bot Enhanced Trade Layer: Auto-fetched {len(trades)} bot trades for {symbol}")
|
|
|
|
# Use parent render method
|
|
return super().render(fig, data, trades, **kwargs)
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Bot Enhanced Trade Layer: Error rendering bot-integrated trades: {e}")
|
|
# Add error annotation
|
|
fig.add_annotation(
|
|
text=f"Bot Trade Error: {str(e)}",
|
|
x=0.5, y=0.95,
|
|
xref="paper", yref="paper",
|
|
showarrow=False,
|
|
font=dict(color="red", size=10)
|
|
)
|
|
return fig
|
|
|
|
|
|
class BotMultiLayerIntegration:
|
|
"""
|
|
Integration utility for managing multiple bot-related chart layers.
|
|
"""
|
|
|
|
def __init__(self):
|
|
"""Initialize multi-layer bot integration."""
|
|
self.integration = BotSignalLayerIntegration()
|
|
self.logger = logger
|
|
|
|
def create_bot_layers_for_symbol(self,
|
|
symbol: str,
|
|
timeframe: str = None,
|
|
bot_filter: BotFilterConfig = None,
|
|
include_signals: bool = True,
|
|
include_trades: bool = True,
|
|
time_window_days: int = 7) -> Dict[str, Any]:
|
|
"""
|
|
Create a complete set of bot-integrated layers for a symbol.
|
|
|
|
Args:
|
|
symbol: Trading symbol
|
|
timeframe: Chart timeframe (optional)
|
|
bot_filter: Bot filtering configuration
|
|
include_signals: Include signal layer
|
|
include_trades: Include trade layer
|
|
time_window_days: Time window for data
|
|
|
|
Returns:
|
|
Dictionary with layer instances and metadata
|
|
"""
|
|
layers = {}
|
|
metadata = {}
|
|
|
|
try:
|
|
if bot_filter is None:
|
|
bot_filter = BotFilterConfig(symbols=[symbol], active_only=True)
|
|
|
|
# Create signal layer
|
|
if include_signals:
|
|
signal_config = BotSignalLayerConfig(
|
|
name=f"{symbol} Bot Signals",
|
|
enabled=True,
|
|
bot_filter=bot_filter,
|
|
time_window_days=time_window_days,
|
|
signal_types=['buy', 'sell'],
|
|
confidence_threshold=0.3,
|
|
include_bot_info=True
|
|
)
|
|
|
|
layers['signals'] = BotIntegratedSignalLayer(signal_config)
|
|
metadata['signals'] = {
|
|
'layer_type': 'bot_signals',
|
|
'symbol': symbol,
|
|
'timeframe': timeframe,
|
|
'time_window_days': time_window_days
|
|
}
|
|
|
|
# Create trade layer
|
|
if include_trades:
|
|
trade_config = BotTradeLayerConfig(
|
|
name=f"{symbol} Bot Trades",
|
|
enabled=True,
|
|
bot_filter=bot_filter,
|
|
time_window_days=time_window_days,
|
|
show_pnl=True,
|
|
show_trade_lines=True,
|
|
include_bot_info=True
|
|
)
|
|
|
|
layers['trades'] = BotIntegratedTradeLayer(trade_config)
|
|
metadata['trades'] = {
|
|
'layer_type': 'bot_trades',
|
|
'symbol': symbol,
|
|
'timeframe': timeframe,
|
|
'time_window_days': time_window_days
|
|
}
|
|
|
|
# Get bot summary for metadata
|
|
bot_summary = self.integration.get_bot_summary_stats()
|
|
metadata['bot_summary'] = bot_summary
|
|
|
|
self.logger.info(f"Bot Enhanced Multi Layer Integration: Created {len(layers)} bot layers for {symbol}")
|
|
|
|
return {
|
|
'layers': layers,
|
|
'metadata': metadata,
|
|
'symbol': symbol,
|
|
'timeframe': timeframe,
|
|
'success': True
|
|
}
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Bot Enhanced Multi Layer Integration: Error creating bot layers for {symbol}: {e}")
|
|
return {
|
|
'layers': {},
|
|
'metadata': {},
|
|
'symbol': symbol,
|
|
'timeframe': timeframe,
|
|
'success': False,
|
|
'error': str(e)
|
|
}
|
|
|
|
def create_strategy_comparison_layers(self,
|
|
symbol: str,
|
|
strategies: List[str],
|
|
timeframe: str = None,
|
|
time_window_days: int = 7) -> Dict[str, Any]:
|
|
"""
|
|
Create layers to compare different strategies for a symbol.
|
|
|
|
Args:
|
|
symbol: Trading symbol
|
|
strategies: List of strategy names to compare
|
|
timeframe: Chart timeframe (optional)
|
|
time_window_days: Time window for data
|
|
|
|
Returns:
|
|
Dictionary with strategy comparison layers
|
|
"""
|
|
layers = {}
|
|
metadata = {}
|
|
|
|
try:
|
|
for strategy in strategies:
|
|
bot_filter = BotFilterConfig(
|
|
symbols=[symbol],
|
|
strategies=[strategy],
|
|
active_only=False # Include all bots for comparison
|
|
)
|
|
|
|
# Create signal layer for this strategy
|
|
signal_config = BotSignalLayerConfig(
|
|
name=f"{strategy} Signals",
|
|
enabled=True,
|
|
bot_filter=bot_filter,
|
|
time_window_days=time_window_days,
|
|
group_by_strategy=True,
|
|
include_bot_info=True
|
|
)
|
|
|
|
layers[f"{strategy}_signals"] = BotIntegratedSignalLayer(signal_config)
|
|
|
|
# Create trade layer for this strategy
|
|
trade_config = BotTradeLayerConfig(
|
|
name=f"{strategy} Trades",
|
|
enabled=True,
|
|
bot_filter=bot_filter,
|
|
time_window_days=time_window_days,
|
|
group_by_strategy=True,
|
|
include_bot_info=True
|
|
)
|
|
|
|
layers[f"{strategy}_trades"] = BotIntegratedTradeLayer(trade_config)
|
|
|
|
metadata[strategy] = {
|
|
'strategy': strategy,
|
|
'symbol': symbol,
|
|
'timeframe': timeframe,
|
|
'layer_count': 2
|
|
}
|
|
|
|
self.logger.info(f"Bot Enhanced Multi Layer Integration: Created strategy comparison layers for {len(strategies)} strategies on {symbol}")
|
|
|
|
return {
|
|
'layers': layers,
|
|
'metadata': metadata,
|
|
'symbol': symbol,
|
|
'strategies': strategies,
|
|
'success': True
|
|
}
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Bot Enhanced Multi Layer Integration: Error creating strategy comparison layers: {e}")
|
|
return {
|
|
'layers': {},
|
|
'metadata': {},
|
|
'symbol': symbol,
|
|
'strategies': strategies,
|
|
'success': False,
|
|
'error': str(e)
|
|
}
|
|
|
|
|
|
# Global instance for easy access
|
|
bot_multi_layer = BotMultiLayerIntegration()
|
|
|
|
|
|
# Convenience functions for creating bot-integrated layers
|
|
|
|
def create_bot_signal_layer(symbol: str,
|
|
timeframe: str = None,
|
|
active_only: bool = True,
|
|
confidence_threshold: float = 0.3,
|
|
time_window_days: int = 7,
|
|
**kwargs) -> BotIntegratedSignalLayer:
|
|
"""
|
|
Create a bot-integrated signal layer for a symbol.
|
|
|
|
Args:
|
|
symbol: Trading symbol
|
|
timeframe: Chart timeframe (optional)
|
|
active_only: Only include active bots
|
|
confidence_threshold: Minimum confidence threshold
|
|
time_window_days: Time window for data fetching
|
|
**kwargs: Additional configuration options
|
|
|
|
Returns:
|
|
Configured BotIntegratedSignalLayer
|
|
"""
|
|
bot_filter = BotFilterConfig(
|
|
symbols=[symbol],
|
|
active_only=active_only
|
|
)
|
|
|
|
config = BotSignalLayerConfig(
|
|
name=f"{symbol} Bot Signals",
|
|
enabled=True,
|
|
bot_filter=bot_filter,
|
|
confidence_threshold=confidence_threshold,
|
|
time_window_days=time_window_days,
|
|
signal_types=kwargs.get('signal_types', ['buy', 'sell']),
|
|
include_bot_info=kwargs.get('include_bot_info', True),
|
|
group_by_strategy=kwargs.get('group_by_strategy', False),
|
|
**{k: v for k, v in kwargs.items() if k not in [
|
|
'signal_types', 'include_bot_info', 'group_by_strategy'
|
|
]}
|
|
)
|
|
|
|
return BotIntegratedSignalLayer(config)
|
|
|
|
|
|
def create_bot_trade_layer(symbol: str,
|
|
timeframe: str = None,
|
|
active_only: bool = True,
|
|
show_pnl: bool = True,
|
|
time_window_days: int = 7,
|
|
**kwargs) -> BotIntegratedTradeLayer:
|
|
"""
|
|
Create a bot-integrated trade layer for a symbol.
|
|
|
|
Args:
|
|
symbol: Trading symbol
|
|
timeframe: Chart timeframe (optional)
|
|
active_only: Only include active bots
|
|
show_pnl: Show profit/loss information
|
|
time_window_days: Time window for data fetching
|
|
**kwargs: Additional configuration options
|
|
|
|
Returns:
|
|
Configured BotIntegratedTradeLayer
|
|
"""
|
|
bot_filter = BotFilterConfig(
|
|
symbols=[symbol],
|
|
active_only=active_only
|
|
)
|
|
|
|
config = BotTradeLayerConfig(
|
|
name=f"{symbol} Bot Trades",
|
|
enabled=True,
|
|
bot_filter=bot_filter,
|
|
show_pnl=show_pnl,
|
|
time_window_days=time_window_days,
|
|
show_trade_lines=kwargs.get('show_trade_lines', True),
|
|
include_bot_info=kwargs.get('include_bot_info', True),
|
|
group_by_strategy=kwargs.get('group_by_strategy', False),
|
|
**{k: v for k, v in kwargs.items() if k not in [
|
|
'show_trade_lines', 'include_bot_info', 'group_by_strategy'
|
|
]}
|
|
)
|
|
|
|
return BotIntegratedTradeLayer(config)
|
|
|
|
|
|
def create_complete_bot_layers(symbol: str,
|
|
timeframe: str = None,
|
|
active_only: bool = True,
|
|
time_window_days: int = 7) -> Dict[str, Any]:
|
|
"""
|
|
Create a complete set of bot-integrated layers for a symbol.
|
|
|
|
Args:
|
|
symbol: Trading symbol
|
|
timeframe: Chart timeframe (optional)
|
|
active_only: Only include active bots
|
|
time_window_days: Time window for data fetching
|
|
|
|
Returns:
|
|
Dictionary with signal and trade layers
|
|
"""
|
|
return bot_multi_layer.create_bot_layers_for_symbol(
|
|
symbol=symbol,
|
|
timeframe=timeframe,
|
|
bot_filter=BotFilterConfig(symbols=[symbol], active_only=active_only),
|
|
time_window_days=time_window_days
|
|
) |