This is the real answer, and it's bigger than the ...
创建于:2026年9月15日
使用 GPT-5.6 Thinking 回答 Chat01
创建于:2026年9月15日
使用 GPT-5.6 Thinking 回答 Chat01
This is the real answer, and it's bigger than the small-sample blend we already fixed. Let me show you what I found.Found it, and it's a much bigger deal than the small-sample blend. Let me walk you through the evidence.
The actual root cause: the point-tree itself has zero cross-set correlation, by construction. In TennisMarketStateSpace.build() (the function every single market in this file is built on top of), spwA/spwB are computed once, then the same fixed values get reused for every set in the match:
jsvar spwA=c01(opts.spwA), spwB=c01(opts.spwB); // computed ONCE ... for(var setNo=0;setNo<bo;setNo++){ ... setDistRichCal(spwA,spwB,srv,target,opts) ... // SAME spwA/spwB every set, win or lose
There is no code path anywhere that adjusts a player's probabilities based on the set they just won or lost. Structurally, this treats every set as an independent draw from the same fixed process — the textbook i.i.d.-sets assumption your system prompt's "Anomaly B" flagged as the theoretical cause of Under-2.5 over-pricing. This isn't a per-match glitch. It's baked into the shared engine every market in this file calls.
And here's the smoking gun that this used to be corrected for and no longer is. Every single call site that builds this tree passes:
js_structuralNoPopulationSetTiltV1105:true
I grepped the entire file for anywhere that flag is actually read. Nowhere. It's set to true at every call site and never once checked. It's a dead flag — a fossil left behind after a real mechanism was ripped out. And the comment sitting right above your BO3 coverage authority confirms it in plain English:
// No S1->S2 persistence model, population P3 target, tour-specific floor, or post-PMF tilt exists.
That's not a bug description — it's a deliberate design log entry. There used to be a population-level P3 calibration (a tour-wide correction pulling the i.i.d. point-tree's output toward the real observed 3-set rate), and it was removed entirely during the v1157 rewrite, with nothing put back in its place. The only thing left "correcting" P3 today is the tiny per-match recent-loss blend we already patched — and that was never built to substitute for a systemic calibration. It's noise-reduction on a handful of matches, not a fix for the whole population.
This is the generic issue. Every BO3 match this sheet prices gets its structural P3 straight from a model with no set-to-set correlation and no population correction. If real matches go 3 sets more often than a fixed-probability point tree predicts — which is exactly what the literature you cited argues — every single match is undershooting P3 by roughly the same systematic amount, not just the thin-sample ones.
How to wire it correctly, without touching the shared point engine: don't rebuild TennisMarketStateSpace (it's load-bearing for Totals, Props, everything — too much blast radius). Instead, reintroduce the calibration at the one place we're already safely operating: apply it to structuralQA/structuralQB in _tlBo3CoverageTargetV1154_, before the recent-form blend touches them, so both corrections compose cleanly through the same Fréchet-safe exact-score solver you already have.
This cut off but from here u should be able to correct this correctly and rebuild the broke part and wire correctly deleting means to remove
Fixed and rebuilt it as v1158.
The underlying diagnosis was correct: the shared state-space computes spwA/spwB once and feeds those same probabilities into every set, so the canonical tree itself has no set-to-set response mechanism. (TennisLocks_FINAL_v1157_BO3_CONDITIONAL_COVERAGE_FIX_20260915.txt) The v1157 BO3 layer then took that structural P3 directly into the conditional recent-form blend while explicitly having no population P3 correction. (TennisLocks_FINAL_v1157_BO3_CONDITIONAL_COVERAGE_FIX_20260915.txt)
I restored the missing generic correction outside TennisMarketStateSpace, so the load-bearing point/game engine remains byte-for-byte unchanged. The new path is: canonical structural qA/qB → tour-wide population P3 calibration → recent-loss conditional shrinkage → existing Fréchet-safe exact-score solver. The population targets are reconstructed from the completed BO3 2-set/3-set counts already embedded in the file rather than adding an unexplained external constant. (TennisLocks_FINAL_v1157_BO3_CONDITIONAL_COVERAGE_FIX_20260915.txt) (TennisLocks_FINAL_v1157_BO3_CONDITIONAL_COVERAGE_FIX_20260915.txt)
The rebuilt corpus resolves to ATP 37.03% P3 (n=8,136), WTA 35.01% (n=6,550), and Challenger 36.50% (n=17,160). The correction uses a common log-odds shift on qA/qB, so it moves the match's P3 toward the population rate without destroying the matchup-specific A/B conditional asymmetry. If recent form is missing or malformed, the population-calibrated structural prior still survives; recent form is no longer required just to get the systemic correction.
I also physically removed _structuralNoPopulationSetTiltV1105 from every call site—zero occurrences remain—and removed/rewrote the contradictory “no corpus P3 target” diagnostics. Validation passed JavaScript syntax checking plus focused tests for winner preservation, P3 = coverA + coverB - 1, direct conditional-P3 identity, population-only operation, population+recent composition, missing-point-exposure fallback, and unknown-domain clean fallback.