562 lines
11 KiB
TypeScript
Executable File
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";
|