> ## 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.

# prediction_markets.open_interest_hourly

> Cross-venue hourly open interest and traded volume per market across Polymarket and Kalshi.

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 `prediction_markets.open_interest_hourly` table provides hourly open interest and traded volume per market across Polymarket and Kalshi. Grain: one row per `(venue, hour, market_id)`, with a row for every hour from the market's first open contract to the hour it settles. Open interest is a level at the end of the hour; volume is the flow within it. Every row is the state at the end of its hour, so open interest reads zero in the settlement hour.

The table is a union of [`polymarket_polygon.open_interest_hourly`](/data-catalog/curated/prediction-markets/polymarket/open_interest_hourly) and [`kalshi.open_interest_hourly`](/data-catalog/curated/prediction-markets/kalshi/open_interest_hourly), which share one layout. Those pages explain how each venue's figures are built. Hyperliquid HIP-4 is not included yet; use [`hip4_hyperliquid.open_interest_hourly`](/data-catalog/curated/prediction-markets/hip4/open_interest_hourly).

<Note>
  Polymarket Combos and Kalshi parlays are not included, so totals cover single markets only.
</Note>

<Warning>
  For total open interest, take `event_oi_contracts` once per `(venue, COALESCE(event_id, market_id), hour)`, as in the example below. Don't sum it across the members of an event, because it is repeated on every member row. Don't sum `market_oi_yes_contracts` across Polymarket event members either. Converting No tokens mints Yes tokens of every sibling outcome without adding collateral, so that sum can overstate the money at stake several times over. On Kalshi the two methods agree.
</Warning>

Market names and attributes are in [`prediction_markets.markets`](/data-catalog/curated/prediction-markets/prediction_markets/markets) and prices in [`prediction_markets.ohlcv_hourly`](/data-catalog/curated/prediction-markets/prediction_markets/ohlcv_hourly), both joined on `(venue, market_id)`.

## Table Schema

| Column | Type | Description |
| - | - | - |
| `venue` | `VARCHAR` | `polymarket` or `kalshi` |
| `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` | Polymarket `condition_id` or Kalshi ticker. Joins `prediction_markets.markets` on `(venue, market_id)` |
| `event_id` | `VARCHAR` | Event this market is one outcome of, when the event's outcomes are mutually exclusive. NULL for a standalone market, which counts as its own event |
| `market_oi_yes_contracts` | `DOUBLE` | Yes contracts outstanding at the end of the hour. Each contract pays \$1 |
| `market_oi_no_contracts` | `DOUBLE` | No contracts outstanding at the end of the hour. Equal to the Yes side, except on a Polymarket event member whose No contracts have been converted into Yes contracts of sibling outcomes, where it is lower |
| `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 traded in the hour across both sides of the market, each trade counted once |
| `volume_usd` | `DOUBLE` | Cash traded in the hour in USD, each trade counted once from the taker's side |
| `trade_count` | `BIGINT` | Trades in the hour across both sides of the market |
| `_updated_at` | `TIMESTAMP` | When this row was last written by the pipeline |

## Table sample

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

## Query performance

`block_month` is the partition key. Always include a `block_month` or `hour` filter, and a `venue` filter when you only need one venue.

## 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
    venue,
    CAST(hour AS DATE) AS day,
    COALESCE(event_id, market_id) AS event_key,
    MAX(event_oi_contracts) AS open_interest_contracts
  FROM prediction_markets.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, 3
)
SELECT
  venue,
  day,
  SUM(open_interest_contracts) AS open_interest_contracts
FROM per_event
GROUP BY 1, 2
ORDER BY 2, 1
```


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