TCPDashboard/dashboard/callbacks/realtime_strategies.py
Vasily.onl 8c23489ff0 4.0 - 4.0 Implement real-time strategy execution and data integration features
- Added `realtime_execution.py` for real-time strategy execution, enabling live signal generation and integration with the dashboard's chart refresh cycle.
- Introduced `data_integration.py` to manage market data orchestration, caching, and technical indicator calculations for strategy signal generation.
- Implemented `validation.py` for comprehensive validation and quality assessment of strategy-generated signals, ensuring reliability and consistency.
- Developed `batch_processing.py` to facilitate efficient backtesting of multiple strategies across large datasets with memory management and performance optimization.
- Updated `__init__.py` files to include new modules and ensure proper exports, enhancing modularity and maintainability.
- Enhanced unit tests for the new features, ensuring robust functionality and adherence to project standards.

These changes establish a solid foundation for real-time strategy execution and data integration, aligning with project goals for modularity, performance, and maintainability.
2025-06-12 18:29:39 +08:00

291 lines
11 KiB
Python

"""
Real-time Strategy Callbacks
This module provides callbacks for integrating real-time strategy execution
with the dashboard chart refresh cycle and user interactions.
"""
import json
from dash import Output, Input, State, Patch, ctx, html, no_update, dcc, callback
import dash_bootstrap_components as dbc
from datetime import datetime, timedelta
from typing import Dict, Any, List, Optional
from utils.logger import get_logger
from strategies.realtime_execution import (
get_realtime_strategy_processor,
initialize_realtime_strategy_system,
RealTimeConfig,
RealTimeSignal
)
from strategies.manager import StrategyManager
from config.strategies.config_utils import StrategyConfigurationManager
logger = get_logger()
# Global processor instance
_processor = None
def get_processor():
"""Get or initialize the real-time strategy processor."""
global _processor
if _processor is None:
config = RealTimeConfig(
refresh_interval_seconds=30,
max_strategies_concurrent=3,
incremental_calculation=True,
signal_batch_size=50,
enable_signal_broadcasting=True
)
_processor = initialize_realtime_strategy_system(config)
return _processor
def register_realtime_strategy_callbacks(app):
"""Register real-time strategy callbacks."""
@app.callback(
Output('realtime-strategies-store', 'data'),
[Input('realtime-strategy-toggle', 'value'),
Input('symbol-dropdown', 'value'),
Input('timeframe-dropdown', 'value'),
Input('strategy-dropdown', 'value')],
[State('realtime-strategies-store', 'data')],
prevent_initial_call=True
)
def manage_realtime_strategies(enable_realtime, symbol, timeframe, strategy_name, current_data):
"""
Manage real-time strategy registration based on user selections.
This callback handles enabling/disabling real-time strategy execution
and registers strategies based on current chart selections.
"""
try:
current_data = current_data or {'active_strategies': [], 'enabled': False}
processor = get_processor()
if not enable_realtime:
# Disable all strategies
for context_id in current_data.get('active_strategies', []):
processor.unregister_strategy(context_id)
logger.info(f"Unregistered real-time strategy: {context_id}")
return {'active_strategies': [], 'enabled': False}
# Enable real-time strategies
if symbol and timeframe and strategy_name and strategy_name != 'basic':
# Load strategy configuration
try:
config_manager = StrategyConfigurationManager()
strategy_config = config_manager.load_user_strategy_config(strategy_name)
if not strategy_config:
# Load from templates if user config doesn't exist
strategy_config = config_manager.load_strategy_template(strategy_name)
if strategy_config:
# Register strategy for real-time execution
context_id = processor.register_strategy(
strategy_name=strategy_name,
strategy_config=strategy_config,
symbol=symbol,
timeframe=timeframe
)
active_strategies = [context_id]
logger.info(f"Registered real-time strategy: {context_id}")
return {
'active_strategies': active_strategies,
'enabled': True,
'current_symbol': symbol,
'current_timeframe': timeframe,
'current_strategy': strategy_name
}
except Exception as e:
logger.error(f"Error loading strategy configuration for {strategy_name}: {e}")
return current_data
return current_data
except Exception as e:
logger.error(f"Error managing real-time strategies: {e}")
return current_data or {'active_strategies': [], 'enabled': False}
@app.callback(
Output('realtime-strategy-status', 'children'),
[Input('realtime-strategies-store', 'data'),
Input('interval-component', 'n_intervals')],
prevent_initial_call=True
)
def update_realtime_status(strategy_data, n_intervals):
"""
Update real-time strategy status display.
Shows current status of real-time strategy execution including
active strategies and performance metrics.
"""
try:
if not strategy_data or not strategy_data.get('enabled'):
return dbc.Alert("Real-time strategy execution is disabled", color="secondary", className="mb-2")
processor = get_processor()
active_strategies = processor.get_active_strategies()
perf_stats = processor.get_performance_stats()
if not active_strategies:
return dbc.Alert("No active real-time strategies", color="warning", className="mb-2")
# Build status display
status_items = []
# Active strategies
for context_id, context in active_strategies.items():
status_items.append(
html.Li([
html.Strong(f"{context.strategy_name}: "),
f"{context.symbol} {context.timeframe}",
html.Span(
"" if context.is_active else " ⚠️",
style={'color': 'green' if context.is_active else 'orange'}
)
])
)
# Performance metrics
success_rate = 0
if perf_stats['total_calculations'] > 0:
success_rate = (perf_stats['successful_calculations'] / perf_stats['total_calculations']) * 100
metrics_text = f"Calculations: {perf_stats['total_calculations']} | " \
f"Success Rate: {success_rate:.1f}% | " \
f"Signals Generated: {perf_stats['signals_generated']}"
return dbc.Card([
dbc.CardHeader("Real-time Strategy Status"),
dbc.CardBody([
html.H6("Active Strategies:", className="mb-2"),
html.Ul(status_items, className="mb-3"),
html.P(metrics_text, className="small mb-0")
])
], className="mb-2")
except Exception as e:
logger.error(f"Error updating real-time status: {e}")
return dbc.Alert(f"Error updating status: {str(e)}", color="danger", className="mb-2")
# Integration with chart refresh cycle
@app.callback(
Output('realtime-execution-trigger', 'data'),
[Input('interval-component', 'n_intervals')],
[State('symbol-dropdown', 'value'),
State('timeframe-dropdown', 'value'),
State('realtime-strategies-store', 'data'),
State('analysis-mode-toggle', 'value')],
prevent_initial_call=True
)
def trigger_realtime_execution(n_intervals, symbol, timeframe, strategy_data, analysis_mode):
"""
Trigger real-time strategy execution when new data is available.
This callback integrates with the existing chart refresh cycle to
execute real-time strategies when new candle data arrives.
"""
try:
# Only execute in live mode
if analysis_mode == 'locked':
return no_update
# Only execute if real-time strategies are enabled
if not strategy_data or not strategy_data.get('enabled'):
return no_update
# Only execute if we have symbol and timeframe
if not symbol or not timeframe:
return no_update
processor = get_processor()
# Execute real-time strategy update
signals = processor.execute_realtime_update(
symbol=symbol,
timeframe=timeframe,
exchange="okx"
)
if signals:
logger.info(f"Real-time execution generated {len(signals)} signals for {symbol} {timeframe}")
return {
'timestamp': datetime.now().isoformat(),
'signals_generated': len(signals),
'symbol': symbol,
'timeframe': timeframe
}
return no_update
except Exception as e:
logger.error(f"Error in real-time strategy execution: {e}")
return no_update
def add_realtime_strategy_components():
"""
Add real-time strategy components to the dashboard layout.
Returns:
List of Dash components for real-time strategy controls
"""
return [
# Real-time strategy toggle
dbc.Row([
dbc.Col([
dbc.Label("Real-time Strategy Execution", className="fw-bold"),
dbc.Switch(
id="realtime-strategy-toggle",
label="Enable Real-time Execution",
value=False,
className="mb-2"
),
], width=12)
], className="mb-3"),
# Status display
html.Div(id="realtime-strategy-status"),
# Hidden stores for state management
dcc.Store(id="realtime-strategies-store", data={'active_strategies': [], 'enabled': False}),
dcc.Store(id="realtime-execution-trigger", data={}),
]
def setup_chart_update_callback():
"""
Setup chart update callback for real-time signals.
This function configures the real-time processor to trigger
chart updates when new signals are generated.
"""
def chart_update_callback(signal: RealTimeSignal):
"""Handle chart updates for real-time signals."""
try:
# This would trigger chart refresh for the specific symbol/timeframe
# For now, we'll log the signal and let the regular refresh cycle handle it
logger.debug(
f"Chart update requested for signal: {signal.context.strategy_name} "
f"on {signal.context.symbol} {signal.context.timeframe}"
)
# Future enhancement: Could trigger specific chart layer updates here
except Exception as e:
logger.error(f"Error in chart update callback: {e}")
processor = get_processor()
processor.set_chart_update_callback(chart_update_callback)
# Initialize the chart update callback when module is imported
setup_chart_update_callback()