feat(runtime): audit log include threshold rolling e window usata
Risponde al final review (spec §6.4): il decisions log ora contiene iv_rv_threshold_used (la soglia P_q effettivamente applicata) e iv_rv_window_used_days (giorni di history nella finestra). Permette ricostruire ex-post perché un trade è stato saltato e con quali numeri. Helper privi di I/O — la soglia viene ricomputata in base alla history già caricata, costo trascurabile. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,7 @@ from cerbero_bite.clients.macro import MacroClient
|
|||||||
from cerbero_bite.clients.portfolio import PortfolioClient
|
from cerbero_bite.clients.portfolio import PortfolioClient
|
||||||
from cerbero_bite.clients.sentiment import SentimentClient
|
from cerbero_bite.clients.sentiment import SentimentClient
|
||||||
from cerbero_bite.config.schema import StrategyConfig
|
from cerbero_bite.config.schema import StrategyConfig
|
||||||
|
from cerbero_bite.core.adaptive_threshold import compute_adaptive_threshold
|
||||||
from cerbero_bite.core.combo_builder import ComboProposal, build, select_strikes
|
from cerbero_bite.core.combo_builder import ComboProposal, build, select_strikes
|
||||||
from cerbero_bite.core.entry_validator import (
|
from cerbero_bite.core.entry_validator import (
|
||||||
EntryContext,
|
EntryContext,
|
||||||
@@ -315,6 +316,44 @@ async def _build_quotes(
|
|||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def _audit_threshold(
|
||||||
|
entry_cfg: object,
|
||||||
|
iv_rv_history: tuple[Decimal, ...],
|
||||||
|
) -> str | None:
|
||||||
|
"""Soglia P_q rolling effettivamente usata dal gate, per il decisions log."""
|
||||||
|
if not getattr(entry_cfg, "iv_minus_rv_filter_enabled", False):
|
||||||
|
return None
|
||||||
|
if not getattr(entry_cfg, "iv_minus_rv_adaptive_enabled", False):
|
||||||
|
return str(getattr(entry_cfg, "iv_minus_rv_min", Decimal("0")))
|
||||||
|
threshold = compute_adaptive_threshold(
|
||||||
|
history=iv_rv_history,
|
||||||
|
percentile=entry_cfg.iv_minus_rv_percentile, # type: ignore[attr-defined]
|
||||||
|
absolute_floor=entry_cfg.iv_minus_rv_min, # type: ignore[attr-defined]
|
||||||
|
min_days=entry_cfg.iv_minus_rv_window_min_days, # type: ignore[attr-defined]
|
||||||
|
target_days=entry_cfg.iv_minus_rv_window_target_days, # type: ignore[attr-defined]
|
||||||
|
)
|
||||||
|
return None if threshold is None else str(threshold)
|
||||||
|
|
||||||
|
|
||||||
|
def _audit_window_days(
|
||||||
|
entry_cfg: object,
|
||||||
|
iv_rv_history: tuple[Decimal, ...],
|
||||||
|
) -> int | None:
|
||||||
|
"""Numero di giorni effettivamente usati dalla finestra rolling."""
|
||||||
|
if not getattr(entry_cfg, "iv_minus_rv_adaptive_enabled", False):
|
||||||
|
return None
|
||||||
|
n_days = len(iv_rv_history) // 96
|
||||||
|
target = int(getattr(entry_cfg, "iv_minus_rv_window_target_days", 60))
|
||||||
|
min_days = int(getattr(entry_cfg, "iv_minus_rv_window_min_days", 30))
|
||||||
|
if n_days < 1:
|
||||||
|
return 0
|
||||||
|
if n_days >= target:
|
||||||
|
return target
|
||||||
|
if n_days >= min_days:
|
||||||
|
return min_days
|
||||||
|
return n_days
|
||||||
|
|
||||||
|
|
||||||
def _max_loss_per_contract_usd(short_strike: Decimal, long_strike: Decimal) -> Decimal:
|
def _max_loss_per_contract_usd(short_strike: Decimal, long_strike: Decimal) -> Decimal:
|
||||||
return (short_strike - long_strike).copy_abs()
|
return (short_strike - long_strike).copy_abs()
|
||||||
|
|
||||||
@@ -490,6 +529,10 @@ async def run_entry_cycle(
|
|||||||
str(snap.iv_minus_rv) if snap.iv_minus_rv is not None else None
|
str(snap.iv_minus_rv) if snap.iv_minus_rv is not None else None
|
||||||
),
|
),
|
||||||
"iv_rv_history_n": len(iv_rv_history),
|
"iv_rv_history_n": len(iv_rv_history),
|
||||||
|
"iv_rv_threshold_used": _audit_threshold(entry_cfg, iv_rv_history),
|
||||||
|
"iv_rv_window_used_days": _audit_window_days(
|
||||||
|
entry_cfg, iv_rv_history
|
||||||
|
),
|
||||||
"dvol_24h_ago": (
|
"dvol_24h_ago": (
|
||||||
str(dvol_24h_ago) if dvol_24h_ago is not None else None
|
str(dvol_24h_ago) if dvol_24h_ago is not None else None
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user