Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 1.2.1 (2026-11-06)

### Fixed
- Docs: `expectedValue` on value bets is bookmaker odds / fair odds x 100, not a fraction. 103.42 is a 3.42% edge (edge % = `expectedValue - 100`). The `ValueBet` docstring, `get_value_bets` docstrings, README and `examples/value_bets.py` now say so; the example prints and filters on `expectedValue - 100`.

## 1.2.0 (2026-11-06)

Brings the SDK up to the full Odds-API.io v3 API.
Expand Down
2 changes: 1 addition & 1 deletion CITATION.cff
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cff-version: 1.2.0
cff-version: 1.2.1
message: "If you use this software, please cite it using the metadata from this file."
type: software
title: "odds-api-io: Official Python SDK for Odds-API.io"
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,10 @@ arbs = client.get_arbitrage_bets(
["Bet365", "SingBet"], sport="football", markets=["ML", "Totals"], min_profit=1.0,
include_event_details=True,
)
# profitMargin is already a percentage (2.48 means 2.48%)
value = client.get_value_bets("Bet365", sport="baseball", league="usa-mlb")
# expectedValue is bookmaker odds / fair odds x 100, so 103.42 is a 3.42% edge
edges = [b for b in value if b["expectedValue"] - 100 >= 3]
drops = client.get_dropping_odds(sport="football", markets=["Spread"], time_window="24h", min_drop=10)
```

Expand Down Expand Up @@ -276,5 +279,5 @@ MIT. See [LICENSE](LICENSE).
If you use this package in research or a publication, please cite it. Citation metadata is in [CITATION.cff](CITATION.cff) (GitHub renders a "Cite this repository" button from it) and Zenodo metadata is in `.zenodo.json`.

```
Outlier AS. odds-api-io: Official Python SDK for Odds-API.io (version 1.2.0). https://github.com/odds-api-io/odds-api-python
Outlier AS. odds-api-io: Official Python SDK for Odds-API.io (version 1.2.1). https://github.com/odds-api-io/odds-api-python
```
7 changes: 5 additions & 2 deletions examples/value_bets.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""
Find prices above a fair-odds estimate at one bookmaker.

expectedValue is a fraction: 0.0523 means +5.23% expected value at that price.
expectedValue is bookmaker odds / fair odds x 100: 103.42 means a 3.42% edge at that price.
The edge in percent is expectedValue - 100; values below 100 are a negative edge.
"""

import os
Expand All @@ -10,12 +11,14 @@

# Get an API key at https://odds-api.io/pricing
API_KEY = os.getenv("ODDS_API_KEY", "your_api_key_here")
MIN_EDGE_PERCENT = 2


def main():
with OddsAPIClient(api_key=API_KEY) as client:
bets = client.get_value_bets("Bet365", sport="football", include_event_details=True)
bets = sorted(bets, key=lambda b: b["expectedValue"], reverse=True)
bets = [b for b in bets if b["expectedValue"] - 100 >= MIN_EDGE_PERCENT]
if not bets:
print("No value bets at the moment.")
return
Expand All @@ -28,7 +31,7 @@ def main():
print(f"{event.get('home')} vs {event.get('away')} ({event.get('date')})")
print(
f" {market['name']}{line} {bet['betSide']} @ {price}: "
f"EV {bet['expectedValue'] * 100:+.2f}%"
f"edge {bet['expectedValue'] - 100:+.2f}%"
)


Expand Down
2 changes: 1 addition & 1 deletion odds_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Official Python client for the Odds-API.io sports betting odds API.
"""

__version__ = "1.2.0"
__version__ = "1.2.1"

from .client import OddsAPIClient
from .async_client import AsyncOddsAPIClient
Expand Down
3 changes: 3 additions & 0 deletions odds_api/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,9 @@ async def get_value_bets(
"""
Get prices above a fair-odds estimate at one bookmaker.

``expectedValue`` in each result is bookmaker odds / fair odds x 100, so
103.42 is a 3.42% edge. Edge in percent = ``expectedValue - 100``.

Args:
bookmaker: Bookmaker name
include_event_details: Include teams, date, sport and league
Expand Down
3 changes: 3 additions & 0 deletions odds_api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,9 @@ def get_value_bets(
"""
Get prices above a fair-odds estimate at one bookmaker.

``expectedValue`` in each result is bookmaker odds / fair odds x 100, so
103.42 is a 3.42% edge. Edge in percent = ``expectedValue - 100``.

Args:
bookmaker: Bookmaker name
include_event_details: Include teams, date, sport and league
Expand Down
6 changes: 6 additions & 0 deletions odds_api/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,12 @@ class OddsSummary(TypedDict, total=False):


class ValueBet(TypedDict, total=False):
"""A price above the fair-odds estimate.

``expectedValue`` is bookmaker odds / fair odds x 100: 100 is fair, 103.42 is a
3.42% edge (edge % = ``expectedValue - 100``), below 100 is a negative edge.
"""

id: str
eventId: int
bookmaker: str
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "odds-api-io"
version = "1.2.0"
version = "1.2.1"
description = "Official Python SDK for Odds-API.io, the sports betting odds API: live and pre-match odds from 450+ bookmakers across 34 sports, player props, golf outrights, closing lines, settlement, arbitrage, value bets and WebSocket"
readme = "README.md"
requires-python = ">=3.8"
Expand Down
Loading