< Back to Blog

Order Book Imbalance: Reading the Hidden Liquidity on Kalshi

TL;DR / Key Takeaways

  • Order book imbalance measures depth pressure, not just the visible bid-ask spread.
  • Thin Kalshi weather books can turn a good model edge into a bad average fill price.
  • The bot uses order book depth as part of the composite edge score before placing trades.
  • Imbalance is a trade-quality filter, not a standalone forecast signal.

When evaluating a Kalshi weather contract, most traders look at two numbers: the last traded price and total daily volume. I understand why — they are the most visible numbers. But they are also both backward-looking. They tell you what already happened, not what is about to happen.

To get good fills and avoid entering into thin markets where your own order moves the price, you need to look at the order book itself — specifically, the imbalance between resting bids and resting asks.

What order book imbalance measures

| Measure | Looks at | What it catches | Limitation | | --- | --- | --- | --- | | Bid-ask spread | Best bid versus best ask | Immediate crossing cost | Ignores depth behind top level | | Order book depth | Size available at price levels | Whether the desired order can fill | Does not predict weather outcome | | Imbalance | Relative depth on each side | Pressure and liquidity asymmetry | Must be combined with model edge |

Order book imbalance is the difference between buying pressure and selling pressure at a given moment. It is calculated from the depth of the book, not just the best bid and ask.

imbalance = (total_bid_volume - total_ask_volume) / (total_bid_volume + total_ask_volume)

The result is a number between -1 and +1.

A value near +1 means there is heavy buy-side pressure — significantly more contracts resting on the bid than the ask. If a large market order comes in on the ask side, there is real buying interest to absorb it, and you are likely to get a clean fill near the posted price.

A value near -1 means the opposite. Sellers are stacked up and buyers are scarce. Even a moderate buy order can push through the thin ask side and fill at progressively worse prices.

A value near 0 means the book is balanced. The market is in equilibrium and the posted price is a reasonable estimate of fair value at that moment.

Why this matters for weather market bots

Weather contracts on Kalshi can have surprisingly thin order books, especially for contracts more than a few days out or for smaller cities. A contract showing a favorable price of $0.62 on a 70-degree threshold might have 200 contracts resting on the ask at that price — and almost nothing behind it. Buy 500 contracts with a market order and you will fill the first 200 at $0.62 and the rest at $0.65, $0.68, and wherever else the next sellers are sitting. Your average entry price is $0.64 instead of $0.62. That two cents matters when the fee-adjusted edge was only five cents to begin with.

The order book imbalance check protects against this. If the imbalance is significantly negative — a lot of sell pressure, very little buy interest — the bot holds execution even if the ensemble signal is strong. It is not that the signal is wrong. It is that now is not the right moment to enter, because fills will be poor and the market may be about to move against you.

Pulling order book depth via WebSocket

The Kalshi WebSocket API delivers orderbook deltas in real time. Here is a minimal example of tracking order book state and computing imbalance:

# Source: predictandprofit.io
from collections import defaultdict

class OrderBook:
    def __init__(self, ticker: str):
        self.ticker = ticker
        self.bids = defaultdict(int)  # price -> quantity
        self.asks = defaultdict(int)

    def apply_delta(self, delta: dict):
        side = delta.get("side")
        price = delta.get("price")
        delta_qty = delta.get("delta", 0)

        book = self.bids if side == "yes" else self.asks
        book[price] += delta_qty
        if book[price] <= 0:
            del book[price]

    def imbalance(self) -> float:
        total_bid = sum(self.bids.values())
        total_ask = sum(self.asks.values())
        total = total_bid + total_ask
        if total == 0:
            return 0.0
        return (total_bid - total_ask) / total

    def best_ask(self) -> float | None:
        if not self.asks:
            return None
        return min(self.asks.keys())

    def best_bid(self) -> float | None:
        if not self.bids:
            return None
        return max(self.bids.keys())

    def spread(self) -> float | None:
        if self.best_ask() is None or self.best_bid() is None:
            return None
        return self.best_ask() - self.best_bid()

Usage in the main trading loop:

# Source: predictandprofit.io
books = {}  # ticker -> OrderBook

async def handle_orderbook_update(data: dict):
    ticker = data["market_ticker"]
    if ticker not in books:
        books[ticker] = OrderBook(ticker)

    for delta in data.get("deltas", []):
        books[ticker].apply_delta(delta)

def should_enter_trade(ticker: str, min_imbalance: float = -0.3) -> bool:
    book = books.get(ticker)
    if book is None:
        return False

    imb = book.imbalance()
    spread = book.spread()

    # Skip if book is too thin or heavily skewed against us
    if imb < min_imbalance:
        return False
    if spread is not None and spread > 0.05:
        return False

    return True

How imbalance fits into the composite edge score

In the Predict & Profit system, order book imbalance is one of four inputs to the composite edge score. It contributes roughly 30% of the score weight, alongside ensemble spread, ensemble confidence, and fee efficiency.

A strong ensemble signal with terrible book conditions scores lower than a slightly weaker signal with a clean, balanced book. The score reflects the full picture of how good the trade actually is — not just what the weather model says, but whether the market structure supports entering at a fair price.

This is the difference between a signal that is correct and a trade that makes money. You can be right about the temperature and still lose money if you get bad fills on entry and exit.

What imbalance is not

Order book imbalance is not a prediction of future price movement. It is a snapshot of current market structure. A heavily negative imbalance does not necessarily mean the price is about to fall — it might mean institutional participants are selling down a position and the imbalance will clear in 60 seconds. The bot checks imbalance at the moment of potential entry, not as a predictive signal.

This also means the imbalance check is a gate, not a driver. The decision to trade is driven by the ensemble. The imbalance check is one of several conditions that must be satisfied before the order goes to the exchange.


The full order book management, imbalance calculation, and composite edge scoring system are included in the Python source code.

Get the Source Code — $67

Frequently Asked Questions

Q: What does order book imbalance measure?

A: It measures how much depth exists on one side of the book compared with the other. That gives more information than the best bid and ask alone.

Q: Why can a tight spread still be risky?

A: A tight top-of-book spread can hide shallow depth. If only a small quantity is available at the target price, a larger order can slip into worse prices and erase the edge.

Q: How does imbalance enter the edge score?

A: The bot treats order book quality as one component of the composite score alongside ensemble confidence, spread, and fee efficiency. It is an execution filter, not the forecast itself.

Related Reading