<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: 杰克法拉利</title>
    <description>The latest articles on DEV Community by 杰克法拉利 (@_73f88ca6d9f9bd82d23).</description>
    <link>https://dev.to/_73f88ca6d9f9bd82d23</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4132257%2F888702c4-1558-434a-93b5-ac20a9643393.png</url>
      <title>DEV Community: 杰克法拉利</title>
      <link>https://dev.to/_73f88ca6d9f9bd82d23</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/_73f88ca6d9f9bd82d23"/>
    <language>en</language>
    <item>
      <title>The Poisson Distribution: Football Prediction’s Most Overrated “Mathematically Correct” Tool</title>
      <dc:creator>杰克法拉利</dc:creator>
      <pubDate>Tue, 20 Oct 2026 01:15:39 +0000</pubDate>
      <link>https://dev.to/_73f88ca6d9f9bd82d23/the-poisson-distribution-football-predictions-most-overrated-mathematically-correct-tool-nj2</link>
      <guid>https://dev.to/_73f88ca6d9f9bd82d23/the-poisson-distribution-football-predictions-most-overrated-mathematically-correct-tool-nj2</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;If you've read any football prediction tutorial, you've seen this formula:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P(goals = k) = λᵏ · e⁻ᵏ / k!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's called the Poisson distribution, born a hundred years ago to describe "how many phone calls a telephone exchange receives per minute."&lt;br&gt;
Today, millions of people use it to predict football scores — and then, match after match of 3:3, 0:0, 4:2, they question their life choices.&lt;/p&gt;

&lt;p&gt;This article aims to explain it thoroughly: what Poisson does right, where it goes wrong on the football pitch, and why "mathematically correct" is precisely its biggest trap.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  1. First, in plain language: what is the Poisson distribution?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The math:&lt;/strong&gt;&lt;br&gt;
Let X be the number of times an event occurs in a unit of time. If X follows a Poisson distribution with parameter λ, then:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Probability mass function: P(X = k) = λᵏ·e⁻ᵏ / k!, k = 0, 1, 2, …&lt;/li&gt;
&lt;li&gt;Expectation E(X) = λ&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Variance Var(X) = λ&lt;/strong&gt; ← remember this one; the whole tragedy starts here&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;In plain words:&lt;/strong&gt;&lt;br&gt;
The Poisson distribution answers: &lt;strong&gt;"If an event happens λ times per unit time on average, what's the probability it happens exactly 0 times, 1 time, 2 times…?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It was first used like this: a telephone exchange receives 2 calls per minute on average. What's the probability of zero calls in this minute? What's the probability of 5 calls? The answer is the Poisson distribution.&lt;/p&gt;

&lt;p&gt;Why is it a good fit for "telephones"? Because phone calls have three features:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Each call &lt;strong&gt;doesn't affect others&lt;/strong&gt; (Zhang San calling doesn't make Li Si want to call more)&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;average arrival rate is stable&lt;/strong&gt; (no sudden 100 calls per minute at 8 AM)&lt;/li&gt;
&lt;li&gt;Two calls &lt;strong&gt;never arrive simultaneously&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;These three are exactly all of the Poisson distribution's assumptions.&lt;/strong&gt; And on the football pitch, almost none of them hold.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The bivariate Poisson model: how Poisson predicts scores
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The math:&lt;/strong&gt;&lt;br&gt;
Assume home goals X ~ Poisson(λ_h), away goals Y ~ Poisson(λ_a), with X and Y &lt;strong&gt;mutually independent&lt;/strong&gt;. Then the probability of score (i, j) is:&lt;/p&gt;

&lt;p&gt;P(X = i, Y = j) = P(X = i) · P(Y = j) = (λ_hⁱ·e⁻λ_h / i!) · (λ_aʲ·e⁻λ_a / j!)&lt;/p&gt;

&lt;p&gt;So we can compute probabilities for every score from 0:0 to 6:6, sort them, and take the Top-1 as the "predicted score."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In plain words:&lt;/strong&gt;&lt;br&gt;
Assume "home team averages 1.6 goals, away team averages 1.1 goals," multiply the two "independent dice" distributions, and you get a "score probability table." It looks very rigorous: probability of 0:0, of 2:1, of 3:3 — all computed for you.&lt;/p&gt;

&lt;p&gt;The problem: &lt;strong&gt;this table's correctness rests on the premise that "home goals and away goals don't interfere with each other."&lt;/strong&gt; In football, that premise is a flat-out lie.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Four assumptions — three and a half collapse on the pitch
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Assumption ①: X and Y are mutually independent ← collapses hardest
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The math:&lt;/strong&gt;&lt;br&gt;
Independence requires Cov(X, Y) = 0, i.e. home goals and away goals are uncorrelated. But in real football data, the two teams' goal counts are significantly correlated — &lt;strong&gt;the scoreline itself is a tactical variable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In plain words:&lt;/strong&gt;&lt;br&gt;
Football is not two independently operating telephone exchanges; it's a &lt;strong&gt;zero-sum game&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Home 2:0 up → park the bus; both teams' goal probabilities drop together&lt;/li&gt;
&lt;li&gt;Home 0:2 down → push forward recklessly; both rise together&lt;/li&gt;
&lt;li&gt;1:1 locked → neither dares to commit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can't claim "home goals and away goals don't affect each other" — &lt;strong&gt;it's precisely the opponent's goals that determine your next behavior.&lt;/strong&gt; That's like saying "my pulling force in tug-of-war is unrelated to yours."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consequence:&lt;/strong&gt; the independence assumption makes the model systematically underestimate the scores with the strongest correlation — blowouts (3:3, 4:2, one side collapsing) and goalless stalemates (0:0, both defending). These are exactly the highest-correlation scenarios, the ones Poisson computes as "very unlikely" yet which occur frequently in reality.&lt;/p&gt;

&lt;h3&gt;
  
  
  Assumption ②: Events arrive independently (memorylessness) ← collapses
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The math:&lt;/strong&gt; The Poisson process requires inter-arrival times to be i.i.d., and P(next event within t seconds | already waited s seconds) to be independent of s — "memorylessness."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In plain words:&lt;/strong&gt; Goals don't fall uniformly; they &lt;strong&gt;cluster and burst&lt;/strong&gt;. Red cards, physical collapse, tactical shifts, substitutions cause goals to concentrate in short windows. You've seen "three goals after the 80th minute," but you'll never see "telephone exchange receiving a steady 2 calls per minute"-style goal rhythm. Goals have a clustering effect; Poisson pretends it doesn't exist.&lt;/p&gt;

&lt;h3&gt;
  
  
  Assumption ③: λ is constant through the match ← collapses
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The math:&lt;/strong&gt; Poisson requires the rate λ(t) ≡ λ to be constant. In real football λ is time-varying: it changes with match progress, scoreline, fitness, weather, tactics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In plain words:&lt;/strong&gt; The goal rate in the 10th minute and the 85th minute are completely different things. The trailing side's "late surge" and the strong side's "garbage-time coasting" are evidence of λ drifting. Measuring the whole match with one fixed ruler erases "the process of the game" itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Assumption ④: variance = mean ← collapses (the most insidious one)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The math:&lt;/strong&gt; The Poisson distribution's most famous property: Var(X) = E(X) = λ. The distribution's dispersion is fully determined by its mean — no freedom to express "extra volatility." Real football score distributions are &lt;strong&gt;over-dispersed&lt;/strong&gt;: actual variance significantly exceeds the mean.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In plain words:&lt;/strong&gt; Poisson's "personality" is locked by its mean. A match with λ = 2 must have volatility exactly equal to 2 — no more, no less. But real football: two matches both "averaging 4 goals," one can end 7:6, the other 1:0. &lt;strong&gt;The real world's variance is far larger than Poisson allows.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  4. The key mechanism: why "perfectly tuned parameters" can't save it
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;This is the most important section of the article.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The math:&lt;/strong&gt;&lt;br&gt;
The Poisson distribution's shape (kurtosis, skewness, tail fatness) is entirely determined by the single parameter λ, and variance is locked to λ. Therefore, no matter how finely you tune λ (with xG, historical averages, or market-implied values), you can only translate the distribution — &lt;strong&gt;you cannot change its shape&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When the true distribution is "sharp peak + fat tails" (lots of boring scores + a few extreme ones), while Poisson is "sharp peak + thin tails" (probability mass squeezed around the mean), the two rankings must systematically misalign:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Poisson's Top-1 is always a low-priced score near the mean (1:0, 2:1, 1:1, 2:0)&lt;/li&gt;
&lt;li&gt;Real-world frequent outcomes (0:0, 3:3, 0:2 upsets) are systematically down-ranked&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The KL divergence is nonzero and does not converge as λ estimation improves&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;In plain words:&lt;/strong&gt;&lt;br&gt;
Imagine Poisson as a &lt;strong&gt;ruler with a fixed shape and no adjustable markings&lt;/strong&gt;. You can slide it forward and backward (tuning λ), but you can't make it thicker, thinner, longer, or shorter. The real distribution of football scores is a "differently shaped ruler." &lt;strong&gt;You can position it perfectly, but if the ruler's shape is wrong, the rankings it produces are wrong.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the essential difference between "model structural error" and "parameter estimation error":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parameter error → can be tuned, can be fixed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Structural error → welds the prediction ceiling shut; tuning is futile&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Backtest proof (our data):&lt;/strong&gt;&lt;br&gt;
On 44,479 real matches, the Poisson model's Top-1 score hit rate was &lt;strong&gt;13.33%&lt;/strong&gt;, logloss &lt;strong&gt;2.87&lt;/strong&gt; — significantly worse than the "de-vigged market probability" baseline. And 148,397 real score bins show: &lt;strong&gt;88% of actual outcomes fall in {1:0, 2:1, 1:1, 0:1, 2:0} — five boring scores.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Notice the irony in this comparison:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Poisson's "predicted" Top-1 also happens to fall in these boring scores — the direction coincidentally aligns, but &lt;strong&gt;it bets the same way in every match&lt;/strong&gt;, which is equivalent to erasing variance entirely. When a match actually ends 3:3, Poisson's assigned probability might be under 2%.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faonjdqnwzmxhvmzwzc8i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faonjdqnwzmxhvmzwzc8i.png" alt="Causal chain: why the Poisson distribution welds shut the score-prediction ceiling (backtest: 44,479 matches, Top-1 hit rate 13.33%, logloss 2.87)" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. So should I delete Poisson? — No, demote it
&lt;/h2&gt;

&lt;p&gt;Many people hearing this would say: "Then Poisson is useless, delete it."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't delete it.&lt;/strong&gt; Poisson gets "ranking" wrong, but it gets two things right:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Candidate-pool generation&lt;/strong&gt;: Poisson can propose a "reasonable score set" (0:0 to 4:2), ensuring you don't miss "possible worlds." Real scores do mostly fall near its mean neighborhood, so it's a decent "possibility filter."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;λ's physical meaning&lt;/strong&gt;: λ itself (expected goals) remains a useful intermediate quantity, feeding magnitude judgment and over/under calibration.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The correct division of labor:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Poisson opens the possibility space (breadth); the market prices each possibility (precision).&lt;br&gt;
One manages "which scores exist in the world," the other manages "which score is most likely."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's the choice our model finally made: &lt;strong&gt;Poisson exits ranking (weight zeroed), remains as candidate-pool generator; ranking is fully handed to de-vigged market probability + evidence scores.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  6. One-paragraph summary (take it and go)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What you want Poisson for&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Generate a "possible score set"&lt;/td&gt;
&lt;td&gt;✅ Yes — this is what it's good at&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Predict "which score is most likely"&lt;/td&gt;
&lt;td&gt;❌ Don't trust it — wrong shape, ceiling welded shut&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Derive expected goals λ&lt;/td&gt;
&lt;td&gt;✅ Useful — as an intermediate quantity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Judge direction and winner&lt;/td&gt;
&lt;td&gt;❌ Market odds carry far more information&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;One last plain sentence:&lt;/strong&gt;&lt;br&gt;
Poisson is a mathematical tool invented a hundred years ago for "telephones." Football is not a telephone — football has tactics, emotion, collapses, and late winners, and those are precisely the things erased by the three words "independent, constant, memoryless" in Poisson's formula.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Being mathematically correct is not the same as being really correct. The one who truly understands the market is the market itself.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Data source: backtest data from my football prediction model's full historical library (44,479-match Poisson ranking backtest, 148,397 real score bins, 230,557 match odds). Conclusions come from real backtests, not theoretical derivation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: This article is a knowledge explainer on probability theory and football market mechanics. It is not betting advice. Every prediction carries variance — stay rational.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>football</category>
      <category>machinelearning</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Why Your "Safe Bet" Keeps Losing: Retail Emotion and Institutional Intent Live in Different Markets</title>
      <dc:creator>杰克法拉利</dc:creator>
      <pubDate>Tue, 20 Oct 2026 01:09:14 +0000</pubDate>
      <link>https://dev.to/_73f88ca6d9f9bd82d23/why-your-safe-bet-keeps-losing-retail-emotion-and-institutional-intent-live-in-different-markets-3in7</link>
      <guid>https://dev.to/_73f88ca6d9f9bd82d23/why-your-safe-bet-keeps-losing-retail-emotion-and-institutional-intent-live-in-different-markets-3in7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is not a model showcase. It's a set of conclusions I arrived at after repeatedly validating football odds-market mechanics against data. They won't necessarily make you win — but they will help you see why some odds look "rock solid" and still blow up, and why the direction of big money was always written in the odds.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  First, a counterintuitive fact
&lt;/h2&gt;

&lt;p&gt;I hold a historical dataset of 230,557 real matches: results, European &amp;amp; Asian handicap odds, China Sports Lottery (竞彩) official tick-by-tick odds, and full correct-score (exact score) odds tables.&lt;/p&gt;

&lt;p&gt;When I started, I did what most people do: &lt;strong&gt;treat the lowest-priced option as the most likely outcome, and treat odds movement as "market direction."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After several rounds of backtesting, I arrived at a conclusion that made me uncomfortable:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Looking at odds &lt;em&gt;levels&lt;/em&gt; shows you consensus; only looking at how odds &lt;em&gt;move&lt;/em&gt; — and in which direction — shows you where the money is going.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And there's a further complication: &lt;strong&gt;not all odds are worth watching.&lt;/strong&gt; 竞彩 (China Sports Lottery) odds and European/Asian odds stand behind two completely different groups of people.&lt;/p&gt;




&lt;h2&gt;
  
  
  Finding 1: The market is two-channel — retail emotion and institutional intent live in different books
&lt;/h2&gt;

&lt;p&gt;I split all 220,000+ matches into two channels:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Channel A: 竞彩 official book (China retail pool)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tick-by-tick 1X2, handicap, over/under, correct score&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High time-point density&lt;/strong&gt; (5-6 snapshots per match), but participants are &lt;strong&gt;mass retail bettors&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Retail behavior is highly patterned: loves favorites, loves "safe-looking" home wins, chases momentum, blindly optimistic about strong teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Channel B: European/Asian books (institutional pool)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1xbet, Bet365 and other international books: European odds, Asian handicap, O/U, correct score full market&lt;/li&gt;
&lt;li&gt;Fewer time points (usually 2-4), but participants are &lt;strong&gt;institutions and large money&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Institutional behavior is different: they &lt;strong&gt;manage risk, hedge, and exploit retail emotion with counter-positioning&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key finding: the two channels' signals are frequently opposite.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A real example from my testing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On the 竞彩 book, a correct-score price keeps dropping — looks like "big money is buying it" — but it's actually retail chasing the hot pick&lt;/li&gt;
&lt;li&gt;Meanwhile on the European/Asian book, the same score's price is &lt;strong&gt;rising&lt;/strong&gt; — institutions are pulling out, distributing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you only watch 竞彩, you'd think the market likes this score. In reality, institutions are leaving.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Conclusion: the China retail pool is an "emotion pool"; the international institutional pool is an "intent pool." Using the emotion pool to judge direction is finding signals inside noise.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This was the most important surgery I later performed on the model: &lt;strong&gt;rebuild direction judgments on the de-vigged consensus price of the European/Asian book; keep only what 竞彩 genuinely contributes — the &lt;em&gt;shape&lt;/em&gt; of its tick-by-tick movement (is retail panicking or chasing?) — not its &lt;em&gt;price&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Finding 2: The direction of odds movement is worth far more than the odds themselves
&lt;/h2&gt;

&lt;p&gt;Most people only look at "what's the price now." The truly useful information is &lt;strong&gt;how the price moved from opening to kickoff&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I ran longitudinal comparisons on correct-score odds: from early book to close, every score's price moves. Inside those moves is the real attitude of large money:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Weight in my testing&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A score's price &lt;strong&gt;falls sharply&lt;/strong&gt; (≥15%)&lt;/td&gt;
&lt;td&gt;Large money is genuinely buying this score&lt;/td&gt;
&lt;td&gt;Strong bullish&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Falls moderately (5%-15%)&lt;/td&gt;
&lt;td&gt;Some interest, but modest&lt;/td&gt;
&lt;td&gt;Mildly bullish&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rises moderately (-15%~-5%)&lt;/td&gt;
&lt;td&gt;Money pulling out, popularity fading&lt;/td&gt;
&lt;td&gt;Mildly bearish&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rises sharply (≤-15%)&lt;/td&gt;
&lt;td&gt;Institutions distributing/steaming — beware the reverse&lt;/td&gt;
&lt;td&gt;Strong bearish&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;A real example&lt;/strong&gt; (a big-match fixture I ran): late, the 3:3 correct-score price dropped ~16%, the system flagged "sharp water drop" — institutions directionally buying "goals galore." You can never see that signal from static prices alone.&lt;/p&gt;

&lt;p&gt;Handicap markets work the same way, and are subtler:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Line up + water down&lt;/strong&gt; (handicap raised, price lowered) = institutions genuinely confident, willing to add&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Line up + water up&lt;/strong&gt; (handicap raised, price also rising) = steaming — looks confident but is &lt;strong&gt;luring you onto the top side&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Line down + water down&lt;/strong&gt; = institutions reducing risk, possibly genuinely negative&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Conclusion: water is the institution's tone of voice; the line is its stance. "Line up + water up" is a trap zone.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Finding 3: Why "rock-solid-looking" scores keep blowing up (anchor–market consistency)
&lt;/h2&gt;

&lt;p&gt;This is the most counterintuitive and most practical finding in my data.&lt;/p&gt;

&lt;p&gt;I graded 157 anchored matches by "expected total goals × margin band" and computed anchor reliability. The results are brutal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Matches with actual total goals ≤3 and margin ≤1 → anchor hit rate &lt;strong&gt;40%&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;High-scoring expectations (≥4) or deep-handicap blowout matches → &lt;strong&gt;2.9%~4.9%&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;5+ goal matches → &lt;strong&gt;0%&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Of all hits, 88% concentrated in {1:0, 2:1, 1:1, 0:1, 2:0} — five "boring" scores&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;In plain words:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The more a match looks like a "locked-in big win," the less predictable the exact score. Your "3:0 is safe" is precisely the outcome the data says you're least likely to anchor.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Why? In deep-handicap blowouts, the institution has already priced in "the strong team wins" — the directional value is fully consumed; all that's left is variance. What you &lt;em&gt;can&lt;/em&gt; anchor is the low-scoring, small-margin "boring matches."&lt;/p&gt;

&lt;p&gt;So I adopted a hard rule: &lt;strong&gt;the anchor must agree with the market&lt;/strong&gt; —&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Market strongly over → anchor must sit in the high-total-goals spectrum&lt;/li&gt;
&lt;li&gt;Asian handicap gives the home team (+handicap) → &lt;strong&gt;no home-win anchor allowed&lt;/strong&gt; (if the market doesn't think you win, why anchor 2:0?)&lt;/li&gt;
&lt;li&gt;Anchor total deviating from market expectation by &amp;gt;1.5 goals → automatic mismatch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This rule has killed countless "I feel like it'll be 2:0" impulses.&lt;/p&gt;




&lt;h2&gt;
  
  
  Finding 4: The Poisson distribution stepped down — the market is the best predictor
&lt;/h2&gt;

&lt;p&gt;Most football-prediction tutorials start with "build a Poisson model and compute expected goals."&lt;/p&gt;

&lt;p&gt;I did too. But backtesting told me one thing:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Poisson model's Top-1 score hit rate was only 13.33%, and it was systematically biased toward low-priced scores — because its core assumptions (independent Poisson arrivals) don't match football's correlation structure (tactics, injuries, motivation, refereeing).&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;More importantly: &lt;strong&gt;the market has already done the math.&lt;/strong&gt; Institutional odds contain more information than any mathematical model — player form, inside knowledge of injuries, money flow, even weather. Using Poisson to "predict" is challenging a more complete pricing system with a simplified model.&lt;/p&gt;

&lt;p&gt;So I made a decision many people would hesitate to make: &lt;strong&gt;remove Poisson from ranking entirely, keep it only as a "candidate-pool generator"&lt;/strong&gt; — it proposes plausible scores, but &lt;strong&gt;ranking is driven by market baseline + evidence scores.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Result: direction judgment stabilized at &lt;strong&gt;70-80% accuracy&lt;/strong&gt; (including three-way coverage), and pre-transition anchoring quality was far messier.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Conclusion: it's not that Poisson is useless — it's that the market understands football better than Poisson does. Instead of building your own model, learn to read the market's pricing.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Finding 5: Big-over games are a double-edged sword — the mean trap
&lt;/h2&gt;

&lt;p&gt;I reviewed a batch of extreme over matches (O2.5 &amp;lt; 1.4, i.e. the market strongly expects goals):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Match&lt;/th&gt;
&lt;th&gt;Market expected total goals&lt;/th&gt;
&lt;th&gt;Actual total goals&lt;/th&gt;
&lt;th&gt;Deviation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;3.97&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;+3.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;3.99&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;-3.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;market expectations were nearly identical (~4 goals)&lt;/strong&gt;, but the outcomes were 7 and 1 — &lt;strong&gt;the mean was perfect; the variance exploded&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is the insidious part of big-over games&lt;/strong&gt;: the expectation isn't lying to you (averages really are ~4), but a single match is completely uncontrollable. If you treat "expected 4" as "this game will have 4," you'll lose on both.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Conclusion: for big-over games, watch the variance &lt;em&gt;range&lt;/em&gt; (1-6 goals all possible), not the expectation &lt;em&gt;center&lt;/em&gt;. For extreme overs, honestly admitting "the score is unpredictable" is far more honest — and far safer — than forcing an anchor.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Finding 6: Direction is achievable; the exact score is hard — but "hard" isn't "impossible"
&lt;/h2&gt;

&lt;p&gt;Overall numbers, so you have realistic expectations about what football prediction can do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Direction (1X2)&lt;/strong&gt;: with three-way coverage discipline, 70-80% hit rate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exact score&lt;/strong&gt;: ~27% overall, but up to 40% on low-scoring, small-margin matches&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Perfect anchor (primary or secondary)&lt;/strong&gt;: ~23%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why is direction easier and score harder?&lt;/strong&gt;&lt;br&gt;
Direction is a direct mapping of "market consensus + large-money movement" — high signal, low noise. Exact score requires four variables to hit simultaneously (expected goals + margin band + total-goals magnitude + direction) — miss any one, and the score misses.&lt;/p&gt;

&lt;p&gt;The correct usage:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Use market signals for direction (high confidence), narrow the candidate pool by magnitude bands (medium confidence), enforce anchor–market consistency as a hard constraint (protects against impulses), and honestly admit "unpredictable" for extreme matches.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Three takeaways you can use immediately
&lt;/h2&gt;

&lt;p&gt;If you don't want to build a model, take these three from my data:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Don't buy "hot" picks just because 竞彩 prices are dropping&lt;/strong&gt; — that's often retail emotion while institutions counter-position in another book. Watch the international books' water movement instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Line up + water up" is a trap signal&lt;/strong&gt; — the institution builds a "safe illusion" to lure you onto the top side.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never touch "locked-in blowout" scores&lt;/strong&gt; — exact-score anchor hit rates on deep-handicap blowouts are under 5%. Boring scores (1:0, 2:1, 1:1, 2:0) are what actually happens.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;Data source: my football prediction model's full historical library (230,557 real matches with European/Asian odds, 148,397 real score bins, 105 multi-time-point market snapshots). All conclusions come from backtesting and live review, not gut feeling.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: This article shares analytical methods and research findings about odds-market mechanics. It is not betting advice. Football is round; every prediction carries variance — stay rational and bet within your means.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>football</category>
      <category>python</category>
    </item>
    <item>
      <title>I Split 220,000 Matches Into Two Channels: Retail Emotion vs. Institutional Intent</title>
      <dc:creator>杰克法拉利</dc:creator>
      <pubDate>Tue, 29 Sep 2026 04:30:05 +0000</pubDate>
      <link>https://dev.to/_73f88ca6d9f9bd82d23/i-split-220000-matches-into-two-channels-retail-emotion-vs-institutional-intent-e5l</link>
      <guid>https://dev.to/_73f88ca6d9f9bd82d23/i-split-220000-matches-into-two-channels-retail-emotion-vs-institutional-intent-e5l</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;GitHub: github.com/MENG-COOLMAN/PitchQuant&lt;br&gt;
For academic research and technical exchange only. Not betting advice.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What's new in this update
&lt;/h2&gt;

&lt;p&gt;In my previous post I wrote about building a complete football data analysis pipeline from 220,000 matches, pushing direction accuracy from 48% to 55%. But one question kept bugging me — &lt;strong&gt;how should you actually read odds movement?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Over the last two weeks I figured it out: the odds aren't set by one person. Two groups are buying them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retail bettors&lt;/strong&gt; chase Chinese lottery odds, piling into whichever direction is dropping, convinced "dropping odds = smart money." &lt;strong&gt;Institutions&lt;/strong&gt; move the Asian/European market with real money, pushing lines toward what they believe. These two groups disagree all the time — and when they do, who's right?&lt;/p&gt;

&lt;p&gt;The answer: &lt;strong&gt;most of the time, retail is wrong.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So in this update (V3.5.76) I did one thing: split these two groups into two independent channels that cross-validate — and expose — each other. This post walks through the "dual-channel" mechanism and the uncomfortable finding it surfaced.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why two channels are necessary
&lt;/h2&gt;

&lt;p&gt;First, a measured data point. I backtested the tick-by-tick Chinese lottery odds: &lt;strong&gt;when a direction's odds keep dropping before kickoff (retail reads this as "the bookmaker likes it"), that direction actually hits only 25% of the time.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Four-match sample — the dropping direction won a quarter of them.&lt;/p&gt;

&lt;p&gt;The drop isn't wrong; the &lt;strong&gt;cause&lt;/strong&gt; of the drop is wrong. The Chinese lottery vig is as high as 12.8%, and its water levels mostly follow retail sentiment, not information. Retail piles in, odds drop, and the bookmaker is happy — because with lower odds, retail's expected value evaporates and the bookmaker's exposure shrinks.&lt;/p&gt;

&lt;p&gt;The Asian/European market, by contrast, has only ~6.9% vig. Line and water movement there is backed by real hedging pressure. Institutions don't buy retail sentiment; they buy &lt;strong&gt;their own positions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So I split the model's data flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Lottery tick-by-tick odds  →  Retail channel (sentiment·12.8% vig)
Asian/European time series →  Institutional channel (intent·6.9% vig)
             ↓ cross-validate ↓
       Quadrant decision (Q1 consensus/Q2 trap/Q3 upset/Q4 block)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The four quadrants: how the two groups fight
&lt;/h2&gt;

&lt;p&gt;Crossing the two channels produces four scenarios, ranked by priority:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q2 Trap alarm (most dangerous)&lt;/strong&gt;: retail floods direction A with dropping odds, institutions stay still or push the other way.&lt;br&gt;
→ Classic "trap." Retail is moving exactly where the bookmaker wants. Handling: knock the favorite down one confidence notch and force the second direction into a tie.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q1 Consensus (most trustworthy)&lt;/strong&gt;: retail drops odds on A, institutions follow by deepening the line.&lt;br&gt;
→ Both groups agree — only now is the signal actually worth something. Confidence up half a notch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q4 Block signal&lt;/strong&gt;: retail sees odds rise on A (too scared to buy), institutions quietly move toward A.&lt;br&gt;
→ The bookmaker is "blocking" — deliberately inflating odds to scare off retail while quietly favoring A itself. Follow the institutional direction, +0.5 notch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q3 Upset hint (weakest)&lt;/strong&gt;: retail hasn't moved, institutions move alone.&lt;br&gt;
→ Flag for attention only, no adjustment. Wait for confirmation.&lt;/p&gt;

&lt;p&gt;One hard rule here: &lt;strong&gt;the quadrants may only adjust confidence, by at most ±1 notch, and may never reverse the hardcore direction.&lt;/strong&gt; I learned this the hard way — letting weak signals overturn strong ones just hands control to noise.&lt;/p&gt;
&lt;h2&gt;
  
  
  The time dimension: when is a signal real?
&lt;/h2&gt;

&lt;p&gt;The other dimension I added is &lt;strong&gt;time&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Lines older than 48 hours before kickoff I call "smoke screens" — they're shaped by capital flows and the bookmaker's exploratory positioning, and carry little signal. Lines within 90 minutes of kickoff carry the most information density, because by then the money that was going to arrive has arrived, and the line basically reflects real views.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;48h   early line  → smoke screen·institutional channel downgraded to weak reference
≤90min late line  → highest information density·full weight
in between        → normal window
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It sounds simple, but this grading filtered out a lot of "fake signals" in backtesting. Many seemingly bizarre odds movements, zoomed out on the time axis, turn out to be early-line noise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Engineering debt I paid off along the way
&lt;/h2&gt;

&lt;p&gt;Beyond the algorithm, the engineering got a lot of attention too. The model now runs &lt;strong&gt;413 automated checks&lt;/strong&gt; — if rules and data disagree, it fails loudly. "Looks about right" doesn't pass.&lt;/p&gt;

&lt;p&gt;A few fixes worth mentioning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cross-language team matching&lt;/strong&gt;: snapshots store English team names, but the lottery txt files use Chinese names, and they used to never match. Now there are 191 bilingual alias mappings, covering all top-5 leagues + UCL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The auditor audits itself&lt;/strong&gt;: my check rules used to have a loophole — "keyword present = pass." Now a check needs the keyword &lt;strong&gt;plus a number&lt;/strong&gt; to count, so the auditor can't be lazy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fixture regression&lt;/strong&gt;: every parsing bug we've ever hit is now frozen as a real input sample, and the model re-runs all of them on every pass — so the same bug can't come back in a different function.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The other big stuff this fortnight
&lt;/h2&gt;

&lt;p&gt;Besides the dual channel, several new modules landed that weren't in v1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;UEFA Nations League sub-model&lt;/strong&gt;: national-team football is a completely different game — no transfers, no form continuity, mystery motivation in friendlies. I built a dedicated tiered rule set for the NL, backtested on 658 national-team matches, and set a "domain discipline": top-5 league thresholds don't apply to national teams, and vice versa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;European competition three-layer calibration&lt;/strong&gt;: UCL knockout two-legged ties, group-stage round-robins, and neutral-venue finals all have completely different motivation and formats. Now each is calibrated by tier — the first-leg leader parks the bus in the second leg, group-stage dead rubbers get tanked, all quantified into the model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-league sub-models&lt;/strong&gt;: each of the top-5 leagues gets its own distilled rule set (7,000-9,000 backtested matches each). Bundesliga is a goals machine, Serie A is draw-heavy, Ligue 1 is low-scoring — applying one universal threshold to every league is wrong by construction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Post-match learning loop&lt;/strong&gt;: after every match, the model writes the result, prediction, and actual odds back to the case library, then periodically re-runs backtests to recalibrate the lookup tables. It doesn't retrain everything on every update — only the parameters whose backtests show genuine drift.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The honest numbers
&lt;/h2&gt;

&lt;p&gt;As always, the cold-water section:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Direction accuracy: &lt;strong&gt;~55-58%&lt;/strong&gt; (clear gains on weak-signal matches, stable on strong-signal matches)&lt;/li&gt;
&lt;li&gt;Dual-channel core scenario: low European/Asian dispersion (spread&amp;lt;2%) hits **52.7%** direction accuracy; high dispersion (spread&amp;gt;10%) drops to &lt;strong&gt;44%&lt;/strong&gt; — the more aligned the institutions, the more trustworthy the signal&lt;/li&gt;
&lt;li&gt;Deep favorite + institutional alignment (home &amp;lt;1.50 and spread&amp;lt;2%): &lt;strong&gt;80.0%&lt;/strong&gt; (smaller sample, reference only)&lt;/li&gt;
&lt;li&gt;Top-2 score hit rate: &lt;strong&gt;~30%&lt;/strong&gt; (strong-signal matches)&lt;/li&gt;
&lt;li&gt;All numbers are time-split backtests on 220k historical matches. &lt;strong&gt;They do not predict the future.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the line from the project's front page: football is chaotic, markets are efficient. This project helps you &lt;strong&gt;make fewer mistakes&lt;/strong&gt; — it doesn't help you &lt;strong&gt;beat probability&lt;/strong&gt;. Negative long-term EV on sports lottery is structural, independent of any model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open source
&lt;/h2&gt;

&lt;p&gt;The project is on GitHub under MIT license:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Core scripts are all Python, stdlib-heavy&lt;/li&gt;
&lt;li&gt;Distilled JSON lookup tables (de-vig calibration, score depth, handicap tiers, etc.) are included&lt;/li&gt;
&lt;li&gt;The raw 220k-match CSV is too large and has source terms, so it's not included&lt;/li&gt;
&lt;li&gt;You'll need your own API keys (odds-api and api-football both have free tiers)&lt;/li&gt;
&lt;li&gt;Calibrated for top-5 European leagues + UCL; other leagues aren't calibrated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;One last thing&lt;/strong&gt;: for academic research and technical exchange only. Not investment advice.&lt;/p&gt;

&lt;p&gt;If you're curious about telling retail and institutional money apart in odds, star it and drop an issue. Happy to discuss.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;A student studying for grad school in financial math. This project was built bit by bit in my spare time. All the data, rules, and code are on GitHub. Come build with me.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>football</category>
      <category>datascience</category>
      <category>python</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I Built a Football Data Analysis Pipeline From 220,000 Matches</title>
      <dc:creator>杰克法拉利</dc:creator>
      <pubDate>Sat, 19 Sep 2026 02:17:32 +0000</pubDate>
      <link>https://dev.to/_73f88ca6d9f9bd82d23/i-built-a-football-data-analysis-pipeline-from-220000-matches-4gen</link>
      <guid>https://dev.to/_73f88ca6d9f9bd82d23/i-built-a-football-data-analysis-pipeline-from-220000-matches-4gen</guid>
      <description>&lt;p&gt;&lt;em&gt;For academic research only. Not betting advice.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/MENG-COOLMAN/PitchQuant" rel="noopener noreferrer"&gt;MENG-COOLMAN/PitchQuant&lt;/a&gt; — MIT license, free to use.&lt;/p&gt;




&lt;h2&gt;
  
  
  The TL;DR
&lt;/h2&gt;

&lt;p&gt;Six months. 227,000 matches. One question: &lt;strong&gt;what can you actually learn from football odds?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is not a "prediction oracle." Football is chaotic and markets are efficient — I put that on the front page. But if you've ever stared at a line of odds and wondered if there's a signal hiding in the noise, this post is for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built this
&lt;/h2&gt;

&lt;p&gt;It started with a simple frustration. Two teams both at 1.50. One wins every time. The other doesn't. Why?&lt;/p&gt;

&lt;p&gt;I started pulling data — de-vigging, ELO ratings, Poisson models. At first it felt like I was onto something. Then reality hit: after a few hundred matches, &lt;strong&gt;no single indicator beats the market&lt;/strong&gt;. De-vigged probabilities land within ±5pp. ELO gaps explain maybe 10% of variance. Standard Poisson is basically guessing on 3:2 vs 2:1.&lt;/p&gt;

&lt;p&gt;But here's the thing: when you combine weak signals with proper weights and strict backtesting gates, directional accuracy climbs from 48% to around 55%. That number isn't flashy. But in the odds world, every single percentage point is real money.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it looks like
&lt;/h2&gt;

&lt;p&gt;It's an &lt;strong&gt;LLM-as-runtime&lt;/strong&gt; architecture. Think of it as a very picky analyst who refuses to skip steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python scripts&lt;/strong&gt; do the math — de-vigging, Kelly criterion, Dixon-Coles Poisson, score lookup tables. The LLM doesn't question what the numbers say.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;34 knowledge files&lt;/strong&gt; tell the LLM what to look for — league quirks, European two-leg adjustments, halftime patterns, water-level traps. Every rule comes from backtests, not gut feel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;238 automated checks&lt;/strong&gt; catch mistakes. If a rule says one thing and the data says another, it fails loudly. "No number = not done" is a hard rule.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuuu9hd4swroi2fpt1fw5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuuu9hd4swroi2fpt1fw5.png" alt="PitchQuant project README showing architecture and badges" width="800" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For a single match, the pipeline runs like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Odds input → De-vig probabilities → 12 hardcore checks → Odds movement morphology →
Scenario rules → 26 inference checks → League calibration → Home/away factor →
Direction → Goals magnitude → Score spectrum → Totals → Self-check
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The magic isn't the number of steps. It's that &lt;strong&gt;each step's output feeds directly into the next&lt;/strong&gt;. No skipping. No "these two steps just happened to both be in the report."&lt;/p&gt;

&lt;h2&gt;
  
  
  Five things I learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. The weak-consensus trap
&lt;/h3&gt;

&lt;p&gt;When the market isn't strongly convinced (skew &amp;lt; 150%), the "favorite" wins only &lt;strong&gt;36-43%&lt;/strong&gt; of the time. That's a coin flip. Betting the favorite here loses over time. The draw is consistently underpriced and must be listed as a co-primary outcome. I learned this the expensive way.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Deep odds don't always mean safe
&lt;/h3&gt;

&lt;p&gt;Home odds below 1.30 look like a lock. But if the Asian handicap only moves 0.5-0.75 (shallow at low odds), actual home wins drop from &lt;strong&gt;74% to 56%&lt;/strong&gt;. Low odds + shallow handicap = trap. You can't see this from European odds alone — you need the Asian water level. This one signal alone was worth the entire project.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Over 2.5 and exact score are different games
&lt;/h3&gt;

&lt;p&gt;Everyone assumes "over 2.5 means big scores." Wrong. When the O2.5 line is low (strong over expectation), the Top-2 score hit rate actually &lt;strong&gt;drops&lt;/strong&gt;. Why? Because high-scoring matches have more dispersed scorelines. 2:1, 3:1, 2:2, 3:2 all go over 2.5. You nail the direction but can't pin the exact score. Took me weeks to accept this trade-off.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. More machine learning isn't always better
&lt;/h3&gt;

&lt;p&gt;I was excited about online ML (River's ADWIN drift detection). It sounded cutting-edge. Backtesting showed only a &lt;strong&gt;0.68pp&lt;/strong&gt; improvement — and only on matches where the market was already weak. Forcing it onto strong-signal matches just added noise. So I built a gate: strong market signal → learning stays out. Weak signal → learning gets a co-reference slot. Sometimes the best ML model is the one you don't use.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Poisson isn't a crystal ball
&lt;/h3&gt;

&lt;p&gt;Dixon-Coles correction helps, but it still assumes goals are independent events. In reality, a leading team sits back, the trailing team throws everyone forward. Poisson can't model that. So it's just one engine — you also need to fuse with the actual score odds distribution from the market. The market already did the hard work; your job is to read it, not replace it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest numbers
&lt;/h2&gt;

&lt;p&gt;Before anyone gets too excited:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Direction accuracy: ~50% baseline, &lt;strong&gt;~55-58%&lt;/strong&gt; with model optimization&lt;/li&gt;
&lt;li&gt;Top-2 score hit rate: ~25% baseline, &lt;strong&gt;~30%&lt;/strong&gt; on strong-signal matches&lt;/li&gt;
&lt;li&gt;These are time-split backtest numbers from 227k matches. They do &lt;strong&gt;not&lt;/strong&gt; predict the future.&lt;/li&gt;
&lt;li&gt;Long-term EV on sports lottery is structurally negative. No model changes that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The point isn't "how to win." It's building a data analysis methodology. If you're into quant/data science, these ideas (de-vig calibration, anti-overfitting gates, evidence-bound self-checks) generalize to any prediction project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open source
&lt;/h2&gt;

&lt;p&gt;The project is on GitHub under MIT license:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkgs8bzkbzrx29dxb75k3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkgs8bzkbzrx29dxb75k3.png" alt="GitHub repository file structure" width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All core scripts are Python, stdlib-heavy, no heavy frameworks&lt;/li&gt;
&lt;li&gt;Distilled JSON lookup tables (backtest artifacts) are included&lt;/li&gt;
&lt;li&gt;Raw 227k-match CSV not included (size + source terms)&lt;/li&gt;
&lt;li&gt;You need your own API keys (odds-api and api-football both have free tiers)&lt;/li&gt;
&lt;li&gt;Calibrated for top-5 European leagues + Champions League / Europa League&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One last thing: this project is for academic research and technical exchange only. It does not constitute investment advice. Football is round. Data reduces mistakes; it doesn't beat probability.&lt;/p&gt;

&lt;p&gt;If you found this interesting, star it on GitHub and drop an issue. Happy to discuss architecture, backtesting, or anything in between.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;A student studying for grad school in financial math. Built this bit by bit in my spare time. All the data, rules, and code are on GitHub. Come build with me.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>quantitativefinance</category>
      <category>footballanalytic</category>
      <category>python</category>
      <category>datasciencu</category>
    </item>
  </channel>
</rss>
