Getting Orderbook Data

The Get Market Orderbook endpoint returns the current state of bids for a specific market.

Request Format

GET /markets/{ticker}/orderbook
No authentication is required for this endpoint.

Example Request

import requests

# Get orderbook for a specific market
market_ticker = "KXHIGHNY-24JAN01-T60"
url = f"https://api.elections.kalshi.com/trade-api/v2/markets/{market_ticker}/orderbook"

response = requests.get(url)
orderbook_data = response.json()

Response Structure

The orderbook response contains two arrays of bids - one for YES positions and one for NO positions. Each bid is represented as a two-element array: [price, quantity].

Example Response

{
  "orderbook": {
    "yes": [
      [1, 200],    // 200 contracts bid at 1¢
      [15, 100],   // 100 contracts bid at 15¢
      [20, 50],    // 50 contracts bid at 20¢
      [25, 20],    // 20 contracts bid at 25¢
      [30, 11],    // 11 contracts bid at 30¢
      [31, 10],    // 10 contracts bid at 31¢
      [32, 10],    // 10 contracts bid at 32¢
      [33, 11],    // 11 contracts bid at 33¢
      [34, 9],     // 9 contracts bid at 34¢
      [35, 11],    // 11 contracts bid at 35¢
      [41, 10],    // 10 contracts bid at 41¢
      [42, 13]     // 13 contracts bid at 42¢
    ],
    "no": [
      [1, 100],    // 100 contracts bid at 1¢
      [16, 3],     // 3 contracts bid at 16¢
      [25, 50],    // 50 contracts bid at 25¢
      [28, 19],    // 19 contracts bid at 28¢
      [36, 5],     // 5 contracts bid at 36¢
      [37, 50],    // 50 contracts bid at 37¢
      [38, 300],   // 300 contracts bid at 38¢
      [44, 29],    // 29 contracts bid at 44¢
      [45, 20],    // 20 contracts bid at 45¢
      [56, 17]     // 17 contracts bid at 56¢
    ]
  }
}

Understanding the Arrays

  • First element: Price in cents (1-99)
  • Second element: Number of contracts available at that price
  • Arrays are sorted by price in ascending order
  • The highest bid (best bid) is the last element in each array

Why Only Bids?

Important: Kalshi’s orderbook only returns bids, not asks. This is because in binary prediction markets, there’s a reciprocal relationship between YES and NO positions.
In binary prediction markets, every position has a complementary opposite:
  • A YES BID at price X is equivalent to a NO ASK at price (100 - X)
  • A NO BID at price Y is equivalent to a YES ASK at price (100 - Y)

The Reciprocal Relationship

Since binary markets must sum to 100¢, these relationships always hold:
ActionEquivalent ToWhy
YES BID at 60¢NO ASK at 40¢Willing to pay 60¢ for YES = Willing to receive 40¢ to take NO
NO BID at 30¢YES ASK at 70¢Willing to pay 30¢ for NO = Willing to receive 70¢ to take YES
This reciprocal nature means that by showing only bids, the orderbook provides complete market information while avoiding redundancy.

Calculating Spreads

To find the bid-ask spread for a market:
  1. YES spread:
    • Best YES bid: Highest price in the yes array
    • Best YES ask: 100 - (Highest price in the no array)
    • Spread = Best YES ask - Best YES bid
  2. NO spread:
    • Best NO bid: Highest price in the no array
    • Best NO ask: 100 - (Highest price in the yes array)
    • Spread = Best NO ask - Best NO bid

Example Calculation

# Using the example orderbook above
best_yes_bid = 42  # Highest YES bid (last in array)
best_yes_ask = 100 - 56  # 100 - highest NO bid = 44

spread = best_yes_ask - best_yes_bid  # 44 - 42 = 2

# The spread is 2¢
# You can buy YES at 44¢ (implied ask) and sell at 42¢ (bid)

Working with Orderbook Data

Display Best Prices

def display_best_prices(orderbook_data):
    """Display the best bid prices and implied asks"""
    orderbook = orderbook_data['orderbook']
    
    # Best bids (if any exist)
    if orderbook['yes']:
        best_yes_bid = orderbook['yes'][-1][0]  # Last element is highest
        print(f"Best YES Bid: {best_yes_bid}¢")
    
    if orderbook['no']:
        best_no_bid = orderbook['no'][-1][0]  # Last element is highest
        best_yes_ask = 100 - best_no_bid
        print(f"Best YES Ask: {best_yes_ask}¢ (implied from NO bid)")
    
    print()
    
    if orderbook['no']:
        best_no_bid = orderbook['no'][-1][0]  # Last element is highest
        print(f"Best NO Bid: {best_no_bid}¢")
    
    if orderbook['yes']:
        best_yes_bid = orderbook['yes'][-1][0]  # Last element is highest
        best_no_ask = 100 - best_yes_bid
        print(f"Best NO Ask: {best_no_ask}¢ (implied from YES bid)")

Calculate Market Depth

def calculate_depth(orderbook_data, depth_cents=5):
    """Calculate total volume within X cents of best bid"""
    orderbook = orderbook_data['orderbook']
    
    yes_depth = 0
    no_depth = 0
    
    # YES side depth (iterate backwards from best bid)
    if orderbook['yes']:
        best_yes = orderbook['yes'][-1][0]  # Last element is highest
        for price, quantity in reversed(orderbook['yes']):
            if best_yes - price <= depth_cents:
                yes_depth += quantity
            else:
                break
    
    # NO side depth (iterate backwards from best bid)
    if orderbook['no']:
        best_no = orderbook['no'][-1][0]  # Last element is highest
        for price, quantity in reversed(orderbook['no']):
            if best_no - price <= depth_cents:
                no_depth += quantity
            else:
                break
    
    return {"yes_depth": yes_depth, "no_depth": no_depth}

Next Steps