> ## Documentation Index
> Fetch the complete documentation index at: https://oddsstream.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# EV Math & Quality Filters

> How implied probability, devigging, fair odds, EV%, and payout_rate are calculated — and why each filter exists.

## Overview

Every value bet in `/api/value-bets` passes through 5 mathematical layers before reaching you. This page explains each one in plain language, with formulas and worked examples.

The fields returned by the API map directly to these layers:

| API field       | What it represents                                               |
| --------------- | ---------------------------------------------------------------- |
| `pinnacle_odds` | Raw Pinnacle quoted price                                        |
| `fair_odds`     | Pinnacle devigged (margin removed)                               |
| `ev_pct`        | Edge over fair value (`bookmaker_odds / fair_odds - 1`)          |
| `payout_rate`   | Display quality gate (raw opposite Pinnacle odds substituted in) |

***

## Step 1 — Implied probability

Every decimal odds price implies a win probability:

```
implied_probability = 1 / decimal_odds
```

Examples:

* `2.00` → `1 / 2.00 = 0.500` (50%)
* `3.50` → `1 / 3.50 = 0.286` (28.6%)
* `1.70` → `1 / 1.70 = 0.588` (58.8%)

If you sum implied probabilities across all outcomes in a market, the total is always **above 100%** — the excess is the bookmaker's margin.

***

## Step 2 — Raw Pinnacle TRJ (devig input only)

For a market with N outcomes, **Raw TRJ** is the sum of all implied probabilities:

```
Raw TRJ = Σ (1 / pinnacle_odds_i)

# 2-way example: spread or total
TRJ = 1/2.05 + 1/1.88 = 0.488 + 0.532 = 1.020  → 2.0% margin

# 3-way example: football moneyline
TRJ = 1/2.05 + 1/3.40 + 1/3.50 = 0.488 + 0.294 + 0.286 = 1.068  → 6.8% margin
```

Pinnacle's natural TRJ ranges:

* **2-way markets** (spread, total, tennis): \~1.02–1.05
* **3-way markets** (football 1X2): \~1.05–1.10

<Note>
  Raw TRJ is a **devig input** — it feeds into the fair-odds formula below. It is not the quality gate shown as `payout_rate` in the API. See Step 5 for the distinction.
</Note>

***

## Step 3 — Fair odds (devigging)

Devigging removes Pinnacle's margin to produce the **true consensus probability** for each outcome.

**Formula for 2-way markets** (spread, total, tennis moneyline, BTTS):

```
fair_odds = (2 × pinnacle_odds) / (2 − pinnacle_odds × (1/TRJ − 1))
```

**Formula for 3-way markets** (football moneyline, European handicap):

```
fair_odds = (3 × pinnacle_odds) / (3 − pinnacle_odds × (1/TRJ − 1))
```

### Worked example — 2-way total

```
Pinnacle: Over 2.5 @ 1.92 | Under 2.5 @ 1.98

TRJ = 1/1.92 + 1/1.98 = 0.521 + 0.505 = 1.026

fair_odds(Over) = (2 × 1.92) / (2 − 1.92 × (1/1.026 − 1))
               = 3.84 / (2 − 1.92 × 0.0253)
               = 3.84 / 1.9514
               = 1.967   ← true market price for Over 2.5
```

### Worked example — 3-way football

```
Pinnacle: Home 2.05 | Draw 3.40 | Away 3.50

TRJ = 1/2.05 + 1/3.40 + 1/3.50 = 0.488 + 0.294 + 0.286 = 1.068

fair_odds(Home) = (3 × 2.05) / (3 − 2.05 × (1/1.068 − 1))
               = 6.15 / (3 − 2.05 × (−0.0637))
               = 6.15 / 3.131
               = 1.964
```

The fair odds represent the bet's **true consensus price** — what Pinnacle would offer if they had zero margin.

***

## Step 4 — Fair odds floor (safety buffer)

Before EV is computed, a small safety buffer is applied to the fair odds to prevent noise:

```
fair_odds_final = fair_odds × 1.01           # all markets (+1% buffer)
fair_odds_final = fair_odds × 1.01 × 1.03   # player props (+4.04% total)
```

**Why this exists:** Tiny Pinnacle pricing fluctuations can create apparent EV at the margin. The floor ensures only bets with a genuine edge clear the minimum.

**Effect:** For standard markets (spread, total, moneyline), a bookmaker needs roughly **+2% raw edge** over devigged Pinnacle to show `ev_pct ≥ 1%`. For player props, it's roughly **+5% raw edge**. This explains why many bets that look close don't appear in the feed.

***

## Step 5 — EV% calculation

Once fair odds are established (with floor applied):

```
EV% = (bookmaker_odds / fair_odds_final − 1) × 100
```

### Worked example

```
Pinnacle: PSG @ 1.90 (fair odds after devig + floor = 1.929)
Betsson offers PSG @ 2.05

EV% = (2.05 / 1.929 − 1) × 100 = +6.27%
```

**What `ev_pct` means in plain English:**

> A `+5.0%` EV bet means that if you placed this exact bet repeatedly under the same conditions, you'd expect to profit an average of **$5 per $100 wagered** over the long run.

Short-term variance is high — a single bet can win or lose. EV only plays out over large sample sizes. The edge comes from the bookmaker mispricing one outcome relative to Pinnacle's efficient market.

***

## Step 6 — Payout rate (quality gate)

`payout_rate` in the API response is **not** the raw Pinnacle TRJ. It is a distinct quality metric: the TRJ of the market with the bookmaker's odds substituted in **for its own Pinnacle side**, keeping raw Pinnacle odds for all other sides.

```
# 2-way market (spread, total, tennis ML)
payout_rate = 1 / (1/bookmaker_odds + 1/pinnacle_opposite_raw)

# 3-way market (football ML on one side)
payout_rate = 1 / (1/bookmaker_odds + 1/pinnacle_draw_raw + 1/pinnacle_opposite_raw)
```

This measures whether the bookmaker is pricing its side generously relative to Pinnacle's raw pricing on every other side. A value bet should produce a market with **total payout close to 100%** when you combine the bookmaker price with Pinnacle's opposing prices.

### Worked example — 2-way

```
Bookmaker: Over 2.5 @ 2.10
Pinnacle:  Under 2.5 @ 1.88 (raw, not devigged)

payout_rate = 1 / (1/2.10 + 1/1.88)
            = 1 / (0.476 + 0.532)
            = 1 / 1.008
            = 0.992  → 99.2%   ✓ passes quality gate
```

### Worked example — 3-way (fails)

```
Bookmaker: Home @ 2.40
Pinnacle raw: Draw @ 3.40, Away @ 2.90

payout_rate = 1 / (1/2.40 + 1/3.40 + 1/2.90)
            = 1 / (0.417 + 0.294 + 0.345)
            = 1 / 1.056
            = 0.947  → 94.7%   ✗ below 99% floor → rejected
```

In the second case, even though the bookmaker offers Home at 2.40 vs Pinnacle's fair \~2.30, the raw Pinnacle opposing prices are so favorable that the combined market payout is only 94.7%. This indicates the bookmaker's price isn't genuinely better than the Pinnacle market when raw opposing odds are considered.

***

## Quality filters applied before the API responds

All results from `/api/value-bets` have already passed every filter. Nothing is returned that fails any gate:

| Filter                      | Threshold            | Why                                                                                    |
| --------------------------- | -------------------- | -------------------------------------------------------------------------------------- |
| `EV ≥ 1%`                   | Minimum edge         | Noise below this — line movement can eliminate sub-1% edges before placement           |
| `EV ≤ 20%`                  | Maximum edge         | Above this = almost certainly stale or miscoded odds, not real                         |
| `EV ≤ 10%` (ML / spread)    | Efficient market cap | Moneylines and spreads in efficient markets don't produce 10%+ edges legitimately      |
| Raw Pinnacle TRJ `≤ 1.05`   | Structural sanity    | Above 1.05 = duplicate sides or arbitrage data — structurally invalid, not a value bet |
| `payout_rate ∈ [99%, 105%]` | Quality gate         | Below 99% = edge is noise; above 105% = fair odds calculation error                    |
| Odds freshness `≤ 15 min`   | Staleness guard      | Rejects outdated bookmaker prices                                                      |
| Both Pinnacle sides present | Devig requirement    | Single-side devig produces absurd fair odds — skip                                     |
| Odds ratio `≤ 1.15×`        | Sanity check         | `bookmaker_odds / fair_odds > 1.15` = likely data mismatch                             |

***

## Why bets with "3% EV" sometimes don't appear

The fair odds floor (+1% for all markets, +4% for props) means:

* A bookmaker offering 3% raw edge over raw devigged Pinnacle on a **moneyline** needs \~2% net after the floor → passes `EV_MIN=1%`
* A bookmaker offering 3% raw edge on a **player prop** needs \~5% net after the prop floor → does **not** pass `EV_MIN=1%`

Additionally, `payout_rate < 99%` can reject a bet even when EV% is positive — this happens when the bookmaker's "edge" disappears once you price it against raw (non-devigged) opposing Pinnacle odds.

***

## Formula reference

| Formula             | Expression                                     |
| ------------------- | ---------------------------------------------- |
| Implied probability | `1 / decimal_odds`                             |
| Raw Pinnacle TRJ    | `Σ (1 / pinnacle_odds_i)`                      |
| Fair odds (2-way)   | `(2 × pin) / (2 − pin × (1/TRJ − 1))`          |
| Fair odds (3-way)   | `(3 × pin) / (3 − pin × (1/TRJ − 1))`          |
| Fair odds floor     | `× 1.01` all markets; `× 1.01 × 1.03` props    |
| EV%                 | `(bookmaker_odds / fair_odds_final − 1) × 100` |
| Payout rate (2-way) | `1 / (1/book + 1/pin_opposite)`                |
| Payout rate (3-way) | `1 / (1/book + Σ 1/pin_others)`                |

<CardGroup cols={2}>
  <Card title="Value Bets Reference" icon="chart-line" href="/api-reference/value-bets">
    Full endpoint docs with all response fields.
  </Card>

  <Card title="Best Practices" icon="shield-check" href="/guides/best-practices">
    Polling, freshness checks, and production patterns.
  </Card>
</CardGroup>
