aether_quant.performance¶
Performance triggers and the rank-IC monitor (the Postgres writer stays out).
Performance triggers and the rank-IC monitor (the Postgres writer stays out).
cluster_drift_trigger ¶
cluster_drift_trigger(events: list[dict], window: int = 50, drift_threshold: float = 0.5, min_persistent_fraction: float = 0.6) -> list[dict]
Fires when learned-neighbor-set drift (neighbor_shift_score) stays elevated across the window - persistence-guarded the same way as topology_uncertainty_trigger, so small bar-to-bar noise never fires.
compute_production_rank_ic ¶
compute_production_rank_ic(observations: list[dict], non_overlapping_stride: int = 1) -> dict[str, Any]
Thin re-export of evaluation.rank_ic_core.aggregate_rank_ic_observations() - see that function's docstring for the actual algorithm.
compute_realized_rank_ic_observations ¶
compute_realized_rank_ic_observations(events: list[dict], horizon_days: int = 20) -> list[dict]
Thin re-export of evaluation.rank_ic_core.resolve_realized_rank_ic_observations() - see that function's docstring for the actual algorithm.
confidence_decay_trigger ¶
confidence_decay_trigger(events: list[dict], window: int = 50, decay_ratio_threshold: float = 0.5, instability_std_threshold: float = 0.25) -> list[dict]
A trigger when the model's confidence falls well below its earlier level or turns unstable over the window.
drawdown_trigger ¶
drawdown_trigger(events: list[dict], max_drawdown_threshold: float = -0.1) -> list[dict]
A trigger when the simulated or real drawdown is worse than the threshold.
evaluate_all_triggers ¶
evaluate_all_triggers(events: list[dict], config: dict[str, Any], recent_triggers: list[dict] | None = None, rank_ic_observations: list[dict] | None = None) -> dict[str, Any]
Every performance trigger on the recent events, deduplicated against the recent ones (what the retraining worker reads).
executed_trade_count_trigger ¶
executed_trade_count_trigger(events: list[dict], interval: int = 100) -> list[dict]
Retraining-cadence trigger based on actually executed trades, not raw observation volume. observation_count_trigger counts every per-asset-per- bar event regardless of action (most are hold/observe/simulate) and fires at "info" severity, which phase_v2.retraining.eligible_severities excludes - so it can never itself select a retraining run. This trigger counts only event["action"] == "trade" entries and fires at "warning" (a fixed severity, not breach-ratio-derived - there is no "how bad" axis for a count-reached signal), so a periodic cadence tied to real trading activity can actually drive retraining.
liquidity_warning_trigger ¶
liquidity_warning_trigger(events: list[dict], max_liquidity_rejection_rate: float = 0.25, window: int = 100) -> list[dict]
A trigger when liquidity vetoes too many decisions in the window.
live_order_permission_blocked_trigger ¶
live_order_permission_blocked_trigger(events: list[dict], window: int = 100) -> list[dict]
V2-22 deployment-health trigger: fires critical when mode=='live' but recent execution_notes are still 'simulated_*' - the order gate is silently blocking what should be a real order (misconfigured credentials/allow_live_orders flag/risk lock in a deployment that believes it's live). Unlike the model-quality triggers above, this is never retrain-eligible - see _NON_RETRAIN_TRIGGERS.
model_topology_disagreement_trigger ¶
model_topology_disagreement_trigger(events: list[dict], window: int = 50, disagreement_threshold: float = 0.5, min_persistent_fraction: float = 0.6) -> list[dict]
Fires when the learned topology model's cluster/regime read stays persistently at odds with the deterministic topology (topology_disagreement).
observation_count_trigger ¶
observation_count_trigger(events: list[dict], interval: int = 100) -> list[dict]
A routine trigger every interval observations.
rank_ic_decay_trigger ¶
rank_ic_decay_trigger(rank_ic_observations: list[dict], rolling_window: int = 100, min_mean_ic: float = 0.02, min_t_stat: float = 2.0) -> list[dict]
Phase 6 of the 5/10 -> 9/10 roadmap: the one trigger in this module
whose input isn't the standard events list - rank_ic_observations
comes from performance/rank_ic_monitor.py::compute_realized_rank_ic_observations(),
already resolved against each prediction's realized 20-trading-day
forward return (a prediction made today can't be scored until then -
see that module's docstring for why this is structurally different
from every other trigger here). Fires when EITHER the rolling mean
rank-IC or its t-stat falls below its own floor - a real edge needs
both a real mean and real statistical confidence in it, not just one.
Mirrors sharpe_degradation_trigger()'s exact shape (rolling window, _breach_ratio_below()/_severity_for_breach() severity scoring, _make_trigger()) so this composes with every existing trigger-handling code path (evaluate_all_triggers(), retraining/planning.py) without special-casing.
regime_shift_trigger ¶
regime_shift_trigger(events: list[dict], window: int = 20, sensitivity: float = 0.6) -> list[dict]
A trigger when the dominant regime changed across the window beyond the sensitivity.
risk_lock_trigger ¶
risk_lock_trigger(events: list[dict], max_consecutive_locked_events: int = 20) -> list[dict]
A trigger when trading has been locked for too many consecutive events.
sharpe_degradation_trigger ¶
sharpe_degradation_trigger(events: list[dict], min_sharpe: float = 0.3, window: int = 100) -> list[dict]
A trigger when the simulated Sharpe over the window falls below the floor.
sustained_drawdown_trigger ¶
sustained_drawdown_trigger(events: list[dict], max_drawdown_threshold: float = -0.1, consecutive_days: int = 2) -> list[dict]
A slower, day-granularity companion to drawdown_trigger's single-bar
point-in-time check - not a replacement. drawdown_trigger still fires
immediately on one severe bar; this fires only when the real portfolio's
worst drawdown breaches max_drawdown_threshold on consecutive_days
distinct trailing trading days in a row, catching a moderate-but-
persistent decline a point check might miss (or a single noisy bad bar
that recovers the next day, which this correctly does not fire on).
topology_regime_mismatch_trigger ¶
topology_regime_mismatch_trigger(events: list[dict], window: int = 50, mismatch_threshold: float = 0.5) -> list[dict]
Fires when the deterministic per-asset regime_label disagrees with
its cluster's dominant_regime_label for a persistent share of the
window. The rate itself (over window observations) is the persistence
guard - a single mismatched bar cannot push the rate above threshold.
topology_uncertainty_trigger ¶
topology_uncertainty_trigger(events: list[dict], window: int = 50, max_avg_uncertainty: float = 0.6, min_persistent_fraction: float = 0.6) -> list[dict]
Fires when learned-topology uncertainty (topology.learned_topology's topology_uncertainty) stays elevated across the window - both the rolling average AND a minimum fraction of individually-breaching bars must clear the threshold, so one noisy bar never fires this alone.
trigger_frequency_spike ¶
trigger_frequency_spike(recent_triggers: list[dict], window_minutes: int = 60, baseline_window_minutes: int = 1440, spike_multiplier: float = 3.0, min_recent_count: int = 3) -> list[dict]
Fires when the rate of other triggers firing spikes relative to
their own recent baseline - a meta-trigger over trigger rows, not
experience events. recent_triggers should already be scoped to
roughly baseline_window_minutes of history (the caller/worker fetches
that window from Postgres); this function only needs min_recent_count
triggers inside the newest window_minutes slice AND a rate at least
spike_multiplier times the whole-window baseline rate to fire, so a
handful of unrelated triggers can't spike this on their own.
win_rate_trigger ¶
win_rate_trigger(events: list[dict], min_win_rate: float = 0.45, window: int = 100) -> list[dict]
A trigger when the win rate over the window falls below the floor.