fix(anomaly): exclude non-directional kinds from grading and backtest
Review follow-up (HIGH): the three detectors fed the same evaluator/backtest, but SuspensionFreeze is non-directional (favourite unchanged) — grading it as "favourite won" polluted the hit-rate with the base favourite-win rate, and its high frozen-ness score always cleared the backtest threshold. - Add AnomalyKind.IsDirectional() (flip + steam = true, freeze = false). - AnomalyOutcomeEvaluator returns Unresolved for non-directional kinds (favourites still surfaced for display) so they don't distort calibration. - RunBacktestUseCase skips non-directional anomalies when building candidates. - Tests for the classification, the evaluator path, and the backtest skip.
This commit is contained in:
@@ -3,6 +3,7 @@ using Marathon.Application.Storage;
|
||||
using Marathon.Domain.AnomalyDetection;
|
||||
using Marathon.Domain.Backtesting;
|
||||
using Marathon.Domain.Entities;
|
||||
using Marathon.Domain.Enums;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using DomainEventId = Marathon.Domain.ValueObjects.EventId;
|
||||
|
||||
@@ -95,6 +96,11 @@ public sealed class RunBacktestUseCase
|
||||
{
|
||||
ct.ThrowIfCancellationRequested();
|
||||
|
||||
// Only directional kinds are betting signals; SuspensionFreeze (favourite
|
||||
// unchanged) is informational and must not be staked or it would skew ROI.
|
||||
if (!anomaly.Kind.IsDirectional())
|
||||
continue;
|
||||
|
||||
// Cannot simulate a bet whose event hasn't been graded yet.
|
||||
if (!resultLookup.TryGetValue(anomaly.EventId, out var result))
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user