"""Rule protocol for Wyckoff Rule Registry.""" from __future__ import annotations from abc import ABC, abstractmethod from dataclasses import dataclass, field from typing import Any @dataclass class RuleHit: """A single rule match.""" rule_id: str event: str | None = None phase: str | None = None cycle: str | None = None confidence: float = 0.0 score: float = 0.0 reasons: list[str] = field(default_factory=list) metrics: dict[str, Any] = field(default_factory=dict) class WyckoffRule(ABC): """Pluggable rule. Engines iterate registry; never hardcode rule lists.""" rule_id: str category: str # cycle | phase | event timeframes: tuple[str, ...] = ("1d", "1w", "1M") @abstractmethod def evaluate(self, context: dict[str, Any]) -> RuleHit | None: """Return RuleHit if matched, else None. Pure — no I/O."""