book: leva_tetto unica per cuscino USDE e giornale (#28)
La leva lorda massima del libro era ridichiarata con tre formule diverse: usde.frazione_cuscino (N_ASSET fisso, senza scala), la regola `leva` del giornale (senza scala) e journal.movimenti_capitale (con scala). A scala 1,25 il cuscino USDC risultava 0,30 dell'equity invece di 0,375. Nuova src/live/book.leva_tetto(cfg) = len(ASSETS) x min(WEIGHT, frac) x scala, al piu' LEVA_LORDA_MAX; su ScalaNonAutorizzata non solleva, ritorna il tetto di codice (cuscino_watch non deve morire sulla config sbagliata). usde.frazione_cuscino e la regola `leva` del giornale ora la derivano; movimenti_capitale idem, nel suo try/except esistente. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -136,6 +136,42 @@ def _scala(real_equity: float | None = None, eq_fallback: str | None = None,
|
||||
return s
|
||||
|
||||
|
||||
def leva_tetto(cfg: dict | None = None) -> tuple[float, str]:
|
||||
"""Leva lorda massima che il libro PUO' prendere. UNA formula, non tre (#28): prima era
|
||||
ridichiarata in `usde.frazione_cuscino` (N_ASSET fisso, senza scala) e nella regola `leva` del
|
||||
giornale (senza scala) -> a scala 1,25 il cuscino USDC risultava 0,30 dell'equity invece di
|
||||
0,375, e la regola `leva` mostrava un tetto diverso da quello che il libro rispetta davvero.
|
||||
|
||||
leva = len(ASSETS) x min(WEIGHT, frac) x scala, al piu' LEVA_LORDA_MAX. -> (leva, come).
|
||||
- frac = cfg["max_notional_per_asset_frac"] se presente, altrimenti WEIGHT. Il min(WEIGHT, frac)
|
||||
viene dal fatto che `book_net_target` non supera mai weight*equity*(W_TP01+W_SKH) =
|
||||
weight*equity (i due pesi sommano a 1): |raw| <= weight*equity, quindi |net_target| <=
|
||||
scala*min(cap, weight*equity) -- un frac oltre WEIGHT alza il cap nominale ma non la leva
|
||||
REALE che il libro puo' esprimere.
|
||||
- scala = la scala DICHIARATA (`_scala(real_equity=1.0, cfg=cfg)`, gia' validata): un tetto
|
||||
descrive quanto la config AUTORIZZA, non quanto un giro con equity illeggibile ha preso.
|
||||
- Su `ScalaNonAutorizzata` (config fuori scaletta o fuori tetto) NON si solleva: un
|
||||
sorvegliante (`cuscino_watch`) non deve morire proprio quando la config e' sbagliata
|
||||
(verifica fable B5) -> si ritorna il tetto di CODICE, dichiarando l'anomalia in `come`.
|
||||
"""
|
||||
if cfg is None:
|
||||
cfg = json.loads(CONFIG.read_text()) if CONFIG.exists() else {}
|
||||
try:
|
||||
scala = _scala(real_equity=1.0, cfg=cfg)
|
||||
except ScalaNonAutorizzata as e:
|
||||
breve = str(e).splitlines()[0]
|
||||
breve = breve if len(breve) <= 80 else breve[:77] + "..."
|
||||
return LEVA_LORDA_MAX, (f"config fuori scaletta/tetto ({breve}): "
|
||||
f"tetto di codice LEVA_LORDA_MAX")
|
||||
raw_frac = cfg.get("max_notional_per_asset_frac")
|
||||
frac = float(raw_frac) if raw_frac is not None else WEIGHT
|
||||
frac_eff = min(WEIGHT, frac)
|
||||
leva = len(ASSETS) * frac_eff * scala
|
||||
base = f"{len(ASSETS)} asset x frac {frac_eff} x scala {scala} = {leva:.2f}x"
|
||||
if leva > LEVA_LORDA_MAX + 1e-12:
|
||||
return LEVA_LORDA_MAX, f"{base}, troncato al tetto di codice {LEVA_LORDA_MAX}x"
|
||||
return leva, base
|
||||
|
||||
|
||||
def _read_watermark() -> float | None:
|
||||
"""Ultima equity REALE osservata sul conto. None se mai vista o file illeggibile."""
|
||||
|
||||
Reference in New Issue
Block a user