Disclosure: I run the Live Tennis API — judge this on the merits. No affiliation with PolyClaw; this is a data-source suggestion, not a request.
Where this fits in PolyClaw today
PolyClaw's whole loop is driven off market price and market question text:
- Browse —
scripts/markets.py → GammaClient.get_trending_markets / search_markets returns each Market with yes_price, no_price, and volume.
- Positions —
scripts/positions.py tracks entry price vs current price for P&L. It knows the price moved; it doesn't know why.
- Hedge —
scripts/hedge.py runs IMPLICATION_PROMPT over the trending set and derives covering portfolios from logically-necessary implications (the contrapositive/direct covers in derive_covers_from_implications), tiered by coverage.
For tennis event markets (match-winner, set-winner, "reach N games", etc.) there's a signal PolyClaw currently has no input for: the live state of the underlying match. A market can move — or become resolvable — because a break point was converted, a set closed, or a player retired, well before that's fully reflected in price. Right now the agent can only infer that indirectly from no_price/yes_price.
The suggestion — a read-only enrichment, not an execution path
Add an optional live-match-state lookup for tennis markets. It is strictly a data feed: it does not browse, price, sign, or execute anything. PolyClaw keeps its exact Gamma + CLOB split/execute path untouched. The feed only answers "what is the underlying match doing right now" for a market you already found:
- score — sets / games / points / who is serving
- break-point flag — three-valued:
TRUE / FALSE / UNDEF (receiver at AD or 40 vs server on 0/15/30; never flagged inside a tiebreak; UNDEF when points are null)
- terminal status —
completed / retirement / walkover — the states that determine how a tennis market resolves
Concretely, this slots in two natural places:
- Position tracking — alongside price-based P&L in
scripts/positions.py, surface the live match state for a tennis position, so a retirement/walkover/completed terminal flag is visible next to the number rather than inferred from a price jump.
- Hedge context — the
hedge scan covers between, say, a match-winner market and a set-winner market are logically related; live score/terminal-state is the ground truth that tells you whether that logical cover is still live.
Player-name matching keys off the market question (same text markets.py already carries), so it stays a thin, side-car lookup.
What it is
- Free tier (live scores + match-state + players with ranking/Elo + fixtures), 30/min · 100/day, no card: https://livetennisapi.com/subscribe/free
- Base
https://api.livetennisapi.com/api/public/v1, X-API-Key header, {data:[...]} — players.p1.name/p2.name, status, a score object (sets/games/points/server), id.
- Coverage runs ATP/WTA/Challenger/ITF/juniors — strongest on deep draws where generic feeds thin out, which is where in-play tennis markets are least efficient.
- MIT observe-only reference toolkit (no keys, no trading): https://github.com/livetennisapi/polymarket-tennis
- Also on the official MCP Registry as
io.github.livetennisapi/livetennisapi-mcp if you'd rather wire it as an MCP tool than a subprocess.
If this is interesting I'm happy to open a small PR adding an optional tennis-state lookup that reads a market's question and returns the state block — behind its own flag, no change to the split/CLOB path, no new required env var. Equally fine if it's out of scope; wanted to offer the feed since the browse→positions→hedge loop is otherwise blind to what the actual match is doing.
Disclosure: I run the Live Tennis API — judge this on the merits. No affiliation with PolyClaw; this is a data-source suggestion, not a request.
Where this fits in PolyClaw today
PolyClaw's whole loop is driven off market price and market question text:
scripts/markets.py→GammaClient.get_trending_markets/search_marketsreturns eachMarketwithyes_price,no_price, and volume.scripts/positions.pytracks entry price vs current price for P&L. It knows the price moved; it doesn't know why.scripts/hedge.pyrunsIMPLICATION_PROMPTover the trending set and derives covering portfolios from logically-necessary implications (the contrapositive/direct covers inderive_covers_from_implications), tiered by coverage.For tennis event markets (match-winner, set-winner, "reach N games", etc.) there's a signal PolyClaw currently has no input for: the live state of the underlying match. A market can move — or become resolvable — because a break point was converted, a set closed, or a player retired, well before that's fully reflected in price. Right now the agent can only infer that indirectly from
no_price/yes_price.The suggestion — a read-only enrichment, not an execution path
Add an optional live-match-state lookup for tennis markets. It is strictly a data feed: it does not browse, price, sign, or execute anything. PolyClaw keeps its exact Gamma + CLOB split/execute path untouched. The feed only answers "what is the underlying match doing right now" for a market you already found:
TRUE/FALSE/UNDEF(receiver at AD or 40 vs server on 0/15/30; never flagged inside a tiebreak;UNDEFwhen points are null)completed/retirement/walkover— the states that determine how a tennis market resolvesConcretely, this slots in two natural places:
scripts/positions.py, surface the live match state for a tennis position, so aretirement/walkover/completedterminal flag is visible next to the number rather than inferred from a price jump.hedge scancovers between, say, a match-winner market and a set-winner market are logically related; live score/terminal-state is the ground truth that tells you whether that logical cover is still live.Player-name matching keys off the market question (same text
markets.pyalready carries), so it stays a thin, side-car lookup.What it is
https://api.livetennisapi.com/api/public/v1,X-API-Keyheader,{data:[...]}—players.p1.name/p2.name,status, ascoreobject (sets/games/points/server),id.io.github.livetennisapi/livetennisapi-mcpif you'd rather wire it as an MCP tool than a subprocess.If this is interesting I'm happy to open a small PR adding an optional
tennis-statelookup that reads a market's question and returns the state block — behind its own flag, no change to the split/CLOB path, no new required env var. Equally fine if it's out of scope; wanted to offer the feed since the browse→positions→hedge loop is otherwise blind to what the actual match is doing.