Files
iddaai-be/src/modules/predictions/dto/index.ts
T

562 lines
11 KiB
TypeScript
Executable File

import { ApiProperty } from "@nestjs/swagger";
export type SignalTier = "CORE" | "VALUE" | "LEAN" | "LONGSHOT" | "PASS";
export class MatchInfoDto {
@ApiProperty()
match_id: string;
@ApiProperty()
match_name: string;
@ApiProperty()
home_team: string;
@ApiProperty()
away_team: string;
@ApiProperty()
league: string;
@ApiProperty()
match_date_ms: number;
@ApiProperty({ required: false, nullable: true })
league_id?: string | null;
@ApiProperty({ required: false, default: false })
is_top_league?: boolean;
@ApiProperty({
required: false,
enum: ["football", "basketball"],
})
sport?: "football" | "basketball";
}
export class DataQualityDto {
@ApiProperty({ enum: ["HIGH", "MEDIUM", "LOW"] })
label: "HIGH" | "MEDIUM" | "LOW";
@ApiProperty()
score: number;
@ApiProperty()
home_lineup_count: number;
@ApiProperty()
away_lineup_count: number;
@ApiProperty({ required: false, default: "none" })
lineup_source?: string;
@ApiProperty({ type: [String] })
flags: string[];
}
export class ConfidenceIntervalDto {
@ApiProperty()
lower: number;
@ApiProperty()
upper: number;
@ApiProperty()
width: number;
@ApiProperty({ enum: ["HIGH", "MEDIUM", "LOW"] })
band: "HIGH" | "MEDIUM" | "LOW";
@ApiProperty()
threshold_met: boolean;
}
export class RiskDto {
@ApiProperty({ enum: ["LOW", "MEDIUM", "HIGH", "EXTREME"] })
level: "LOW" | "MEDIUM" | "HIGH" | "EXTREME";
@ApiProperty()
score: number;
@ApiProperty()
is_surprise_risk: boolean;
@ApiProperty({ nullable: true })
surprise_type: string | null;
@ApiProperty({ required: false, default: 0 })
surprise_score?: number;
@ApiProperty({ required: false, nullable: true })
surprise_comment?: string | null;
@ApiProperty({ type: [String], required: false })
surprise_reasons?: string[];
@ApiProperty({ type: [String] })
warnings: string[];
}
export class EngineBreakdownDto {
@ApiProperty()
team: number;
@ApiProperty()
player: number;
@ApiProperty()
odds: number;
@ApiProperty()
referee: number;
}
export class MatchPickDto {
@ApiProperty()
market: string;
@ApiProperty({ required: false, default: "standard" })
strategy_channel?: string;
@ApiProperty()
pick: string;
@ApiProperty()
probability: number;
@ApiProperty()
confidence: number;
@ApiProperty()
odds: number;
@ApiProperty()
raw_confidence: number;
@ApiProperty()
calibrated_confidence: number;
@ApiProperty()
min_required_confidence: number;
@ApiProperty()
edge: number;
@ApiProperty({ required: false, default: 0 })
ev_edge?: number;
@ApiProperty({ required: false, default: 0 })
implied_prob?: number;
@ApiProperty({ required: false, default: 0 })
model_probability?: number;
@ApiProperty({ required: false, default: 0 })
model_edge?: number;
@ApiProperty({ required: false, default: 0 })
calibrated_probability?: number;
@ApiProperty({ required: false, default: 0 })
odds_band_probability?: number;
@ApiProperty({ required: false, default: 0 })
odds_band_sample?: number;
@ApiProperty({ required: false, default: 0 })
odds_band_edge?: number;
@ApiProperty({ required: false, default: false })
odds_band_aligned?: boolean;
@ApiProperty()
play_score: number;
@ApiProperty()
playable: boolean;
@ApiProperty({ enum: ["A", "B", "C", "PASS"] })
bet_grade: "A" | "B" | "C" | "PASS";
@ApiProperty()
stake_units: number;
@ApiProperty({ type: [String] })
decision_reasons: string[];
@ApiProperty({ type: ConfidenceIntervalDto, required: false })
confidence_interval?: ConfidenceIntervalDto;
@ApiProperty({
required: false,
enum: ["CORE", "VALUE", "LEAN", "LONGSHOT", "PASS"],
})
signal_tier?: SignalTier;
@ApiProperty({ required: false, default: false })
is_guaranteed?: boolean;
}
export class MatchBetAdviceDto {
@ApiProperty()
playable: boolean;
@ApiProperty()
suggested_stake_units: number;
@ApiProperty()
reason: string;
@ApiProperty({ required: false, enum: ["HIGH", "MEDIUM", "LOW"] })
confidence_band?: "HIGH" | "MEDIUM" | "LOW";
@ApiProperty({ required: false })
min_confidence_for_play?: number;
@ApiProperty({
required: false,
enum: ["CORE", "VALUE", "LEAN", "LONGSHOT", "PASS"],
})
signal_tier?: SignalTier;
}
export class MatchBetSummaryItemDto {
@ApiProperty()
market: string;
@ApiProperty()
pick: string;
@ApiProperty()
raw_confidence: number;
@ApiProperty()
calibrated_confidence: number;
@ApiProperty({ enum: ["A", "B", "C", "PASS"] })
bet_grade: "A" | "B" | "C" | "PASS";
@ApiProperty()
playable: boolean;
@ApiProperty()
stake_units: number;
@ApiProperty()
play_score: number;
@ApiProperty({ required: false, default: 0 })
ev_edge?: number;
@ApiProperty({ required: false, default: 0 })
implied_prob?: number;
@ApiProperty({ required: false, default: 0 })
model_probability?: number;
@ApiProperty({ required: false, default: 0 })
model_edge?: number;
@ApiProperty({ required: false, default: 0 })
calibrated_probability?: number;
@ApiProperty({ required: false, default: 0 })
odds_band_probability?: number;
@ApiProperty({ required: false, default: 0 })
odds_band_sample?: number;
@ApiProperty({ required: false, default: 0 })
odds_band_edge?: number;
@ApiProperty({ required: false, default: false })
odds_band_aligned?: boolean;
@ApiProperty({ required: false, default: 0 })
odds?: number;
@ApiProperty({ type: [String] })
reasons: string[];
@ApiProperty({ type: ConfidenceIntervalDto, required: false })
confidence_interval?: ConfidenceIntervalDto;
@ApiProperty({
required: false,
enum: ["CORE", "VALUE", "LEAN", "LONGSHOT", "PASS"],
})
signal_tier?: SignalTier;
}
export class HtFtPredictionDto {
@ApiProperty()
"1/1": number;
@ApiProperty()
"1/X": number;
@ApiProperty()
"1/2": number;
@ApiProperty()
"X/1": number;
@ApiProperty()
"X/X": number;
@ApiProperty()
"X/2": number;
@ApiProperty()
"2/1": number;
@ApiProperty()
"2/X": number;
@ApiProperty()
"2/2": number;
@ApiProperty()
pick: string;
@ApiProperty()
confidence: number;
}
export class AggressivePickDto {
@ApiProperty()
market: string;
@ApiProperty()
pick: string;
@ApiProperty()
probability: number;
@ApiProperty()
confidence: number;
@ApiProperty()
odds: number;
@ApiProperty()
raw_confidence: number;
@ApiProperty()
calibrated_confidence: number;
@ApiProperty()
min_required_confidence: number;
@ApiProperty()
edge: number;
@ApiProperty({ required: false, default: 0 })
ev_edge?: number;
@ApiProperty({ required: false, default: 0 })
implied_prob?: number;
@ApiProperty()
play_score: number;
@ApiProperty()
playable: boolean;
@ApiProperty({ enum: ["A", "B", "C", "PASS"] })
bet_grade: "A" | "B" | "C" | "PASS";
@ApiProperty()
stake_units: number;
@ApiProperty({ type: [String] })
decision_reasons: string[];
@ApiProperty({ type: ConfidenceIntervalDto, required: false })
confidence_interval?: ConfidenceIntervalDto;
}
export class ScenarioTop5ItemDto {
@ApiProperty()
scenario: string;
@ApiProperty()
score: number;
@ApiProperty()
probability: number;
}
export class ScorePredictionDto {
@ApiProperty()
ft: string;
@ApiProperty()
ht: string;
@ApiProperty()
xg_home: number;
@ApiProperty()
xg_away: number;
@ApiProperty()
xg_total: number;
}
export class MatchPredictionDto {
@ApiProperty()
model_version: string;
@ApiProperty({ required: false, nullable: true })
calibration_version?: string | null;
@ApiProperty({ required: false, nullable: true })
shadow_engine_version?: string | null;
@ApiProperty({ required: false, nullable: true })
decision_trace_id?: string | null;
@ApiProperty({ type: MatchInfoDto })
match_info: MatchInfoDto;
@ApiProperty({ type: DataQualityDto })
data_quality: DataQualityDto;
@ApiProperty({ type: RiskDto })
risk: RiskDto;
@ApiProperty({ type: EngineBreakdownDto })
engine_breakdown: EngineBreakdownDto;
@ApiProperty({ type: MatchPickDto, nullable: true })
main_pick: MatchPickDto | null;
@ApiProperty({ type: MatchPickDto, nullable: true })
value_pick: MatchPickDto | null;
@ApiProperty({ type: MatchPickDto, nullable: true, required: false })
surprise_pick?: MatchPickDto | null;
@ApiProperty({ type: MatchBetAdviceDto })
bet_advice: MatchBetAdviceDto;
@ApiProperty({ type: [MatchBetSummaryItemDto] })
bet_summary: MatchBetSummaryItemDto[];
@ApiProperty({ type: [MatchPickDto] })
supporting_picks: MatchPickDto[];
@ApiProperty({ type: AggressivePickDto, nullable: true })
aggressive_pick: AggressivePickDto | null;
@ApiProperty({ type: HtFtPredictionDto, required: false })
htft?: HtFtPredictionDto;
@ApiProperty({ type: [ScenarioTop5ItemDto] })
scenario_top5: ScenarioTop5ItemDto[];
@ApiProperty({ type: ScorePredictionDto })
score_prediction: ScorePredictionDto;
@ApiProperty({ type: Object })
market_board: Record<string, unknown>;
@ApiProperty({ type: [String] })
reasoning_factors: string[];
@ApiProperty({ type: Object, required: false })
market_reliability?: Record<string, number>;
@ApiProperty({ type: Object, required: false })
shadow_engine?: Record<string, unknown>;
@ApiProperty({ type: Object, required: false })
surprise_hunter?: Record<string, unknown>;
@ApiProperty({
type: Object,
required: false,
description:
"V28 Odds-Band engine output: historical band analytics, triple-value detection, cards profiling, and HTFT 9-combo analysis",
})
v27_engine?: Record<string, unknown>;
}
export class ValueBetDto {
@ApiProperty()
matchId: string;
@ApiProperty()
matchName: string;
@ApiProperty()
betType: string;
@ApiProperty()
prediction: string;
@ApiProperty()
confidence: number;
@ApiProperty()
odd: number;
@ApiProperty()
expectedValue: number;
}
export class PredictionHistoryStatsDto {
@ApiProperty()
totalPredictions: number;
@ApiProperty()
totalResolved: number;
@ApiProperty()
correctPredictions: number;
@ApiProperty()
accuracyRate: number;
}
export class PredictionHistoryResponseDto {
@ApiProperty({ type: PredictionHistoryStatsDto })
stats: PredictionHistoryStatsDto;
@ApiProperty({ type: [Object] })
history: Record<string, unknown>[];
}
export class UpcomingPredictionsDto {
@ApiProperty()
count: number;
@ApiProperty({ type: [MatchPredictionDto] })
matches: MatchPredictionDto[];
@ApiProperty()
modelVersion: string;
}
export class AIHealthDto {
@ApiProperty()
status: string;
@ApiProperty()
modelLoaded: boolean;
@ApiProperty()
predictionServiceReady: boolean;
@ApiProperty({ required: false, default: true })
aiEngineReachable?: boolean;
@ApiProperty({ required: false, enum: ["closed", "open"] })
circuitState?: "closed" | "open";
@ApiProperty({ required: false, default: 0 })
consecutiveFailures?: number;
@ApiProperty({ required: false })
endpoint?: string;
@ApiProperty({ required: false, nullable: true })
detail?: string | null;
@ApiProperty({ required: false, nullable: true })
mode?: string | null;
}
export * from "./smart-coupon.dto";