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

# Perpetuals

> Discover perpetual markets and analyze carry, trade flow, liquidity, and order books with Polaris clients.

Use this guide when you want to study perpetual markets across venues. Polaris
provides normalized executions, point series, order books, and derived analytics
through the same source and market identity.

## Representative coverage

This cross-section comes from the public Catalog at
`2026-08-27T20:33:10.112Z`. It is representative, not exhaustive. Use
[Catalog](/reference/catalog) for current coverage and exact market IDs.

| Venue       | Source ID     | Example market                   | Access  |
| ----------- | ------------- | -------------------------------- | ------- |
| Hyperliquid | `hyperliquid` | `BTC`                            | Open    |
| Lighter     | `lighter`     | `1` (`instrument.base` is `BTC`) | Open    |
| Pacifica    | `pacifica`    | `BTC`                            | Preview |
| Aster       | `aster`       | `BTCUSDT`                        | Preview |
| dYdX v4     | `dydxv4`      | `BTC-USD`                        | Preview |
| Paradex     | `paradex`     | `BTC-USD-PERP`                   | Preview |

Venue IDs are not interchangeable. For example, Lighter uses numeric market IDs,
while other venues expose asset or pair-like identifiers. Always use the exact
`market` value returned by Catalog.

## Choose a client method

| Workflow                      | Python                                                      | TypeScript                                                  | Rust                                                        |
| ----------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------- |
| Discovery                     | `catalog(...)`                                              | `catalog(...)`                                              | `catalog(CatalogQuery)`                                     |
| Funding                       | `funding_rates(...)`                                        | `fundingRates(...)`                                         | `funding_rates(HistoricalQuery)`                            |
| Mark price                    | `mark_prices(...)`                                          | `markPrices(...)`                                           | `mark_prices(HistoricalQuery)`                              |
| Executions                    | `trades(...)`                                               | `trades(...)`                                               | `trades(HistoricalQuery)`                                   |
| Bars and trade-derived series | `ohlcv(...)`, `volume(...)`, `vwap(...)`, `volatility(...)` | `ohlcv(...)`, `volume(...)`, `vwap(...)`, `volatility(...)` | `ohlcv(...)`, `volume(...)`, `vwap(...)`, `volatility(...)` |
| Top of book and liquidity     | `bbo(...)`, `depth_metrics(...)`                            | `bbo(...)`, `depthMetrics(...)`                             | `bbo(...)`, `depth_metrics(...)`                            |
| Complete or raw L2            | `l2_snapshots(...)`, `l2_updates(...)`                      | `l2Snapshots(...)`, `l2Updates(...)`                        | `l2_snapshots(...)`, `l2_updates(...)`                      |
| Application-managed book      | `OrderbookBuilder`                                          | `OrderbookBuilder`                                          | `OrderbookBuilder`                                          |
| Mixed events and replay       | `events(...)`, `replay(...)`                                | `events(...)`, `replay(...)`                                | `events(...)`, `replay(...)`                                |
| Realtime updates              | `stream(...)`                                               | `stream(...)`                                               | `stream(StreamQuery)`                                       |
| Venue-native payloads         | `raw(...)`                                                  | Not exposed                                                 | `raw(RawQuery)`                                             |

Choose the narrowest typed method for the series you need. Use `events` or
`replay` when event interleaving and stored order matter more than a single
derived dataset.

## Set one bounded analysis range

Use one Catalog row and one time window across the following recipes. This makes
the resulting series easier to compare.

```python theme={null}
from datetime import timedelta

import pandas as pd
from polaris_data import OrderbookBuilder, PolarisClient

source = "hyperliquid"
market = "BTC"

with PolarisClient() as client:
    catalog = client.catalog(source=source, market=market)

coverage = catalog["markets"][0]
coverage_start = pd.Timestamp(coverage["start"])
coverage_end = pd.Timestamp(coverage["end"])
public_cutoff = coverage["access"].get("public_cutoff_date")
if public_cutoff:
    public_day = pd.Timestamp(public_cutoff, tz="UTC")
    start = max(coverage_start, public_day)
    end = min(coverage_end, start + timedelta(hours=1))
else:
    end = coverage_end
    start = max(coverage_start, end - timedelta(hours=1))
query = {
    "source": source,
    "market": market,
    "from_": start.to_pydatetime(),
    "to": end.to_pydatetime(),
}
```

## Compare carry and mark price

Funding and mark-price rows are point series. DataFrame output gives you flat,
timezone-aware columns for alignment and resampling.

```python theme={null}
with PolarisClient() as client:
    funding = client.funding_rates(**query, output="dataframe")
    marks = client.mark_prices(**query, output="dataframe")

if funding.empty or marks.empty:
    print("Funding or mark-price data is unavailable in this interval.")
else:
    funding = funding.sort_values("timestamp")
    marks = marks.sort_values("timestamp")
    carry = pd.merge_asof(
        funding,
        marks,
        on="timestamp",
        by=["source", "market"],
        direction="backward",
        suffixes=("_funding", "_mark"),
    )
    print(carry.tail())
```

Funding conventions and intervals can vary by venue. Compare the published
`funding_rate` and `funding_interval` together instead of assuming every rate
uses the same period.

## Analyze trade flow

Use raw trades for signed flow and interval methods for price, participation,
benchmark, and realized-volatility series.

```python theme={null}
with PolarisClient() as client:
    trades = client.trades(**query, output="dataframe")
    bars = pd.DataFrame(client.ohlcv(**query, interval="1m"))
    volume = pd.DataFrame(client.volume(**query, interval="1m"))
    vwap = pd.DataFrame(client.vwap(**query, interval="1m"))
    volatility = pd.DataFrame(client.volatility(**query, interval="1m"))

if trades.empty:
    print("No trades in the selected interval.")
else:
    trades["signed_notional"] = trades["price"] * trades["quantity"]
    trades.loc[trades["side"].str.lower().eq("sell"), "signed_notional"] *= -1
    flow = trades.set_index("timestamp")["signed_notional"].resample("1min").sum()
    print(flow.tail())
```

Column names in venue-specific extras remain under `extra.<name>`. Use the
normalized trade fields for cross-venue comparisons.

## Measure liquidity

Use BBO for top-of-book spreads and `depth_metrics` for depth, imbalance, and
slippage estimates. Both support DataFrame output.

```python theme={null}
with PolarisClient() as client:
    quotes = client.bbo(**query, interval="1m", output="dataframe")
    depth = client.depth_metrics(
        **query,
        depth_pct=0.01,
        slippage_notional=10_000,
        output="dataframe",
    )

if quotes.empty:
    print("No BBO rows in the selected interval.")
else:
    quotes["midpoint"] = (quotes["bid_price"] + quotes["ask_price"]) / 2
    quotes["spread_bps"] = (
        (quotes["ask_price"] - quotes["bid_price"]) / quotes["midpoint"] * 10_000
    )
    print(quotes[["timestamp", "midpoint", "spread_bps"]].tail())

if not depth.empty:
    print(depth.tail())
```

Treat the requested slippage notional as a scenario input, not a universal
measure. Use the same notional when comparing markets.

## Choose an order-book workflow

`l2_snapshots` reconstructs complete books for you. Use it when you want to
inspect or sample full state:

```python theme={null}
with PolarisClient() as client:
    books = client.l2_snapshots(**query)
    latest_book = None
    for latest_book in books:
        pass

if latest_book is not None:
    print(latest_book)
```

`l2_updates` returns raw standardized snapshots and deltas. Feed them into
`OrderbookBuilder` when your application controls when complete books are
materialized:

```python theme={null}
builder = OrderbookBuilder()

with PolarisClient() as client:
    for update in client.l2_updates(**query):
        builder.update(update)

complete_book = builder.snapshot(source, market)
if complete_book is not None:
    print(complete_book)
```

State clears after gaps and reconnects, and deltas are skipped until another
snapshot arrives. Do not treat a delta as a complete book.

## Related documentation

* [Funding rates](/schemas/funding-rates) and [Mark prices](/schemas/mark-prices) for carry and reference-price fields
* [Trades](/schemas/trades), [OHLCV](/schemas/ohlcv), [Volume](/schemas/volume), [VWAP](/schemas/vwap), and [Volatility](/schemas/volatility) for trade-flow analysis
* [BBO](/schemas/bbo) and [Depth metrics](/schemas/depth-metrics) for derived liquidity fields
* [L2 snapshots and updates](/schemas/l2-snapshots) for reconstruction behavior
* [Event envelope](/concepts/event-envelope) for timestamps and stored ordering
