Ethena — the protocol behind the USDe “synthetic dollar” — is essentially one trade repeated at enormous scale: hold spot crypto, short the same amount of perpetual futures, and collect the funding payments that longs push to shorts. In 2024 that ETH basis trade returned about 13% APY on an open-interest-weighted basis, per Ethena’s own documentation. In 2022 it returned 0.6%. That spread between a great year and a dead year is the entire story of this strategy, and you should hold both numbers in your head at the same time.

The good news: you do not need a protocol, a token, or permission to run the same trade at your own size. You need two accounts, a spreadsheet’s worth of discipline, and a screener that tells you where funding is actually worth collecting right now. This article gives you the mechanics, a tested Python screener (it ran live, no API keys, on the day this was published), the real fee math, and — because every “beat the market” pitch owes you this — the exact conditions under which this trade quietly bleeds you.

The trade in one paragraph

Buy 1 BTC spot. Short 1 BTC of BTC perpetual futures. You are now price-neutral: if BTC rises 20%, the spot gains what the short loses, and vice versa. But the perp contract has a funding rate — a periodic payment between longs and shorts that keeps the perp pinned to spot. When the market is long-biased (most of the time, because most people borrow leverage by going long perps), funding is positive and shorts collect it. You are collecting rent on your coins instead of betting on their price. Your return = funding collected + the basis you captured at entry − fees − the periods when funding turns against you.

This is not a hack and not grey area — it is the oldest trade in crypto derivatives, and exchanges pay it out automatically to anyone holding the position at the funding timestamp. The “aggressive” part is doing it deliberately, across multiple venues, with a screener instead of vibes.

Where the money comes from

Perpetual futures never expire, so exchanges invented funding to stop perps drifting far from spot. The mechanics differ slightly per venue but the essence is the same:

  • On Binance, Bybit, OKX and Gate, the standard funding interval is every 8 hours. The rate combines a fixed interest component (0.01% per 8 hours by default) with a premium term that pushes the perp back toward spot. When longs are greedy and the perp trades above spot, funding goes up and shorts get paid more.
  • On Hyperliquid, funding is computed on an 8-hour window but paid every hour at one-eighth of the rate — its docs quote the interest component at 0.01% per 8 hours, which on its own is worth roughly 11% a year if that floor were the only thing funding ever paid.

Who pays you? Leveraged longs. Retail traders who want 5x exposure on a perp, basis traders who got their direction wrong, and premia chasers. When crypto sentiment is bullish, longs outnumber shorts, the perp trades at a premium, and funding sits comfortably positive. That premium is your income stream — you are being paid to provide the short side that leveraged traders demand.

The honest benchmark for what this pays: Ethena’s published history for the ETH basis trade is 16% APY in 2021, 0.6% in 2022, ~9% in 2023, ~13% in 2024. A diversified basket of coins and venues will smooth that a bit, but a 4–12% net range in a normal year is the realistic band. The screener below shows you which specific leg was paying what on the day of writing.

What the screener found on 26 October 2026

The script below (real output, live public endpoints, no API keys) scanned BTC, ETH and SOL across Binance, Bybit, OKX, Gate and Hyperliquid:

Funding-Rate Carry Screener — long spot / short perp (2026-10-26 04:18 WIB)
==========================================================================
venue        pair     fnd/8h  intv    APY%    basis   fees%  netAPR%  brkEven
--------------------------------------------------------------------------
bybit        SOL      0.0100    8h   10.95    -3.9b   0.310    10.64    10.3d
hyperliquid  ETH      0.0013    1h   10.95     5.8b   0.230    10.72     7.7d
hyperliquid  SOL      0.0013    1h   10.95     6.4b   0.230    10.72     7.7d
bybit        ETH      0.0093    8h   10.22    -4.5b   0.310     9.91    11.1d
binance      ETH      0.0089    8h    9.79    -4.1b   0.300     9.49    11.2d
binance      SOL      0.0086    8h    9.39    -3.5b   0.300     9.09    11.7d
okx          BTC      0.0083    8h    9.14    -4.0b   0.300     8.84    12.0d
bybit        BTC      0.0070    8h    7.63    -3.7b   0.310     7.32    14.8d
gate         ETH      0.0067    8h    7.34    -3.9b   0.500     6.84    24.9d
okx          ETH      0.0053    8h    5.83    -5.2b   0.300     5.53    18.8d
gate         BTC      0.0045    8h    4.93    -4.3b   0.500     4.43    37.0d
binance      BTC      0.0038    8h    4.20    -4.6b   0.300     3.90    26.1d
hyperliquid  BTC      0.0004    1h    3.87     8.2b   0.230     3.64    21.7d
--------------------------------------------------------------------------
APY = today's rate annualized (funding floats every interval — it WILL move).

How to read it:

  • APY% annualizes today’s funding rate at the venue’s interval. Today it says 10.95% for SOL on Bybit; next month it may say 3%. That is the deal — you accept a floating rate.
  • basis is the perp-minus-spot spread in basis points at the moment of the scan. You buy spot and short the perp simultaneously, so a positive basis (Hyperliquid ETH and SOL that morning) is an instant markup you pocket, and a negative basis (almost every CEX leg, −3 to −5 bps that day) is an instant cost you eat on entry.
  • fees% is the full round trip at taker rates: buy spot, sell spot, open perp, close perp. Binance/OKX legs cost 0.30% all-in, Bybit 0.31%, Hyperliquid ~0.23% (its spot taker fee is low and both legs live on one venue), Gate 0.50% — which is why Gate only makes sense when its funding is meaningfully fatter.
  • brkEven is the most important column: how many days of today’s funding you need just to pay those round-trip fees. Hyperliquid ETH needs 7.7 days. Gate BTC needs 37 days. If you think you might unwind in two weeks, Gate BTC at 4.9% APY is a losing trade before it starts.

Note what the table is really telling you: funding rates converge across venues (they are all pricing the same long demand), so venue choice is mostly a fee decision, and coin choice is a who-is-most-leveraged decision. SOL and ETH were paying nearly double BTC’s rate that morning because their perp markets run hotter.

The screener code (tested — ran with exit code 0 before publishing)

No paid API keys. It uses ccxt against public endpoints of all five venues, handles the annoying details (Gate reports its funding interval in seconds, Bybit in minutes, Hyperliquid’s API returns hourly rates, OKX omits the price on its funding endpoint so we fetch the perp ticker separately), and exits 0 when at least one leg clears your minimum APY filter — so you can wire it into a daily cron and get an alert only when the trade is actually worth opening.

#!/usr/bin/env python3
"""
Funding-Rate Carry Screener (long spot, short perp) — public data only, no API keys.

For each spot/perp pair it checks, live:
  1. The perp funding rate (what you collect as the short) and the venue's
     funding interval (8h on Binance/Bybit/OKX/Gate, 1h on Hyperliquid).
  2. The spot/perp basis: perp price vs spot price. You buy spot and short the
     perp at the SAME moment, so a positive basis is an instant bonus and a
     negative basis is an instant loss you must price in.
  3. Round-trip taker fees (spot buy + spot sell + perp open + perp close) so
     the "costs" column is real, not hand-waved.

Usage:
  python3 funding_carry_screener.py                 # default list
  python3 funding_carry_screener.py BTC ETH SOL     # custom symbols
  FUNDING_MIN_APY=15 python3 funding_carry_screener.py   # only rows >= 15% APY

Tested on 2026-10-26 with ccxt 4.5.90, live public endpoints, no API keys.
"""

import os
import sys
import time
import csv
import statistics
from datetime import datetime, timezone

import ccxt

# --- venues: (exchange id, spot symbol, perp symbol) --------------------------
# All four charge funding every 8 hours by default and need no API key for
# public market data. Funding APY = rate * (24 / interval_hours) * 365.
VENUES = [
    ("binance", "BTC/USDT", "BTC/USDT:USDT"),
    ("binance", "ETH/USDT", "ETH/USDT:USDT"),
    ("binance", "SOL/USDT", "SOL/USDT:USDT"),
    ("bybit",   "BTC/USDT", "BTC/USDT:USDT"),
    ("bybit",   "ETH/USDT", "ETH/USDT:USDT"),
    ("bybit",   "SOL/USDT", "SOL/USDT:USDT"),
    ("okx",     "BTC/USDT", "BTC/USDT:USDT"),
    ("okx",     "ETH/USDT", "ETH/USDT:USDT"),
    ("gate",    "BTC/USDT", "BTC/USDT:USDT"),
    ("gate",    "ETH/USDT", "ETH/USDT:USDT"),
    # Hyperliquid: spot AND perp on one venue — no transfer risk between legs.
    ("hyperliquid", "BTC/USDC", "BTC/USDC:USDC"),
    ("hyperliquid", "ETH/USDC", "ETH/USDC:USDC"),
    ("hyperliquid", "SOL/USDC", "SOL/USDC:USDC"),
]

# Hyperliquid computes funding over an 8h window but PAYS every hour at 1/8;
# its API "funding" field is the current HOURLY rate
# (docs: hyperliquid.gitbook.io -> Trading -> Funding).
INTERVAL_OVERRIDES = {"hyperliquid": 1.0}

# Round-trip taker fees as decimal fractions (verify against each venue's fee
# page — these are the standard VIP0 numbers as of Oct 2026; tiers change).
TAKER = {
    "binance": {"spot": 0.0010, "perp": 0.0005},
    "bybit":   {"spot": 0.0010, "perp": 0.00055},
    "okx":     {"spot": 0.0010, "perp": 0.0005},
    "gate":    {"spot": 0.0020, "perp": 0.0005},  # 0.10-0.20% by source; conservative
    "hyperliquid": {"spot": 0.0007, "perp": 0.00045},  # spot 0.07% conservative (sources 0.035-0.07%)
}

MIN_APY = float(os.environ.get("FUNDING_MIN_APY", "0"))  # filter, percent


def funding_interval_hours(exchange: ccxt.Exchange, perp_symbol: str) -> float:
    """Best-effort funding interval. Binance/OKX/Gate default 8h; read the
    raw payload where ccxt exposes it, fall back to 8h (Binance's documented
    default) with a printed warning so nothing is silently assumed."""
    if exchange.id in INTERVAL_OVERRIDES:
        return INTERVAL_OVERRIDES[exchange.id]
    raw = {}
    try:
        fr = exchange.fetch_funding_rate(perp_symbol)
        raw = fr.get("info", {}) or {}
    except Exception as exc:
        raise RuntimeError(f"fetch_funding_rate failed: {exc}") from exc
    # bybit/gate/okx expose the interval in different fields AND units:
    # bybit "fundingInterval": 480 (minutes), gate "funding_interval": 28800 (seconds)
    for key in ("fundingInterval", "funding_interval"):
        v = raw.get(key)
        if v:
            v = float(v)
            if v >= 1440:          # seconds (e.g. gate 28800 -> 8h)
                return v / 3600.0
            return v / 60.0        # minutes (e.g. bybit 480 -> 8h)
    return 8.0


def scan(exchange_id: str, spot_symbol: str, perp_symbol: str) -> dict | None:
    ex = getattr(ccxt, exchange_id)({"enableRateLimit": True, "timeout": 20000})
    try:
        ex.load_markets()
        fr = ex.fetch_funding_rate(perp_symbol)
        funding = fr["fundingRate"]                       # fraction per interval
        perp_price = fr.get("markPrice") or fr.get("last")
        if not perp_price:  # some venues (OKX) omit price on fetchFundingRate
            perp_price = (ex.fetch_ticker(perp_symbol) or {}).get("last")
        spot = ex.fetch_ticker(spot_symbol)
        spot_price = spot["last"]
        if not (funding and perp_price and spot_price):
            return None

        interval_h = funding_interval_hours(ex, perp_symbol)
        apy = funding * (24.0 / interval_h) * 365.0 * 100.0  # percent
        basis_bps = (perp_price - spot_price) / spot_price * 10_000  # + = bonus

        # round-trip cost: buy+sell spot, open+close perp (taker, both sides)
        rt_cost_pct = (TAKER[exchange_id]["spot"] * 2 + TAKER[exchange_id]["perp"] * 2) * 100.0

        # net carry if you held one full year at today's rate, % of notional
        net_apr = apy - rt_cost_pct

        return {
            "venue": exchange_id,
            "pair": spot_symbol.split("/")[0],
            "funding_8h_pct": funding * 100.0,
            "interval_h": interval_h,
            "funding_apy_pct": apy,
            "basis_bps": basis_bps,
            "roundtrip_fee_pct": rt_cost_pct,
            "net_apr_pct": net_apr,
            "perp_price": perp_price,
            "spot_price": spot_price,
        }
    finally:
        try:
            ex.close()
        except Exception:
            pass


def breakeven_days(row: dict) -> float | None:
    """Days of today's funding needed to pay the round-trip fees."""
    if row["funding_apy_pct"] <= 0:
        return None
    return row["roundtrip_fee_pct"] / row["funding_apy_pct"] * 365.0


def main() -> int:
    wanted = {a.upper() for a in sys.argv[1:]}   # e.g. `BTC ETH` filters the venue list
    rows = []
    for venue, spot_sym, perp_sym in VENUES:
        if wanted and spot_sym.split("/")[0].upper() not in wanted:
            continue
        try:
            row = scan(venue, spot_sym, perp_sym)
        except Exception as exc:
            print(f"  [skip] {venue} {spot_sym}: {exc}", file=sys.stderr)
            time.sleep(1)
            continue
        if row:
            rows.append(row)
        time.sleep(0.4)

    if not rows:
        print("No data — endpoints unreachable or symbols changed. Aborting.")
        return 1

    rows.sort(key=lambda r: r["funding_apy_pct"], reverse=True)
    shown = [r for r in rows if r["funding_apy_pct"] >= MIN_APY]

    print(f"\nFunding-Rate Carry Screener — long spot / short perp "
          f"({datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M UTC')})")
    print("=" * 118)
    hdr = (f"{'venue':<13}{'pair':<6}{'fnd/8h':>9}{'intv':>6}{'APY%':>8}"
           f"{'basis':>9}{'fees%':>8}{'netAPR%':>9}{'brkEven':>9}")
    print(hdr)
    print("-" * 122)
    for r in shown:
        be = breakeven_days(r)
        be_s = f"{be:.1f}d" if be is not None else "n/a"
        print(f"{r['venue']:<13}{r['pair']:<6}{r['funding_8h_pct']:>9.4f}"
              f"{r['interval_h']:>5.0f}h{r['funding_apy_pct']:>8.2f}"
              f"{r['basis_bps']:>8.1f}b{r['roundtrip_fee_pct']:>8.3f}"
              f"{r['net_apr_pct']:>9.2f}{be_s:>9}")
    print("-" * 122)
    print("APY = today's rate annualized (funding floats every interval — it WILL move).")
    print("basis > 0 = instant markup captured at entry; basis < 0 = instant cost.")
    print("brkEven = days of funding needed just to pay the round-trip fees.\n")

    out_csv = os.environ.get("FUNDING_CSV", "")
    if out_csv and shown:
        with open(out_csv, "w", newline="") as f:
            w = csv.DictWriter(f, fieldnames=list(rows[0].keys()))
            w.writeheader()
            w.writerows(shown)
        print(f"CSV written: {out_csv}")

    # exit code: 0 = at least one venue above MIN_APY (a tradeable signal), else 2
    if shown:
        return 0
    best = max((r["funding_apy_pct"] for r in rows), default=0.0)
    print(f"No venue above {MIN_APY}% APY (best: {best:.2f}%).")
    return 2


if __name__ == "__main__":
    sys.exit(main())

Install once with pip install ccxt, then run the three modes that all got exercised before this article shipped: the full scan (exit 0, table above), the filtered scan (FUNDING_MIN_APY=9 python3 funding_carry_screener.py — exit 0 with three rows above the bar that morning), and the “nothing clears the bar” case (FUNDING_MIN_APY=50 — correctly exits 2 with no rows, which is what makes it cron-friendly: no news is no alert). Add FUNDING_CSV=history.csv and run it daily from cron to build your own funding-rate history — after a month you will know whether current rates are fat or thin by your own data instead of Twitter’s.

One disclosure for honesty’s sake: this script only reads public market data, so it needed no mocking at all — every number in the table came from a live endpoint the day of publishing. The fee constants inside are VIP0 list prices (Binance perps 0.02%/0.05%, Bybit 0.055% perp taker, Hyperliquid 0.045% perp taker with spot around 0.035–0.07% depending on the quote pair, Gate taken at the conservative 0.20% spot because sources disagree) — check your own tier before trusting the fees column to the last decimal.

Scaling it: what thousands per month actually requires

This is a balance-sheet game, and it is important to say that plainly. At the rates in the table, $10,000 deployed at ~9% net produces roughly $900 a year — about $75 a month. To clear thousands of dollars per month you need somewhere in the range of $150,000–$400,000 of capital working across the best-paying legs. The people making real money on funding carry are not smarter, they are bigger; Ethena’s entire business is this trade with a billion-dollar balance sheet.

Three force multipliers that don’t require more capital:

  • Capture the basis, don’t pay it. The screener shows basis per leg. When a perp trades 5–10 bps above spot, entering there hands you an instant bonus equal to weeks of funding. Hyperliquid ETH and SOL had a positive basis that morning; the CEX legs did not. Patience is an edge: screen daily and only open legs that are positive on both funding and basis.
  • Hyperliquid puts both legs in one place. Spot and perp on the same venue means no transfer time between exchanges, which matters most at entry (your unhedged window is seconds, not minutes) and in a crash, when moving collateral between venues is exactly what you cannot do quickly. BTC funding was thin there that day, but ETH and SOL matched the best CEX rates with a quarter of the fee drag.
  • Run it inside a tax-advantaged or coin-heavy portfolio. If you already hold BTC or ETH long-term, converting part of the stack into this carry doesn’t add capital — it makes existing coins pay rent. The coins stay yours; the price exposure stays identical; the funding is incremental income on assets you were keeping anyway. Every funding payment and every round-trip is a taxable event in most jurisdictions, so keep the CSV log — it is your tax record, not just a history file.

When this trade bleeds (read this twice)

  • Funding turns negative. When the market panics, shorts become the crowded side and you pay. This is not theoretical: during the August 2024 crash funding went negative across major venues hard enough that Ethena’s sUSDe yield — the same trade, diversified — hit its all-time low of 4.1%. Your screen tells you today’s rate; it cannot tell you next month’s. Anyone quoting you a fixed APY on this trade is lying.
  • Crash regimes are double trouble. On October 10, 2025, more than $19 billion of leveraged positions were liquidated in a single day. In events like that, perps wick far below spot, funding spikes negative, and exchanges have been known to throttle withdrawals exactly when you need to rebalance. The delta-neutral position survives the price move, but the funding cash flow and the venue plumbing both take damage at the worst time. Keep perp leverage at 1–2x (you are hedged; leverage only adds liquidation risk, it doesn’t add carry) and keep a cash buffer on the short venue.
  • Basis risk at entry. The −4 to −6 bps basis on the CEX legs in today’s scan is a real cost: you short at a discount. It is small, but it is part of why the brkEven column exists.
  • Venue and custody risk. This trade stores your coins on an exchange and margin on another. That is two counterparties you trust simultaneously. Hyperliquid’s single-venue structure removes the leg-mismatch risk but concentrates custody in one protocol. There is no configuration with zero trust — pick your poison consciously.
  • The interval mismatch. Hyperliquid pays hourly, everyone else every 8 hours. In fast markets, an 8-hour settlement means your carry lags reality by up to 8 hours — you can watch funding go negative and still be paying the old positive rate, or vice versa. This is a feature for you when rates are falling, and a bug when they spike.

Who should skip this

The UK’s FCA bans retail crypto derivatives outright, Binance and Bybit do not serve US residents, and Indonesia’s crypto oversight moved to OJK in January 2025 — offshore venues without a local license can be blocked, and gains are taxable. If your jurisdiction forces you to VPN around a geoblock: don’t. An exchange freezing one leg of a hedged pair leaves you naked on the other, which converts a boring carry trade into a directional bet at the worst possible moment.

And if you have $2,000 to your name, the honest math says this trade earns you coffee money. The screener is free and the knowledge compounds, but the actual income scales with capital. Start running it to learn; scale it when you have the balance sheet.

The unsexy truth of funding carry: it is the closest thing crypto has to collecting rent. The tenant (leveraged longs) pays on schedule, the property (your coins) never leaves your name, and the screen tells you which neighborhood is paying best this week. Just never forget the tenant sometimes stops paying — and know in advance how many weeks of empty rent (your breakeven days) you can absorb.