Add backtest pipeline, betting_brain filters, score coherence + social v3

betting_brain.py:
- HARD_MIN_SAMPLES=50 floor for calibrator bypass
- ev_edge < 0 + >= 0.20 hard vetoes
- BTTS muted (grid search found no profitable config)
- Per-market optimal envelopes (MS, OU25)
- Score coherence filter: main_pick must agree with score prediction
- HTFT reversal cross-check for MS picks

feature_builder.py / data_loader.py:
- Real home/away_position from data (was hardcoded 10)
- Cup detection wired into UpsetEngine
- _estimate_league_position with 300-day season filter

New scripts:
- diagnostic_backtest.py: per-bet diagnostic backtest with loss patterns
- optimize_filters.py: grid search per-market optimal thresholds
- analyze_backtest_csv.py: root-cause hypothesis testing on CSV
- compare_backtests.py: side-by-side validation with verdict
- test_score_coherence.py: smoke test for coherence filter (20/20 pass)

Reports:
- diagnostic_backtest_20260525_024437 (50-match smoke)
- diagnostic_backtest_20260525_035649 (1000-match in-sample)
- filter_optimization_patch.json (grid search winners per market)

Social poster v3:
- satori + resvg HTML/CSS rendering pipeline
- Twemoji football/basketball + flag SVGs
- caption SEO: 12 curated hashtags per post
- image SEO: descriptive filenames + .json metadata sidecar
- /health, /preview-png, /run-now endpoints

Docs:
- mds/SESSION_HANDOFF.md: full session state for cross-machine continuity
- mds/SOCIAL_POSTER_SETUP.md: API keys + test commands

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 20:43:28 +03:00
parent b619c2454a
commit 988ee2f50d
36 changed files with 5268 additions and 46 deletions
@@ -0,0 +1,335 @@
{
"args": {
"days": 14,
"max_matches": 1000,
"start": null,
"end": null,
"progress_interval": 50
},
"aggregate": {
"overall": {
"n_total": 1000,
"n_playable_settled": 524,
"wins": 287,
"losses": 237,
"hit_rate_pct": 54.77,
"unit_profit": -17.897,
"staked": 107.0,
"roi_pct": -16.73
},
"by_market": {
"OU25": {
"n_total": 236,
"n_playable_settled": 236,
"wins": 134,
"losses": 102,
"hit_rate_pct": 56.78,
"unit_profit": -6.271,
"staked": 48.5,
"roi_pct": -12.93
},
"BTTS": {
"n_total": 205,
"n_playable_settled": 205,
"wins": 105,
"losses": 100,
"hit_rate_pct": 51.22,
"unit_profit": -8.89,
"staked": 41.1,
"roi_pct": -21.63
},
"MS": {
"n_total": 76,
"n_playable_settled": 76,
"wins": 44,
"losses": 32,
"hit_rate_pct": 57.89,
"unit_profit": -2.396,
"staked": 16.0,
"roi_pct": -14.98
},
"OU35": {
"n_total": 3,
"n_playable_settled": 3,
"wins": 0,
"losses": 3,
"hit_rate_pct": 0.0,
"unit_profit": -0.6,
"staked": 0.6,
"roi_pct": -100.0
},
"DC": {
"n_total": 4,
"n_playable_settled": 4,
"wins": 4,
"losses": 0,
"hit_rate_pct": 100.0,
"unit_profit": 0.26,
"staked": 0.8,
"roi_pct": 32.5
}
},
"by_confidence": {
"65-70": {
"n_total": 420,
"n_playable_settled": 420,
"wins": 233,
"losses": 187,
"hit_rate_pct": 55.48,
"unit_profit": -14.057,
"staked": 85.1,
"roi_pct": -16.52
},
"60-65": {
"n_total": 33,
"n_playable_settled": 33,
"wins": 16,
"losses": 17,
"hit_rate_pct": 48.48,
"unit_profit": -1.61,
"staked": 6.6,
"roi_pct": -24.39
},
"55-60": {
"n_total": 52,
"n_playable_settled": 52,
"wins": 28,
"losses": 24,
"hit_rate_pct": 53.85,
"unit_profit": -0.668,
"staked": 10.5,
"roi_pct": -6.36
},
"50-55": {
"n_total": 5,
"n_playable_settled": 5,
"wins": 2,
"losses": 3,
"hit_rate_pct": 40.0,
"unit_profit": -0.64,
"staked": 1.3,
"roi_pct": -49.23
},
"45-50": {
"n_total": 8,
"n_playable_settled": 8,
"wins": 4,
"losses": 4,
"hit_rate_pct": 50.0,
"unit_profit": -0.382,
"staked": 1.9,
"roi_pct": -20.11
},
"70-80": {
"n_total": 6,
"n_playable_settled": 6,
"wins": 4,
"losses": 2,
"hit_rate_pct": 66.67,
"unit_profit": -0.54,
"staked": 1.6,
"roi_pct": -33.75
}
},
"by_odds": {
"1.3-1.5": {
"n_total": 241,
"n_playable_settled": 241,
"wins": 148,
"losses": 93,
"hit_rate_pct": 61.41,
"unit_profit": -7.408,
"staked": 49.0,
"roi_pct": -15.12
},
"1.5-1.8": {
"n_total": 221,
"n_playable_settled": 221,
"wins": 115,
"losses": 106,
"hit_rate_pct": 52.04,
"unit_profit": -6.926,
"staked": 44.3,
"roi_pct": -15.63
},
"1.8-2.2": {
"n_total": 56,
"n_playable_settled": 56,
"wins": 23,
"losses": 33,
"hit_rate_pct": 41.07,
"unit_profit": -2.789,
"staked": 12.2,
"roi_pct": -22.86
},
"2.2-3.0": {
"n_total": 5,
"n_playable_settled": 5,
"wins": 1,
"losses": 4,
"hit_rate_pct": 20.0,
"unit_profit": -0.574,
"staked": 1.3,
"roi_pct": -44.15
},
"3.0-5.0": {
"n_total": 1,
"n_playable_settled": 1,
"wins": 0,
"losses": 1,
"hit_rate_pct": 0.0,
"unit_profit": -0.2,
"staked": 0.2,
"roi_pct": -100.0
}
},
"by_grade": {
"B": {
"n_total": 518,
"n_playable_settled": 518,
"wins": 285,
"losses": 233,
"hit_rate_pct": 55.02,
"unit_profit": -16.931,
"staked": 105.3,
"roi_pct": -16.08
},
"A": {
"n_total": 6,
"n_playable_settled": 6,
"wins": 2,
"losses": 4,
"hit_rate_pct": 33.33,
"unit_profit": -0.966,
"staked": 1.7,
"roi_pct": -56.82
}
},
"by_competition": {
"league": {
"n_total": 524,
"n_playable_settled": 524,
"wins": 287,
"losses": 237,
"hit_rate_pct": 54.77,
"unit_profit": -17.897,
"staked": 107.0,
"roi_pct": -16.73
}
}
},
"loss_diagnostics": {
"n_losses": 237,
"total_loss_units": -48.7,
"patterns": {
"high_htft_reversal_prob (>=0.20)": [
0,
0.0
],
"cup_match": [
0,
0.0
],
"low_league_reliability (<0.45)": [
42,
17.72
],
"v27_disagree": [
60,
25.32
],
"trap_market_flagged": [
81,
34.18
],
"low_calibrated_conf (<55)": [
7,
2.95
],
"high_odds_underdog (>=2.5)": [
4,
1.69
],
"low_data_quality (<0.55)": [
40,
16.88
],
"high_risk_level": [
20,
8.44
],
"inferred_features": [
0,
0.0
]
},
"by_market": [
[
"OU25",
102
],
[
"BTTS",
100
],
[
"MS",
32
],
[
"OU35",
3
]
],
"by_league": [
[
null,
237
]
],
"top_bb_issues_in_losses": [
[
"triple_value_not_confirmed",
230
],
[
"trap_market_market_overpriced",
81
],
[
"low_reliability_league",
40
],
[
"v25_v27_soft_disagreement",
10
],
[
"engine_consensus_disagree",
5
],
[
"historical_sample_too_low",
3
],
[
"very_low_reliability_league",
2
],
[
"htft_reversal_prob_minor=0.13",
1
]
],
"top_bb_vetoes_in_losses": []
},
"recommendations": [
{
"type": "raise_confidence_threshold",
"confidence_band": "65-70",
"evidence": "n=420, roi=-16.52%",
"suggested_fix": "Raise MIN_BET_SCORE or market_min_conf above 65"
}
],
"errors_sample": []
}