mirror of
https://github.com/B-Wear/QuantumEdge.git
synced 2026-07-27 15:37:46 +00:00
407fe4bb5e
updates Signed-off-by: B-Wear <Bwear008@gmail.com>
372 lines
14 KiB
Python
372 lines
14 KiB
Python
import dash
|
|
from dash import dcc, html
|
|
from dash.dependencies import Input, Output, State
|
|
import plotly.graph_objects as go
|
|
from plotly.subplots import make_subplots
|
|
import pandas as pd
|
|
import json
|
|
import os
|
|
from datetime import datetime
|
|
import numpy as np
|
|
from .code_guardian import create_guardian, CodeGuardian
|
|
|
|
def load_backtest_results(results_dir):
|
|
"""Load all backtest results from directory"""
|
|
results = {}
|
|
for file in os.listdir(results_dir):
|
|
if file.startswith('backtest_results_') and file.endswith('.json'):
|
|
with open(os.path.join(results_dir, file), 'r') as f:
|
|
scenario_name = file.replace('backtest_results_', '').replace('.json', '')
|
|
results[scenario_name] = json.load(f)
|
|
return results
|
|
|
|
def create_dashboard(results_dir='backtest_results'):
|
|
"""Create and run the dashboard"""
|
|
app = dash.Dash(__name__)
|
|
|
|
# Load results
|
|
results = load_backtest_results(results_dir)
|
|
|
|
# Initialize Code Guardian
|
|
guardian = create_guardian(os.path.dirname(os.path.dirname(__file__)))
|
|
|
|
# Dashboard layout
|
|
app.layout = html.Div([
|
|
# Header
|
|
html.Div([
|
|
html.H1('AI Trading Bot - Backtest Results & System Health Dashboard',
|
|
style={'textAlign': 'center', 'color': '#2c3e50', 'marginBottom': 30}),
|
|
], style={'backgroundColor': '#ecf0f1', 'padding': '20px'}),
|
|
|
|
# Tabs for different sections
|
|
dcc.Tabs([
|
|
# Backtest Results Tab
|
|
dcc.Tab(label='Backtest Results', children=[
|
|
# Scenario Selection
|
|
html.Div([
|
|
html.Label('Select Scenario:'),
|
|
dcc.Dropdown(
|
|
id='scenario-dropdown',
|
|
options=[{'label': k, 'value': k} for k in results.keys()],
|
|
value=list(results.keys())[0] if results else None,
|
|
style={'width': '100%'}
|
|
),
|
|
], style={'margin': '20px'}),
|
|
|
|
# Main Charts
|
|
html.Div([
|
|
# Trading Chart
|
|
html.Div([
|
|
dcc.Graph(id='trading-chart')
|
|
], style={'width': '100%', 'marginBottom': '20px'}),
|
|
|
|
# Performance Metrics Cards
|
|
html.Div([
|
|
html.Div([
|
|
html.Div(id='metrics-cards'),
|
|
], style={'display': 'flex', 'flexWrap': 'wrap', 'justifyContent': 'space-around'})
|
|
], style={'marginBottom': '20px'}),
|
|
|
|
# Trade Distribution Chart
|
|
html.Div([
|
|
dcc.Graph(id='trade-distribution')
|
|
], style={'width': '100%', 'marginBottom': '20px'}),
|
|
|
|
# Drawdown Chart
|
|
html.Div([
|
|
dcc.Graph(id='drawdown-chart')
|
|
], style={'width': '100%'})
|
|
], style={'padding': '20px'})
|
|
]),
|
|
|
|
# System Health Tab
|
|
dcc.Tab(label='System Health', children=[
|
|
html.Div([
|
|
# Code Health Overview
|
|
html.Div([
|
|
html.H2('Code Health Overview', style={'textAlign': 'center'}),
|
|
html.Div(id='code-health-cards', style={
|
|
'display': 'flex',
|
|
'flexWrap': 'wrap',
|
|
'justifyContent': 'space-around',
|
|
'margin': '20px'
|
|
})
|
|
]),
|
|
|
|
# Code Issues Table
|
|
html.Div([
|
|
html.H3('Active Code Issues'),
|
|
html.Div(id='code-issues-table')
|
|
], style={'margin': '20px'}),
|
|
|
|
# Performance Metrics
|
|
html.Div([
|
|
html.H3('Module Performance'),
|
|
dcc.Graph(id='performance-chart')
|
|
], style={'margin': '20px'}),
|
|
|
|
# Auto-Fix Controls
|
|
html.Div([
|
|
html.H3('Issue Resolution'),
|
|
html.Button('Auto-Fix Selected Issues', id='auto-fix-button'),
|
|
html.Div(id='auto-fix-status')
|
|
], style={'margin': '20px'})
|
|
])
|
|
]),
|
|
|
|
# System Logs Tab
|
|
dcc.Tab(label='System Logs', children=[
|
|
html.Div([
|
|
html.H2('System Logs'),
|
|
dcc.Interval(id='log-update', interval=5000), # Update every 5 seconds
|
|
html.Pre(id='log-content', style={
|
|
'backgroundColor': '#2c3e50',
|
|
'color': '#ecf0f1',
|
|
'padding': '20px',
|
|
'borderRadius': '5px',
|
|
'height': '500px',
|
|
'overflow': 'auto'
|
|
})
|
|
], style={'margin': '20px'})
|
|
])
|
|
])
|
|
])
|
|
|
|
@app.callback(
|
|
[Output('trading-chart', 'figure'),
|
|
Output('metrics-cards', 'children'),
|
|
Output('trade-distribution', 'figure'),
|
|
Output('drawdown-chart', 'figure')],
|
|
[Input('scenario-dropdown', 'value')]
|
|
)
|
|
def update_charts(selected_scenario):
|
|
if not selected_scenario or selected_scenario not in results:
|
|
return {}, [], {}, {}
|
|
|
|
result = results[selected_scenario]
|
|
trades_df = pd.DataFrame(result['trades'])
|
|
equity_df = pd.DataFrame(result['equity_curve'])
|
|
metrics = result['performance_metrics']
|
|
|
|
# 1. Trading Chart
|
|
trading_fig = make_subplots(
|
|
rows=2, cols=1,
|
|
shared_xaxes=True,
|
|
vertical_spacing=0.03,
|
|
subplot_titles=('Price and Trades', 'Equity Curve'),
|
|
row_heights=[0.7, 0.3]
|
|
)
|
|
|
|
# Add price line
|
|
trading_fig.add_trace(
|
|
go.Scatter(
|
|
x=trades_df['timestamp'],
|
|
y=trades_df['price'],
|
|
name='Price',
|
|
line=dict(color='#2980b9')
|
|
),
|
|
row=1, col=1
|
|
)
|
|
|
|
# Add buy/sell markers
|
|
for action, color in [('buy', '#27ae60'), ('sell', '#c0392b')]:
|
|
mask = trades_df['action'] == action
|
|
trading_fig.add_trace(
|
|
go.Scatter(
|
|
x=trades_df[mask]['timestamp'],
|
|
y=trades_df[mask]['price'],
|
|
mode='markers',
|
|
name=action.capitalize(),
|
|
marker=dict(color=color, size=10)
|
|
),
|
|
row=1, col=1
|
|
)
|
|
|
|
# Add equity curve
|
|
trading_fig.add_trace(
|
|
go.Scatter(
|
|
x=equity_df['timestamp'],
|
|
y=equity_df['equity'],
|
|
name='Equity',
|
|
line=dict(color='#8e44ad')
|
|
),
|
|
row=2, col=1
|
|
)
|
|
|
|
trading_fig.update_layout(
|
|
title='Trading Activity and Equity Curve',
|
|
height=800,
|
|
template='plotly_white'
|
|
)
|
|
|
|
# 2. Metrics Cards
|
|
cards = []
|
|
metrics_style = {
|
|
'width': '200px',
|
|
'margin': '10px',
|
|
'padding': '15px',
|
|
'borderRadius': '5px',
|
|
'boxShadow': '2px 2px 5px rgba(0,0,0,0.1)',
|
|
'textAlign': 'center'
|
|
}
|
|
|
|
metrics_data = [
|
|
('Total Return', f"{metrics['total_return']:.2%}", '#27ae60'),
|
|
('Win Rate', f"{metrics['win_rate']:.2%}", '#2980b9'),
|
|
('Sharpe Ratio', f"{metrics['sharpe_ratio']:.2f}", '#8e44ad'),
|
|
('Max Drawdown', f"{metrics['max_drawdown']:.2%}", '#c0392b'),
|
|
('Total Trades', str(metrics['total_trades']), '#2c3e50')
|
|
]
|
|
|
|
for label, value, color in metrics_data:
|
|
cards.append(html.Div([
|
|
html.H4(label, style={'color': '#7f8c8d'}),
|
|
html.H3(value, style={'color': color})
|
|
], style=metrics_style))
|
|
|
|
# 3. Trade Distribution
|
|
returns = pd.Series([float(x) for x in trades_df['price'].pct_change().dropna()])
|
|
dist_fig = go.Figure()
|
|
dist_fig.add_trace(go.Histogram(
|
|
x=returns,
|
|
nbinsx=30,
|
|
name='Returns Distribution',
|
|
marker_color='#3498db'
|
|
))
|
|
|
|
dist_fig.update_layout(
|
|
title='Trade Returns Distribution',
|
|
xaxis_title='Return',
|
|
yaxis_title='Frequency',
|
|
template='plotly_white'
|
|
)
|
|
|
|
# 4. Drawdown Chart
|
|
equity_series = pd.Series([float(x) for x in equity_df['equity']])
|
|
rolling_max = equity_series.expanding().max()
|
|
drawdowns = (equity_series - rolling_max) / rolling_max
|
|
|
|
dd_fig = go.Figure()
|
|
dd_fig.add_trace(go.Scatter(
|
|
x=equity_df['timestamp'],
|
|
y=drawdowns,
|
|
fill='tozeroy',
|
|
name='Drawdown',
|
|
line=dict(color='#e74c3c')
|
|
))
|
|
|
|
dd_fig.update_layout(
|
|
title='Drawdown Over Time',
|
|
xaxis_title='Date',
|
|
yaxis_title='Drawdown',
|
|
template='plotly_white'
|
|
)
|
|
|
|
return trading_fig, cards, dist_fig, dd_fig
|
|
|
|
@app.callback(
|
|
[Output('code-health-cards', 'children'),
|
|
Output('code-issues-table', 'children'),
|
|
Output('performance-chart', 'figure'),
|
|
Output('auto-fix-status', 'children')],
|
|
[Input('auto-fix-button', 'n_clicks')],
|
|
[State('code-issues-table', 'selected_rows')]
|
|
)
|
|
def update_system_health(n_clicks, selected_rows):
|
|
# Get guardian status
|
|
status = guardian.get_status_report()
|
|
|
|
# Create health cards
|
|
health_cards = []
|
|
health_metrics = [
|
|
('Total Issues', status['total_issues'], '#e74c3c'),
|
|
('Fixed Issues', status['fixed_issues'], '#27ae60'),
|
|
('Active Issues', status['active_issues'], '#f39c12'),
|
|
('Code Coverage', '85%', '#3498db') # Example metric
|
|
]
|
|
|
|
for label, value, color in health_metrics:
|
|
health_cards.append(html.Div([
|
|
html.H4(label),
|
|
html.H3(str(value))
|
|
], style={
|
|
'width': '200px',
|
|
'margin': '10px',
|
|
'padding': '15px',
|
|
'borderRadius': '5px',
|
|
'boxShadow': '2px 2px 5px rgba(0,0,0,0.1)',
|
|
'textAlign': 'center',
|
|
'backgroundColor': color,
|
|
'color': 'white'
|
|
}))
|
|
|
|
# Create issues table
|
|
issues_table = html.Table([
|
|
html.Thead(html.Tr([
|
|
html.Th('File'),
|
|
html.Th('Line'),
|
|
html.Th('Type'),
|
|
html.Th('Severity'),
|
|
html.Th('Description'),
|
|
html.Th('Status')
|
|
])),
|
|
html.Tbody([
|
|
html.Tr([
|
|
html.Td(issue.file_path),
|
|
html.Td(issue.line_number),
|
|
html.Td(issue.issue_type),
|
|
html.Td(issue.severity),
|
|
html.Td(issue.description),
|
|
html.Td('Fixed' if issue.fixed else 'Active')
|
|
]) for issue in guardian.issues
|
|
])
|
|
], style={'width': '100%'})
|
|
|
|
# Create performance chart
|
|
perf_data = status['performance_metrics']
|
|
perf_fig = go.Figure()
|
|
|
|
for module, metrics in perf_data.items():
|
|
perf_fig.add_trace(go.Scatter(
|
|
x=list(range(len(guardian.performance_metrics[module]))),
|
|
y=guardian.performance_metrics[module],
|
|
name=module,
|
|
mode='lines+markers'
|
|
))
|
|
|
|
perf_fig.update_layout(
|
|
title='Module Performance Over Time',
|
|
xaxis_title='Execution Count',
|
|
yaxis_title='Execution Time (s)',
|
|
template='plotly_white'
|
|
)
|
|
|
|
# Handle auto-fix status
|
|
fix_status = None
|
|
if n_clicks and selected_rows:
|
|
fixed_count = sum(1 for i in selected_rows if guardian.fix_issue(guardian.issues[i]))
|
|
fix_status = f"Fixed {fixed_count} out of {len(selected_rows)} selected issues"
|
|
|
|
return health_cards, issues_table, perf_fig, fix_status
|
|
|
|
@app.callback(
|
|
Output('log-content', 'children'),
|
|
[Input('log-update', 'n_intervals')]
|
|
)
|
|
def update_logs(_):
|
|
try:
|
|
with open('analysis.log', 'r') as f:
|
|
logs = f.readlines()
|
|
return ''.join(logs[-100:]) # Show last 100 lines
|
|
except Exception as e:
|
|
return f"Error reading logs: {str(e)}"
|
|
|
|
return app
|
|
|
|
def run_dashboard(port=8050):
|
|
"""Run the dashboard"""
|
|
app = create_dashboard()
|
|
app.run_server(debug=True, port=port)
|
|
|
|
if __name__ == '__main__':
|
|
run_dashboard() |