Premchan369's picture
Upload app.py
7cce354 verified
"""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")