"""AlphaForge Dashboard - Live Quant System Monitor.""" import gradio as gr import numpy as np import pandas as pd import plotly.graph_objects as go from plotly.subplots import make_subplots def create_metrics_panel(): """Create top-level metrics panel.""" with gr.Row(): with gr.Column(scale=1): sharpe = gr.Number(label="Sharpe Ratio", value=1.85, interactive=False) sortino = gr.Number(label="Sortino Ratio", value=2.34, interactive=False) with gr.Column(scale=1): pnl = gr.Number(label="Total Return (%)", value=32.5, interactive=False) max_dd = gr.Number(label="Max Drawdown (%)", value=-12.3, interactive=False) with gr.Column(scale=1): var95 = gr.Number(label="VaR 95% (daily)", value=-1.87, interactive=False) cvar95 = gr.Number(label="CVaR 95% (daily)", value=-2.91, interactive=False) with gr.Column(scale=1): regime = gr.Textbox(label="Current Regime", value="Bull", interactive=False) exposure = gr.Number(label="Current Exposure (%)", value=85.0, interactive=False) def create_equity_curve_chart(): """Create interactive equity curve with drawdown.""" dates = pd.date_range('2023-01-01', periods=252, freq='B') np.random.seed(42) returns = np.random.normal(0.0008, 0.008, 252) equity = 1_000_000 * np.cumprod(1 + returns) cumulative = np.cumprod(1 + returns) running_max = np.maximum.accumulate(cumulative) drawdown = (cumulative - running_max) / running_max * 100 fig = make_subplots( rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.05, row_heights=[0.7, 0.3], subplot_titles=("Portfolio Equity", "Drawdown") ) fig.add_trace( go.Scatter(x=dates, y=equity, mode='lines', fill='tozeroy', name='Portfolio Value', line=dict(color='#00ff88', width=2)), row=1, col=1 ) fig.add_trace( go.Scatter(x=dates, y=drawdown, mode='lines', fill='tozeroy', name='Drawdown %', line=dict(color='#ff4444', width=1), fillcolor='rgba(255, 0, 0, 0.2)'), row=2, col=1 ) fig.update_layout( height=500, showlegend=False, template='plotly_dark', margin=dict(l=20, r=20, t=40, b=20) ) fig.update_yaxes(title_text="Value ($)", row=1, col=1) fig.update_yaxes(title_text="DD (%)", row=2, col=1) return fig def create_portfolio_weights_chart(): """Create portfolio weights sunburst/bar chart.""" assets = ['SPY', 'QQQ', 'AAPL', 'MSFT', 'GOOGL', 'AMZN', 'META', 'NVDA', 'TSLA', 'JPM'] np.random.seed(123) weights = np.random.dirichlet(np.ones(10), size=1)[0] weights.sort() weights = weights[::-1] fig = go.Figure(data=[ go.Bar( x=assets, y=weights * 100, marker=dict( color=weights * 100, colorscale='Viridis', showscale=False ), text=[f'{w:.1f}%' for w in weights * 100], textposition='outside' ) ]) fig.update_layout( height=400, template='plotly_dark', title="Portfolio Weights", xaxis_title="Asset", yaxis_title="Weight (%)", margin=dict(l=20, r=20, t=50, b=20) ) return fig def create_risk_heatmap(): """Create correlation heatmap.""" assets = ['SPY', 'QQQ', 'AAPL', 'MSFT', 'GOOGL', 'AMZN', 'META', 'NVDA', 'TSLA', 'JPM'] n = len(assets) np.random.seed(42) corr = np.zeros((n, n)) for i in range(n): for j in range(n): if i == j: corr[i, j] = 1.0 else: corr[i, j] = 0.3 + np.random.random() * 0.5 corr = (corr + corr.T) / 2 fig = go.Figure(data=go.Heatmap( z=corr, x=assets, y=assets, colorscale='RdBu_r', zmin=-1, zmax=1, text=np.round(corr, 2), texttemplate='%{text}', textfont=dict(size=10) )) fig.update_layout( height=400, template='plotly_dark', title="Covariance Matrix", margin=dict(l=20, r=20, t=50, b=20) ) return fig def create_factor_exposure_chart(): """Create factor exposure bar chart.""" factors = ['Market', 'Momentum', 'Value', 'Size', 'Volatility', 'Quality'] exposures = np.random.normal(0.3, 0.15, 6) exposures[0] = 0.95 # Market beta colors = ['#00ff88' if e > 0 else '#ff4444' for e in exposures] fig = go.Figure(data=[ go.Bar( x=factors, y=exposures, marker_color=colors, text=[f'{e:.2f}' for e in exposures], textposition='outside' ) ]) fig.update_layout( height=350, template='plotly_dark', title="Factor Exposures", xaxis_title="Factor", yaxis_title="Beta", margin=dict(l=20, r=20, t=50, b=20), showlegend=False ) return fig def create_ic_chart(): """Create IC tracking chart.""" dates = pd.date_range('2023-01-01', periods=252, freq='B') np.random.seed(42) ic = np.random.normal(0.05, 0.15, 252) rolling_ic = pd.Series(ic).rolling(21).mean() fig = go.Figure() fig.add_trace(go.Scatter( x=dates, y=ic, mode='markers', name='Daily IC', marker=dict(size=3, opacity=0.3, color='gray') )) fig.add_trace(go.Scatter( x=dates, y=rolling_ic, mode='lines', name='21d Rolling IC', line=dict(width=2, color='#00ffff') )) fig.add_hline(y=0, line_dash="dash", line_color="gray", opacity=0.5) fig.update_layout( height=350, template='plotly_dark', title="Information Coefficient (IC) Tracking", xaxis_title="Date", yaxis_title="IC", margin=dict(l=20, r=20, t=50, b=20), legend=dict(orientation='h', yanchor='bottom', y=1.02) ) return fig def create_regime_timeline(): """Create regime timeline chart.""" dates = pd.date_range('2023-01-01', periods=120, freq='B') np.random.seed(42) regimes = np.random.choice(['Bull', 'Bear', 'Neutral', 'High Vol'], 120, p=[0.5, 0.15, 0.25, 0.1]) regime_colors = {'Bull': '#00ff88', 'Bear': '#ff4444', 'Neutral': '#888888', 'High Vol': '#ffaa00'} regime_nums = {'Bull': 3, 'Neutral': 2, 'Bear': 1, 'High Vol': 0} y = [regime_nums[r] for r in regimes] colors = [regime_colors[r] for r in regimes] fig = go.Figure() for i in range(len(dates) - 1): fig.add_trace(go.Scatter( x=[dates[i], dates[i+1]], y=[y[i], y[i]], mode='lines', line=dict(color=colors[i], width=8), showlegend=False )) fig.update_layout( height=200, template='plotly_dark', title="Market Regime", yaxis=dict( tickmode='array', tickvals=[0, 1, 2, 3], ticktext=['High Vol', 'Bear', 'Neutral', 'Bull'] ), margin=dict(l=20, r=20, t=50, b=20) ) return fig def create_risk_decomposition(): """Create risk decomposition pie/donut chart.""" risk_sources = ['Equity Beta', 'Sector', 'Momentum', 'Value', 'Volatility', 'Residual'] np.random.seed(42) contribution = np.random.dirichlet(np.ones(6), size=1)[0] * 100 fig = go.Figure(data=[go.Pie( labels=risk_sources, values=contribution, hole=0.4, marker=dict(colors=['#00ff88', '#00ccff', '#ffaa00', '#ff4444', '#aa44ff', '#888888']) )]) fig.update_layout( height=350, template='plotly_dark', title="Risk Decomposition", margin=dict(l=20, r=20, t=50, b=20) ) return fig def create_anomaly_tracker(): """Create anomaly detection tracker.""" dates = pd.date_range('2023-01-01', periods=120, freq='B') np.random.seed(42) anomaly_score = np.random.exponential(0.5, 120) # Mark anomalies threshold = np.percentile(anomaly_score, 95) colors = ['#ff4444' if s > threshold else '#00ff88' for s in anomaly_score] fig = go.Figure(data=go.Bar( x=dates, y=anomaly_score, marker_color=colors, name='Anomaly Score' )) fig.add_hline(y=threshold, line_dash="dash", line_color="orange", annotation_text=f"Threshold: {threshold:.2f}") fig.update_layout( height=300, template='plotly_dark', title="Anomaly Detection", xaxis_title="Date", yaxis_title="Score", margin=dict(l=20, r=20, t=50, b=20), showlegend=False ) return fig def create_options_surface(): """Create options volatility surface.""" S_range = np.arange(50, 200, 5) T_range = np.arange(30, 365, 30) X, Y = np.meshgrid(S_range, T_range) Z = 0.2 + 0.05 * (X - 100) / 50 - 0.03 * (Y - 180) / 180 + \ np.random.normal(0, 0.02, X.shape) fig = go.Figure(data=[go.Surface( x=X, y=Y, z=Z, colorscale='Viridis', contours=dict(z=dict(show=True, usecolormap=True)) )]) fig.update_layout( height=400, template='plotly_dark', title="Implied Volatility Surface", scene=dict( xaxis_title='Spot Price', yaxis_title='Days to Expiry', zaxis_title='IV' ), margin=dict(l=20, r=20, t=50, b=20) ) return fig # Build Gradio UI with gr.Blocks(theme=gr.themes.Soft(), title="AlphaForge Dashboard") as demo: gr.Markdown(""" # 🏦 AlphaForge - Autonomous Quant Fund OS Real-time multi-asset alpha signals | Sentiment analysis | Risk engine | Portfolio optimizer | Options pricing """) with gr.Tabs(): with gr.TabItem("📊 Overview"): create_metrics_panel() with gr.Row(): with gr.Column(scale=2): eq_chart = gr.Plot(label="Equity Curve", value=create_equity_curve_chart()) with gr.Column(scale=1): regime_chart = gr.Plot(label="Regime Timeline", value=create_regime_timeline()) with gr.Row(): with gr.Column(scale=1): weights_chart = gr.Plot(label="Portfolio Weights", value=create_portfolio_weights_chart()) with gr.Column(scale=1): risk_chart = gr.Plot(label="Risk Decomposition", value=create_risk_decomposition()) with gr.TabItem("📈 Alpha Signals"): gr.Markdown("### Alpha Model Performance") with gr.Row(): ic_chart = gr.Plot(label="IC Tracking", value=create_ic_chart()) with gr.Row(): factor_chart = gr.Plot(label="Factor Exposures", value=create_factor_exposure_chart()) gr.Dataframe( label="Recent Alpha Signals", value=pd.DataFrame({ 'Date': pd.date_range('2025-05-01', periods=10), 'Ticker': ['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'META', 'NVDA', 'TSLA', 'JPM', 'V', 'WMT'], 'Predicted Return': [0.0021, 0.0018, 0.0009, -0.0003, 0.0015, 0.0032, -0.0012, 0.0007, 0.0011, -0.0005], 'Confidence': [0.85, 0.78, 0.62, 0.55, 0.81, 0.92, 0.48, 0.71, 0.65, 0.52], 'Sentiment': [0.7, 0.5, 0.3, -0.2, 0.6, 0.9, -0.4, 0.1, 0.4, -0.1] }) ) with gr.TabItem("⚠️ Risk Analytics"): gr.Markdown("### Risk Dashboard (VaR, CVaR, Stress Tests)") with gr.Row(): risk_heatmap = gr.Plot(label="Covariance Matrix", value=create_risk_heatmap()) with gr.Row(): anomaly_chart = gr.Plot(label="Anomaly Detection", value=create_anomaly_tracker()) gr.Dataframe( label="Stress Test Results", value=pd.DataFrame({ 'Scenario': ['2008 Crisis', 'COVID Crash', 'Rate Hike', 'Vol Spike', 'Flash Crash'], 'PnL Impact': ['-24.3%', '-18.7%', '-8.2%', '-15.1%', '-12.8%'], 'VaR Breach': ['Yes', 'Yes', 'No', 'Yes', 'No'], 'Recovery Days': [145, 89, 32, 67, 15] }) ) with gr.TabItem("📉 Options"): options_chart = gr.Plot(label="IV Surface", value=create_options_surface()) gr.Dataframe( label="Options Mispricing Signals", value=pd.DataFrame({ 'Option': ['SPY 550C 30d', 'QQQ 480P 45d', 'AAPL 220C 60d'], 'Market IV': [0.18, 0.22, 0.25], 'ML IV': [0.15, 0.26, 0.21], 'Mispricing %': [16.7, 18.2, -16.0], 'Signal': ['OVERPRICED', 'UNDERPRICED', 'UNDERPRICED'], 'PnL Estimate': [340, -250, -180] }) ) with gr.TabItem("🧠 Model Insights"): gr.Markdown("### Meta-Model & Explainability") gr.Dataframe( label="Model Performance", value=pd.DataFrame({ 'Model': ['LSTM', 'Transformer', 'XGBoost', 'Sentiment', 'Meta-Model'], 'IC': [0.042, 0.038, 0.055, 0.028, 0.061], 'IC Std': [0.12, 0.14, 0.10, 0.16, 0.09], 'Weight': [0.25, 0.20, 0.35, 0.05, 0.15], 'Recent IC': [0.048, 0.032, 0.058, 0.031, 0.063] }) ) gr.Dataframe( label="Feature Importance (Top 10)", value=pd.DataFrame({ 'Feature': ['rsi_14', 'sma_ratio', 'rvol_21d', 'macd', 'volume_change', 'return_5d', 'bb_position', 'SPY_beta', 'intraday_range', 'return_21d'], 'Importance': [0.18, 0.15, 0.12, 0.10, 0.09, 0.08, 0.07, 0.06, 0.05, 0.04], 'Direction': ['Negative', 'Positive', 'Negative', 'Positive', 'Neutral', 'Positive', 'Neutral', 'Negative', 'Neutral', 'Positive'] }) ) with gr.TabItem("⚙️ Configuration"): gr.Markdown("### System Configuration") with gr.Row(): tickers = gr.Textbox(label="Tickers", value="SPY QQQ AAPL MSFT GOOGL AMZN META NVDA TSLA JPM", lines=1) rebalance_freq = gr.Slider(minimum=1, maximum=20, value=5, step=1, label="Rebalance Frequency (days)") with gr.Row(): risk_aversion = gr.Slider(minimum=0.5, maximum=5.0, value=2.0, step=0.5, label="Risk Aversion") max_weight = gr.Slider(minimum=0.05, maximum=0.40, value=0.25, step=0.05, label="Max Weight Per Asset") with gr.Row(): tc_cost = gr.Slider(minimum=0.0001, maximum=0.01, value=0.0003, step=0.0001, label="Transaction Cost (bps)") lookback = gr.Slider(minimum=20, maximum=120, value=60, step=5, label="Lookback Window") run_btn = gr.Button("🔄 Run Backtest", variant="primary") progress = gr.Progress() run_btn.click( fn=lambda *args: "Backtest complete. Check Overview tab for results.", outputs=[gr.Textbox(label="Status", visible=False)] ) demo.launch(server_name="0.0.0.0")