NPU (wip); docker
This commit is contained in:
@@ -99,7 +99,6 @@ except ImportError:
|
||||
from core.realtime_rl_cob_trader import RealtimeRLCOBTrader, PredictionResult
|
||||
|
||||
# Import multi-timeframe prediction system
|
||||
from NN.models.multi_timeframe_predictor import MultiTimeframePredictor, PredictionHorizon
|
||||
|
||||
# Single unified orchestrator with full ML capabilities
|
||||
|
||||
@@ -133,8 +132,10 @@ class CleanTradingDashboard:
|
||||
self._initialize_enhanced_training_system()
|
||||
|
||||
# Initialize multi-timeframe prediction system
|
||||
self.multi_timeframe_predictor = None
|
||||
self._initialize_multi_timeframe_predictor()
|
||||
# Initialize prediction tracking
|
||||
self.current_10min_prediction = None
|
||||
self.chained_predictions = [] # Store chained inference results
|
||||
self.last_chained_inference_time = None
|
||||
|
||||
# Initialize 10-minute prediction storage
|
||||
self.current_10min_prediction = None
|
||||
@@ -1156,6 +1157,30 @@ class CleanTradingDashboard:
|
||||
}
|
||||
return "Error", "Error", "0.0%", "0.00", "❌ Error", "❌ Error", "❌ Error", "❌ Error", empty_fig, empty_fig
|
||||
|
||||
# Add callback for minute-based chained inference
|
||||
@self.app.callback(
|
||||
Output('chained-inference-status', 'children'),
|
||||
[Input('minute-interval-component', 'n_intervals')]
|
||||
)
|
||||
def update_chained_inference(n):
|
||||
"""Run chained inference every minute"""
|
||||
try:
|
||||
# Run chained inference every minute
|
||||
success = self.run_chained_inference("ETH/USDT", n_steps=10)
|
||||
|
||||
if success:
|
||||
status = f"✅ Chained inference completed ({len(self.chained_predictions)} predictions)"
|
||||
if self.last_chained_inference_time:
|
||||
status += f" at {self.last_chained_inference_time.strftime('%H:%M:%S')}"
|
||||
else:
|
||||
status = "❌ Chained inference failed"
|
||||
|
||||
return status
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in chained inference callback: {e}")
|
||||
return f"❌ Error: {str(e)}"
|
||||
|
||||
def _get_real_model_performance_data(self) -> Dict[str, Any]:
|
||||
"""Get real model performance data from orchestrator"""
|
||||
try:
|
||||
@@ -1932,155 +1957,11 @@ class CleanTradingDashboard:
|
||||
self._add_dqn_predictions_to_chart(fig, symbol, df_main, row)
|
||||
self._add_cnn_predictions_to_chart(fig, symbol, df_main, row)
|
||||
self._add_cob_rl_predictions_to_chart(fig, symbol, df_main, row)
|
||||
self._add_iterative_predictions_to_chart(fig, symbol, df_main, row)
|
||||
self._add_prediction_accuracy_feedback(fig, symbol, df_main, row)
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"Error adding model predictions to chart: {e}")
|
||||
|
||||
def _add_iterative_predictions_to_chart(self, fig: go.Figure, symbol: str, df_main: pd.DataFrame, row: int = 1):
|
||||
"""Add 10-minute iterative predictions to the main chart with fading opacity"""
|
||||
try:
|
||||
if not hasattr(self, 'multi_timeframe_predictor') or not self.multi_timeframe_predictor:
|
||||
logger.debug("❌ Multi-timeframe predictor not available")
|
||||
return
|
||||
|
||||
# Run iterative prediction every minute
|
||||
current_time = datetime.now()
|
||||
if not hasattr(self, '_last_prediction_time') or \
|
||||
(current_time - self._last_prediction_time).total_seconds() >= 60:
|
||||
|
||||
try:
|
||||
prediction_result = self.run_iterative_prediction_10min(symbol)
|
||||
if prediction_result:
|
||||
self._last_prediction_time = current_time
|
||||
logger.info("✅ 10-minute iterative prediction completed")
|
||||
else:
|
||||
logger.warning("❌ 10-minute iterative prediction returned None")
|
||||
except Exception as e:
|
||||
logger.error(f"Error running iterative prediction: {e}")
|
||||
|
||||
# Get current predictions from stored result
|
||||
if hasattr(self, 'current_10min_prediction') and self.current_10min_prediction:
|
||||
predictions = self.current_10min_prediction.get('predictions', [])
|
||||
logger.debug(f"🔍 Found {len(predictions)} predictions in current_10min_prediction")
|
||||
|
||||
if predictions:
|
||||
logger.info(f"📊 Processing {len(predictions)} predictions for chart display")
|
||||
# Group predictions by age for fading effect
|
||||
prediction_groups = {}
|
||||
current_time = datetime.now()
|
||||
|
||||
for pred in predictions[-50:]: # Last 50 predictions
|
||||
prediction_time = pred.get('timestamp')
|
||||
if not prediction_time:
|
||||
logger.debug(f"❌ Prediction missing timestamp: {pred}")
|
||||
continue
|
||||
|
||||
if isinstance(prediction_time, str):
|
||||
try:
|
||||
prediction_time = pd.to_datetime(prediction_time)
|
||||
except Exception as e:
|
||||
logger.debug(f"❌ Could not parse timestamp '{prediction_time}': {e}")
|
||||
continue
|
||||
|
||||
# Calculate age in minutes (how long ago this prediction was made)
|
||||
# For future predictions, use a small positive age to show them as current
|
||||
if prediction_time > current_time:
|
||||
age_minutes = 0.1 # Future predictions treated as very recent
|
||||
else:
|
||||
age_minutes = (current_time - prediction_time).total_seconds() / 60
|
||||
|
||||
logger.debug(f"🔍 Prediction age: {age_minutes:.2f} min, timestamp: {prediction_time}, current: {current_time}")
|
||||
|
||||
# Group by age ranges for fading
|
||||
if age_minutes <= 1:
|
||||
group = 'current' # Very recent, high opacity
|
||||
elif age_minutes <= 3:
|
||||
group = 'recent' # Recent, medium opacity
|
||||
elif age_minutes <= 5:
|
||||
group = 'old' # Older, low opacity
|
||||
else:
|
||||
continue # Too old, skip
|
||||
|
||||
if group not in prediction_groups:
|
||||
prediction_groups[group] = []
|
||||
|
||||
prediction_groups[group].append({
|
||||
'x': prediction_time,
|
||||
'y': pred.get('close', 0),
|
||||
'high': pred.get('high', 0),
|
||||
'low': pred.get('low', 0),
|
||||
'confidence': pred.get('confidence', 0),
|
||||
'age': age_minutes
|
||||
})
|
||||
|
||||
# Add predictions with fading opacity
|
||||
opacity_levels = {
|
||||
'current': 0.8, # Bright for very recent
|
||||
'recent': 0.5, # Medium for recent
|
||||
'old': 0.3 # Dim for older
|
||||
}
|
||||
|
||||
logger.info(f"📊 Adding {len(prediction_groups)} prediction groups to chart")
|
||||
|
||||
for group, preds in prediction_groups.items():
|
||||
if not preds:
|
||||
continue
|
||||
|
||||
opacity = opacity_levels[group]
|
||||
logger.info(f"📈 Adding {group} predictions: {len(preds)} points, opacity: {opacity}")
|
||||
|
||||
# Add prediction line
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=[p['x'] for p in preds],
|
||||
y=[p['y'] for p in preds],
|
||||
mode='lines+markers',
|
||||
line=dict(
|
||||
color=f'rgba(255, 215, 0, {opacity})', # Gold color
|
||||
width=2,
|
||||
dash='dash'
|
||||
),
|
||||
marker=dict(
|
||||
symbol='diamond',
|
||||
size=6,
|
||||
color=f'rgba(255, 215, 0, {opacity})',
|
||||
line=dict(width=1, color='rgba(255, 140, 0, 0.8)')
|
||||
),
|
||||
name=f'🔮 10min Pred ({group})',
|
||||
showlegend=True,
|
||||
hovertemplate="<b>🔮 10-Minute Prediction</b><br>" +
|
||||
"Predicted Close: $%{y:.2f}<br>" +
|
||||
"Time: %{x}<br>" +
|
||||
"Age: %{customdata:.1f} min<br>" +
|
||||
"Confidence: %{text:.1%}<extra></extra>",
|
||||
customdata=[p['age'] for p in preds],
|
||||
text=[p['confidence'] for p in preds]
|
||||
),
|
||||
row=row, col=1
|
||||
)
|
||||
|
||||
# Add confidence bands (high/low range)
|
||||
if len(preds) > 1:
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=[p['x'] for p in preds] + [p['x'] for p in reversed(preds)],
|
||||
y=[p['high'] for p in preds] + [p['low'] for p in reversed(preds)],
|
||||
fill='toself',
|
||||
fillcolor=f'rgba(255, 215, 0, {opacity * 0.2})',
|
||||
line=dict(width=0),
|
||||
mode='lines',
|
||||
name=f'Prediction Range ({group})',
|
||||
showlegend=False,
|
||||
hoverinfo='skip'
|
||||
),
|
||||
row=row, col=1
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.debug(f"Error adding iterative predictions to chart: {e}")
|
||||
|
||||
def _add_dqn_predictions_to_chart(self, fig: go.Figure, symbol: str, df_main: pd.DataFrame, row: int = 1):
|
||||
"""Add DQN action predictions as directional arrows"""
|
||||
try:
|
||||
@@ -5292,68 +5173,44 @@ class CleanTradingDashboard:
|
||||
logger.error(f"Error exporting trade history: {e}")
|
||||
return ""
|
||||
|
||||
def run_chained_inference(self, symbol: str = "ETH/USDT", n_steps: int = 10) -> bool:
|
||||
"""Run chained inference using the orchestrator's real models"""
|
||||
try:
|
||||
if not self.orchestrator:
|
||||
logger.warning("No orchestrator available for chained inference")
|
||||
return False
|
||||
|
||||
logger.info(f"🔗 Running chained inference for {symbol} with {n_steps} steps")
|
||||
|
||||
# Run chained inference
|
||||
predictions = self.orchestrator.chain_inference(symbol, n_steps)
|
||||
|
||||
if predictions:
|
||||
# Store predictions
|
||||
self.chained_predictions = predictions
|
||||
self.last_chained_inference_time = datetime.now()
|
||||
|
||||
logger.info(f"✅ Chained inference completed: {len(predictions)} predictions generated")
|
||||
|
||||
# Log first few predictions for debugging
|
||||
for i, pred in enumerate(predictions[:3]):
|
||||
logger.info(f" Step {i}: {pred.get('model', 'Unknown')} - Confidence: {pred.get('confidence', 0):.3f}")
|
||||
|
||||
return True
|
||||
else:
|
||||
logger.warning("❌ Chained inference returned no predictions")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error running chained inference: {e}")
|
||||
return False
|
||||
|
||||
def export_trades_now(self) -> str:
|
||||
"""Convenience method to export trades immediately with timestamp"""
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
filename = f"trades_export_{timestamp}.csv"
|
||||
return self.export_trade_history_csv(filename)
|
||||
|
||||
def run_iterative_prediction_10min(self, symbol: str = "ETH/USDT") -> Optional[Dict]:
|
||||
"""Run 10-minute iterative prediction using the multi-timeframe predictor"""
|
||||
try:
|
||||
if not self.multi_timeframe_predictor:
|
||||
logger.warning("Multi-timeframe predictor not available")
|
||||
return None
|
||||
|
||||
logger.info(f"🔮 Running 10-minute iterative prediction for {symbol}")
|
||||
|
||||
# Get current price and market conditions
|
||||
current_price = self._get_current_price(symbol)
|
||||
if not current_price:
|
||||
logger.warning(f"Could not get current price for {symbol}")
|
||||
return None
|
||||
|
||||
# Run iterative prediction for 10 minutes
|
||||
iterative_predictions = self.multi_timeframe_predictor._generate_iterative_predictions(
|
||||
symbol=symbol,
|
||||
base_data=self.multi_timeframe_predictor._get_sequence_data_for_horizon(
|
||||
symbol, self.multi_timeframe_predictor.horizons[PredictionHorizon.TEN_MINUTES]['sequence_length']
|
||||
),
|
||||
num_steps=10, # 10 steps for 10-minute prediction
|
||||
market_conditions={'confidence_multiplier': 1.0}
|
||||
)
|
||||
|
||||
if iterative_predictions:
|
||||
# Analyze the 10-minute prediction
|
||||
config = self.multi_timeframe_predictor.horizons[PredictionHorizon.TEN_MINUTES]
|
||||
market_conditions = self.multi_timeframe_predictor._assess_market_conditions(symbol)
|
||||
|
||||
horizon_prediction = self.multi_timeframe_predictor._analyze_horizon_prediction(
|
||||
iterative_predictions, config, market_conditions
|
||||
)
|
||||
|
||||
if horizon_prediction:
|
||||
# Store the prediction for dashboard display
|
||||
self.current_10min_prediction = {
|
||||
'symbol': symbol,
|
||||
'timestamp': datetime.now(),
|
||||
'predictions': iterative_predictions,
|
||||
'horizon_analysis': horizon_prediction,
|
||||
'current_price': current_price
|
||||
}
|
||||
|
||||
logger.info(f"✅ 10-minute iterative prediction completed for {symbol}")
|
||||
logger.info(f"📊 Generated {len(iterative_predictions)} candle predictions")
|
||||
|
||||
return self.current_10min_prediction
|
||||
|
||||
logger.warning("Failed to generate 10-minute iterative prediction")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error running 10-minute iterative prediction: {e}")
|
||||
return None
|
||||
|
||||
def create_10min_prediction_chart(self, opacity: float = 0.4) -> Dict[str, Any]:
|
||||
"""DEPRECATED: Create a chart visualizing the 10-minute iterative predictions with opacity
|
||||
Note: Predictions are now integrated directly into the main 1-minute chart"""
|
||||
@@ -6737,20 +6594,6 @@ class CleanTradingDashboard:
|
||||
logger.error(f"Error initializing enhanced training system: {e}")
|
||||
self.training_system = None
|
||||
|
||||
def _initialize_multi_timeframe_predictor(self):
|
||||
"""Initialize multi-timeframe prediction system"""
|
||||
try:
|
||||
if self.orchestrator:
|
||||
self.multi_timeframe_predictor = MultiTimeframePredictor(self.orchestrator)
|
||||
logger.info("Multi-timeframe prediction system initialized")
|
||||
else:
|
||||
logger.warning("Cannot initialize multi-timeframe predictor - no orchestrator available")
|
||||
self.multi_timeframe_predictor = None
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error initializing multi-timeframe predictor: {e}")
|
||||
self.multi_timeframe_predictor = None
|
||||
|
||||
def _initialize_cob_integration(self):
|
||||
"""Initialize COB integration using orchestrator's COB system"""
|
||||
try:
|
||||
@@ -7070,69 +6913,24 @@ class CleanTradingDashboard:
|
||||
|
||||
logger.info(f"COB SIGNAL: {symbol} {signal['action']} signal generated - imbalance: {imbalance:.3f}, confidence: {signal['confidence']:.3f}")
|
||||
|
||||
# Enhance signal with multi-timeframe predictions if available
|
||||
enhanced_signal = self._enhance_signal_with_multi_timeframe(signal)
|
||||
if enhanced_signal:
|
||||
signal = enhanced_signal
|
||||
|
||||
# Process the signal for potential execution
|
||||
self._process_dashboard_signal(signal)
|
||||
|
||||
except Exception as e:
|
||||
logger.debug(f"Error generating COB signal for {symbol}: {e}")
|
||||
|
||||
def _enhance_signal_with_multi_timeframe(self, signal: Dict) -> Optional[Dict]:
|
||||
"""Enhance signal with multi-timeframe predictions for better accuracy and hold times"""
|
||||
def _get_rl_state_for_training(self, symbol: str, current_price: float) -> Dict[str, Any]:
|
||||
"""Get RL state for training purposes"""
|
||||
try:
|
||||
if not self.multi_timeframe_predictor:
|
||||
return signal
|
||||
|
||||
symbol = signal.get('symbol', 'ETH/USDT')
|
||||
|
||||
# Generate multi-timeframe prediction
|
||||
multi_prediction = self.multi_timeframe_predictor.generate_multi_timeframe_prediction(symbol)
|
||||
|
||||
if not multi_prediction:
|
||||
return signal
|
||||
|
||||
# Check if we should execute the trade
|
||||
should_execute, reason = self.multi_timeframe_predictor.should_execute_trade(multi_prediction)
|
||||
|
||||
if not should_execute:
|
||||
logger.debug(f"Multi-timeframe analysis: Not executing - {reason}")
|
||||
return None # Don't execute this signal
|
||||
|
||||
# Find the best prediction for enhanced signal
|
||||
best_prediction = None
|
||||
best_confidence = 0
|
||||
|
||||
for horizon, pred in multi_prediction.predictions.items():
|
||||
if pred['confidence'] > best_confidence:
|
||||
best_confidence = pred['confidence']
|
||||
best_prediction = (horizon, pred)
|
||||
|
||||
if best_prediction:
|
||||
horizon, pred = best_prediction
|
||||
|
||||
# Enhance original signal with multi-timeframe data
|
||||
enhanced_signal = signal.copy()
|
||||
enhanced_signal['confidence'] = pred['confidence'] # Use higher confidence
|
||||
enhanced_signal['prediction_horizon'] = horizon.value # Store horizon
|
||||
enhanced_signal['hold_time_minutes'] = horizon.value # Suggested hold time
|
||||
enhanced_signal['multi_timeframe'] = True
|
||||
enhanced_signal['models_used'] = pred.get('models_used', 1)
|
||||
enhanced_signal['reasoning'] = f"{signal.get('reasoning', '')} | Multi-timeframe {horizon.value}min prediction"
|
||||
|
||||
logger.info(f"Enhanced signal: {symbol} {pred['action']} with {pred['confidence']:.2f} confidence "
|
||||
f"for {horizon.value}-minute horizon")
|
||||
|
||||
return enhanced_signal
|
||||
|
||||
return signal
|
||||
|
||||
return {
|
||||
'symbol': symbol,
|
||||
'price': current_price,
|
||||
'timestamp': datetime.now(),
|
||||
'features': [current_price, 0, 0, 0, 0] # Placeholder features
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Error enhancing signal with multi-timeframe: {e}")
|
||||
return signal
|
||||
logger.error(f"Error getting RL state: {e}")
|
||||
return {}
|
||||
|
||||
def _feed_cob_data_to_models(self, symbol: str, cob_snapshot: dict):
|
||||
"""Feed COB data to ALL models for training and inference - Enhanced integration"""
|
||||
@@ -7601,6 +7399,11 @@ class CleanTradingDashboard:
|
||||
"""Start the Dash server"""
|
||||
try:
|
||||
logger.info(f"TRADING: Starting Clean Dashboard at http://{host}:{port}")
|
||||
|
||||
# Run initial chained inference when dashboard starts
|
||||
logger.info("🔗 Running initial chained inference...")
|
||||
self.run_chained_inference("ETH/USDT", n_steps=10)
|
||||
|
||||
# Run the Dash app normally; launch/activation is handled by the runner
|
||||
if hasattr(self, 'app') and self.app is not None:
|
||||
# Dash 3.x: use app.run
|
||||
|
Reference in New Issue
Block a user