display predictions

This commit is contained in:
Dobromir Popov
2025-06-27 01:12:55 +03:00
parent 63f26a6749
commit 97ea27ea84
3 changed files with 1229 additions and 16 deletions

View File

@ -106,6 +106,10 @@ class CleanTradingDashboard:
else:
self.orchestrator = orchestrator
# Initialize enhanced training system for predictions
self.training_system = None
self._initialize_enhanced_training_system()
# Initialize layout and component managers
self.layout_manager = DashboardLayoutManager(
starting_balance=self._get_initial_balance(),
@ -711,9 +715,9 @@ class CleanTradingDashboard:
x=0.5, y=0.5, showarrow=False)
def _add_model_predictions_to_chart(self, fig: go.Figure, symbol: str, df_main: pd.DataFrame, row: int = 1):
"""Add model predictions to the chart - ONLY EXECUTED TRADES on main chart"""
"""Add enhanced model predictions to the chart with real-time feedback"""
try:
# Only show EXECUTED TRADES on the main 1m chart
# 1. Add executed trades (existing functionality)
executed_signals = [signal for signal in self.recent_decisions if self._get_signal_attribute(signal, 'executed', False)]
if executed_signals:
@ -721,8 +725,7 @@ class CleanTradingDashboard:
buy_trades = []
sell_trades = []
for signal in executed_signals[-50:]: # Last 50 executed trades (increased from 20)
# Try to get full timestamp first, fall back to string timestamp
for signal in executed_signals[-50:]: # Last 50 executed trades
signal_time = self._get_signal_attribute(signal, 'full_timestamp')
if not signal_time:
signal_time = self._get_signal_attribute(signal, 'timestamp')
@ -732,10 +735,9 @@ class CleanTradingDashboard:
signal_confidence = self._get_signal_attribute(signal, 'confidence', 0)
if signal_time and signal_price and signal_confidence > 0:
# FIXED: Better timestamp conversion to prevent race conditions
# Enhanced timestamp handling
if isinstance(signal_time, str):
try:
# Handle time-only format with current date
if ':' in signal_time and len(signal_time.split(':')) == 3:
now = datetime.now()
time_parts = signal_time.split(':')
@ -745,7 +747,6 @@ class CleanTradingDashboard:
second=int(time_parts[2]),
microsecond=0
)
# Handle day boundary issues - if signal seems from future, subtract a day
if signal_time > now + timedelta(minutes=5):
signal_time -= timedelta(days=1)
else:
@ -754,7 +755,6 @@ class CleanTradingDashboard:
logger.debug(f"Error parsing timestamp {signal_time}: {e}")
continue
elif not isinstance(signal_time, datetime):
# Convert other timestamp formats to datetime
try:
signal_time = pd.to_datetime(signal_time)
except Exception as e:
@ -766,7 +766,7 @@ class CleanTradingDashboard:
elif signal_action == 'SELL':
sell_trades.append({'x': signal_time, 'y': signal_price, 'confidence': signal_confidence})
# Add EXECUTED BUY trades (large green circles)
# Add executed trades with enhanced visualization
if buy_trades:
fig.add_trace(
go.Scatter(
@ -790,7 +790,6 @@ class CleanTradingDashboard:
row=row, col=1
)
# Add EXECUTED SELL trades (large red circles)
if sell_trades:
fig.add_trace(
go.Scatter(
@ -813,9 +812,363 @@ class CleanTradingDashboard:
),
row=row, col=1
)
# 2. NEW: Add real-time model predictions overlay
self._add_dqn_predictions_to_chart(fig, symbol, df_main, row)
self._add_cnn_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 executed trades to main chart: {e}")
logger.warning(f"Error adding model 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:
# Get recent DQN predictions from orchestrator
dqn_predictions = self._get_recent_dqn_predictions(symbol)
if not dqn_predictions:
return
# Separate predictions by action
buy_predictions = []
sell_predictions = []
hold_predictions = []
for pred in dqn_predictions[-30:]: # Last 30 DQN predictions
action = pred.get('action', 2) # 0=BUY, 1=SELL, 2=HOLD
confidence = pred.get('confidence', 0)
timestamp = pred.get('timestamp', datetime.now())
price = pred.get('price', 0)
if confidence > 0.3: # Only show predictions with reasonable confidence
pred_data = {
'x': timestamp,
'y': price,
'confidence': confidence,
'q_values': pred.get('q_values', [0, 0, 0])
}
if action == 0: # BUY
buy_predictions.append(pred_data)
elif action == 1: # SELL
sell_predictions.append(pred_data)
else: # HOLD
hold_predictions.append(pred_data)
# Add DQN BUY predictions (green arrows pointing up)
if buy_predictions:
fig.add_trace(
go.Scatter(
x=[p['x'] for p in buy_predictions],
y=[p['y'] for p in buy_predictions],
mode='markers',
marker=dict(
symbol='triangle-up',
size=[8 + p['confidence'] * 12 for p in buy_predictions], # Size based on confidence
color=[f'rgba(0, 200, 0, {0.3 + p["confidence"] * 0.7})' for p in buy_predictions], # Opacity based on confidence
line=dict(width=1, color='darkgreen')
),
name='DQN BUY Prediction',
showlegend=True,
hovertemplate="<b>DQN BUY PREDICTION</b><br>" +
"Price: $%{y:.2f}<br>" +
"Time: %{x}<br>" +
"Confidence: %{customdata[0]:.1%}<br>" +
"Q-Values: [%{customdata[1]:.3f}, %{customdata[2]:.3f}, %{customdata[3]:.3f}]<extra></extra>",
customdata=[[p['confidence']] + p['q_values'] for p in buy_predictions]
),
row=row, col=1
)
# Add DQN SELL predictions (red arrows pointing down)
if sell_predictions:
fig.add_trace(
go.Scatter(
x=[p['x'] for p in sell_predictions],
y=[p['y'] for p in sell_predictions],
mode='markers',
marker=dict(
symbol='triangle-down',
size=[8 + p['confidence'] * 12 for p in sell_predictions],
color=[f'rgba(200, 0, 0, {0.3 + p["confidence"] * 0.7})' for p in sell_predictions],
line=dict(width=1, color='darkred')
),
name='DQN SELL Prediction',
showlegend=True,
hovertemplate="<b>DQN SELL PREDICTION</b><br>" +
"Price: $%{y:.2f}<br>" +
"Time: %{x}<br>" +
"Confidence: %{customdata[0]:.1%}<br>" +
"Q-Values: [%{customdata[1]:.3f}, %{customdata[2]:.3f}, %{customdata[3]:.3f}]<extra></extra>",
customdata=[[p['confidence']] + p['q_values'] for p in sell_predictions]
),
row=row, col=1
)
# Add DQN HOLD predictions (small gray circles)
if hold_predictions:
fig.add_trace(
go.Scatter(
x=[p['x'] for p in hold_predictions],
y=[p['y'] for p in hold_predictions],
mode='markers',
marker=dict(
symbol='circle',
size=[4 + p['confidence'] * 6 for p in hold_predictions],
color=[f'rgba(128, 128, 128, {0.2 + p["confidence"] * 0.5})' for p in hold_predictions],
line=dict(width=1, color='gray')
),
name='DQN HOLD Prediction',
showlegend=True,
hovertemplate="<b>DQN HOLD PREDICTION</b><br>" +
"Price: $%{y:.2f}<br>" +
"Time: %{x}<br>" +
"Confidence: %{customdata[0]:.1%}<br>" +
"Q-Values: [%{customdata[1]:.3f}, %{customdata[2]:.3f}, %{customdata[3]:.3f}]<extra></extra>",
customdata=[[p['confidence']] + p['q_values'] for p in hold_predictions]
),
row=row, col=1
)
except Exception as e:
logger.debug(f"Error adding DQN predictions to chart: {e}")
def _add_cnn_predictions_to_chart(self, fig: go.Figure, symbol: str, df_main: pd.DataFrame, row: int = 1):
"""Add CNN price direction predictions as trend lines"""
try:
# Get recent CNN predictions from orchestrator
cnn_predictions = self._get_recent_cnn_predictions(symbol)
if not cnn_predictions:
return
# Create trend prediction lines
prediction_lines = []
for i, pred in enumerate(cnn_predictions[-20:]): # Last 20 CNN predictions
direction = pred.get('direction', 1) # 0=DOWN, 1=SAME, 2=UP
confidence = pred.get('confidence', 0)
timestamp = pred.get('timestamp', datetime.now())
current_price = pred.get('current_price', 0)
predicted_price = pred.get('predicted_price', current_price)
if confidence > 0.4 and current_price > 0: # Only show confident predictions
# Calculate prediction end point (5 minutes ahead)
end_time = timestamp + timedelta(minutes=5)
# Determine color based on direction
if direction == 2: # UP
color = f'rgba(0, 255, 0, {0.3 + confidence * 0.4})'
line_color = 'green'
prediction_name = 'CNN UP'
elif direction == 0: # DOWN
color = f'rgba(255, 0, 0, {0.3 + confidence * 0.4})'
line_color = 'red'
prediction_name = 'CNN DOWN'
else: # SAME
color = f'rgba(128, 128, 128, {0.2 + confidence * 0.3})'
line_color = 'gray'
prediction_name = 'CNN FLAT'
# Add prediction line
fig.add_trace(
go.Scatter(
x=[timestamp, end_time],
y=[current_price, predicted_price],
mode='lines',
line=dict(
color=line_color,
width=2 + confidence * 3, # Line width based on confidence
dash='dot' if direction == 1 else 'solid'
),
name=f'{prediction_name} Prediction',
showlegend=i == 0, # Only show legend for first instance
hovertemplate=f"<b>{prediction_name} PREDICTION</b><br>" +
"From: $%{y[0]:.2f}<br>" +
"To: $%{y[1]:.2f}<br>" +
"Time: %{x[0]}%{x[1]}<br>" +
f"Confidence: {confidence:.1%}<br>" +
f"Direction: {['DOWN', 'SAME', 'UP'][direction]}<extra></extra>"
),
row=row, col=1
)
# Add prediction end point marker
fig.add_trace(
go.Scatter(
x=[end_time],
y=[predicted_price],
mode='markers',
marker=dict(
symbol='diamond',
size=6 + confidence * 8,
color=color,
line=dict(width=1, color=line_color)
),
name=f'{prediction_name} Target',
showlegend=False,
hovertemplate=f"<b>{prediction_name} TARGET</b><br>" +
"Target Price: $%{y:.2f}<br>" +
"Target Time: %{x}<br>" +
f"Confidence: {confidence:.1%}<extra></extra>"
),
row=row, col=1
)
except Exception as e:
logger.debug(f"Error adding CNN predictions to chart: {e}")
def _add_prediction_accuracy_feedback(self, fig: go.Figure, symbol: str, df_main: pd.DataFrame, row: int = 1):
"""Add prediction accuracy feedback with color-coded results"""
try:
# Get prediction accuracy history
accuracy_data = self._get_prediction_accuracy_history(symbol)
if not accuracy_data:
return
# Add accuracy feedback markers
correct_predictions = []
incorrect_predictions = []
for acc in accuracy_data[-50:]: # Last 50 accuracy points
timestamp = acc.get('timestamp', datetime.now())
price = acc.get('actual_price', 0)
was_correct = acc.get('correct', False)
prediction_type = acc.get('prediction_type', 'unknown')
accuracy_score = acc.get('accuracy_score', 0)
if price > 0:
acc_data = {
'x': timestamp,
'y': price,
'type': prediction_type,
'score': accuracy_score
}
if was_correct:
correct_predictions.append(acc_data)
else:
incorrect_predictions.append(acc_data)
# Add correct prediction markers (green checkmarks)
if correct_predictions:
fig.add_trace(
go.Scatter(
x=[p['x'] for p in correct_predictions],
y=[p['y'] for p in correct_predictions],
mode='markers',
marker=dict(
symbol='x',
size=8,
color='rgba(0, 255, 0, 0.8)',
line=dict(width=2, color='darkgreen')
),
name='Correct Predictions',
showlegend=True,
hovertemplate="<b>CORRECT PREDICTION</b><br>" +
"Price: $%{y:.2f}<br>" +
"Time: %{x}<br>" +
"Type: %{customdata[0]}<br>" +
"Accuracy: %{customdata[1]:.1%}<extra></extra>",
customdata=[[p['type'], p['score']] for p in correct_predictions]
),
row=row, col=1
)
# Add incorrect prediction markers (red X marks)
if incorrect_predictions:
fig.add_trace(
go.Scatter(
x=[p['x'] for p in incorrect_predictions],
y=[p['y'] for p in incorrect_predictions],
mode='markers',
marker=dict(
symbol='x',
size=8,
color='rgba(255, 0, 0, 0.8)',
line=dict(width=2, color='darkred')
),
name='Incorrect Predictions',
showlegend=True,
hovertemplate="<b>INCORRECT PREDICTION</b><br>" +
"Price: $%{y:.2f}<br>" +
"Time: %{x}<br>" +
"Type: %{customdata[0]}<br>" +
"Accuracy: %{customdata[1]:.1%}<extra></extra>",
customdata=[[p['type'], p['score']] for p in incorrect_predictions]
),
row=row, col=1
)
except Exception as e:
logger.debug(f"Error adding prediction accuracy feedback to chart: {e}")
def _get_recent_dqn_predictions(self, symbol: str) -> List[Dict]:
"""Get recent DQN predictions from enhanced training system (forward-looking only)"""
try:
predictions = []
# Get REAL forward-looking predictions from enhanced training system
if hasattr(self, 'training_system') and self.training_system:
if hasattr(self.training_system, 'recent_dqn_predictions'):
predictions.extend(self.training_system.recent_dqn_predictions.get(symbol, []))
# Get from orchestrator as fallback
if hasattr(self.orchestrator, 'recent_dqn_predictions'):
predictions.extend(self.orchestrator.recent_dqn_predictions.get(symbol, []))
# REMOVED: Mock prediction generation - now using REAL predictions only
# No more artificial past predictions or random data
return sorted(predictions, key=lambda x: x.get('timestamp', datetime.now()))
except Exception as e:
logger.debug(f"Error getting DQN predictions: {e}")
return []
def _get_recent_cnn_predictions(self, symbol: str) -> List[Dict]:
"""Get recent CNN predictions from enhanced training system (forward-looking only)"""
try:
predictions = []
# Get REAL forward-looking predictions from enhanced training system
if hasattr(self, 'training_system') and self.training_system:
if hasattr(self.training_system, 'recent_cnn_predictions'):
predictions.extend(self.training_system.recent_cnn_predictions.get(symbol, []))
# Get from orchestrator as fallback
if hasattr(self.orchestrator, 'recent_cnn_predictions'):
predictions.extend(self.orchestrator.recent_cnn_predictions.get(symbol, []))
# REMOVED: Mock prediction generation - now using REAL predictions only
# No more artificial past predictions or random data
return sorted(predictions, key=lambda x: x.get('timestamp', datetime.now()))
except Exception as e:
logger.debug(f"Error getting CNN predictions: {e}")
return []
def _get_prediction_accuracy_history(self, symbol: str) -> List[Dict]:
"""Get REAL prediction accuracy history from validated forward-looking predictions"""
try:
accuracy_data = []
# Get REAL accuracy data from training system validation
if hasattr(self, 'training_system') and self.training_system:
if hasattr(self.training_system, 'prediction_accuracy_history'):
accuracy_data.extend(self.training_system.prediction_accuracy_history.get(symbol, []))
# REMOVED: Mock accuracy data generation - now using REAL validation results only
# Accuracy is now based on actual prediction outcomes, not random data
return sorted(accuracy_data, key=lambda x: x.get('timestamp', datetime.now()))
except Exception as e:
logger.debug(f"Error getting prediction accuracy history: {e}")
return []
def _add_signals_to_mini_chart(self, fig: go.Figure, symbol: str, ws_data_1s: pd.DataFrame, row: int = 2):
"""Add ALL signals (executed and non-executed) to the 1s mini chart"""
@ -2566,6 +2919,33 @@ class CleanTradingDashboard:
except Exception as e:
logger.warning(f"Error clearing old signals: {e}")
def _initialize_enhanced_training_system(self):
"""Initialize enhanced training system for model predictions"""
try:
# Try to import and initialize enhanced training system
from enhanced_realtime_training import EnhancedRealtimeTrainingSystem
self.training_system = EnhancedRealtimeTrainingSystem(
orchestrator=self.orchestrator,
data_provider=self.data_provider,
dashboard=self
)
# Initialize prediction storage
if not hasattr(self.orchestrator, 'recent_dqn_predictions'):
self.orchestrator.recent_dqn_predictions = {}
if not hasattr(self.orchestrator, 'recent_cnn_predictions'):
self.orchestrator.recent_cnn_predictions = {}
logger.info("Enhanced training system initialized for model predictions")
except ImportError:
logger.warning("Enhanced training system not available - using mock predictions")
self.training_system = None
except Exception as e:
logger.error(f"Error initializing enhanced training system: {e}")
self.training_system = None
def _initialize_cob_integration(self):
"""Initialize COB integration with high-frequency data handling"""
try: