Skip to content

Cross-Exchange Arbitrage API

Cross-exchange arbitrage exploits funding rate differentials for the same asset across two venues: long where funding is lowest, short where it is highest. The board covers every funding venue (30+ CEXs and perp DEXs; a venue whose markets are halted is left out) across every asset class — crypto plus RWA perps (tokenized equities, commodities, FX, indices) — keeps one row per asset, and ranks executable pairs first by net APR after both venues' taker fees and the adverse entry spread. Pairs never cross asset classes, an RWA leg whose funding reads exactly 0 (paused for its session, or a market that never funds) is not paired, and unknown market data is null, never zero.


GET/v1/arbitrage/cross-exchange

List cross-exchange opportunities

Returns one row per asset: its executable pair with the highest netApr, else its best no_depth pair (book-priced, a venue reports no size), else its largest gross differential (indicative). Legs pair within one instrument-master asset, so lot spellings of one coin (BONK, 1000BONK, KBONK) pair with each other and prices compare per asset unit. Rows rank executable first by netApr, then no_depth rows (a venue reports no book size), then the other indicative rows, each by netApr where they have one, else gross apr.

The board is composed every 5 minutes by a scheduled job, never per request, and is stale after 10 minutes; each pair is priced again at the time of the request from its legs' own quote times, so a quote older than 10 minutes makes the row indicative (stale_quote). An asset needs current funding with a verified per-market settlement interval on at least two selected venues. Only funding rates inside the 10-minute freshness window are paired, and a venue that reports a market as not trading (halted, settling, delisted or pre-launch) is left out for it. With no board to serve the endpoint answers 503 (service_unavailable, Retry-After: 30).

Query parameters

  • Name
    exchanges
    Type
    string
    Description

    Comma-separated list of venues to include, e.g. Binance, OKX, Bybit, Hyperliquid, WhiteBIT, Kraken, Lighter. Omit to include all venues. X-Data-Venues lists the venues a filter can offer.

  • Name
    minOiUsd
    Type
    number
    Description

    Minimum open interest in USD on the smaller leg. Defaults to 0 (no floor). A leg with unknown OI fails a positive floor. The floor applies to each asset's chosen pair: a failing asset leaves, it is not re-paired.

  • Name
    minVolUsd
    Type
    number
    Description

    Minimum 24h perp volume in USD on the smaller leg. Defaults to 0 (no floor). A leg with unknown volume fails a positive floor.

  • Name
    assetClass
    Type
    string
    Description

    Underlying filter. One of all (default), crypto, or rwa — the latter covering equity, commodity, FX and index perps. Pairing always stays within one asset class.

  • Name
    sector
    Type
    string
    Description

    Narrative filter. One of all (default), memes, ai-agents, layer-1 or defi: keeps only crypto coins in that narrative's CoinGecko category, the constituents the narratives endpoint lists. A coin the category does not list, and every RWA perp, is left out when a sector is set. The free route reads it too.

  • Name
    limit
    Type
    integer
    Description

    Return at most this many rows, the first in board order. Omit it (and cursor) for every row. On v1 a limited answer carries pagination.

  • Name
    cursor
    Type
    string
    Description

    Opaque cursor from the previous page's pagination.cursor (100 rows a page when limit is omitted).

Response headers

Besides the freshness headers, both the v1 and the free route send:

  • X-Data-Missing: each configured venue that is not a quoted member of the board, comma-separated as Venue:reason. not_live (every contract halted; the venue is not asked), stale (no funding row inside the funding SLA), no_ticker (its rows are served unpriced: its ticker or book reads failed). edgeX, ApeX and GRVT publish no bulk ticker, so their legs are priced from per-contract top-of-book reads of the board's contracts (up to 60 per venue, 5 at a time, cached 60 s). Absent when every venue is a quoted member.
  • X-Data-Venues: the venues a venue filter may offer, comma-separated: the configured venues less those not_live or stale (a venue whose funding rows are all past the funding SLA, such as a halted venue, is not offered).

Request

GET
/v1/arbitrage/cross-exchange
curl -G https://www.sharpe.ai/api/v1/arbitrage/cross-exchange \
  -H "Authorization: Bearer sk_live_your_key_here" \
  -d exchanges=Binance,OKX,Bybit,Aster,Gate.io \
  -d limit=50

Response

{
  "data": [
    {
      "symbol": "ZCAT",
      "assetClass": "crypto",
      "longExchange": "Aster",
      "shortExchange": "Gate.io",
      "longRate": -0.0054679,
      "shortRate": -0.000003,
      "netFundingRate": 0.00546715,
      "apr": 47.892234,
      "grossApr": 47.892234,
      "netApr": 47.600961,
      "spreadRate": 0.02214022,
      "spreadSource": "book",
      "longAsk": 0.08357,
      "shortBid": 0.08174,
      "executableDepthUsd": null,
      "holdingDays": 30,
      "executionStatus": "indicative",
      "oiLong": null,
      "oiShort": 148993.29,
      "volumeLong24hUsd": 141557.06,
      "volumeShort24hUsd": 218730,
      "nextSettlement": "2026-09-27T00:00:00.000Z",
      "intervalHours": 1,
      "pairStatus": "eligible",
      "fundingAsOf": "2026-09-26T23:47:05.000Z",
      "pricesAsOf": "2026-09-26T23:50:38.000Z",
      "indicativeReason": "no_depth",
      "roundTripFeeRate": 0.0018,
      "breakEvenDays": 0.18,
      "longSymbol": "ZCATUSDT",
      "shortSymbol": "ZCAT_USDT",
      "longIntervalHours": 1,
      "shortIntervalHours": 4,
      "longPricesAsOf": "2026-09-26T23:50:38.000Z",
      "shortPricesAsOf": "2026-09-26T23:50:41.000Z"
    }
  ],
  "pagination": { "cursor": "NTA", "has_more": true, "total": 1017 },
  "meta": {
    "request_id": "req_def456ghi789jklm",
    "timestamp": "2026-09-26T23:51:19.000Z",
    "elapsed_ms": 12
  }
}

Formulas

All rates are decimal fractions. Each leg's funding rate is per its own market's interval (longIntervalHours, shortIntervalHours); both are normalized to hourly before they are compared, so mixed 1h/4h/8h legs compare correctly. A tool that annualizes every rate as if it were 8-hourly shows a 1-hour leg 8× smaller and a 4-hour leg 2× smaller than it pays.

  • netFundingRate = (shortRate / shortIntervalHours − longRate / longIntervalHours) × intervalHours, at the faster leg's cadence (intervalHours).
  • apr = |netFundingRate| × 8760 / intervalHours (gross, simple).
  • spreadRate = (longAsk − shortBid) / midpoint from both books (spreadSource: book), else from last or mark prices (reference), else null. Prices are per asset unit (a 1000PEPE contract's price ÷ 1000).
  • roundTripFeeRate = 2 × long-venue taker fee + 2 × short-venue taker fee, each venue's standard (VIP 0) perpetual rate.
  • netApr = apr − (roundTripFeeRate + max(spreadRate, 0)) × 365 / 30, only on book-priced rows. A favourable (negative) spread is never credited as income.
  • breakEvenDays = (roundTripFeeRate + max(spreadRate, 0)) ÷ (apr / 365); null without a netApr.

A row is executable when its spread is book-priced, the legs' prices are within 5% of each other, both quotes are at most 10 minutes old at the time of the request, and both venues report top-of-book depth of at least $10,000. Unknown depth is not evidence of a fill. Otherwise it is indicative. The board ranks executable rows first, then no_depth rows, then the other indicative rows:

indicativeReasonMeaning
unpricedA leg has no price at all. netApr is null.
reference_onlyA leg has no book: the spread comes from last or mark prices, so netApr is null.
price_gapThe legs are 5–20% apart (netApr kept) or more than 20% apart (likely two instruments: netApr is null).
thin_bookA venue reports top-of-book depth under $10,000.
stale_quoteA leg's quote is older than 10 minutes at the time of the request.
oi_below_notionalA venue reports open interest under $10,000 on its leg. Unknown open interest is no evidence either way.
no_depthEvery other check passes, but a venue reports no top-of-book size, so the fill at $10,000 is unproven.
identity_mismatch, not_live, contract_type, margin_typeThe pair check failed on identity, trading status or contract terms.

Response fields

Each object in the data array is the chosen long/short pair for one asset.

  • Name
    symbol
    Type
    string
    Description

    The base asset ticker (e.g., BTC, ETH, TSLA).

  • Name
    assetClass
    Type
    string
    Description

    Underlying category: crypto, equity, commodity, fx, or index. A pair's two legs always share it.

  • Name
    longExchange
    Type
    string
    Description

    The exchange where you open the long position (receiving funding or paying the least).

  • Name
    shortExchange
    Type
    string
    Description

    The exchange where you open the short position (receiving the most funding).

  • Name
    longSymbol
    Type
    string | null
    Description

    The long venue's own contract symbol (e.g. 1000PEPEUSDT, kPEPE).

  • Name
    shortSymbol
    Type
    string | null
    Description

    The short venue's own contract symbol.

  • Name
    longRate
    Type
    number
    Description

    Current funding rate on the long leg, per longIntervalHours.

  • Name
    shortRate
    Type
    number
    Description

    Current funding rate on the short leg, per shortIntervalHours.

  • Name
    longIntervalHours
    Type
    number | null
    Description

    The long leg's own funding interval in hours.

  • Name
    shortIntervalHours
    Type
    number | null
    Description

    The short leg's own funding interval in hours.

  • Name
    netFundingRate
    Type
    number
    Description

    The differential you collect per intervalHours period (see Formulas).

  • Name
    intervalHours
    Type
    number
    Description

    The faster of the two legs' intervals: the cadence netFundingRate is expressed at.

  • Name
    apr
    Type
    number
    Description

    Gross annualized funding differential. Fees and the entry spread are charged in netApr.

  • Name
    grossApr
    Type
    number
    Description

    Deprecated alias of apr.

  • Name
    netApr
    Type
    number | null
    Description

    apr after both venues' taker fees and the adverse entry spread over a 30-day hold. Present only on book-priced rows; every executable row has one.

  • Name
    roundTripFeeRate
    Type
    number | null
    Description

    Two perpetual taker fills on each venue at its standard fee, as a fraction of notional.

  • Name
    breakEvenDays
    Type
    number | null
    Description

    Days of carry that pay back the fees and adverse entry spread. null without a netApr.

  • Name
    spreadRate
    Type
    number | null
    Description

    Signed entry spread (see Formulas); null when either leg has no price.

  • Name
    spreadSource
    Type
    string | null
    Description

    book (both order books), reference (last or mark prices), or null.

  • Name
    longAsk
    Type
    number | null
    Description

    Best ask on the long venue, per asset unit.

  • Name
    shortBid
    Type
    number | null
    Description

    Best bid on the short venue, per asset unit.

  • Name
    executableDepthUsd
    Type
    number | null
    Description

    The smaller of the long venue's ask size and the short venue's bid size in USD, among the venues that report one. With only one venue reporting it is that leg's figure, an upper bound, and the row is indicative; null when neither venue reports depth.

  • Name
    holdingDays
    Type
    number
    Description

    Cost-amortization horizon for netApr. Currently 30.

  • Name
    executionStatus
    Type
    string
    Description

    executable or indicative (see Formulas). Indicative rows keep every figure and rank below executable ones.

  • Name
    indicativeReason
    Type
    string | null
    Description

    Why the row is indicative (table above); null when executable.

  • Name
    pairStatus
    Type
    string
    Description

    Whether the legs are one instrument: eligible, unpriced (a leg has no price to check), else the first check that failed: identity_mismatch, not_live, contract_type, margin_type or price_gap (more than 20% apart).

  • Name
    oiLong
    Type
    number | null
    Description

    Open interest in USD on the long leg, from the venue's ticker, else the contract's latest stored open interest. null when unknown, never 0.

  • Name
    oiShort
    Type
    number | null
    Description

    Open interest in USD on the short leg. null when unknown, never 0.

  • Name
    volumeLong24hUsd
    Type
    number | null
    Description

    24h perp turnover in USD on the long leg, or null when the venue does not report it.

  • Name
    volumeShort24hUsd
    Type
    number | null
    Description

    24h perp turnover in USD on the short leg, or null when unknown.

  • Name
    nextSettlement
    Type
    string | null
    Description

    ISO 8601 time of the sooner of the two legs' next settlements, or null when neither venue reports it.

  • Name
    longNextSettlement
    Type
    string | null
    Description

    The long leg's own next settlement. On a mixed-interval pair (4h against 8h) the slower leg's larger print lands at its own time, which nextSettlement does not show.

  • Name
    shortNextSettlement
    Type
    string | null
    Description

    The short leg's own next settlement, or null when the venue does not report it.

  • Name
    fundingAsOf
    Type
    string | null
    Description

    ISO 8601 time the older leg's funding rate was written.

  • Name
    pricesAsOf
    Type
    string | null
    Description

    When the older of the two legs' quotes was read; null when neither leg has a quote.

  • Name
    longPricesAsOf
    Type
    string | null
    Description

    When the long venue's quote was read.

  • Name
    shortPricesAsOf
    Type
    string | null
    Description

    When the short venue's quote was read.

Indicative row (a leg without a price)

{
  "symbol": "BTC",
  "assetClass": "crypto",
  "longExchange": "Aster",
  "shortExchange": "Extended",
  "longRate": -0.00012237,
  "shortRate": 0.000013,
  "netFundingRate": 0.00002829625,
  "apr": 0.24787515,
  "grossApr": 0.24787515,
  "netApr": null,
  "spreadRate": null,
  "spreadSource": null,
  "longAsk": 84393.1,
  "shortBid": null,
  "executableDepthUsd": null,
  "holdingDays": 30,
  "executionStatus": "indicative",
  "oiLong": null,
  "oiShort": 42173242.55,
  "volumeLong24hUsd": 139787090.28,
  "volumeShort24hUsd": null,
  "nextSettlement": "2026-09-27T00:00:00.000Z",
  "intervalHours": 1,
  "pairStatus": "unpriced",
  "fundingAsOf": "2026-09-26T23:47:05.000Z",
  "pricesAsOf": "2026-09-26T23:50:38.000Z",
  "indicativeReason": "unpriced",
  "roundTripFeeRate": 0.0013,
  "breakEvenDays": null,
  "longSymbol": "BTCUSDT",
  "shortSymbol": "BTC-USD",
  "longIntervalHours": 8,
  "shortIntervalHours": 1,
  "longPricesAsOf": "2026-09-26T23:50:38.000Z",
  "shortPricesAsOf": null
}

Was this page helpful?