> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dune.com/llms.txt
> Use this file to discover all available pages before exploring further.

# kalshi.open_interest_hourly

> Kalshi hourly open interest and traded volume per single market, from the first open contract to settlement.

export const TableSample = ({tableName, tableSchema}) => <>
    <div className="hidden dark:block">
      <iframe src={`https://dune.com/embeds/3419983/5785629?table_schema_t6f0df=${tableSchema}&table_name_t6f0df=${tableName}&darkMode=true`} style={{
  width: '100%',
  height: '500px',
  border: 'none',
  marginTop: '10px'
}} />
    </div>
    <div className="dark:hidden">
      <iframe src={`https://dune.com/embeds/3419983/5785629?table_schema_t6f0df=${tableSchema}&table_name_t6f0df=${tableName}`} style={{
  width: '100%',
  height: '500px',
  border: 'none',
  marginTop: '10px'
}} />
    </div>
  </>;

The `kalshi.open_interest_hourly` table provides hourly open interest and traded volume per Kalshi single market. Grain: one row per `(hour, market_id)`, with a row for every hour from the market's first open contract to its settlement. An unsettled market runs to its expected expiration. Open interest is a level at the end of the hour; volume is the flow within it. The layout matches [`polymarket_polygon.open_interest_hourly`](/data-catalog/curated/prediction-markets/polymarket/open_interest_hourly) and [`hip4_hyperliquid.open_interest_hourly`](/data-catalog/curated/prediction-markets/hip4/open_interest_hourly).

Open interest comes from the snapshots on Kalshi's live ticker stream. It is not rebuilt from trades. An hour with no update carries the last published value. Coverage starts on May 11, 2026, when the stream came online, so there is no earlier history. Every Kalshi contract has one Yes holder and one No holder, so the two sides are always equal. As a result, summing `market_oi_yes_contracts` across markets gives the same total as the example query.

Every row is the state at the end of its hour. A settled market has no open interest, so the settlement hour reads zero and is the market's last row. The latest hours show up once Kalshi's settlements through those hours are recorded, so the table runs a little behind real time.

<Note>
  Parlays are not included, so totals cover single markets only. A market nobody has ever held has no rows.
</Note>

<Warning>
  `event_oi_contracts` is repeated on every member row of an event. Summing it across members overstates event open interest. Take it once per `event_id` and `hour`.
</Warning>

Prices are in [`kalshi.ohlcv_hourly`](/data-catalog/curated/prediction-markets/kalshi/ohlcv_hourly).

## Table Schema

| Column | Type | Description |
| - | - | - |
| `block_month` | `DATE` | First day of the UTC month of `hour`. Partition key |
| `hour` | `TIMESTAMP` | UTC hour the figures describe. Open interest is the level at the end of it, volume the flow within it |
| `market_id` | `VARCHAR` | Kalshi market ticker. Joins `kalshi.market_details` on `market_id` |
| `event_id` | `VARCHAR` | Event this market is one outcome of, when the event's outcomes are mutually exclusive. NULL for a market whose event allows several outcomes to win. Such a market counts as its own event |
| `market_oi_yes_contracts` | `DOUBLE` | Yes contracts outstanding at the end of the hour, each open contract counted once. Each contract pays \$1 |
| `market_oi_no_contracts` | `DOUBLE` | No contracts outstanding at the end of the hour. Always equal to the Yes side |
| `event_oi_contracts` | `DOUBLE` | Collateral locked behind the market's event at the end of the hour: the Yes contracts of one member plus the No contracts of every other member, which is the payout whichever outcome wins. Equal to the Yes side on a standalone market |
| `volume_contracts` | `DOUBLE` | Contracts that changed hands in the hour, each fill counted once |
| `volume_usd` | `DOUBLE` | Cash that changed hands in the hour in USD, each fill counted once from the taker's side |
| `trade_count` | `BIGINT` | Fills in the hour |
| `_updated_at` | `TIMESTAMP` | When this row was last written by the pipeline |

## Table sample

<TableSample tableSchema="kalshi" tableName="open_interest_hourly" />

## Query performance

`block_month` is the partition key. Always include a `block_month` or `hour` filter.

## Example query

```sql theme={null}
-- Total open interest at the end of each UTC day, last 30 days.
-- event_oi_contracts repeats on every market of an event, so take it once per event.
-- A market without an event_id is its own event.
WITH per_event AS (
  SELECT
    CAST(hour AS DATE) AS day,
    COALESCE(event_id, market_id) AS event_key,
    MAX(event_oi_contracts) AS open_interest_contracts
  FROM kalshi.open_interest_hourly
  WHERE block_month >= DATE_TRUNC('month', CURRENT_DATE - INTERVAL '30' DAY)
    AND hour >= CURRENT_DATE - INTERVAL '30' DAY
    AND HOUR(hour) = 23 -- the 23:00 row is the level at the end of the day
  GROUP BY 1, 2
)
SELECT
  day,
  SUM(open_interest_contracts) AS open_interest_contracts
FROM per_event
GROUP BY 1
ORDER BY 1
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.