115872aad0
Adds the 4th IAnomalyDetector: flags a sharp drop in the bookmaker's overround (raw implied-probability sum / margin) over a continuous live window. Informational/non-directional — excluded from outcome grading and backtest staking via AnomalyKind.IsDirectional(). - OverroundCompressionDetector: sliding-window scan mirroring SteamMove, score = min(1, compression / 0.10 reference), suspension-gap aware. - MatchWinEvidence.Probabilities gains Overround (pre-normalisation margin); evidence JSON shape unchanged. - Wired into DetectAnomaliesUseCase fan-out; AnomalyOptions + appsettings (window 120s, threshold 0.02); en/ru resx + KindLabel arms. - 11 detector tests incl. score saturation/scaling, inclusive threshold boundary, and a three-way (draw-leg) overround case.
26 lines
1.1 KiB
C#
26 lines
1.1 KiB
C#
namespace Marathon.Domain.Enums;
|
|
|
|
/// <summary>Semantic classification of anomaly kinds.</summary>
|
|
public static class AnomalyKindExtensions
|
|
{
|
|
/// <summary>
|
|
/// Whether the kind makes a <i>directional</i> prediction — a specific side/favourite
|
|
/// expected to win — that can be graded against the result and bet on in a backtest.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <see cref="AnomalyKind.SuspensionFlip"/> and <see cref="AnomalyKind.SteamMove"/> are
|
|
/// directional (they point at a favourite). <see cref="AnomalyKind.SuspensionFreeze"/> is
|
|
/// informational — the line did NOT move — so "predicting" the unchanged favourite would
|
|
/// merely measure the base favourite-win rate; it is excluded from outcome grading and
|
|
/// from backtest staking so it does not distort detector calibration.
|
|
/// </remarks>
|
|
public static bool IsDirectional(this AnomalyKind kind) => kind switch
|
|
{
|
|
AnomalyKind.SuspensionFlip => true,
|
|
AnomalyKind.SteamMove => true,
|
|
AnomalyKind.SuspensionFreeze => false,
|
|
AnomalyKind.OverroundCompression => false,
|
|
_ => false,
|
|
};
|
|
}
|