Files
nexus-quant-terminal/backend/app/routers/scenarios.py
T
KansaramandClaude Sonnet 4.6 61e145a442 feat: launch NEXUS TERMINAL — Bloomberg-style FX options analytics platform
Full-stack forex options analytics terminal with Bloomberg-inspired UI.

Backend (FastAPI + Python):
- Garman-Kohlhagen options pricing engine with full Greeks
- Goldman Sachs gs-quant AI signals (RSI, MACD, Bollinger, Hurst, OU)
- Monte Carlo GBM simulation and volatility surface generation
- CFTC COT institutional positioning + Forex Factory economic calendar
- Live data proxy: OpenSky aircraft + USGS earthquakes (CORS-safe)
- Multi-leg strategy library (straddle, iron condor, butterfly, spreads)

Frontend (React 18 + Vite):
- NEXUS animated orbital logo (3-ring SVG) + canvas favicon animation
- Bloomberg terminal design: JetBrains Mono, color-mix() tokens
- 11 dashboard tabs: Greeks, Chart, AI Signals, 3D Surfaces, Breakeven,
  Scenarios, Monte Carlo, Institutional, Calendar, Live Map, Live Feeds
- Live World Map (react-leaflet): aircraft, earthquakes, weather radar
- Live Feeds: CoinGecko crypto top-12 + Windy.com global webcams
- Economic calendar with filters + institutional flow (CFTC COT)
- Animated landing page + session-based routing
- Fully responsive dark-only terminal design system

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 18:19:23 +05:30

31 lines
1.1 KiB
Python

from fastapi import APIRouter
from ..schemas import ScenarioRequest
from ..core.garman_kohlhagen import gk_price
router = APIRouter(prefix="/scenarios", tags=["scenarios"])
@router.post("")
def compute_scenarios(req: ScenarioRequest):
options = [o.model_dump() for o in req.options]
def portfolio_value(S, sigma):
return sum(
gk_price(S, opt["K"], opt.get("T", req.T), req.r_d, req.r_f, sigma, opt["type"])
* opt["qty"] for opt in options
)
base = portfolio_value(req.S0, req.sigma0)
results = []
for shock in req.shocks:
S_s = req.S0 * (1 + shock.dS_pct)
vol_s = max(0.005, req.sigma0 + shock.dVol)
pnl = portfolio_value(S_s, vol_s) - base
results.append({
"label": shock.label,
"dS_pct": shock.dS_pct, "dVol": shock.dVol,
"S_shocked": round(S_s, 5), "vol_shocked": round(vol_s, 4),
"pnl": round(pnl, 5),
"pnl_pct": round(pnl / abs(base) * 100, 2) if base else 0,
})
return {"base_value": round(base, 5), "scenarios": results}