How Can One Arbitrage in Football Betting? (Part 4)

The previous article discussed the mathematical model: payout vectors, return matrices, stake ratios, and linear equation solving. This article explains how the model runs inside a real-time strategy script.

My strategy does not manually input a few odds and calculate them. It reads real-time markets from a standardized odds database across multiple companies, aggregates them by match, filters candidate combinations, solves stake ratios, and writes the current best result to the result table.

Q: What is the strategy input?

The strategy mainly uses two types of data:

  1. Match links after team-name and match normalization.
  2. Normalized odds after format unification.

The first type solves the question "are these odds for the same match?" The second type solves "what markets and odds does each company currently provide?"

After reading odds, the script first applies freshness filtering. Quotes that are too old, fail validation, or cannot be traced back to a source should not enter arbitrage calculation. Arbitrage is highly time sensitive. An expired high price can create fake arbitrage space.

After filtering, each market row is split into standard betting legs.

For example, moneyline is split into three legs:

Original market Split legs
moneyline moneyline_home
moneyline moneyline_draw
moneyline moneyline_away

Asian handicap is split into two legs:

Original market Split legs
asiahandicap asiahandicap_home
asiahandicap asiahandicap_away

Over/under is split by direction:

Original market Split legs
over over
under under
total total

Each leg is finally normalized into:

[bettype, handicap, dealer, odd]

For example:

["over", "2.5", "m88", "2.05"]
["under", "2.5", "ps888", "1.98"]

This unified format is very important. The later payout matrix does not care which raw table it came from. It only cares what rule it is, what the market line is, which company it belongs to, and what odds it has.

Q: How do odds from different companies enter the same match?

The script aggregates data by a unified event key. Under the same match, there may be markets from China Sports Lottery, Beidan, M88, PS888, Betway, HaoBo, and other sources.

After aggregation, one match may look like this:

event = "World Cup|ArgentinaVS Cape Verde"

[
  ["moneyline_home", "0", "m88", "2.30"],
  ["moneyline_draw", "0", "ps888", "3.70"],
  ["moneyline_away", "0", "betway", "4.20"],
  ["over", "2.5", "m88", "2.05"],
  ["under", "2.5", "ps888", "1.98"]
]

Before calculation, the strategy also records source information for each leg, including source event id, source game id, quote timestamp, quote age, snapshot run id, and other fields. These fields do not change the arbitrage mathematics, but they matter for troubleshooting. If a result looks abnormal, we need to know which crawl and which raw market produced it.

Q: How do candidate combinations move from theory to the current match?

In theory, payout vectors can be pre-generated for all bet types and market lines. But a specific match only contains part of them. So the strategy first collects the legs that actually appear in the current match and forms available keys.

Each standard leg has a stable leg id, for example:

("moneyline_home", 0)
("asiahandicap_home", "-0.25")
("over", "2.5")

The strategy uses these leg ids to build the real-time payout matrix. Rows are betting legs, columns are the 49 score states, and cells are still settlement codes such as 0, 50, 100, 150, and 200.

Then it generates a coverage mask for each row. If a leg has a return code greater than 0 under a score state, that state is marked as covered.

For a candidate group:

\[ L_1,L_2,\ldots,L_n \]

their coverage states are merged by bit operation:

\[ \text{mask}(L_1)\lor\text{mask}(L_2)\lor\cdots\lor\text{mask}(L_n) \]

If the merged mask equals the full score-state mask, this group covers all score states and can enter linear solving.

This step only judges whether the rules cover all outcomes. It does not yet judge whether the odds make money. It first removes combinations that can never cover full-match results no matter how stakes are allocated.

Q: Why only enumerate 2 to 4 legs?

The strategy currently enumerates 2-, 3-, and 4-leg combinations. The reason is practical:

  1. Fewer legs are easier to execute.
  2. More legs are more vulnerable to one company's odds changing.
  3. Multi-leg combinations may improve theoretical coverage, but they significantly increase limit, order sequence, and capital occupation problems.

In arbitrage trading, mathematical validity is not the same as executable trading. If a combination needs 7 legs and any one leg fails, the whole group may turn from arbitrage into naked exposure. So the strategy prioritizes short combinations.

Q: How are multiple company quotes for the same leg handled?

The same leg may be quoted by many companies. For example, several companies may all offer Over 2.5. The strategy does not put every quote into exhaustive search. It deduplicates by dealer and keeps the best odds from each company for that leg.

Then it only keeps the top few candidates for the same leg. The current default is top 2 per leg. This is an engineering acceleration. The assumption is: if a lower-odds version of the same leg does not produce a better return, it usually does not need to enter expensive combination solving.

For example:

Leg Company Odds
Over 2.5 A 2.01
Over 2.5 B 2.05
Over 2.5 C 1.96

The strategy keeps 2.05 first, then 2.01, instead of putting all quotes into combinations.

In addition, the strategy requires an output group to involve at least two companies. If all legs come from the same dealer, even if the math covers all outcomes, it is not output as a cross-bookmaker arbitrage result.

Q: How do odds enter the return matrix?

After a candidate combination passes the coverage mask, it enters real-odds solving. Only at this stage are settlement codes converted into return multipliers:

Code Conversion
0 0
50 0.5
100 1
150 \((O+1)/2\)
200 \(O\)

This converts:

[200, 0]
[0, 200]

into:

[2.05, 0]
[0, 1.98]

It also converts Asian handicap half-win and half-loss states:

150 -> (odd + 1) / 2
50  -> 0.5

Only here do odds truly participate in calculation.

Q: What does the linear solver do?

For each candidate combination, the strategy generates:

odd_list
payout_rows

where payout_rows is the deduplicated return matrix. Then it solves:

\[ (p_j-p_1)\cdot x=0 \]

and:

\[ \sum_i x_i=1,\quad x_i\ge0 \]

If a nonnegative stake ratio \(x\) can be solved, a candidate result is produced:

amount_rate = [x1, x2, ..., xn]
rate_back   = p1 dot x

amount_rate is stake ratio, not absolute amount. rate_back is the unified return multiplier before rebate.

To speed this up, the strategy uses several caches and batch operations:

  1. Solving results with identical odds and payout rows are cached.
  2. Multiple candidates can be sent to the Fortran solver in batches.
  3. LP cases already solved inside one match are reused.
  4. An LP cache is saved on disk and reused in the next run.

These do not change strategy logic. They only reduce repeated calculation.

Q: How does rebate enter EV?

If a company has rebate, it is equivalent to returning part of the stake. For stake ratio \(x_i\), and dealer rebate rate \(b_i\), the rebate contribution is:

\[ b_i x_i \]

The whole group's rebate contribution is:

\[ B=\sum_i b_i x_i \]

So the effective return multiplier used by the strategy is:

\[ EV=R+B \]

where \(R\) is the return multiplier from odds settlement, and \(B\) is the rebate contribution.

For example, a group has odds return multiplier 0.998. It does not look like arbitrage. But if the corresponding stakes earn a 0.5% combined rebate:

\[ EV=0.998+0.005=1.003 \]

Then it is not arbitrage from pure odds, but may become positive return from actual trading return.

Rebate must be confirmed by dealer, account, and settlement rule. If rebate is not stable, it cannot be treated as a safety margin.

Q: How are final results filtered?

One match may produce many candidate combinations. The strategy does not output all of them. It applies several filters:

  1. At least two companies are involved.
  2. Effective return multiplier reaches the configured threshold.
  3. Only the highest-EV group is kept for the same match.
  4. Results are sorted by EV from high to low.

This means the output table has at most one recommended group per match, avoiding multiple conflicting suggestions under the same match.

At this point, the strategy has completed the calculation from real-time odds to candidate arbitrage combinations. The next article continues with the final step: what each result-table column means, how to convert amount ratio into real stake amount, and why the output still needs execution-layer confirmation.