score
Deploy Iddaai Backend / build-and-deploy (push) Successful in 37s

This commit is contained in:
2026-06-10 22:24:50 +03:00
parent 9a8f9941b6
commit 950add373f
3 changed files with 326 additions and 8 deletions
+84
View File
@@ -0,0 +1,84 @@
"""Unit tests for V36 market-anchored score matrix (pure, no DB/model deps)."""
import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from models.score_matrix import (
MAX_GOALS,
_raw_matrix,
_outcome_sums,
build_calibrated_score_package,
ipf_to_outcomes,
split_lambdas,
top_scores,
total_lambda_from_over25,
)
def _approx(a, b, tol=1e-6):
return abs(a - b) <= tol
def test_total_lambda_solver_roundtrip():
import math
for t_true in (1.5, 2.4, 3.5):
p_over = 1.0 - math.exp(-t_true) * (1 + t_true + t_true * t_true / 2)
assert _approx(total_lambda_from_over25(p_over), t_true, 1e-3)
def test_split_matches_win_gap_direction():
lh, la = split_lambdas(2.6, 0.60, 0.18) # strong home side
assert lh > la
lh2, la2 = split_lambdas(2.6, 0.18, 0.60) # strong away side
assert la2 > lh2
def test_ipf_makes_matrix_exactly_consistent_with_1x2():
p1, px, p2 = 0.62, 0.21, 0.17
lh, la = split_lambdas(2.7, p1, p2)
mat = ipf_to_outcomes(_raw_matrix(lh, la), p1, px, p2)
w, d, l = _outcome_sums(mat)
assert _approx(w, p1, 1e-9) and _approx(d, px, 1e-9) and _approx(l, p2, 1e-9)
def test_top_scores_sorted_and_shaped():
mat = _raw_matrix(1.6, 1.1)
top = top_scores(mat, 5)
assert len(top) == 5
probs = [t["prob"] for t in top]
assert probs == sorted(probs, reverse=True)
assert all("-" in t["score"] for t in top)
def test_package_full_fields_and_consistency():
pkg = build_calibrated_score_package(0.526, 0.258, 0.216, 0.55)
assert pkg["ft"] and pkg["ht"]
assert pkg["xg_home"] > pkg["xg_away"] # home is favourite
assert _approx(pkg["xg_total"], pkg["xg_home"] + pkg["xg_away"], 0.02)
assert len(pkg["scenario_top5"]) == 5
assert pkg["calibration_source"] == "market_anchor_v36_score"
# HT must be a lower-scoring line than FT on average
fh, fa = map(int, str(pkg["ft"]).split("-"))
hh, ha = map(int, str(pkg["ht"]).split("-"))
assert hh + ha <= fh + fa
def test_ht_ipf_applied_when_probs_given():
base = build_calibrated_score_package(0.40, 0.30, 0.30, 0.50)
forced = build_calibrated_score_package(
0.40, 0.30, 0.30, 0.50, ht_probs=(0.05, 0.90, 0.05)
)
# forcing a near-certain HT draw must make the modal HT score a draw line
hh, ha = map(int, str(forced["ht"]).split("-"))
assert hh == ha
assert base["ft"] == forced["ft"] # FT untouched by HT anchoring
if __name__ == "__main__":
fns = [v for k, v in sorted(globals().items()) if k.startswith("test_")]
for fn in fns:
fn()
print(f"PASS {fn.__name__}")
print(f"\nAll {len(fns)} tests passed.")