This commit is contained in:
+9
-9
@@ -201,11 +201,11 @@
|
|||||||
"missing_total_odds": "Over/Under odds are missing.",
|
"missing_total_odds": "Over/Under odds are missing.",
|
||||||
"missing_spread_odds": "Spread (Handicap) odds are missing.",
|
"missing_spread_odds": "Spread (Handicap) odds are missing.",
|
||||||
"no_bet_conditions_met": "The algorithm could not find a safe/valuable bet for this match.",
|
"no_bet_conditions_met": "The algorithm could not find a safe/valuable bet for this match.",
|
||||||
"insufficient_play_score": "Play score is below the playability threshold.",
|
"insufficient_play_score": "Model signal is below the threshold.",
|
||||||
"no_ev_edge_minimum_stake": "Passed safety gates but no mathematical edge — minimum stake applied.",
|
"no_ev_edge_minimum_stake": "Passed safety gates but no mathematical edge — minimum stake applied.",
|
||||||
"upset_risk_detected": "High upset risk detected, proceed with caution."
|
"upset_risk_detected": "High upset risk detected, proceed with caution."
|
||||||
},
|
},
|
||||||
"ev-edge": "EV Edge",
|
"ev-edge": "Theoretical Edge",
|
||||||
"implied-prob": "Market Probability",
|
"implied-prob": "Market Probability",
|
||||||
"model-prob": "Model Probability",
|
"model-prob": "Model Probability",
|
||||||
"kelly-stake": "Kelly Stake",
|
"kelly-stake": "Kelly Stake",
|
||||||
@@ -238,23 +238,23 @@
|
|||||||
},
|
},
|
||||||
"ui": {
|
"ui": {
|
||||||
"summary-title": "Prediction Summary",
|
"summary-title": "Prediction Summary",
|
||||||
"summary-info": "Shows what stands out first and then explains why it stands out.",
|
"summary-info": "Shows model signals and uncertainty in a conservative summary.",
|
||||||
"main-recommendation": "Main Recommendation",
|
"main-recommendation": "Highlighted Signal",
|
||||||
"best-market-copy": "is the strongest option in this market.",
|
"best-market-copy": "is the strongest option in this market.",
|
||||||
"confidence-label": "Confidence",
|
"confidence-label": "Confidence",
|
||||||
"odds-label": "Odds",
|
"odds-label": "Odds",
|
||||||
"edge-label": "Expected Advantage (Edge)",
|
"edge-label": "Theoretical Edge",
|
||||||
"edge-info": "Edge is the gap between the model probability and the market probability. If it is positive, the model sees value in this price.",
|
"edge-info": "The theoretical gap between model probability and market probability; it is not a guarantee or a certain profit expectation.",
|
||||||
"stake-label": "Suggested Bet Size (Stake)",
|
"stake-label": "Suggested Bet Size (Stake)",
|
||||||
"stake-label-short": "Bet Size",
|
"stake-label-short": "Bet Size",
|
||||||
"stake-info": "Stake is the suggested bet size. 2.0u means a 2-unit bet in your own bankroll plan.",
|
"stake-info": "Stake is the suggested bet size. 2.0u means a 2-unit bet in your own bankroll plan.",
|
||||||
"play-score-label": "Playability Score",
|
"play-score-label": "Model Signal",
|
||||||
"playability-label": "Playability",
|
"playability-label": "Model signal",
|
||||||
"quick-read": "Quick read",
|
"quick-read": "Quick read",
|
||||||
"lineup-source": "Lineup Source",
|
"lineup-source": "Lineup Source",
|
||||||
"model-label": "Model",
|
"model-label": "Model",
|
||||||
"engine-info": "Shows which components influence the prediction the most.",
|
"engine-info": "Shows which components influence the prediction the most.",
|
||||||
"best-single-pick": "Best Single Pick",
|
"best-single-pick": "Strongest Signal",
|
||||||
"alternative-markets": "Alternative Markets",
|
"alternative-markets": "Alternative Markets",
|
||||||
"alternative-markets-info": "Options outside the main recommendation.",
|
"alternative-markets-info": "Options outside the main recommendation.",
|
||||||
"alternative": "Alternative",
|
"alternative": "Alternative",
|
||||||
|
|||||||
+9
-9
@@ -202,10 +202,10 @@
|
|||||||
"missing_total_odds": "Alt/Üst oranları eksik.",
|
"missing_total_odds": "Alt/Üst oranları eksik.",
|
||||||
"missing_spread_odds": "Handikap oranları eksik.",
|
"missing_spread_odds": "Handikap oranları eksik.",
|
||||||
"no_bet_conditions_met": "Algoritma bu maç için güvenli/değerli bir bahis önerisi bulamadı.",
|
"no_bet_conditions_met": "Algoritma bu maç için güvenli/değerli bir bahis önerisi bulamadı.",
|
||||||
"insufficient_play_score": "Oynanabilirlik skoru eşiğin altında kaldı.",
|
"insufficient_play_score": "Model sinyali eşiğin altında kaldı.",
|
||||||
"no_ev_edge_minimum_stake": "Güvenlik kontrollerini geçti ancak matematik avantaj yok — minimum bahis uygulandı."
|
"no_ev_edge_minimum_stake": "Güvenlik kontrollerini geçti ancak matematik avantaj yok — minimum bahis uygulandı."
|
||||||
},
|
},
|
||||||
"ev-edge": "EV Edge",
|
"ev-edge": "Teorik Avantaj",
|
||||||
"implied-prob": "Piyasa Olasılığı",
|
"implied-prob": "Piyasa Olasılığı",
|
||||||
"model-prob": "Model Olasılığı",
|
"model-prob": "Model Olasılığı",
|
||||||
"kelly-stake": "Kelly Bahis",
|
"kelly-stake": "Kelly Bahis",
|
||||||
@@ -238,23 +238,23 @@
|
|||||||
},
|
},
|
||||||
"ui": {
|
"ui": {
|
||||||
"summary-title": "Tahmin Özeti",
|
"summary-title": "Tahmin Özeti",
|
||||||
"summary-info": "Önce neyin oynanabileceğini, sonra bunun neden öne çıktığını gösterir.",
|
"summary-info": "Model sinyallerini ve belirsizlikleri sade şekilde gösterir.",
|
||||||
"main-recommendation": "Ana Öneri",
|
"main-recommendation": "Öne Çıkan Sinyal",
|
||||||
"best-market-copy": "marketinde en güçlü seçim.",
|
"best-market-copy": "marketinde en güçlü seçim.",
|
||||||
"confidence-label": "Güven",
|
"confidence-label": "Güven",
|
||||||
"odds-label": "Oran",
|
"odds-label": "Oran",
|
||||||
"edge-label": "Beklenen Avantaj (Edge)",
|
"edge-label": "Teorik Avantaj",
|
||||||
"edge-info": "Edge, model olasılığı ile piyasa olasılığı arasındaki farktır. Pozitifse model bu oranı avantajlı görüyor demektir.",
|
"edge-info": "Model olasılığı ile piyasa olasılığı arasındaki teorik farktır; tutma garantisi veya kesin kazanç beklentisi değildir.",
|
||||||
"stake-label": "Önerilen Miktar (Stake)",
|
"stake-label": "Önerilen Miktar (Stake)",
|
||||||
"stake-label-short": "Bahis Miktarı",
|
"stake-label-short": "Bahis Miktarı",
|
||||||
"stake-info": "Stake, bu bahis için önerilen bahis birimidir. 2.0u, kendi bankroll planınızdaki 2 birimlik bahis anlamına gelir.",
|
"stake-info": "Stake, bu bahis için önerilen bahis birimidir. 2.0u, kendi bankroll planınızdaki 2 birimlik bahis anlamına gelir.",
|
||||||
"play-score-label": "Oynanabilirlik Puanı",
|
"play-score-label": "Model Sinyali",
|
||||||
"playability-label": "Oynanabilirlik",
|
"playability-label": "Model sinyali",
|
||||||
"quick-read": "Hızlı yorum",
|
"quick-read": "Hızlı yorum",
|
||||||
"lineup-source": "Kadronun Kaynağı",
|
"lineup-source": "Kadronun Kaynağı",
|
||||||
"model-label": "Model",
|
"model-label": "Model",
|
||||||
"engine-info": "Tahmini en çok hangi bileşenlerin etkilediğini gösterir.",
|
"engine-info": "Tahmini en çok hangi bileşenlerin etkilediğini gösterir.",
|
||||||
"best-single-pick": "En İyi Tekli Seçim",
|
"best-single-pick": "En Güçlü Sinyal",
|
||||||
"alternative-markets": "Alternatif Marketler",
|
"alternative-markets": "Alternatif Marketler",
|
||||||
"alternative-markets-info": "Ana tahmin dışındaki seçenekler.",
|
"alternative-markets-info": "Ana tahmin dışındaki seçenekler.",
|
||||||
"alternative": "Alternatif",
|
"alternative": "Alternatif",
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ interface PredictionCardProps {
|
|||||||
function formatReasonFallback(reason: string): string {
|
function formatReasonFallback(reason: string): string {
|
||||||
if (reason.startsWith("risk:")) return formatReasonFallback(reason.slice(5));
|
if (reason.startsWith("risk:")) return formatReasonFallback(reason.slice(5));
|
||||||
const evMatch = reason.match(/^ev_edge_([+\-][\d.]+%)_grade_(\w)$/);
|
const evMatch = reason.match(/^ev_edge_([+\-][\d.]+%)_grade_(\w)$/);
|
||||||
if (evMatch) return `Beklenen avantaj ${evMatch[1]} (Not ${evMatch[2]})`;
|
if (evMatch) return `Teorik avantaj sinyali: Not ${evMatch[2]}`;
|
||||||
const negMatch = reason.match(/^negative_model_edge_([+\-][\d.]+)$/);
|
const negMatch = reason.match(/^negative_model_edge_([+\-][\d.]+)$/);
|
||||||
if (negMatch) return `Model avantajı negatif (${negMatch[1]})`;
|
if (negMatch) return `Model avantajı negatif (${negMatch[1]})`;
|
||||||
const thresholdMatch = reason.match(/^below_market_edge_threshold_([+\-]?[\d.]+)$/);
|
const thresholdMatch = reason.match(/^below_market_edge_threshold_([+\-]?[\d.]+)$/);
|
||||||
@@ -90,6 +90,24 @@ function formatProbability(value?: number, digits = 1): string {
|
|||||||
return `${(value * 100).toFixed(digits)}%`;
|
return `${(value * 100).toFixed(digits)}%`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatSignalScore(value?: number): string {
|
||||||
|
if (value === undefined || value === null || Number.isNaN(value)) return "-";
|
||||||
|
return `${Math.max(0, Math.min(100, value)).toFixed(0)}/100`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatEdgeSignal(value?: number): string {
|
||||||
|
if (value === undefined || value === null || Number.isNaN(value)) return "-";
|
||||||
|
return `${value > 0 ? "+" : ""}${formatPercent(value * 100, 1)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEdgePalette(value?: number): string {
|
||||||
|
if (value === undefined || value === null || Number.isNaN(value)) return "gray";
|
||||||
|
if (value <= 0) return "red";
|
||||||
|
if (value < 0.08) return "yellow";
|
||||||
|
if (value < 0.15) return "orange";
|
||||||
|
return "purple";
|
||||||
|
}
|
||||||
|
|
||||||
function formatOdds(value?: number | null): string {
|
function formatOdds(value?: number | null): string {
|
||||||
if (!value || value <= 1.01) return "-";
|
if (!value || value <= 1.01) return "-";
|
||||||
return value.toFixed(2);
|
return value.toFixed(2);
|
||||||
@@ -485,9 +503,8 @@ function PickCard({
|
|||||||
<Badge colorPalette={confidenceBandPalette} variant="subtle">
|
<Badge colorPalette={confidenceBandPalette} variant="subtle">
|
||||||
{getConfidenceBandLabel(pick.confidence_interval?.band)}
|
{getConfidenceBandLabel(pick.confidence_interval?.band)}
|
||||||
</Badge>
|
</Badge>
|
||||||
<Badge colorPalette={pick.ev_edge > 0 ? "green" : "red"} variant="subtle">
|
<Badge colorPalette={getEdgePalette(pick.ev_edge)} variant="subtle">
|
||||||
EV {pick.ev_edge > 0 ? "+" : ""}
|
Teorik avantaj {formatEdgeSignal(pick.ev_edge)}
|
||||||
{formatPercent(pick.ev_edge * 100, 1)}
|
|
||||||
</Badge>
|
</Badge>
|
||||||
</HStack>
|
</HStack>
|
||||||
</VStack>
|
</VStack>
|
||||||
@@ -498,7 +515,7 @@ function PickCard({
|
|||||||
label={labels.recommendedStake}
|
label={labels.recommendedStake}
|
||||||
value={formatUnits(pick.stake_units || stakeFallback)}
|
value={formatUnits(pick.stake_units || stakeFallback)}
|
||||||
/>
|
/>
|
||||||
<MetricTile label={labels.playScore} value={formatPercent(pick.play_score, 0)} />
|
<MetricTile label={labels.playScore} value={formatSignalScore(pick.play_score)} />
|
||||||
<MetricTile label="Guven Araligi" value={formatInterval(pick.confidence_interval)} />
|
<MetricTile label="Guven Araligi" value={formatInterval(pick.confidence_interval)} />
|
||||||
<MetricTile
|
<MetricTile
|
||||||
label="Band"
|
label="Band"
|
||||||
@@ -514,12 +531,12 @@ function PickCard({
|
|||||||
{labels.playability}
|
{labels.playability}
|
||||||
</Text>
|
</Text>
|
||||||
<Text fontSize="sm" color="fg.muted">
|
<Text fontSize="sm" color="fg.muted">
|
||||||
{formatPercent(pick.play_score, 1)}
|
{formatSignalScore(pick.play_score)}
|
||||||
</Text>
|
</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
<Bar
|
<Bar
|
||||||
value={pick.play_score}
|
value={pick.play_score}
|
||||||
color={pick.ev_edge > 0 ? "green.400" : "orange.400"}
|
color={pick.ev_edge > 0 ? "blue.400" : "orange.400"}
|
||||||
trackBg={trackBg}
|
trackBg={trackBg}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -596,9 +613,8 @@ function SummaryTable({
|
|||||||
</HStack>
|
</HStack>
|
||||||
<HStack gap={5} fontSize="sm">
|
<HStack gap={5} fontSize="sm">
|
||||||
<Text minW="48px">{formatOdds(item.odds)}</Text>
|
<Text minW="48px">{formatOdds(item.odds)}</Text>
|
||||||
<Text minW="68px" color={item.ev_edge > 0 ? "green.500" : "red.500"} fontWeight="semibold">
|
<Text minW="96px" color={`${getEdgePalette(item.ev_edge)}.500`} fontWeight="semibold">
|
||||||
{item.ev_edge > 0 ? "+" : ""}
|
{formatEdgeSignal(item.ev_edge)}
|
||||||
{formatPercent(item.ev_edge * 100, 1)}
|
|
||||||
</Text>
|
</Text>
|
||||||
<Text minW="48px">{formatPercent(item.calibrated_confidence, 0)}</Text>
|
<Text minW="48px">{formatPercent(item.calibrated_confidence, 0)}</Text>
|
||||||
<Badge colorPalette={getConfidenceBandPalette(item.confidence_interval?.band)} variant="subtle">
|
<Badge colorPalette={getConfidenceBandPalette(item.confidence_interval?.band)} variant="subtle">
|
||||||
@@ -867,9 +883,23 @@ export default function PredictionCard({ prediction }: PredictionCardProps) {
|
|||||||
title={uiText("summary-title", "Tahmin Ozeti")}
|
title={uiText("summary-title", "Tahmin Ozeti")}
|
||||||
info={uiText(
|
info={uiText(
|
||||||
"summary-info",
|
"summary-info",
|
||||||
"Kullanicinin once neyi oynayacagini, sonra nedenini anlamasi icin sade ozet.",
|
"Model sinyallerini ve belirsizlikleri sade sekilde gosterir.",
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
<Box
|
||||||
|
p={3}
|
||||||
|
bg={useColorModeValue("orange.50", "orange.950")}
|
||||||
|
borderWidth="1px"
|
||||||
|
borderColor={useColorModeValue("orange.200", "orange.800")}
|
||||||
|
borderRadius="xl"
|
||||||
|
>
|
||||||
|
<HStack align="start" gap={2}>
|
||||||
|
<Icon as={LuShieldAlert} boxSize={4.5} color="orange.500" mt={0.5} />
|
||||||
|
<Text fontSize="sm" color="fg.muted" lineHeight="tall">
|
||||||
|
Bu bir model sinyalidir; kesin sonuç, garanti veya tutma yüzdesi değildir. Sinyal puanı maç içi varyans, kadro ve veri kalitesi nedeniyle yanılabilir.
|
||||||
|
</Text>
|
||||||
|
</HStack>
|
||||||
|
</Box>
|
||||||
|
|
||||||
{recommendedPick ? (
|
{recommendedPick ? (
|
||||||
<Grid templateColumns={{ base: "1fr", xl: "1.4fr 1fr" }} gap={4}>
|
<Grid templateColumns={{ base: "1fr", xl: "1.4fr 1fr" }} gap={4}>
|
||||||
@@ -877,7 +907,7 @@ export default function PredictionCard({ prediction }: PredictionCardProps) {
|
|||||||
<HStack justify="space-between" align="start" mb={4}>
|
<HStack justify="space-between" align="start" mb={4}>
|
||||||
<VStack align="start" gap={2}>
|
<VStack align="start" gap={2}>
|
||||||
<Badge colorPalette="green" variant="solid" borderRadius="full">
|
<Badge colorPalette="green" variant="solid" borderRadius="full">
|
||||||
{uiText("main-recommendation", "Ana Oneri")}
|
{uiText("main-recommendation", "Öne Çıkan Sinyal")}
|
||||||
</Badge>
|
</Badge>
|
||||||
<Text fontSize="2xl" fontWeight="bold">
|
<Text fontSize="2xl" fontWeight="bold">
|
||||||
{recommendedPick.pick}
|
{recommendedPick.pick}
|
||||||
@@ -903,13 +933,13 @@ export default function PredictionCard({ prediction }: PredictionCardProps) {
|
|||||||
<MetricTile label={uiText("odds-label", "Oran")} value={formatOdds(recommendedPick.odds)} />
|
<MetricTile label={uiText("odds-label", "Oran")} value={formatOdds(recommendedPick.odds)} />
|
||||||
<MetricTile label="Guven Araligi" value={formatInterval(recommendedPick.confidence_interval)} />
|
<MetricTile label="Guven Araligi" value={formatInterval(recommendedPick.confidence_interval)} />
|
||||||
<MetricTile
|
<MetricTile
|
||||||
label={uiText("edge-label", "Beklenen Avantaj (Edge)")}
|
label={uiText("edge-label", "Teorik Avantaj")}
|
||||||
value={`${recommendedPick.ev_edge > 0 ? "+" : ""}${formatPercent(recommendedPick.ev_edge * 100, 1)}`}
|
value={formatEdgeSignal(recommendedPick.ev_edge)}
|
||||||
helper={uiText(
|
helper={uiText(
|
||||||
"edge-info",
|
"edge-info",
|
||||||
"Edge, model olasiligi ile piyasa olasiligi arasindaki farktir. Pozitifse model bu orani avantajli buluyor demektir.",
|
"Model olasiligi ile piyasa olasiligi arasindaki teorik farktir; tutma garantisi veya kesin kazanc beklentisi degildir.",
|
||||||
)}
|
)}
|
||||||
accent={recommendedPick.ev_edge > 0 ? "green.500" : "red.500"}
|
accent={`${getEdgePalette(recommendedPick.ev_edge)}.500`}
|
||||||
/>
|
/>
|
||||||
<MetricTile
|
<MetricTile
|
||||||
label={uiText("stake-label", "Onerilen Miktar (Stake)")}
|
label={uiText("stake-label", "Onerilen Miktar (Stake)")}
|
||||||
@@ -1028,7 +1058,7 @@ export default function PredictionCard({ prediction }: PredictionCardProps) {
|
|||||||
{recommendedPick ? (
|
{recommendedPick ? (
|
||||||
<PickCard
|
<PickCard
|
||||||
pick={recommendedPick}
|
pick={recommendedPick}
|
||||||
title={uiText("best-single-pick", "En iyi tekli secim")}
|
title={uiText("best-single-pick", "En güçlü sinyal")}
|
||||||
resolveReason={resolveReason}
|
resolveReason={resolveReason}
|
||||||
palette="green"
|
palette="green"
|
||||||
stakeFallback={prediction.bet_advice.suggested_stake_units}
|
stakeFallback={prediction.bet_advice.suggested_stake_units}
|
||||||
@@ -1037,8 +1067,8 @@ export default function PredictionCard({ prediction }: PredictionCardProps) {
|
|||||||
confidence: uiText("confidence-label", "Guven"),
|
confidence: uiText("confidence-label", "Guven"),
|
||||||
odds: uiText("odds-label", "Oran"),
|
odds: uiText("odds-label", "Oran"),
|
||||||
recommendedStake: uiText("stake-label-short", "Stake"),
|
recommendedStake: uiText("stake-label-short", "Stake"),
|
||||||
playScore: uiText("play-score-label", "Play Score"),
|
playScore: uiText("play-score-label", "Model Sinyali"),
|
||||||
playability: uiText("playability-label", "Oynanabilirlik"),
|
playability: uiText("playability-label", "Model sinyali"),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
@@ -1064,8 +1094,8 @@ export default function PredictionCard({ prediction }: PredictionCardProps) {
|
|||||||
confidence: uiText("confidence-label", "Guven"),
|
confidence: uiText("confidence-label", "Guven"),
|
||||||
odds: uiText("odds-label", "Oran"),
|
odds: uiText("odds-label", "Oran"),
|
||||||
recommendedStake: uiText("stake-label-short", "Stake"),
|
recommendedStake: uiText("stake-label-short", "Stake"),
|
||||||
playScore: uiText("play-score-label", "Play Score"),
|
playScore: uiText("play-score-label", "Model Sinyali"),
|
||||||
playability: uiText("playability-label", "Oynanabilirlik"),
|
playability: uiText("playability-label", "Model sinyali"),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -69,6 +69,13 @@ export interface MatchPickDto {
|
|||||||
edge: number;
|
edge: number;
|
||||||
ev_edge: number;
|
ev_edge: number;
|
||||||
implied_prob: number;
|
implied_prob: number;
|
||||||
|
model_probability?: number;
|
||||||
|
model_edge?: number;
|
||||||
|
calibrated_probability?: number;
|
||||||
|
odds_band_probability?: number;
|
||||||
|
odds_band_sample?: number;
|
||||||
|
odds_band_edge?: number;
|
||||||
|
odds_band_aligned?: boolean;
|
||||||
play_score: number;
|
play_score: number;
|
||||||
playable: boolean;
|
playable: boolean;
|
||||||
bet_grade: BetGrade;
|
bet_grade: BetGrade;
|
||||||
@@ -76,6 +83,7 @@ export interface MatchPickDto {
|
|||||||
decision_reasons: string[];
|
decision_reasons: string[];
|
||||||
confidence_interval?: ConfidenceIntervalDto;
|
confidence_interval?: ConfidenceIntervalDto;
|
||||||
signal_tier?: SignalTier;
|
signal_tier?: SignalTier;
|
||||||
|
is_guaranteed?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MatchBetAdviceDto {
|
export interface MatchBetAdviceDto {
|
||||||
@@ -99,6 +107,13 @@ export interface MatchBetSummaryItemDto {
|
|||||||
play_score: number;
|
play_score: number;
|
||||||
ev_edge: number;
|
ev_edge: number;
|
||||||
implied_prob: number;
|
implied_prob: number;
|
||||||
|
model_probability?: number;
|
||||||
|
model_edge?: number;
|
||||||
|
calibrated_probability?: number;
|
||||||
|
odds_band_probability?: number;
|
||||||
|
odds_band_sample?: number;
|
||||||
|
odds_band_edge?: number;
|
||||||
|
odds_band_aligned?: boolean;
|
||||||
odds: number;
|
odds: number;
|
||||||
reasons: string[];
|
reasons: string[];
|
||||||
confidence_interval?: ConfidenceIntervalDto;
|
confidence_interval?: ConfidenceIntervalDto;
|
||||||
|
|||||||
Reference in New Issue
Block a user