fix(lotto-signals): pstdev→stdev (ddof=1 sample) + z=None contract 문서화

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-20 02:41:09 +09:00
parent 21d46d95dd
commit e5465ad136

View File

@@ -7,7 +7,7 @@ signal_runner.py에서 DB 연동 + cron 진입점 담당.
from __future__ import annotations from __future__ import annotations
import math import math
from dataclasses import dataclass, field from dataclasses import dataclass, field
from statistics import mean, pstdev from statistics import mean, stdev
from typing import Any, Dict, List, Optional, Tuple from typing import Any, Dict, List, Optional, Tuple
@@ -92,7 +92,7 @@ class AdaptiveBaseline:
@property @property
def sigma(self) -> float: def sigma(self) -> float:
return pstdev(self.window) if len(self.window) >= 2 else 0.0 return stdev(self.window) if len(self.window) >= 2 else 0.0
def push(self, value: float, draw_no: Optional[int] = None) -> None: def push(self, value: float, draw_no: Optional[int] = None) -> None:
"""FIFO push. window_max 초과 시 가장 오래된 값 제거.""" """FIFO push. window_max 초과 시 가장 오래된 값 제거."""
@@ -108,6 +108,10 @@ class AdaptiveBaseline:
Returns: Returns:
(z_score, fire_level) — z_score는 cold start/warmup이면 None. (z_score, fire_level) — z_score는 cold start/warmup이면 None.
fire_level ∈ {'warmup', 'noop', 'normal', 'urgent'} fire_level ∈ {'warmup', 'noop', 'normal', 'urgent'}
NOTE: z_score is None when sigma==0 (degenerate window) or warmup.
Callers must treat None as "signal present but unquantified" — do not
compare None with thresholds directly.
""" """
if self.size < 4: if self.size < 4:
return None, "warmup" return None, "warmup"