Stack: FastAPI + React/TypeScript + SQLite + GPT-4o Features: Radar géopolitique, Marchés, Régime Macro, Journal de Bord MTM, Rapport IA, Super Contexte (base de raisonnement évolutive), Boucle feedback IA. Deploy: Docker + docker-compose + nginx pour openfin.open-squared.tech Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
112 lines
3.3 KiB
Python
112 lines
3.3 KiB
Python
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}
|