feat: math core v3 engine upgrade

This commit is contained in:
Celes Renata
2026-06-27 12:21:41 +00:00
parent 365bc5d4b7
commit b4bf0f2361
34 changed files with 11693 additions and 3 deletions
+102
View File
@@ -13,11 +13,15 @@ import logging
import math
from dataclasses import dataclass, field
from datetime import datetime, timezone
from typing import TYPE_CHECKING
import asyncpg
from services.shared.schemas import TrendSummary
if TYPE_CHECKING:
from services.aggregation.regime import V3RegimeClassification
logger = logging.getLogger("projection")
# ---------------------------------------------------------------------------
@@ -493,3 +497,101 @@ async def persist_trend_projection(
projection.diverges_from_current,
)
return str(row_id)
# ---------------------------------------------------------------------------
# V3 Posterior State Projection (Requirements: 11.111.7)
# ---------------------------------------------------------------------------
# Regime decay factors (phi) — Req 11.3
_V3_PHI_DECAY: dict[str, float] = {
"panic": 0.35,
"trend_following": 0.80,
"mean_reversion": 0.55,
"uncertainty": 0.50,
}
def _logit(p: float) -> float:
"""Compute logit = ln(p / (1-p)) with boundary guard."""
p = max(1e-10, min(1 - 1e-10, p))
return math.log(p / (1 - p))
def _sigmoid(x: float) -> float:
"""Compute sigmoid = 1 / (1 + exp(-x)) with overflow guard."""
if x > 500:
return 1.0
if x < -500:
return 0.0
return 1.0 / (1.0 + math.exp(-x))
@dataclass
class V3ProjectionState:
"""V3 posterior state projection result.
Attributes:
a_t: Accumulated evidence state A_t.
p_up_projected: Projected probability sigmoid(logit(P_prior) + phi^h * A_t).
projected_strength: abs(2 * P_up_projected - 1).
diverges: True when sign(P_up_projected - 0.5) != sign(P_up_t - 0.5).
phi_regime: Regime-specific decay factor used.
"""
a_t: float
p_up_projected: float
projected_strength: float
diverges: bool
phi_regime: float
def compute_v3_projection(
a_prev: float,
cluster_llrs: list[float],
regime: V3RegimeClassification,
p_prior: float,
projection_horizon: int,
known_catalyst_llr: float = 0.0,
) -> V3ProjectionState:
"""Compute posterior state projection with regime-aware decay.
Evidence state: A_t = phi_regime * A_{t-1} + sum(LLR_c), init A_0 = 0.0
Projected alpha: A_projected = phi^h * A_t + known_catalyst_LLR
P_up_projected = sigmoid(logit(P_prior) + A_projected)
Projected strength = abs(2 * P_up_projected - 1)
Divergence flagged when sign(P_up_projected - 0.5) != sign(P_up_t - 0.5)
Requirements: 11.111.7
"""
# Resolve phi from regime; default to uncertainty (0.50) if unavailable (Req 11.7)
phi = _V3_PHI_DECAY.get(regime.regime.value, 0.50) if regime else 0.50
# Evidence state update: A_t = phi * A_{t-1} + sum(LLR_c) — Req 11.1, 11.2
a_t = phi * a_prev + sum(cluster_llrs)
# Projected alpha: A_projected = phi^h * A_t + known_catalyst_LLR — Req 11.4
a_projected = (phi ** projection_horizon) * a_t + known_catalyst_llr
# P_up_projected = sigmoid(logit(P_prior) + A_projected) — Req 11.5
p_up_projected = _sigmoid(_logit(p_prior) + a_projected)
# Projected strength = abs(2 * P_up_projected - 1) — Req 11.6
projected_strength = abs(2.0 * p_up_projected - 1.0)
# Compute current P_up_t for divergence check (not projected)
p_up_t = _sigmoid(_logit(p_prior) + a_t)
# Flag divergence when projected direction differs from current — Req 11.6
sign_projected = (p_up_projected - 0.5) >= 0
sign_current = (p_up_t - 0.5) >= 0
diverges = sign_projected != sign_current
return V3ProjectionState(
a_t=a_t,
p_up_projected=p_up_projected,
projected_strength=projected_strength,
diverges=diverges,
phi_regime=phi,
)