From 1cc110d4685bb69cc79b3bba0bea42417890d46c Mon Sep 17 00:00:00 2001 From: Daan Koning Date: Mon, 21 Nov 2022 22:46:47 +0100 Subject: [PATCH] Initial --- .env | 1 + .gitignore | 3 +++ logic.py | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ main.py | 25 +++++++++++++++++++++ requirements.txt | 2 ++ 5 files changed, 89 insertions(+) create mode 100644 .env create mode 100644 .gitignore create mode 100644 logic.py create mode 100644 main.py create mode 100644 requirements.txt diff --git a/.env b/.env new file mode 100644 index 0000000..2387a6f --- /dev/null +++ b/.env @@ -0,0 +1 @@ +API_KEY= \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c01995a --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__pycache__ +venv +.idea diff --git a/logic.py b/logic.py new file mode 100644 index 0000000..f697187 --- /dev/null +++ b/logic.py @@ -0,0 +1,58 @@ +from typing import Iterable, Generator +import time +import requests + +BASE_URL = "https://api.the-odds-api.com/v4" + + +def get_sports(key: str) -> set[str]: + url = f"{BASE_URL}/sports/" + querystring = {"apiKey": key} + + response = requests.get(url, params=querystring) + return {item["group"] for item in response.json()} + + +def get_data(key: str, sport: str, region: str = "eu"): + url = f"{BASE_URL}/sports/{sport}/odds/" + querystring = { + "apiKey": key, + "regions": region, + "oddsFormat": "decimal", + "dateFormat": "unix" + } + + response = requests.get(url, params=querystring) + return response.json() + + +def process_data(matches: Iterable, include_started_matches: bool = True) -> Generator[dict, None, None]: + """Extracts all matches that are available and calculates some things about them, such as the time to start and + the best available implied odds.""" + for match in matches: + start_time = int(match["commence_time"]) + if not include_started_matches and start_time < time.time(): + continue + + best_odd_per_outcome = {} + for bookmaker in match["bookmakers"]: + bookie_name = bookmaker["title"] + for outcome in bookmaker["markets"][0]["outcomes"]: + outcome_name = outcome["name"] + odd = outcome["price"] + if outcome_name not in best_odd_per_outcome.keys() or \ + odd > best_odd_per_outcome[outcome_name][1]: + best_odd_per_outcome[outcome_name] = (bookie_name, odd) + + total_implied_odds = sum(1/i[1] for i in best_odd_per_outcome.values()) + match_name = f"{match['home_team']} v. {match['away_team']}" + time_to_start = (start_time - time.time())/3600 + league = match["sport_key"] + yield { + "match_name": match_name, + "match_start_time": start_time, + "time_to_start": time_to_start, + "league": league, + "best_outcome_odds": best_odd_per_outcome, + "total_implied_odds": total_implied_odds, + } \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..4677180 --- /dev/null +++ b/main.py @@ -0,0 +1,25 @@ +from logic import * +import os +from itertools import chain +from dotenv import load_dotenv +from rich import print + + +load_dotenv() + + +def main(): + key = os.environ.get("API_KEY") + + sports = get_sports(key) + data = chain.from_iterable(get_data(key, sport) for sport in sports) + data = filter(lambda x: x != "message", data) + results = process_data(data) + + arbitrage_opportunities = filter(lambda x: x["total_implied_odds"] < 1, results) + for i in arbitrage_opportunities: + print(i) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..da8de3b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +requests~=2.28.1 +python-dotenv~=0.21.0 \ No newline at end of file