Market Data
Guide for fetching and streaming market data programmatically using the Python SDK.
Prerequisites
Market data endpoints are public — no authentication required:
from turbine_client import TurbineClient, Outcome
client = TurbineClient(
host="https://api.turbinefi.com",
chain_id=137,
)List Markets
Fetch all markets, optionally filtered by chain:
# All markets
markets = client.get_markets()
# Filter by chain
markets = client.get_markets(chain_id=137)
for m in markets:
status = "RESOLVED" if m.resolved else "ACTIVE"
print(f"[{status}] {m.question}")
print(f" ID: {m.id}")
print(f" Contract: {m.contract_address}")
print(f" Volume: {m.volume / 1e6:.2f} USDC")
print()Each Market object contains the market ID (used for API calls) and the contract address (used for claiming winnings). See Types for all fields.
Orderbook Snapshots
Get the current orderbook for a market:
market_id = "0x..."
# Full orderbook (both outcomes)
ob = client.get_orderbook(market_id)
# YES side only
yes_ob = client.get_orderbook(market_id, outcome=Outcome.YES)
# NO side only
no_ob = client.get_orderbook(market_id, outcome=Outcome.NO)Parsing the Orderbook
Bids are sorted highest-first (best bid on top). Asks are sorted lowest-first (best ask on top).
ob = client.get_orderbook(market_id, outcome=Outcome.YES)
print("YES Orderbook:")
print(f"{'BIDS':>40} | ASKS")
print("-" * 80)
max_levels = max(len(ob.bids), len(ob.asks))
for i in range(min(max_levels, 5)):
bid_str = ""
ask_str = ""
if i < len(ob.bids):
b = ob.bids[i]
bid_str = f"{b.size / 1e6:>8.2f} @ {b.price:>6} (${b.price / 1e6:.4f})"
if i < len(ob.asks):
a = ob.asks[i]
ask_str = f"{a.price:>6} (${a.price / 1e6:.4f}) x {a.size / 1e6:.2f}"
print(f"{bid_str:>40} | {ask_str}")Derived Metrics
ob = client.get_orderbook(market_id, outcome=Outcome.YES)
if ob.bids and ob.asks:
best_bid = ob.bids[0].price
best_ask = ob.asks[0].price
mid = (best_bid + best_ask) / 2
spread = best_ask - best_bid
spread_pct = spread / mid * 100 if mid > 0 else 0
print(f"Best bid: {best_bid} (${best_bid / 1e6:.4f})")
print(f"Best ask: {best_ask} (${best_ask / 1e6:.4f})")
print(f"Mid: {mid:.0f} (${mid / 1e6:.4f})")
print(f"Spread: {spread} ({spread_pct:.2f}%)")
# Total depth
bid_depth = sum(level.size for level in ob.bids) / 1e6
ask_depth = sum(level.size for level in ob.asks) / 1e6
print(f"Bid depth: {bid_depth:.2f} shares")
print(f"Ask depth: {ask_depth:.2f} shares")Trade History
Get recent trades for a market:
trades = client.get_trades(market_id, limit=20)
for t in trades:
outcome = "YES" if t.outcome == 0 else "NO"
print(
f"{outcome} {t.size / 1e6:.2f} "
f"@ {t.price} (${t.price / 1e6:.4f}) | "
f"tx={t.tx_hash[:16]}..."
)Aggregate Trade Data
trades = client.get_trades(market_id, limit=100)
if trades:
prices = [t.price for t in trades]
sizes = [t.size for t in trades]
total_volume = sum(t.price * t.size // 1_000_000 for t in trades)
print(f"Trades: {len(trades)}")
print(f"Price range: {min(prices)} (${min(prices) / 1e6:.4f}) — {max(prices)} (${max(prices) / 1e6:.4f})")
print(f"Volume: {total_volume / 1e6:.2f} USDC")Market Statistics
Single Market
stats = client.get_market(market_id)
print(f"Last price: {stats.last_price} (${stats.last_price / 1e6:.4f})")
print(f"24h volume: {stats.volume_24h / 1e6:.2f} USDC")
print(f"Total volume: {stats.total_volume / 1e6:.2f} USDC")Platform-Wide
platform = client.get_platform_stats()
print(f"Total volume: {platform.total_volume / 1e6:.2f} USDC")
print(f"Total trades: {platform.total_trades}")
for chain in platform.chains:
print(f" Chain {chain.chain_id}: {chain.total_volume / 1e6:.2f} USDC, {chain.total_trades} trades")Top Holders
holders = client.get_holders(market_id, limit=10)
for i, h in enumerate(holders, 1):
print(
f"#{i} {h.user_address[:10]}... | "
f"YES={h.yes_shares / 1e6:.2f} | "
f"NO={h.no_shares / 1e6:.2f} | "
f"Invested={h.total_invested / 1e6:.2f} USDC"
)Quick Market Data
Active Quick Market
qm = client.get_quick_market("BTC")
print(f"Question: Will BTC be above ${qm.start_price / 1e8:,.2f}?")
print(f"Market ID: {qm.market_id}")
print(f"Contract: {qm.contract_address}")
print(f"Starts: {qm.start_time}")
print(f"Ends: {qm.end_time}")
print(f"Resolved: {qm.resolved}")Current Price
price = client.get_quick_market_price("BTC")
print(f"BTC: ${price.price / 1e8:,.2f}")Price History
history = client.get_quick_market_price_history("BTC", limit=60)
for p in history:
print(f" {p.timestamp}: ${p.price / 1e8:,.2f}")Quick Market History
past_markets = client.get_quick_market_history("BTC", limit=10)
for qm in past_markets:
if qm.resolved:
outcome = "YES" if qm.outcome == 0 else "NO"
print(f" Strike: ${qm.start_price / 1e8:,.2f} → End: ${qm.end_price / 1e8:,.2f} = {outcome}")
else:
print(f" Strike: ${qm.start_price / 1e8:,.2f} (active)")Real-Time Streaming via WebSocket
import asyncio
from turbine_client.ws import TurbineWSClient
async def stream_market(market_id: str):
ws = TurbineWSClient(host="https://api.turbinefi.com")
async with ws.connect() as stream:
await stream.subscribe(market_id)
print(f"Subscribed to {market_id}")
async for msg in stream:
if msg.type == "orderbook":
ob = msg.orderbook
if ob and ob.bids and ob.asks:
mid = (ob.bids[0].price + ob.asks[0].price) / 2
spread = ob.asks[0].price - ob.bids[0].price
print(f"Book: {ob.bids[0].price}/{ob.asks[0].price} mid={mid:.0f} spread={spread}")
elif msg.type == "trade":
trade = msg.trade
if trade:
outcome = "YES" if trade.outcome == 0 else "NO"
print(f"Trade: {trade.size / 1e6:.2f} {outcome} @ {trade.price} (${trade.price / 1e6:.4f})")
asyncio.run(stream_market("0x..."))Market Transition Detection
Quick markets rotate every 15 minutes. Detect transitions via WebSocket:
async def stream_with_transitions():
client = TurbineClient(host="https://api.turbinefi.com", chain_id=137)
ws = TurbineWSClient(host="https://api.turbinefi.com")
qm = client.get_quick_market("BTC")
current_market_id = qm.market_id
async with ws.connect() as stream:
await stream.subscribe(current_market_id)
async for msg in stream:
if msg.type == "quick_market":
new_qm = msg.quick_market
if new_qm and new_qm.market_id != current_market_id:
# Switch to new market
await stream.unsubscribe(current_market_id)
current_market_id = new_qm.market_id
await stream.subscribe(current_market_id)
print(f"New market: {current_market_id} (strike: ${new_qm.start_price / 1e8:,.2f})")
elif msg.type == "orderbook":
ob = msg.orderbook
if ob and ob.bids and ob.asks:
print(f" {ob.bids[0].price}/{ob.asks[0].price}")
asyncio.run(stream_with_transitions())