2b1025cae3
- Introduce IAnomalyDetector; the existing flip detector implements it. - Extract MatchWinEvidence so every detector writes the identical pre/post evidence shape — the UI parser and outcome evaluator handle new kinds with no branching (steam moves get hit-rate calibrated for free). - Add SteamMoveDetector: flags a rapid one-directional implied-probability rise over a short CONTINUOUS window (no suspension gap inside it), so it never double-flags the same interval as the suspension-flip detector. - DetectAnomaliesUseCase fans out over both detectors; dedup keys on EventId+Kind so flip and steam signals persist independently. Add AnomalyKind.SteamMove + SteamMove window/threshold options. 8 detector tests.
19 lines
686 B
C#
19 lines
686 B
C#
using Marathon.Domain.Entities;
|
|
using Marathon.Domain.ValueObjects;
|
|
|
|
namespace Marathon.Domain.AnomalyDetection;
|
|
|
|
/// <summary>
|
|
/// A pure, stateless detector that scans one event's snapshot timeline and returns
|
|
/// any anomalies it finds. Implementations are deterministic and free of I/O so they
|
|
/// can be composed (fanned out) and unit-tested in isolation.
|
|
/// </summary>
|
|
public interface IAnomalyDetector
|
|
{
|
|
/// <summary>
|
|
/// Analyses <paramref name="snapshots"/> for <paramref name="eventId"/> and returns
|
|
/// 0 or more anomalies. May be empty; never null.
|
|
/// </summary>
|
|
IReadOnlyList<Anomaly> Detect(EventId eventId, IReadOnlyList<OddsSnapshot> snapshots);
|
|
}
|