Files
nexus-quant-terminal/backend/app/core/montecarlo.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

45 lines
1.6 KiB
Python

"""montecarlo.py — GBM Monte Carlo for forex options (uses GK cost basis)."""
import numpy as np
from .garman_kohlhagen import gk_price
def run_montecarlo(options, S0, sigma, r_d, r_f, T, n_paths=1000, n_steps=100):
"""Simulate GBM price paths and compute P&L distribution at expiry."""
dt = T / n_steps
Z = np.random.standard_normal((n_paths, n_steps))
paths = np.zeros((n_paths, n_steps + 1)); paths[:,0] = S0
# GBM: dS = (r_d - r_f)·S·dt + σ·S·dW (Garman-Kohlhagen drift)
for t in range(1, n_steps + 1):
paths[:,t] = paths[:,t-1] * np.exp(
(r_d - r_f - 0.5*sigma**2)*dt + sigma*np.sqrt(dt)*Z[:,t-1]
)
terminal = paths[:,-1]
pnl = np.zeros(n_paths)
for opt in options:
K, qty = float(opt["K"]), float(opt["qty"])
payoff = (np.maximum(terminal - K, 0) if opt["type"]=="call"
else np.maximum(K - terminal, 0))
pnl += payoff * qty
# Subtract initial GK cost
cost = sum(
gk_price(S0, float(o["K"]), float(o.get("T",T)), r_d, r_f, sigma, o["type"])
* float(o["qty"]) for o in options
)
pnl -= cost
idx = np.random.choice(n_paths, size=min(60, n_paths), replace=False)
return {
"time_axis": [round(i*dt, 4) for i in range(n_steps+1)],
"sample_paths": paths[idx].tolist(),
"pnl": pnl.tolist(),
"pnl_mean": round(float(pnl.mean()), 5),
"pnl_std": round(float(pnl.std()), 5),
"pnl_5pct": round(float(np.percentile(pnl, 5)), 5),
"pnl_95pct": round(float(np.percentile(pnl, 95)), 5),
"prob_profit": round(float((pnl > 0).mean()), 4),
}