from fastapi import APIRouter, Query from typing import Optional from services.options_pricer import ( black_scholes, compute_pnl_curve, bull_call_spread, bear_put_spread, long_straddle, implied_vol_surface ) from services.data_fetcher import get_quote, compute_historical_iv router = APIRouter(prefix="/api/options", tags=["options"]) @router.get("/price") def price_option( symbol: str = Query(...), strike: float = Query(...), expiry_days: int = Query(90), option_type: str = Query("call"), rate: float = Query(0.05), ): q = get_quote(symbol) S = q["price"] if q and "price" in q else strike sigma = compute_historical_iv(symbol) T = expiry_days / 365 result = black_scholes(S, strike, T, rate, sigma, option_type) result["underlying_price"] = S result["sigma"] = sigma return result @router.get("/pnl-curve") def pnl_curve( symbol: str = Query(...), strike: float = Query(...), expiry_days: int = Query(90), option_type: str = Query("call"), quantity: int = Query(1), premium_paid: float = Query(...), rate: float = Query(0.05), ): q = get_quote(symbol) S = q["price"] if q and "price" in q else strike sigma = compute_historical_iv(symbol) T = expiry_days / 365 return compute_pnl_curve(S, strike, T, rate, sigma, option_type, quantity, premium_paid) @router.get("/strategy/bull-call-spread") def bull_spread( symbol: str = Query(...), strike_low: float = Query(...), strike_high: float = Query(...), expiry_days: int = Query(90), rate: float = Query(0.05), ): q = get_quote(symbol) S = q["price"] if q and "price" in q else strike_low sigma = compute_historical_iv(symbol) T = expiry_days / 365 result = bull_call_spread(S, strike_low, strike_high, T, rate, sigma) result["underlying_price"] = S result["sigma"] = sigma return result @router.get("/strategy/bear-put-spread") def bear_spread( symbol: str = Query(...), strike_high: float = Query(...), strike_low: float = Query(...), expiry_days: int = Query(90), rate: float = Query(0.05), ): q = get_quote(symbol) S = q["price"] if q and "price" in q else strike_high sigma = compute_historical_iv(symbol) T = expiry_days / 365 result = bear_put_spread(S, strike_high, strike_low, T, rate, sigma) result["underlying_price"] = S result["sigma"] = sigma return result @router.get("/strategy/straddle") def straddle( symbol: str = Query(...), strike: float = Query(...), expiry_days: int = Query(90), rate: float = Query(0.05), ): q = get_quote(symbol) S = q["price"] if q and "price" in q else strike sigma = compute_historical_iv(symbol) T = expiry_days / 365 result = long_straddle(S, strike, T, rate, sigma) result["underlying_price"] = S result["sigma"] = sigma return result @router.get("/iv-surface") def iv_surface( symbol: str = Query(...), rate: float = Query(0.05), ): q = get_quote(symbol) S = q["price"] if q and "price" in q else 100.0 sigma = compute_historical_iv(symbol) strikes_pct = [0.80, 0.85, 0.90, 0.95, 1.00, 1.05, 1.10, 1.15, 1.20] expiries = [7, 14, 30, 60, 90, 180] surface = implied_vol_surface(S, strikes_pct, expiries, rate, sigma) return {"symbol": symbol, "spot": S, "surface": surface}