feat(live): cap/asset dinamico = equity/2 — operazionalizza la decisione frontier (inerte a $600)

Il cap notional per-asset non e' piu' fisso a $300: con max_notional_per_asset_frac
in config diventa equity/2, cosi' cresce col capitale e un deposito futuro non resta
strozzato (frontiera 2026-07-03). Guardrail: dinamico SOLO con equity reale fidata;
su fallback/offline si torna al cap fisso (protezione downside quando E e' ignota).
Live dry-run: cap $299 a equity $598 -> inerte oggi. Suite 172 passed (+4 test).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Adriano Dal Pastro
2026-07-03 09:42:13 +00:00
parent eef200cf14
commit cf7de40dc0
4 changed files with 119 additions and 5 deletions
+20 -4
View File
@@ -13,7 +13,11 @@ deribit_book_sleeves = 0.75*TP01 + 0.25*SKH01):
tp_frac = target TP01 (causale, >=0, long-flat) da TrendPortfolio.current_target
skh_sign = +1 long / -1 short / 0 flat da _skyhook_positions (book 230m)
E = equity reale del conto (fallback paper se offline)
CAP = max_notional_per_asset_usd (config/live.json, $300)
CAP = cap notional per-asset. Fisso = max_notional_per_asset_usd ($300), OPPURE
DINAMICO = equity * max_notional_per_asset_frac (es. 0.5 -> equity/2) se la
frazione e' presente in config -> il cap cresce col capitale e non strozza il
book quando depositi (frontiera 2026-07-03). Dinamico SOLO con equity reale
fidata; su fallback/offline si torna al cap fisso (protezione downside).
GLI EXIT DI SKH01 SONO IMPLICITI: _skyhook_positions() replica il book (ingressi + SL/TP/max_bars +
non-overlap) sulla feed certificata fresca -> quando il trade va chiuso ritorna 'flat' -> skh_sign=0
@@ -42,9 +46,21 @@ W_SKH = 0.25
FLAT_USD = 1.0
def _cap() -> float:
def _cap(equity: float | None = None, real_equity: float | None = None,
eq_fallback: str | None = None) -> float:
"""Cap notional per-asset ($). Se in config c'e' `max_notional_per_asset_frac` (opt-in), il cap
diventa DINAMICO = equity * frac (es. equity/2) -> cresce col capitale, cosi' un deposito non
resta strozzato dal $300 fisso (vedi frontiera 2026-07-03). GUARDRAIL: il cap dinamico si usa
SOLO con equity reale fidata (letta dal conto); se l'equity reale non e' leggibile
(eq_fallback/offline, real_equity=None) si torna al cap FISSO `max_notional_per_asset_usd`, che
protegge il downside quando l'equity e' ignota. Senza `..._frac` in config -> sempre cap fisso."""
cfg = json.loads(CONFIG.read_text()) if CONFIG.exists() else {}
return float(cfg.get("max_notional_per_asset_usd", 300.0))
fixed = float(cfg.get("max_notional_per_asset_usd", 300.0))
frac = cfg.get("max_notional_per_asset_frac")
if frac is None:
return fixed
trusted = (real_equity is not None) and (not eq_fallback) and (equity is not None) and (equity > 0)
return float(equity) * float(frac) if trusted else fixed
def book_net_target(tp_frac: float, skh_sign: int, equity: float, cap: float,
@@ -99,8 +115,8 @@ def book_report(offline: bool = False, equity_override: float | None = None,
segnale 230m all'ultima barra chiusa, per l'esecuzione reale. Default False (feed certificato,
deterministico: dashboard/test). TP01 resta sul certificato (è giornaliero)."""
sh = shadow_report(offline=offline, equity_override=equity_override)
cap = _cap()
equity = sh["equity"]
cap = _cap(equity=equity, real_equity=sh.get("real_equity"), eq_fallback=sh.get("eq_fallback"))
load5m = None
if live_feed:
from src.live.livefeed import fresh_5m