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

67 lines
2.4 KiB
Python

from fastapi import APIRouter, HTTPException
import yfinance as yf
router = APIRouter(prefix="/market", tags=["market"])
@router.get("/{ticker}")
def get_market_data(ticker: str):
"""Return current spot price, company name, and daily change for a ticker."""
try:
t = yf.Ticker(ticker.upper())
info = t.fast_info
spot = info.last_price
prev = info.previous_close
if not spot:
raise HTTPException(status_code=404, detail=f"Ticker '{ticker}' not found.")
change_pct = round((spot - prev) / prev * 100, 2) if prev else 0.0
name = getattr(info, "exchange", ticker.upper())
return {
"ticker": ticker.upper(),
"spot": round(float(spot), 2),
"prev_close": round(float(prev), 2) if prev else None,
"change_pct": change_pct,
}
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
@router.get("/iv-surface/{ticker}")
def get_iv_surface(ticker: str):
"""
Fetch the real implied volatility surface from market option chains.
Returns strikes, expiries, and IV values for a heatmap.
"""
try:
t = yf.Ticker(ticker.upper())
expiries = t.options[:6] # Limit to 6 nearest expiries
if not expiries:
raise HTTPException(status_code=404, detail="No options data found.")
rows = []
for exp in expiries:
chain = t.option_chain(exp)
for _, row in chain.calls.iterrows():
if row.get("impliedVolatility") and row["impliedVolatility"] > 0:
rows.append({
"expiry": exp,
"strike": float(row["strike"]),
"iv": round(float(row["impliedVolatility"]), 4),
"type": "call",
})
for _, row in chain.puts.iterrows():
if row.get("impliedVolatility") and row["impliedVolatility"] > 0:
rows.append({
"expiry": exp,
"strike": float(row["strike"]),
"iv": round(float(row["impliedVolatility"]), 4),
"type": "put",
})
spot = float(t.fast_info.last_price)
return {"ticker": ticker.upper(), "spot": spot, "data": rows}
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))