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

# Perpetuals

> Markets, OHLCV, fills, liquidations, positions, orders, and PnL for Jupiter Perps

GraphQL surface for the perp data model. Mirrors the [`/api/sol/perp/*`](/api-reference/history/perp/markets) REST endpoints field-for-field. All `*UsdE6` and price/size integers are native ClickHouse `UInt64` returned as `Int64`-safe values (divide by 1,000,000 for USD-scaled fields). Timestamps are millis-since-epoch.

`marketId` is always `<venue>:<SYMBOL>-PERP` (e.g. `jup:SOL-PERP`). Today only `jup` is supported.

***

## `perpMarkets`

List supported perpetuals with last-24h volume and trade counts.

### Arguments

| Name    | Type     | Required | Description                                          |
| ------- | -------- | -------- | ---------------------------------------------------- |
| `venue` | `String` | no       | Filter to one venue (e.g. `"jup"`). Defaults to all. |

### Return type

```graphql theme={null}
type PerpMarket {
  marketId: String!
  venue: String!
  asset: String!
  volume24HUsd: Int!
  trades24H: Int!
}
```

`volume24HUsd` is in **USDC e6** (Jupiter `size_usd_delta` convention).

### Example

```graphql theme={null}
query { perpMarkets(venue: "jup") { marketId asset volume24HUsd trades24H } }
```

***

## `perpCandles`

OHLCV candles per market and timeframe. Backed by `perp_ohlcv_{1s,1m,5m,15m,1h,4h,1d}`.

### Arguments

| Name        | Type      | Required | Description                                                 |
| ----------- | --------- | -------- | ----------------------------------------------------------- |
| `marketId`  | `String!` | yes      | `jup:SOL-PERP` etc.                                         |
| `timeframe` | `String`  | no       | One of `1s`, `1m` (default), `5m`, `15m`, `1h`, `4h`, `1d`. |
| `limit`     | `Int`     | no       | Default 100, max 2000.                                      |
| `from`      | `String`  | no       | Inclusive lower bound, ms-since-epoch as a string.          |
| `to`        | `String`  | no       | Inclusive upper bound, ms-since-epoch as a string.          |

### Return type

```graphql theme={null}
type PerpCandle {
  timestamp: Int!     # ms since epoch
  open: Float!
  high: Float!
  low: Float!
  close: Float!
  volumeUsd: Float!   # USD (decimal, NOT e6)
  tradeCount: Int!
}
```

### Example

```graphql theme={null}
query {
  perpCandles(marketId: "jup:SOL-PERP", timeframe: "1m", limit: 60) {
    timestamp open close volumeUsd
  }
}
```

***

## `perpOi`

Per-minute open-interest series sampled from `perp_positions`. Read this alongside `perpCandles` to overlay long/short OI on the chart.

### Arguments

| Name       | Type      | Required | Description               |
| ---------- | --------- | -------- | ------------------------- |
| `marketId` | `String!` | yes      |                           |
| `limit`    | `Int`     | no       | Default 100, max 2000.    |
| `from`     | `String`  | no       | Ms-since-epoch as string. |
| `to`       | `String`  | no       | Ms-since-epoch as string. |

### Return type

```graphql theme={null}
type PerpOiPoint {
  timestamp: Int!
  longOiUsdE6: Int!
  shortOiUsdE6: Int!
  positionCount: Int!
}
```

***

## `perpTrades`

Recent fills (taker prints) on a market, newest first.

### Arguments

| Name       | Type      | Required | Description            |
| ---------- | --------- | -------- | ---------------------- |
| `marketId` | `String!` | yes      |                        |
| `limit`    | `Int`     | no       | Default 100, max 1000. |
| `from`     | `String`  | no       | Ms-since-epoch.        |
| `to`       | `String`  | no       | Ms-since-epoch.        |

### Return type

```graphql theme={null}
type PerpTrade {
  timestamp: Int!
  slot: Int!
  signature: String!
  signer: String!
  side: String!         # "long" | "short"
  size: Int!            # USDC e6
  price: Int!           # USDC e6 per unit base asset
  fee: Int!             # USDC e6
  action: String!       # "open" | "add" | "reduce" | "close" | "fill"
  realizedPnlE6: Int    # signed USDC e6, present on reduce/close; null otherwise
}
```

`action` is derived from the fill's on-chain `extra`: `open` opens a new
position, `add` increases an existing one, `reduce` partially closes, `close`
fully closes. `fill` means no lifecycle fields were present (Phoenix bridge
fills, legacy rows). `realizedPnlE6` carries realized PnL for `reduce`/`close`.

***

## `perpLiquidations`

Liquidation events on a market, newest first.

### Arguments

| Name       | Type      | Required | Description            |
| ---------- | --------- | -------- | ---------------------- |
| `marketId` | `String!` | yes      |                        |
| `limit`    | `Int`     | no       | Default 100, max 1000. |
| `from`     | `String`  | no       |                        |
| `to`       | `String`  | no       |                        |

### Return type

```graphql theme={null}
type PerpLiquidation {
  timestamp: Int!
  slot: Int!
  signature: String!
  signer: String!       # liquidated wallet
  positionPubkey: String!
  side: String!
  sizeClosed: Int!      # USDC e6
  oraclePrice: Int!     # USDC e6
  fee: Int!             # USDC e6
}
```

***

## `perpMarketOrders`

Pending or historical trigger orders on a market — feeds the orderbook view. Aggregates the multi-row `perp_orders` event log per `orderId` via `argMax`. Excludes orders whose underlying position has been liquidated or fully closed.

### Arguments

| Name       | Type      | Required | Description                                     |
| ---------- | --------- | -------- | ----------------------------------------------- |
| `marketId` | `String!` | yes      |                                                 |
| `state`    | `String`  | no       | `open` (default), `filled`, `cancelled`, `all`. |
| `limit`    | `Int`     | no       | Default 100, max 2000.                          |

### Return type

```graphql theme={null}
type PerpOrder {
  orderId: String!         # position_request PDA
  owner: String!
  marketId: String!
  venue: String!
  positionPubkey: String!
  kind: String!            # "limit" | "take_profit" | "stop_loss"
  side: String!
  state: String!           # "open" | "updated" | "filled" | "cancelled"
  sizeUsd: Int!            # USDC e6
  collateral: Int!
  triggerPrice: Int!       # USDC e6
  triggerAbove: Boolean!
  entirePosition: Boolean!
  createdSlot: Int!
  createdTs: Int!
  updatedSlot: Int!
  updatedTs: Int!
  lastSignature: String!
}
```

`triggerAbove` encodes the comparison direction: `true` = fire when oracle ≥ `triggerPrice`, `false` = fire when oracle ≤ `triggerPrice`. The combination with `side` derives whether the order is a TP or SL.

***

## `perpWalletPositions`

Open positions for one wallet. Latest row per `position_pubkey` from `perp_positions FINAL` where `is_open = 1`.

### Arguments

| Name      | Type      | Required | Description                |
| --------- | --------- | -------- | -------------------------- |
| `address` | `String!` | yes      | Wallet pubkey, ≥ 32 chars. |

### Return type

```graphql theme={null}
type PerpPosition {
  marketId: String!
  venue: String!
  positionPubkey: String!
  side: String!
  size: Int!            # USDC e6
  entryPrice: Int!      # USDC e6
  collateral: Int!      # USDC e6
  unrealizedPnl: Int!   # USDC e6, signed
  slot: Int!
  snapshotTs: Int!      # ms since epoch
  isOpen: Boolean!
}
```

These are *derived snapshots* from streaming events. For a live RPC truth-path read, use the trading-side oracle path; this query intentionally returns ClickHouse-derived state.

***

## `perpWalletTrades`

Fills for one wallet across every market.

### Arguments

| Name      | Type      | Required | Description            |
| --------- | --------- | -------- | ---------------------- |
| `address` | `String!` | yes      |                        |
| `limit`   | `Int`     | no       | Default 100, max 1000. |
| `from`    | `String`  | no       |                        |
| `to`      | `String`  | no       |                        |

### Return type

```graphql theme={null}
type PerpWalletTrade {
  timestamp: Int!
  marketId: String!
  venue: String!
  signature: String!
  side: String!
  size: Int!
  price: Int!
  fee: Int!
  positionPubkey: String!
  action: String!       # "open" | "add" | "reduce" | "close" | "fill"
  realizedPnlE6: Int    # signed USDC e6, present on reduce/close; null otherwise
}
```

***

## `perpWalletLiquidations`

Liquidation events for one wallet across every market.

### Arguments

| Name      | Type      | Required | Description            |
| --------- | --------- | -------- | ---------------------- |
| `address` | `String!` | yes      |                        |
| `limit`   | `Int`     | no       | Default 100, max 1000. |
| `from`    | `String`  | no       |                        |
| `to`      | `String`  | no       |                        |

### Return type

```graphql theme={null}
type PerpWalletLiquidation {
  timestamp: Int!
  slot: Int!
  marketId: String!
  venue: String!
  signature: String!
  positionPubkey: String!
  side: String!
  sizeClosed: Int!
  oraclePrice: Int!
  fee: Int!
}
```

***

## `perpWalletOrders`

Pending or historical trigger orders for one wallet. Same `PerpOrder` shape as `perpMarketOrders`.

### Arguments

| Name      | Type      | Required | Description                                     |
| --------- | --------- | -------- | ----------------------------------------------- |
| `address` | `String!` | yes      |                                                 |
| `state`   | `String`  | no       | `open` (default), `filled`, `cancelled`, `all`. |
| `limit`   | `Int`     | no       | Default 100, max 1000.                          |

### Example

```graphql theme={null}
query {
  perpWalletOrders(address: "62ThHC1rs2GUfa8J4Qjcj5GD2MSL2d65pcJtenNieDnm", state: "open") {
    orderId marketId kind side triggerPrice sizeUsd entirePosition updatedTs
  }
}
```

***

## `perpWalletPnl`

Per-(market, venue) volume and fees aggregate for one wallet. Sourced from the `_mv_perp_wallet_positions` materialized view.

### Arguments

| Name      | Type      | Required | Description |
| --------- | --------- | -------- | ----------- |
| `address` | `String!` | yes      |             |

### Return type

```graphql theme={null}
type PerpWalletPnl {
  marketId: String!
  venue: String!
  longSize: Int!         # USDC e6, total long-side size traded
  shortSize: Int!        # USDC e6
  volumeUsdE6: Int!
  feesPaidE6: Int!
  grossPnlE6: Int!       # 0 — pending real PnL field decoding
  netPnlE6: Int!         # currently -feesPaidE6 (placeholder)
  firstFillTs: Int!
  lastFillTs: Int!
}
```

`grossPnlE6` is intentionally `0` until the parser surfaces realized PnL; `netPnlE6` exposes only the negative-fees component to make this state explicit. Don't display either as "PnL" until both fields are populated.

***

## Combined example

A single round trip pulling everything a position dashboard needs:

```graphql theme={null}
query Dashboard($wallet: String!) {
  positions: perpWalletPositions(address: $wallet) {
    marketId side size entryPrice unrealizedPnl
  }
  orders: perpWalletOrders(address: $wallet, state: "open") {
    orderId marketId kind side triggerPrice
  }
  pnl: perpWalletPnl(address: $wallet) {
    marketId volumeUsdE6 feesPaidE6
  }
  recentFills: perpWalletTrades(address: $wallet, limit: 20) {
    timestamp marketId side size price
  }
}
```
