display predictions
This commit is contained in:
@ -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:
|
||||
|
Reference in New Issue
Block a user