CLV & backtesting

Closing line odds data

The closing line is the most efficient price a market produces. PinnFeed records the last prematch price of every Pinnacle market at kickoff and serves it by event or by day.

01CLV & backtesting

Captured at kickoff

When an event goes live (or its start time passes) we snapshot every open market — moneyline, spreads, totals, team totals and periods — including margin, max stake and fair prices.

02CLV & backtesting

Query by event or day

GET /v1/closing/{eventId} returns all closing markets for an event; GET /v1/closing?date=YYYY-MM-DD&sport=soccer pages through a whole day.

03CLV & backtesting

Measure closing-line value

Compare the price you bet with the fair closing price. Consistently beating the close is the strongest evidence that a betting model has an edge.

04CLV & backtesting

Bulk exports

Enterprise plans include CSV/Parquet exports of the whole archive for research and model training.

# pip install websockets
import asyncio, json, os, websockets

async def main():
    url = "wss://pinnfeed.io/v1/stream"
    async with websockets.connect(url, additional_headers={"x-api-key": os.environ["PINNSOCKET_KEY"]}) as ws:
        await ws.send(json.dumps({"type": "subscribe", "sports": ["soccer"], "live": True}))
        async for raw in ws:
            msg = json.loads(raw)
            if msg["type"] == "ping": await ws.send('{"type":"pong"}')
            elif msg["type"] == "delta":
                for c in msg["changes"]:
                    if c["kind"] == "market" and c["op"] == "upsert":
                        m = c["market"]; print(m["key"], [(o["name"], o["decimal"], o["fair"]) for o in m["outcomes"]])

asyncio.run(main())
{
  "type": "delta", "seq": 48213, "ts": 1762679412093,
  "changes": [{
    "kind": "market", "op": "upsert",
    "market": {
      "id": "1640278226:s;0;m", "eventId": 1640278226,
      "type": "moneyline", "period": 0, "main": true, "live": true,
      "margin": 0.0357, "maxStake": 1500,
      "outcomes": [
        { "name": "home", "american": -128, "decimal": 1.781, "fair": 1.845, "fairProb": 0.5421 },
        { "name": "draw", "american": 262,  "decimal": 3.62,  "fair": 3.750, "fairProb": 0.2667 },
        { "name": "away", "american": 405,  "decimal": 5.05,  "fair": 5.230, "fairProb": 0.1912 }
      ]
    }
  }]
}
FAQ

Closing line odds data: common questions

How far back does the archive go?

The archive starts on the day the service launched and grows every day.

Is closing data available on the Free plan?

No. Closing-line history is included from the Builder plan.

Try it free today.

Delayed REST data free forever. Real-time WebSocket from $29/mo.