OddsEdge / Documentation

Developer Docs

OddsEdge is a professional-grade sharp money detection system that monitors soccer betting markets in real-time. By utilizing multiple data sources, algorithmic steam detection, and cryptographic Merkle proof validation, it isolates high-confidence market anomalies and performs transparent paper-trading simulations.

⚡
How It Works

1. Steam Detection

Steam detection identifies rapid and persistent shifts in implied probability across the consensus feed. When the de-vigged implied probability of a specific outcome changes by >= 5.0% over a minimum of 3 consecutive ticks (persistence streak) in the same direction, a steam signal is generated. This isolates sharp, high-volume betting activity that causes market-wide price drops.

2. Tri-Source Divergence

Tri-Source Divergence identifies structural differences between distinct market types (Consensus, Professional Bookmaker, and Prediction Exchange). By comparing probabilities from TxLINE, Pinnacle, and Polymarket, the system calculates absolute divergence. If any source deviates by >= 5.0% from the other two, the outlier is flagged, signaling a localized price lag or exchange anomaly.

3. On-Chain Verification

To guarantee the authenticity and timing of our signals, each update can be validated against the TxLINE Cryptographic Validation API. The system resolves the specific update transaction, retrieves its Merkle path, and verifies the proof cryptographically. This prevents retrospective data manipulation and proves that our detection happened in real-time.

●
Data Sources

OddsEdge aggregates and normalizes three primary feeds to detect anomalies:

  • TxLINE StablePrice: Our primary consensus source. Prices are consumed via a real-time Server-Sent Events (SSE) stream and converted to implied probabilities: Implied Prob = (1 / (price / 1000)) * 100.
  • Pinnacle: Fetched via the OddsPapi client. Pinnacle odds represent the professional market maker standard. Raw odds are de-vigged by removing the overround to calculate fair probabilities.
  • Polymarket: Fetched via the OddsPapi client. Since Polymarket is an exchange-based prediction market, the orderbook back prices (cents) represent the market's implied probability directly (e.g., 52 cents = 52.0% probability). No de-vig is applied.
■
Confidence Scoring

Each signal is evaluated using a weighted multi-factor scoring formula to determine its confidence rating (0.0 to 1.0):

Confidence = (Magnitude * 0.35) + (Persistence * 0.25) + (Source Agreement * 0.25) + (Timing * 0.15)

The component metrics are defined as follows:

  • Magnitude Score (Weight: 0.35): Evaluates the size of the probability movement. It is calculated as min(abs(movement_pct) / 15.0, 1.0), reaching a maximum score at a 15% probability shift.
  • Persistence Score (Weight: 0.25): Measures the duration of the movement. It is calculated as min(streak_ticks / 10.0, 1.0), reaching a maximum score at 10 consecutive ticks.
  • Source Agreement (Weight: 0.25): Measures the agreement between the three key feeds. Pure steam signals have a default score of 1.0. Tri-source signals score based on feed agreement (e.g. 2 out of 3 agreeing sources = 2/3).
  • Timing Score (Weight: 0.15): Incentivizes early signals. It assigns 1.0 for pre-match signals, 0.6 for in-play signals under the 60th minute, and 0.3 for late in-play signals (60th minute onwards).
▲
Paper Trading Methodology

To validate signal profitability, the system runs a flat-stake paper-trading simulation:

  • Flat Staking: Every generated signal triggers a simulated bet of $100.00.
  • Odds Taken: The price taken is the decimal odds at the exact millisecond the signal is registered.
  • Auto-Settlement: An autonomous loop polls the TxLINE historical score feed post-match. Once the game finalization flag is observed, outcomes are scored as CORRECT or INCORRECT.
  • P&L Calculation: Wins are settled at stake * (odds_taken - 1.0), while losses deduct the -stake ($100.00).
★
Technology Stack

OddsEdge is engineered with a modular, lightweight stack:

  • Python Agent: A persistent background agent orchestrating the real-time SSE stream listener, stateful steam detector, pre-kickoff tri-source divergence scanner, and the auto-settlement results thread.
  • SQLite Database: Persistent relational store operating in Write-Ahead Log (WAL) mode to permit concurrent reads and writes between the agent and Flask API.
  • Flask Backend API: Exposes clean, cached REST endpoints serving active fixtures, signals, equity curves, stats, and on-demand commentary.
  • Vanilla Frontend: A high-performance, single-page dashboard featuring responsive grid systems, responsive mobile cards, and backdrop blur.
  • Chart.js: Powers the dynamic P&L equity curve timeline.
  • Gemini 1.5 Flash: Generates contextual, on-demand AI explanations for signal occurrences.
  • TxLINE Merkle Proofs: Validates event data integrity via the TxLINE validation system.
⚙
API Reference

This section documents all HTTP endpoints used by OddsEdge — both the internal Flask REST API consumed by the frontend, and the external TxLINE API called by the Python agent for live market data and cryptographic validation.

● Internal — Flask REST API  ·  Base: http://localhost:5000
Source Endpoint Purpose
Flask API GET/api/signals Returns all detected signals, newest first. Supports ?limit= and ?offset= pagination. Default: limit=100, offset=0.
Flask API GET/api/signals/live Returns signals that belong to fixtures currently marked as LIVE (in-play), ordered by detection time descending.
Flask API GET/api/signals/<fixture_id> Returns all signals for a single fixture, identified by fixture_id, ordered newest first.
Flask API GET/api/pnl Returns the cumulative P&L time series for the equity curve chart. Each row contains settled_at and cumulative_pnl fields, ordered chronologically.
Flask API GET/api/stats Returns aggregate accuracy statistics: total signal count, overall accuracy %, high-confidence accuracy (≥ 0.7), STEAM accuracy, TRI_SOURCE accuracy, and total paper P&L.
Flask API GET/api/fixtures Returns all tracked fixtures and their current lifecycle status: UPCOMING, LIVE, or FINISHED, ordered by start time ascending.
Flask API GET/api/usage Returns the OddsPapi API budget status: calls_used, total_budget, and calls_remaining to track rate-limit consumption.
Flask API POST/api/signals/<signal_id>/commentary Generates (or returns cached) Gemini AI commentary for a specific signal. Returns commentary, signal_id, and a cached boolean flag. Returns 503 if GEMINI_API_KEY is not configured.
Flask API GET/api/signals/<signal_id>/merkle Fetches the cryptographic Merkle proof from the TxLINE Validation API for a given signal. Resolves the MessageId and timestamp, then returns the verified proof confirming real-time data integrity.
● External — TxLINE API  ·  Base: https://txline.txodds.com
Source Endpoint Purpose
TxLINE GET/api/fixtures/snapshot Fetches the fixture list for a given epoch day via ?startEpochDay=N. Returns an array of Fixture objects used to seed and track upcoming World Cup matches.
TxLINE GET/api/odds/snapshot/{fixtureId} Fetches the latest odds snapshot for a single fixture. Returns an array of OddsPayload objects used to bootstrap the steam detector's initial state before the live stream connects.
TxLINE SSE/api/odds/stream Real-time Server-Sent Events stream of live odds updates. Accepts an optional ?fixtureId= filter. The core feed driving steam detection — reconnects automatically with Last-Event-ID on disconnect.
TxLINE GET/api/odds/updates/{epochDay}/{hour}/{interval} Fetches historical odds updates for a specific 5-minute interval bucket. Used during Merkle proof resolution to find the MessageId and Ts closest to a signal's detection timestamp. Accepts optional ?fixtureId= filter.
TxLINE GET/api/odds/validation Fetches the cryptographic Merkle proof for a specific odds update. Requires ?messageId= and ?ts= query params. Returns the proof object that confirms the odds data existed on-chain at the exact timestamp of detection.
TxLINE GET/api/scores/snapshot/{fixtureId} Fetches the latest score per action for a live fixture. Returns an array of Scores objects used by the results thread to check match progress and finalization status.
TxLINE GET/api/scores/historical/{fixtureId} Fetches the full post-match score history for a finished fixture (available 2h–2 weeks after match end). Returns SSE-formatted data: lines parsed into score update objects, used by the auto-settlement loop to determine final outcomes.
TxLINE SSE/api/scores/stream Real-time Server-Sent Events stream of live score updates. Used to monitor in-play match state — minute, goals, and game finalization flag — to trigger paper trade settlement at the final whistle.