feat(ai-engine): value sniper thresholds and logic relaxed
This commit is contained in:
@@ -165,6 +165,11 @@ class BettingBrain:
|
||||
score -= 18.0
|
||||
issues.append("base_model_not_playable")
|
||||
|
||||
is_value_sniper = bool(row.get("is_value_sniper"))
|
||||
if is_value_sniper:
|
||||
score += 35.0
|
||||
positives.append("value_sniper_override")
|
||||
|
||||
score += max(0.0, min(20.0, calibrated_conf * 0.22))
|
||||
score += max(-8.0, min(16.0, ev_edge * 45.0))
|
||||
score += max(0.0, min(14.0, play_score * 0.12))
|
||||
@@ -178,13 +183,13 @@ class BettingBrain:
|
||||
|
||||
if odds < self.MIN_ODDS:
|
||||
vetoes.append("odds_below_minimum")
|
||||
if calibrated_conf < 38.0:
|
||||
if calibrated_conf < 38.0 and not is_value_sniper:
|
||||
vetoes.append("calibrated_confidence_too_low")
|
||||
if play_score < 50.0:
|
||||
if play_score < 50.0 and not is_value_sniper:
|
||||
vetoes.append("play_score_too_low")
|
||||
|
||||
if divergence is not None:
|
||||
if divergence >= self.HARD_DIVERGENCE:
|
||||
if divergence >= self.HARD_DIVERGENCE and not is_value_sniper:
|
||||
score -= 42.0
|
||||
vetoes.append("v25_v27_hard_disagreement")
|
||||
elif divergence >= self.SOFT_DIVERGENCE:
|
||||
@@ -211,7 +216,7 @@ class BettingBrain:
|
||||
else:
|
||||
score -= 16.0
|
||||
issues.append("historical_sample_too_low")
|
||||
if market == "DC":
|
||||
if market == "DC" and not is_value_sniper:
|
||||
vetoes.append("dc_without_historical_sample")
|
||||
elif market in {"MS", "DC", "OU25"}:
|
||||
score -= 10.0
|
||||
@@ -227,20 +232,21 @@ class BettingBrain:
|
||||
and model_prob >= self.EXTREME_MODEL_PROB
|
||||
and model_gap >= self.EXTREME_GAP
|
||||
and not triple_is_value
|
||||
and not is_value_sniper
|
||||
):
|
||||
score -= 24.0
|
||||
vetoes.append("extreme_probability_without_evidence")
|
||||
|
||||
if market in {"HT", "HTFT", "OE"} and score < 86.0:
|
||||
if market in {"HT", "HTFT", "OE"} and score < 86.0 and not is_value_sniper:
|
||||
vetoes.append("volatile_market_requires_exceptional_evidence")
|
||||
|
||||
score = max(0.0, min(100.0, score))
|
||||
action = "BET"
|
||||
if vetoes:
|
||||
action = "REJECT"
|
||||
elif score < self.MIN_WATCH_SCORE:
|
||||
elif score < self.MIN_WATCH_SCORE and not is_value_sniper:
|
||||
action = "REJECT"
|
||||
elif score < self.MIN_BET_SCORE:
|
||||
elif score < self.MIN_BET_SCORE and not is_value_sniper:
|
||||
action = "WATCH"
|
||||
|
||||
row["betting_brain"] = {
|
||||
@@ -276,6 +282,7 @@ class BettingBrain:
|
||||
for source in ("main_pick", "value_pick"):
|
||||
item = package.get(source)
|
||||
if isinstance(item, dict) and item.get("market"):
|
||||
# print(f"DEBUG: {source} is_value_sniper: {item.get('is_value_sniper')}")
|
||||
rows[self._row_key(item)] = dict(item)
|
||||
|
||||
for source in ("supporting_picks", "bet_summary"):
|
||||
@@ -283,6 +290,7 @@ class BettingBrain:
|
||||
if isinstance(item, dict) and item.get("market"):
|
||||
key = self._row_key(item)
|
||||
rows[key] = self._merge_row(rows.get(key), item)
|
||||
|
||||
return list(rows.values())
|
||||
|
||||
@staticmethod
|
||||
|
||||
Reference in New Issue
Block a user