"""Leverage cap server-side per place_order (IBKR Reg-T context). Cap letto dal secret JSON via campo `max_leverage`. Default 1 (cash) se assente. IBKR margin accounts default a 4x intraday / 2x overnight (Reg-T). """ from __future__ import annotations from fastapi import HTTPException def get_max_leverage(creds: dict) -> int: """Legge max_leverage dal secret. Default 1 se mancante.""" raw = creds.get("max_leverage", 1) try: value = int(raw) except (TypeError, ValueError): value = 1 return max(1, value) def enforce_leverage( requested: int | float | None, *, creds: dict, exchange: str, ) -> int: """Verifica e applica leverage cap. Ritorna leverage applicabile. Solleva HTTPException(403, LEVERAGE_CAP_EXCEEDED) se requested > cap. Se requested is None, applica il cap come default. """ cap = get_max_leverage(creds) if requested is None: return cap lev = int(requested) if lev < 1: raise HTTPException( status_code=403, detail={ "error": "LEVERAGE_CAP_EXCEEDED", "exchange": exchange, "requested": lev, "max": cap, "reason": "leverage must be >= 1", }, ) if lev > cap: raise HTTPException( status_code=403, detail={ "error": "LEVERAGE_CAP_EXCEEDED", "exchange": exchange, "requested": lev, "max": cap, }, ) return lev