Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import pandas as pd | |
| import json | |
| def get_run_engine(): | |
| from main import run_engine | |
| return run_engine | |
| run_engine = get_run_engine() | |
| st.set_page_config(page_title="Portfolio Engine Dashboard", layout="wide") | |
| st.title("Quantitative Portfolio Production Engine") | |
| st.sidebar.header("Portfolio Inputs") | |
| tickers_input = st.sidebar.text_input("Tickers (comma separated)", "SPY, TLT, GLD") | |
| capital = st.sidebar.number_input("Capital ($)", value=100000.0) | |
| risk = st.sidebar.slider("Risk Aversion (1=Aggressive, 10=Conservative)", min_value=1, max_value=10, value=5) | |
| model = st.sidebar.selectbox("Return Model", options=[ | |
| (1, "CAPM"), | |
| (2, "Black-Litterman"), | |
| (3, "James-Stein"), | |
| (4, "Fama-French"), | |
| (5, "ML Stacking/BSTS") | |
| ], format_func=lambda x: x[1])[0] | |
| allocation_engine = st.sidebar.selectbox("Allocation Engine", options=[ | |
| (1, "Mean-Variance"), | |
| (2, "Hierarchical Risk Parity") | |
| ], format_func=lambda x: x[1])[0] | |
| st.sidebar.subheader("Advanced Settings") | |
| monthly = st.sidebar.checkbox("Monthly Frequency", value=False) | |
| tax = st.sidebar.checkbox("Enable Tax Calculation", value=False) | |
| with_futures = st.sidebar.checkbox("Enable Futures Overlay", value=False) | |
| import requests | |
| import time | |
| def get_risk_factor(risk_level: int) -> float: | |
| risk_map = { | |
| 1: 0.1, 2: 0.5, 3: 1.0, 4: 2.0, 5: 3.0, | |
| 6: 5.0, 7: 7.5, 8: 10.0, 9: 15.0, 10: 25.0 | |
| } | |
| return risk_map.get(risk_level, 3.0) | |
| if st.button("Run Optimization via API"): | |
| with st.spinner("Calling remote API to run global quantitative optimization..."): | |
| tickers_list = [t.strip() for t in tickers_input.split(",") if t.strip()] | |
| payload = { | |
| "tickers": tickers_list, | |
| "capital": float(capital), | |
| "risk_level": int(risk), | |
| "model": int(model), | |
| "engine": int(allocation_engine), | |
| "currency": "$", | |
| "days": 252, | |
| "current_weights": {} | |
| } | |
| try: | |
| import os | |
| api_key = os.getenv("API_KEY", "SECRET_API_KEY_123") | |
| headers = {"X-API-Key": api_key} | |
| res = requests.post("http://127.0.0.1:8080/run_optimization", json=payload, headers=headers, timeout=300) | |
| res.raise_for_status() | |
| st.success("Optimization complete! Connect to live feed below.") | |
| except Exception as e: | |
| st.error(f"Error during API call: {e}") | |
| st.header("Live Risk Dashboard") | |
| if st.button("Start Live Data Feed"): | |
| import websocket | |
| import json | |
| col1, col2, col3 = st.columns(3) | |
| pnl_metric = col1.empty() | |
| capital_metric = col2.empty() | |
| var_breach_metric = col3.empty() | |
| chart_holder = st.empty() | |
| positions_holder = st.empty() | |
| pnl_history = [] | |
| breaches = 0 | |
| var_limit = - (float(capital) * 0.01) # 1% 1-Day VaR limit for display | |
| try: | |
| ws = websocket.WebSocket() | |
| import os | |
| api_key = os.getenv("API_KEY", "SECRET_API_KEY_123") | |
| ws.connect(f"ws://127.0.0.1:8080/ws?api_key={api_key}") | |
| while True: | |
| data = json.loads(ws.recv()) | |
| if data.get("type") == "live_update": | |
| pnl = data["pnl"] | |
| cap = data["capital"] | |
| prices = data["prices"] | |
| pnl_history.append(pnl) | |
| if pnl < var_limit: | |
| breaches += 1 | |
| pnl_metric.metric("Live P&L", f"${pnl:,.2f}", delta=f"${pnl - (pnl_history[-2] if len(pnl_history) > 1 else 0):,.2f}") | |
| capital_metric.metric("Total Capital", f"${cap:,.2f}") | |
| var_breach_metric.metric("VaR Limit Breaches", breaches) | |
| chart_holder.line_chart(pnl_history) | |
| pdf = pd.DataFrame(list(prices.items()), columns=["Ticker", "Live Price ($)"]) | |
| positions_holder.dataframe(pdf, use_container_width=True) | |
| except Exception as e: | |
| st.error(f"WebSocket disconnected or failed: {e}") | |