This commit is contained in:
Dobromir Popov
2025-09-08 11:44:15 +03:00
parent fe6763c4ba
commit 4fe952dbee
6 changed files with 743 additions and 141 deletions

View File

@@ -345,18 +345,61 @@ class CleanTradingDashboard:
'timestamp': datetime.now().isoformat()
})
@self.app.server.route('/api/predictions/stats', methods=['GET'])
def get_prediction_stats():
"""Get model prediction statistics"""
@self.app.server.route('/api/predictions/recent', methods=['GET'])
def get_recent_predictions():
"""Get recent predictions with their outcomes"""
try:
if (hasattr(self.orchestrator, 'enhanced_training_system') and
self.orchestrator.enhanced_training_system):
stats = self.orchestrator.enhanced_training_system.get_model_performance_stats()
return jsonify(stats)
# Get predictions from database
from core.prediction_database import get_prediction_db
db = get_prediction_db()
# Get recent predictions (last 24 hours)
predictions = []
# Mock data for now - replace with actual database query
import sqlite3
try:
with sqlite3.connect(db.db_path) as conn:
cursor = conn.cursor()
cursor.execute("""
SELECT model_name, symbol, prediction_type, confidence,
timestamp, price_at_prediction, outcome_timestamp,
actual_price_change, reward, is_correct
FROM predictions
ORDER BY timestamp DESC
LIMIT 50
""")
for row in cursor.fetchall():
predictions.append({
'model_name': row[0],
'symbol': row[1],
'prediction_type': row[2],
'confidence': row[3],
'timestamp': row[4],
'price_at_prediction': row[5],
'outcome_timestamp': row[6],
'actual_price_change': row[7],
'reward': row[8],
'is_correct': row[9],
'is_resolved': row[6] is not None
})
except Exception as e:
logger.debug(f"Error fetching predictions from database: {e}")
return jsonify({
'predictions': predictions,
'total_predictions': len(predictions),
'active_predictions': len([p for p in predictions if not p['is_resolved']]),
'timestamp': datetime.now().isoformat()
})
else:
return jsonify({"error": "Training system not available"}), 503
except Exception as e:
logger.error(f"Error getting prediction stats: {e}")
logger.error(f"Error getting recent predictions: {e}")
return jsonify({"error": str(e)}), 500
def _get_ohlcv_data_with_indicators(self, symbol: str, timeframe: str, limit: int = 300):
@@ -980,6 +1023,135 @@ class CleanTradingDashboard:
logger.error(f"Training status error: {e}")
return 'Error', 'badge bg-danger small'
@self.app.callback(
[Output('total-predictions-count', 'children'),
Output('pending-predictions-count', 'children'),
Output('active-models-count', 'children'),
Output('total-rewards-sum', 'children'),
Output('prediction-timeline-chart', 'figure'),
Output('model-performance-chart', 'figure')],
[Input('interval-component', 'n_intervals')]
)
def update_prediction_tracking(n_intervals):
"""Update prediction tracking charts and metrics"""
try:
if (hasattr(self.orchestrator, 'enhanced_training_system') and
self.orchestrator.enhanced_training_system):
# Get prediction data
stats = self.orchestrator.enhanced_training_system.get_model_performance_stats()
models = stats.get('models', [])
total_active = stats.get('total_active_predictions', 0)
# Calculate totals
total_predictions = sum(m.get('total_predictions', 0) for m in models)
total_rewards = sum(m.get('total_reward', 0) for m in models)
active_models = len(models)
# Create timeline chart (simplified)
timeline_fig = {
'data': [],
'layout': {
'title': 'Recent Predictions Timeline',
'xaxis': {'title': 'Time'},
'yaxis': {'title': 'Confidence'},
'template': 'plotly_dark',
'height': 300,
'showlegend': False
}
}
# Add empty annotation if no data
if not models:
timeline_fig['layout']['annotations'] = [{
'text': 'No prediction data yet',
'xref': 'paper', 'yref': 'paper',
'x': 0.5, 'y': 0.5,
'showarrow': False,
'font': {'size': 16, 'color': 'gray'}
}]
# Create performance chart
performance_fig = {
'data': [],
'layout': {
'title': 'Model Performance',
'template': 'plotly_dark',
'height': 300,
'showlegend': True
}
}
if models:
model_names = [m.get('model_name', 'Unknown') for m in models]
accuracies = [m.get('accuracy', 0) * 100 for m in models]
rewards = [m.get('total_reward', 0) for m in models]
# Add accuracy bars
performance_fig['data'].append({
'x': model_names,
'y': accuracies,
'type': 'bar',
'name': 'Accuracy (%)',
'marker': {'color': 'lightblue'}
})
performance_fig['layout']['xaxis'] = {'title': 'Model'}
performance_fig['layout']['yaxis'] = {'title': 'Accuracy (%)'}
else:
performance_fig['layout']['annotations'] = [{
'text': 'No model data yet',
'xref': 'paper', 'yref': 'paper',
'x': 0.5, 'y': 0.5,
'showarrow': False,
'font': {'size': 16, 'color': 'gray'}
}]
return (
str(total_predictions),
str(total_active),
str(active_models),
f"{total_rewards:.1f}",
timeline_fig,
performance_fig
)
else:
# Training system not available
empty_fig = {
'data': [],
'layout': {
'template': 'plotly_dark',
'height': 300,
'annotations': [{
'text': 'Training system not available',
'xref': 'paper', 'yref': 'paper',
'x': 0.5, 'y': 0.5,
'showarrow': False,
'font': {'size': 16, 'color': 'red'}
}]
}
}
return "N/A", "N/A", "N/A", "N/A", empty_fig, empty_fig
except Exception as e:
logger.error(f"Error updating prediction tracking: {e}")
error_fig = {
'data': [],
'layout': {
'template': 'plotly_dark',
'height': 300,
'annotations': [{
'text': f'Error: {str(e)}',
'xref': 'paper', 'yref': 'paper',
'x': 0.5, 'y': 0.5,
'showarrow': False,
'font': {'size': 14, 'color': 'red'}
}]
}
}
return "Error", "Error", "Error", "Error", error_fig, error_fig
@self.app.callback(
[Output('eth-cob-content', 'children'),
Output('btc-cob-content', 'children')],