Skip to main content
skill CX Codex

markets — Claude Code skill: ESPN schedules meet prediction markets

A skill that pairs ESPN schedules with Kalshi and Polymarket prediction markets: dashboards, odds comparison and bet evaluation.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add machina-sports/sports-skills --skill markets -a claude-code
Open on GitHub

What markets does

The markets skill pulls ESPN schedules for NBA, NFL, MLB, NHL, WNBA, CFB and CBB, then matches them against Kalshi and Polymarket prediction markets. Running get_todays_markets --sport=nba returns the day's games with DraftKings odds and the markets found for each one. Prices are normalised to implied probability, so venues sit on the same scale.

Under the hood it is a CLI (sports-skills) plus a Python SDK (sports_skills.markets). You get entity search, odds comparison for a single event, market URL parsing, price history, and bet evaluation that takes a fee per contract. The skill tells you to read references/api-reference.md first for sport codes, command parameters and price normalisation formats.

One caveat matters: raw market lists are search hits, not verified equivalents of a given game's contract. Only side_prices from compare_odds and evaluate_market are identity-checked. Arbitrage figures come from reference prices (price_basis: "reference"), so confirm both legs on each venue's order book before trading. Gemini comparison is NBA-only until settlement equivalence is verified for other sports.

What it helps with

  • line up ESPN schedules and prediction market odds in one view
  • compare prices for the same game across Kalshi and Polymarket
  • find a team or player on Kalshi and Polymarket by sport
  • check for arbitrage between ESPN odds and prediction markets
  • evaluate a game's market value with the venue fee included

Example prompts for the agent

  • show today's NBA prediction market odds next to the ESPN schedule
  • compare odds for the NBA game with event_id 401234567 across venues
  • search for the Lakers across NBA prediction markets

How to install markets

1Skills CLI (Vercel)

npx skills add machina-sports/sports-skills --skill markets -a claude-code

2Manually: put the files in place

~/.claude/skills/markets/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/markets/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about markets

How do I install markets in Claude?

Run npx skills add machina-sports/sports-skills --skill markets -a claude-code. The skill lands in ~/.claude/skills/markets/SKILL.md.

What does markets do?

It connects ESPN schedules with Kalshi and Polymarket prediction markets: unified dashboards, odds comparison, entity search and bet evaluation for a specific game.

How is markets different from the polymarket or kalshi skills?

markets adds ESPN context and orchestration across venues. If you want raw prediction market data without that, use polymarket or kalshi directly.

Source text

SKILL.md · MIT
---
name: markets
description: |
  Markets orchestration — connects ESPN live schedules with Kalshi and Polymarket prediction markets. Unified dashboards, odds comparison, entity search, and bet evaluation across platforms.

  Use when: user wants to see prediction market odds alongside ESPN game schedules, compare odds across platforms, search for a team/player on Kalshi or Polymarket, check for arbitrage between ESPN odds and prediction markets, or evaluate a specific game's market value.
  Don't use when: user wants raw prediction market data without ESPN context — use polymarket or kalshi directly. For pure odds math (conversion, de-vigging, Kelly) — use betting. For live scores without market data — use the sport-specific skill.
license: MIT
metadata:
  author: machina-sports
  version: "0.3.0"
---

# Markets Orchestration

Bridges ESPN live schedules (NBA, NFL, MLB, NHL, WNBA, CFB, CBB) with Kalshi and Polymarket prediction markets. Before writing queries, consult `references/api-reference.md` for supported sport codes, command parameters, and price normalization formats.

## Quick Start

```bash
sports-skills markets get_todays_markets --sport=nba
sports-skills markets search_entity --query="Lakers" --sport=nba
sports-skills markets compare_odds --sport=nba --event_id=401234567
sports-skills markets compare_market_url --url=https://polymarket.com/event/nfl-sf-sea-2026-10-11
sports-skills markets get_sport_markets --sport=nfl
sports-skills markets get_sport_schedule --sport=nba
sports-skills markets normalize_price --price=0.65 --source=polymarket
sports-skills markets evaluate_market --sport=nba --event_id=401234567 --fee_per_contract=<verified fee>
sports-skills markets match_markets --sport=mlb --date=2026-06-06
sports-skills markets get_market_price --venue=kalshi --ticker=KXMENWORLDCUP-26-FR
sports-skills markets get_price_history --venue=kalshi --ticker=KXMENWORLDCUP-26-FR --interval=1d
```

Python SDK:
```python
from sports_skills import markets

markets.get_todays_markets(sport="nba")
markets.search_entity(query="Lakers", sport="nba")
markets.compare_odds(sport="nba", event_id="401234567")
markets.compare_market_url(url="https://kalshi.com/markets/kxnflgame/sf-vs-sea/kxnflgame-26oct11sfsea")
markets.get_sport_markets(sport="nfl")
markets.get_sport_schedule(sport="nba", date="2025-02-26")
markets.normalize_price(price=0.65, source="polymarket")
markets.evaluate_market(sport="nba", event_id="401234567", fee_per_contract=fee)  # fee: verified (user-stated or documented venue fee)
markets.match_markets(sport="mlb", date="2026-06-06")
markets.get_market_price(venue="kalshi", ticker="KXMENWORLDCUP-26-FR", at_time="2026-05-01T12:00:00+00:00")
markets.get_price_history(venue="polymarket", token_id="<token_id>", interval="1h")
```

## CRITICAL: Before Any Query

CRITICAL: Before calling any orchestration command, verify:
- A `sport` code is provided for sport-aware commands (`get_todays_markets`, `compare_odds`, `get_sport_markets`, `evaluate_market`).
- Price sources are identified correctly before normalization: `espn` = American odds, `polymarket`/`novig`/`gemini` = 0-1 probability, `kalshi` = 0-100 integer.

## Important Notes

- **Sport context is passed through.** `--sport=nba` maps automatically to the correct Polymarket sport code and Kalshi series ticker.
- **Venues differ by command.** `get_todays_markets`, `search_entity` and `compare_odds` include Kalshi, Polymarket, ProphetX, Novig and Gemini where supported. Gemini discovery accepts no sport or `nba`, `wnba`, `nfl`, `cfb`, `mlb`, `nhl`, `epl`, `laliga`, `mls`, `ligamx`, `ufc`, `f1`, `golf`. The daily dashboard includes Gemini for supported ESPN scoreboard sports (`nba`, `wnba`, `nfl`, `cfb`, `mlb`, `nhl`). **Gemini comparison is NBA-only** until settlement equivalence is verified for other sports; those sports leave Gemini out of `sources`. Unsupported discovery sports skip Gemini without a request. `normalize_price` accepts `gemini` (0-1 probability). `get_sport_markets`, `match_markets` and `evaluate_market` use Kalshi and Polymarket only; `compare_market_url`, `get_market_price` and `get_price_history` do not support Gemini.
- **Sport-aware search.** Polymarket uses `sport` → series_id; Kalshi searches every series mapped for the sport (game winners, spreads, totals, futures).
- **Prices are normalized.** Everything is converted to implied probability for comparison.
- **Discovery is not verification.** Raw market lists (`*_markets`, `get_sport_markets`, `search_entity`) are search hits, not verified equivalents of a given game's contract. Only `compare_odds` `side_prices` (and `evaluate_market`) are identity-checked.

## Workflows

### Today's NBA Dashboard

```bash
sports-skills markets get_todays_markets --sport=nba
```
Returns each game with ESPN info, DraftKings odds, and matching Kalshi, Polymarket, ProphetX, Novig and Gemini (`gemini_markets`) markets. Gemini dashboard discovery covers NBA, WNBA, NFL, CFB, MLB and NHL; it does not verify that each search hit is the same contract.

### Find Arb on a Specific Game

1. Get the ESPN event ID: `get_sport_schedule --sport=nba`
2. Compare odds: `compare_odds --sport=nba --event_id=<id>`
3. If arbitrage detected, response includes allocation percentages and ROI — computed from **reference** prices (`price_basis: "reference"`), so confirm both legs on each venue's order book before trading it.
4. `sources` and `completeness` say which venues actually priced this game; a provider error is reported as `error`, not as "no markets".
5. For a direct price comparison read `side_prices.home` / `side_prices.away`: each lists `quotes` (`venue`, `implied_probability`, `price_basis: "reference"`, `execution_guaranteed: false`) admitted as this game's full-game moneyline, plus `lowest_reference` (`null` when a side has no quote; ties keep the first-listed venue). The lowest reference is not an executable quote, not fee-adjusted, and not a bet recommendation. Check `warnings` and `completeness.complete` before calling a comparison complete.
6. Venues searched: Kalshi, Polymarket, ProphetX and Novig. Novig counts only when the event date matches and a full-game `MONEY` market has a two-way order book. Its price is the derived ask (1 − best opposite bid), a cached snapshot. Catalog-only markets, spreads and period markets show up in `novig_markets` but never price a side. `search_entity` and `get_todays_markets` also include a `novig` section with the same results.
7. Gemini (nba only) counts only for exactly one active, full-contest moneyline (`moneyline`/`contest`/`full_contest`) of the same league whose `startTime` equals ESPN's start instant, with exactly two active, open, non-combo contracts whose sides agree with ESPN's teams and whose buy-YES prices are both in (0, 1). Its price is that buy-YES price from a cached public snapshot — a reference, not an executable quote, and volume says nothing about liquidity. Child markets (spreads, totals, props, periods), combos, three-way markets, closed/settled contracts, missing or malformed prices, other start times and duplicate candidates are refused with a reason in `sources.gemini.detail`; they still appear in `gemini_markets`. A Gemini failure is `error`; a partial scan (later page failed or scan truncated) is listed in `sources.gemini.warnings`.

### Compare a Pasted Market Link

#### compare_market_url

1. `compare_market_url --url=<link>`. Supported links: `https://polymarket.com/event/<event-slug>[/<market-slug>]` and `https://kalshi.com/markets/<series>/<slug>/<event-ticker>` (`www.` allowed), for single games of nfl, nba, mlb, nhl, wnba, cfb, cbb.
2. The link is never fetched. The host must match exactly. Credentials, ports, fragments, encoded or odd path segments, and unknown query keys are refused before any call (only `utm_*` and other click-tracking keys are ignored).
3. The venue API resolves exactly one **open** full-game two-way moneyline (Polymarket) or the two open game-winner contracts (Kalshi). Closed, non-moneyline, three-way or ambiguous sources are refused, and so is a provider answer that names another slug/ticker.
4. ESPN scoreboards for the source date ±1 day must yield exactly one game whose teams and date validate. Doubleheaders and multiple matches are refused, and a scoreboard failure is reported as a failure, not as "no game".
5. Returns the `compare_odds` payload unchanged (`side_prices`, `sources`, `warnings`, …) plus `source_market` (venue, canonical `url`, event/market ids, `espn_event_id`, `in_downstream_search`). When the source contract is missing from the comparison's venue search, a warning says so and no price is invented.
6. This matches the same game's moneyline only. It does not mean the venues settle identically, and it guarantees no execution. Novig, ProphetX and Gemini links are not accepted yet, though those venues still appear in the comparison where `compare_odds` searches them.

### Full Bet Evaluation

1. `evaluate_market --sport=nba --event_id=<id> --outcome=0 --fee_per_contract=<dollars per $1 contract>`
2. Verifies the market is this game's full-game winner market for the chosen side, then reads the **ask** off the order book
3. Pipes ask + fee through `betting.evaluate_bet`: devig → edge → Kelly
4. Returns fair probability, edge, EV, Kelly fraction, and recommendation

Without `fee_per_contract` the ask is reported but `evaluation` is `null` — the net numbers are refused rather than assumed free. A ticker or `token_id` that names another team, another date, or a derivative (first-half, spread) market is refused, not substituted. Pass the fee via the CLI (`--fee_per_contract=<dollars>`) or the Python wrapper. The fee must be an explicit, verified assumption: one the user stated, or the venue's officially documented fee schedule (say which). Never silently assume `0`. If no fee can be verified, `evaluation` stays `null`.

### Same Game on Both Venues

1. `match_markets --sport=mlb --date=2026-06-06`
2. Each match pairs the Kalshi event (with market tickers) and the Polymarket event (with moneyline token IDs) for the same game — joined deterministically on date + team codes, fuzzy title match as fallback.
3. Feed `kalshi.market_tickers[i]` and `polymarket.markets[i].token_ids[j]` straight into `get_market_price` to compare prices.

### Price Movement Over Time

1. `get_market_price --venue=kalshi --ticker=<ticker> --at_time=2026-05-01` for a single point-in-time price (both `yes`/`no` sides, 0-1).
2. `get_price_history --venue=kalshi --ticker=<ticker> --interval=1d` for the full series — same `{timestamp, price}` shape on either venue.

## Examples

Example 1: Today's games with prediction market odds
User says: "What NBA games are on today and what are the prediction market odds?"
Actions:
1. Call `get_todays_markets(sport="nba")`
Result: Unified dashboard with each game's ESPN info and Kalshi/Polymarket/ProphetX/Novig/Gemini markets

Example 2: Cross-platform team search
User says: "Find me Lakers markets on Kalshi and Polymarket"
Actions:
1. Call `search_entity(query="Lakers", sport="nba")`
Result: Lakers search hits from Kalshi, Polymarket, ProphetX, Novig and Gemini (discovery only — not verified as the same contract)

Example 3: Odds comparison for a specific game
User says: "Compare the odds for this Celtics game across ESPN and Polymarket"
Actions:
1. Get event_id from `get_sport_schedule(sport="nba")`
2. Call `compare_odds(sport="nba", event_id="<id>")`
Result: `side_prices` per side (admitted reference quotes + `lowest_reference`) and an arbitrage check on reference prices

Example 4: Full market evaluation
User says: "Is there edge on the Chiefs game?"
Actions:
1. Get event_id from `get_sport_schedule(sport="nfl")`
2. Establish a verified fee (user-stated or the venue's documented fee), then call `evaluate_market(sport="nfl", event_id="<id>", fee_per_contract=<verified fee>)`
Result: Fair probability, edge percentage, EV, Kelly fraction, and bet recommendation. Without a verified fee, the executable ask is reported and `evaluation` is `null`.

Example 5: Browse all markets for a sport
User says: "Show me all NFL prediction markets"
Actions:
1. Call `get_sport_markets(sport="nfl")`
Result: All open NFL markets across Kalshi and Polymarket

Example 6: Price conversion
User says: "Convert a Polymarket price of 65 cents to American odds"
Actions:
1. Call `normalize_price(price=0.65, source="polymarket")`
Result: Common structure with implied probability (0.65), American odds (-185.7), and decimal (1.54)

Example 7: Pair a game across venues
User says: "Find the Mets game on both Kalshi and Polymarket"
Actions:
1. Call `match_markets(sport="mlb", date="<game date>")`
Result: The game paired across venues — Kalshi market tickers and Polymarket moneyline token IDs side by side

Example 8: Historical price
User says: "What was France's World Cup price a month ago?"
Actions:
1. Call `get_market_price(venue="kalshi", ticker="KXMENWORLDCUP-26-FR", at_time="2026-05-03T12:00:00+00:00")`
Result: Yes/no prices (0-1) as of that moment; use `get_price_history` for the full curve

## Commands that DO NOT exist — never call these

- ~~`get_odds`~~ — does not exist. Use `compare_odds` to see odds across sources.
- ~~`search_markets`~~ — does not exist on the markets module. Use `search_entity` instead.
- ~~`get_schedule`~~ — does not exist. Use `get_sport_schedule` instead.

If a command is not listed in `references/api-reference.md` or in this file's workflows (e.g. `compare_market_url`), it does not exist.

## Troubleshooting

Error: No markets returned for a sport
Cause: Sport code may be missing or incorrect
Solution: Check `references/api-reference.md` for valid sport codes. Use the exact code (e.g., `nba`, `epl`, `laliga`)

Error: `compare_odds` returns no data for an event
Cause: The event_id is incorrect or the game has not been indexed yet
Solution: Call `get_sport_schedule(sport=...)` to retrieve the correct event_id first

Error: One source shows warnings in the response
Cause: Kalshi or Polymarket is temporarily unavailable
Solution: The module returns partial results — use what is available. Retry the unavailable source separately using the kalshi or polymarket skill directly

Error: `normalize_price` returns unexpected American odds value
Cause: Wrong `source` parameter — Kalshi uses 0-100 integers, Polymarket uses 0-1 decimals
Solution: Verify the source. Kalshi price of 65 requires `source="kalshi"`, Polymarket price of 0.65 requires `source="polymarket"`

© machina-sports · MIT · machina-sports/sports-skills

Similar skills

All skills for Agent setup: memory, context, orchestration →

From the same set22

polymarket Pulls live Polymarket sports markets: prices, implied probabilities, order books and events. Useful when you need to know who the market favors. CX Codex +1 1,300installs sports-news Pulls fresh sports headlines from RSS feeds and Google News, searches by query and filters by date. Handy for transfer rumours or match reports. CX Codex +1 1,200installs kalshi This skill gives your agent Kalshi prediction market data: events, series, contracts, trades and candlesticks on sports outcomes. Useful when you want implied probabilities, not match results. CX Codex +1 1,000installs nba-data Skill for querying NBA scores, team rosters, and shot coordinates via CLI without API keys. Useful for analyzing live game summaries, injuries, and historical league stats back to 1946. CX Codex +1 989installs nfl-data The skill gives your agent NFL schedules, rosters, stats and play-by-play through ESPN public endpoints and an nflverse backend. No API keys. CX Codex +1 752installs mlb-data Connects your coding agent to live and historical MLB data from ESPN and the official MLB API. Useful for pulling scores, rosters, injuries, and pitch analytics without API keys. CX Codex +1 737installs tennis-data A skill that lets your coding agent pull ATP and WTA tournament scores, rankings, the season calendar, player profiles and news from ESPN public endpoints. CX Codex +1 719installs cfb-data This skill feeds your agent college football data: scores, standings, rankings, rosters, injuries and player stats. No API keys needed. CX Codex +1 690installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor