Research

Crypto Derivatives Complete Guide for AI Agents: Futures, Options, Perps, and Structured Products

March 6, 2026 Purple Flea Research Team 28 min read

Crypto derivatives are the most powerful and most misunderstood tools in an agent's trading arsenal. The market has evolved from simple quarterly futures into a vast ecosystem of perpetuals, structured products, options on realized volatility, and synthetic instruments—each with distinct risk, return, and operational characteristics.

This guide is a systematic taxonomy of crypto derivatives from first principles, covering how each instrument works, how they differ from each other, and how AI agents can combine them into sophisticated multi-leg strategies. We conclude with a complete Python derivatives agent capable of running basis trades, calendar spreads, and options strategies using Purple Flea's 275-market perp API.

275
Purple Flea perp markets
100x
Max leverage (BTC perp)
$2.3T
Daily crypto deriv volume
8h
Standard funding interval

Derivatives Taxonomy

Crypto derivatives fall into four primary categories, each with sub-types. Understanding which instrument fits which strategy is the first step to building a profitable derivatives agent.

Futures Date-Expiry

Agreement to buy/sell an asset at a set price on a specific future date. Price converges to spot at expiry. Used for hedging, basis trading, and calendar spreads. Key venues: CME, Deribit, OKX quarterly futures.

Perpetual Swaps No Expiry

Like futures but with no expiry date. Instead, a funding rate is paid between longs and shorts every 8 hours to keep price anchored to spot. The dominant crypto derivative by volume. 275 markets on Purple Flea via Hyperliquid.

Options Non-Linear

Right (not obligation) to buy (call) or sell (put) at a strike price by expiry. Non-linear payoff. Used for volatility trading, protection, and income via covered calls. Key venues: Deribit, Lyra, Premia.

Structured Products Packaged

Pre-packaged combinations of derivatives and cash instruments. Examples: dual-currency investments, principal-protected notes, range accruals. Offered by centralized exchanges as yield products.

Futures vs. Perpetuals: Deep Comparison

Futures and perpetuals are both linear derivatives (payoff moves 1:1 with price), but differ fundamentally in their mechanics and use cases.

DimensionFuturesPerpetuals
ExpiryFixed date (weekly/quarterly)None
BasisConverges to 0 at expiryControlled by funding rate
Holding costEmbedded in basis (cash-carry)Explicit 8h funding payments
LiquidityConcentrated near front monthContinuous, highest in market
Strategy useBasis trade, calendar spreadDirectional, funding harvest
Mark priceFair value via cost of carryImpact price + funding tweak
SettlementPhysical or cash at expiryOngoing P&L, no final settle
Purple FleaVia Hyperliquid integration275 markets directly

The Funding Rate Mechanism

Perpetuals stay anchored to spot via the funding rate—a periodic payment between longs and shorts. When perp trades above spot (contango), longs pay shorts; when perp trades below spot (backwardation), shorts pay longs. The formula:

Funding Rate Formula (Binance/Hyperliquid model)
premium_index = (mark_price - spot_index) / spot_index funding_rate = clamp(premium_index + clamp(interest_rate - premium_index, -0.05%, 0.05%), -0.75%, 0.75%) # Annualized funding yield: annual_funding_yield = funding_rate * (365 * 24 / 8) # 8h intervals # At 0.01% per 8h: 0.01% * 1095 = 10.95% APY

For agents, positive annualized funding rates (contango) represent a yield opportunity when combined with a spot hedge. This is the basis of funding rate harvesting—one of the most consistent edge cases in crypto.

Basis Trading

The basis is the price difference between a futures or perp contract and the underlying spot asset. In normal conditions (contango), futures trade above spot because buyers are paying for deferred delivery and associated carry costs. Basis traders profit from this spread converging to zero at expiry.

Cash-and-Carry (Classic Basis Trade)

The cash-and-carry trade is the textbook basis strategy:

  1. Buy 1 BTC spot.
  2. Simultaneously sell 1 BTC futures at a higher price.
  3. Hold until futures expiry; profit = (futures price - spot price) - carry costs.
  4. At expiry, both positions converge to the same price; deliver or cash settle.
Basis Trade Return Calculation
basis_at_entry = futures_price - spot_price carry_cost = spot_price * (risk_free_rate + storage) * (days_to_expiry / 365) net_basis = basis_at_entry - carry_cost annualized_return = (net_basis / spot_price) / (days_to_expiry / 365) # Example: BTC spot $95,000; Dec futures $97,500; 90 days # basis = $2,500; carry = $95,000 * 5% * (90/365) = $1,171 # net = $1,329; annualized = ($1,329/$95,000) / (90/365) = 5.69%

Perpetual Funding Harvest (Basis Proxy)

With perps, basis trading takes the form of funding harvesting—being short the perp and long spot, collecting funding payments when the perp is in contango:

Funding Harvest P&L
position_size = $100,000 notional funding_rate_8h = 0.012% (annualized: ~13.1%) daily_funding_usd = position_size * (funding_rate_8h * 3) = $100,000 * 0.036% = $36/day = $13,140/year # Net yield after hedging cost: net_yield = annual_funding - borrowing_cost - gas - slippage = 13.1% - 0.5% - 0.3% - 0.2% = 12.1% APY
Purple Flea Perps for Funding Harvest

Purple Flea provides access to 275 perp markets via Hyperliquid integration. Agents can systematically scan all markets for the highest funding rates, rank by risk-adjusted yield, and automatically execute delta-neutral short positions while holding spot via the Wallet API. See the Trading API docs.

Calendar Spreads

A calendar spread is simultaneously long and short futures at different expiry dates on the same underlying. Calendar spreads trade the shape of the futures term structure rather than the outright price direction.

Term Structure Mechanics

The futures term structure describes how prices vary across expiry dates. Three configurations:

  • Contango (normal): Far-dated futures > near-dated futures > spot. Positive carry; longs pay to hold.
  • Backwardation: Spot > near > far. Negative carry; shorts pay longs. Often signals supply tightness.
  • Humped: Near futures expensive relative to far. Often occurs near expiry squeezes or spot delivery pressure.
Calendar Spread P&L
long_front_month = buy Jun-26 BTC futures at $94,500 short_back_month = sell Sep-26 BTC futures at $96,200 initial_spread = Sep - Jun = $1,700 # If market shifts to backwardation (spread compresses): new_spread = Sep - Jun = $800 spread_P&L = ($1,700 - $800) = $900 per BTC profit # (long near = gained; short far = gained as far fell more)

Agent Calendar Spread Strategies

Agents are ideally suited for calendar spreads because they require continuous monitoring of term structure across multiple expiry dates. Key signals:

SignalTradeRationale
Steep contango (>8% annual)Long near, short farSpread likely to compress; near rolls up faster
Backwardation emergingShort near, long farNear premium disappears as delivery approaches
Flat term structureNo calendar positionInsufficient spread to justify transaction costs
Expiry week squeezeLong expiring monthBasis tends to spike into forced closeouts
Post-expiry resetShort new front monthNew front typically opens at discount

Options: Greeks and Strategies

Crypto options are the most complex derivatives in the market and offer the richest strategy space. Unlike linear instruments, options have non-linear payoffs shaped by five key sensitivities (the Greeks).

The Greeks for Agent Systems

GreekSymbolMeasuresAgent Use
DeltaΔPrice sensitivity to underlying moveDelta-hedging, directional sizing
GammaΓRate of delta changeGamma scalping, expiry positioning
ThetaΘTime decay per dayShort options for income, theta collection
VegaνSensitivity to IV changeVolatility trading, IV mean reversion
RhoρSensitivity to interest ratesLess critical in crypto; DeFi rate monitoring

Implied Volatility (IV) and Skew

Implied volatility is the market's consensus forecast of future price volatility, derived by inverting the Black-Scholes model. In crypto, IV typically ranges from 40% to 200% annualized—far higher than equity markets.

IV skew describes how IV varies across strikes at the same expiry. In crypto, the skew has historically shown:

  • Right skew (calls expensive): Dominant in bull markets; demand for upside leverage bids up call IV.
  • Left skew (puts expensive): During fear periods; agents and institutions buy put protection, bidding up put IV.
  • Flat skew: Neutral market; IV roughly equal across strikes. Ideal for strangle selling.
25-Delta Risk Reversal (Skew Measure)
RR = IV(25-delta call) - IV(25-delta put) # Positive RR = right skew (calls expensive, market bullish) # Negative RR = left skew (puts expensive, market fearful) # Example: BTC 30-day RR = +12% # 25D call IV = 78%; 25D put IV = 66% # Strategy: sell calls (expensive), buy puts (cheap) + spot long

Volatility Term Structure

Just as futures have a price term structure across expiries, options have a volatility term structure (IV varying by expiry). Agents can trade across term structure axes:

ExpiryTypical BTC IVDecay RateBest Strategy
1 week55-95%Very fastEvent vol sell (post-event)
1 month50-80%FastShort strangle for theta
3 months55-75%ModerateCalendar spread target
6 months60-70%SlowLong vol on IV compression
1 year60-68%SlowLEAPS, structured products

Core Options Strategies for Agents

Covered Call (Yield Generation): Hold spot BTC, sell out-of-the-money calls to collect premium. Caps upside but generates consistent income in sideways markets. Theta decay works in seller's favor.

Cash-Secured Put (Entry at Discount): Sell puts at a lower strike, collect premium. If BTC falls to strike, buy at an effective discount (strike - premium). If not, keep the premium. Ideal for agents accumulating BTC.

Short Strangle (Volatility Sell): Sell OTM call and OTM put simultaneously. Profits if BTC stays range-bound. Best when IV is elevated vs. realized volatility (sell the fear premium).

Gamma Scalping (Long Straddle + Delta Hedge): Buy ATM straddle (call + put same strike), delta-hedge continuously. Profit if realized volatility exceeds IV paid. Agents excel at this—continuous hedging is operationally impossible for humans.

Structured Products

Structured products are pre-packaged derivatives combinations, typically issued by centralized exchanges as yield instruments. They abstract away options complexity for less sophisticated counterparties—but agents can reverse-engineer them to understand the embedded risk.

Dual Currency Investment (DCI)

A DCI is essentially a cash-secured put disguised as a yield product. The user deposits USDC, chooses a BTC strike and expiry. At expiry:

  • If BTC is above the strike: user gets USDC + premium (no conversion). Yield: 5-30% annualized.
  • If BTC is below the strike: user gets BTC at the strike price (converted). Effective buy at discount minus premium.
DCI: The Hidden Risk

Exchanges that offer DCIs are collecting the option premium and paying users only a portion. An agent should calculate the fair premium using Black-Scholes, compare to the advertised yield, and prefer venues offering the most transparent pricing. Self-executing put sales on Deribit offer the full premium with no intermediary cut.

Principal-Protected Notes

A principal-protected note combines a zero-coupon bond (guaranteeing principal return) with a call option on BTC. The bond accrues to $100 at maturity; the premium difference buys an OTM call. Zero downside, capped upside determined by option notional. DeFi implementations use yield-bearing stablecoins (aUSDC) as the bond component.

Range Accrual Notes

Range accruals pay yield for every day the underlying stays within a defined price range. Days outside the range earn nothing. This is equivalent to selling a series of daily binary options. Agents can replicate them synthetically using daily OTM strangle sales on Deribit.

Synthetic Instruments Using Purple Flea Perps

Purple Flea's 275-market perp API, powered by Hyperliquid, enables agents to construct synthetic instruments that would otherwise require centralized exchange accounts and options markets.

Synthetic Futures (Perp + Spot)

A synthetic futures position can be created by combining a perp position with a spot holding, locking in a forward-like payoff:

Synthetic Long Future Using Perp
synthetic_long_future: - Long 1 BTC via Purple Flea perp - Short 1 BTC spot (borrow or use existing short) - Net: long future exposure, hedged basis # Cost = funding payments received or paid (replaces futures basis) # Use case: when perp funding is negative (backwardation), synthetic future # is cheaper than actual futures + better liquidity

Synthetic Covered Call Using Perps

Without options access, agents can replicate covered call economics by dynamically delta-hedging a spot position with a perp short that scales with spot price moves:

  • Hold 1 BTC spot.
  • Short 0.5 BTC perp (replicating short 0.5 delta of an ATM call).
  • As spot rises, increase short toward 1.0 BTC (full hedge).
  • As spot falls, reduce short toward 0 (full exposure).
  • Collect: funding on short perp (if contango) + net delta-hedging rebalancing P&L.

Cross-Asset Spread Trades

With 275 markets, agents can trade correlations between assets—going long one perp and short another. Classic crypto spread trades:

Spread TradeLongShortRationale
BTC dominance sellETH-PERPBTC-PERPETH/BTC ratio mean reversion in risk-on
L1 vs L2OP-PERP, ARB-PERPETH-PERPL2 token beta historically higher in bull
DeFi vs CeFiUNI-PERP, AAVE-PERPBNB-PERPDeFi beta divergence from exchange tokens
AI sector basketTAO-PERP, FET-PERPBTC-PERPAI narrative vs BTC base during AI runs

Term Structure Arbitrage

When the futures or perp term structure deviates from its fair value based on cost-of-carry, arbitrage opportunities emerge. Agents can systematically scan for these mispricings:

Cash-and-Carry Arbitrage (Perp vs. Spot)

Perp-Spot Arb Detection
perp_premium = (perp_price - spot_price) / spot_price # = basis annual_perp_yield = perp_premium * (365 * 24 / hours_to_check) # If annualized basis > stablecoin lending rate + gas: if annual_perp_yield > (lending_rate + gas_cost / position_size): action = "open_cash_carry" # buy spot, short perp elif annual_perp_yield < -(funding_rate_threshold): action = "reverse_carry" # short spot, long perp

Triangular Futures Arbitrage

When BTC/USDT, ETH/USDT, and ETH/BTC perp prices are inconsistent, a triangular arbitrage locks in risk-free profit:

  • Observe: BTC/USDT = $95,000; ETH/USDT = $3,200; ETH/BTC = 0.0340 (implied $3,230).
  • Implied ETH/USDT via BTC = 0.0340 * $95,000 = $3,230 > $3,200 actual.
  • Trade: buy ETH/USDT perp, sell BTC/USDT perp, sell ETH/BTC perp.
  • Lock $30 per ETH of riskless spread (before fees).

Options Skew Strategies

Skew trading profits when the market's relative pricing of calls vs. puts reverts to historical norms. An agent monitoring skew continuously can identify mispricing before human traders react.

Skew Mean Reversion

Historical BTC 25-delta risk reversal (skew) averages +5% in bull markets and -8% during crypto bear markets. When current skew deviates significantly from the 30-day rolling average, mean-reversion trades have positive historical expectancy:

Skew Z-Score Entry Signal
skew_zscore = (current_rr - rolling_30d_mean_rr) / rolling_30d_std_rr if skew_zscore > 2.0: # Calls abnormally expensive vs puts: sell call spread, buy put spread action = "sell_risk_reversal" elif skew_zscore < -2.0: # Puts abnormally expensive vs calls: buy risk reversal action = "buy_risk_reversal"

IV vs. Realized Vol Harvesting

Implied volatility in crypto historically overestimates realized volatility by 5-15% on average (the "vol risk premium"). Short volatility strategies that sell strangles and delta-hedge continuously extract this premium:

Period30D BTC IV avg30D Realized VolIV Premium
2024 Bull Run68%58%+10%
2024 Correction85%92%-7% (realized > IV)
2025 Stable Period52%41%+11%
2025 ETF Approval110%78%+32%
2026 YTD61%54%+7%

Python Comprehensive Derivatives Agent

The following Python agent monitors Purple Flea's perp markets for basis trading opportunities, implements a funding harvest strategy, and tracks term structure changes to identify calendar spread entries.

Python: Derivatives Agent (Basis + Funding + Calendar)
"""
Purple Flea Derivatives Agent
- Scans 275 perp markets for funding rate opportunities
- Executes delta-neutral basis trades
- Monitors term structure for calendar spread entries
- Tracks options skew data from Deribit API
"""

import asyncio, time, logging, math
from dataclasses import dataclass
from typing import List, Dict, Optional
import requests

logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s')
log = logging.getLogger("deriv-agent")

PF_BASE  = "https://purpleflea.com/api"
PF_TOKEN = "pf_live_your_token_here"

DERIBIT_BASE = "https://www.deribit.com/api/v2"

MIN_FUNDING_APY  = 0.08    # 8% APY minimum to open basis trade
MAX_POSITION_USD = 50_000  # $50k max per perp market
REBALANCE_MINS   = 30      # check portfolio every 30 min
SKEW_Z_THRESHOLD = 2.0    # enter skew trade at 2-sigma deviation

@dataclass
class PerpMarket:
    symbol: str
    funding_rate_8h: float
    mark_price: float
    spot_price: float
    basis_pct: float
    annualized_basis: float
    open_interest_usd: float
    volume_24h_usd: float

@dataclass
class VolSurface:
    symbol: str
    expiry: str
    atm_iv: float
    skew_25d: float     # 25D call IV - 25D put IV
    rv_30d: float        # 30-day realized vol
    iv_premium: float    # atm_iv - rv_30d

class DerivativesAgent:
    def __init__(self):
        self.session  = requests.Session()
        self.session.headers["Authorization"] = f"Bearer {PF_TOKEN}"
        self.positions: Dict[str, float] = {}  # symbol: notional USD
        self.skew_history: Dict[str, List[float]] = {}

    # ---- Purple Flea API calls ----

    def get_all_perp_markets(self) -> List[PerpMarket]:
        r = self.session.get(f"{PF_BASE}/trading/markets",
                            params={"type": "perp", "limit": 275})
        markets = []
        for m in r.json().get("markets", []):
            basis = (m["mark_price"] - m["spot_price"]) / m["spot_price"]
            ann_basis = basis * (365 * 24 / 8) # 8h basis → annualized
            markets.append(PerpMarket(
                symbol=m["symbol"],
                funding_rate_8h=m["funding_rate"],
                mark_price=m["mark_price"],
                spot_price=m["spot_price"],
                basis_pct=basis,
                annualized_basis=ann_basis,
                open_interest_usd=m.get("open_interest_usd", 0),
                volume_24h_usd=m.get("volume_24h_usd", 0)
            ))
        return markets

    def place_perp_order(self, symbol: str, side: str, size_usd: float):
        r = self.session.post(f"{PF_BASE}/trading/order", json={
            "symbol": symbol, "side": side,
            "size_usd": size_usd, "type": "market"
        })
        return r.json()

    # ---- Deribit options data ----

    def get_vol_surface(self, currency="BTC") -> List[VolSurface]:
        # Fetch ATM IV and 25D skew from Deribit public API
        r = requests.get(
            f"{DERIBIT_BASE}/public/get_volatility_index_data",
            params={"currency": currency, "resolution": "3600",
                    "count": 30}
        )
        data = r.json().get("result", {}).get("data", [])
        surfaces = []
        for row in data:
            surfaces.append(VolSurface(
                symbol=currency,
                expiry="30d",
                atm_iv=row[4] / 100,
                skew_25d=0.0,   # populated from options chain
                rv_30d=0.0,     # populated from price history
                iv_premium=0.0
            ))
        return surfaces

    # ---- Strategy Logic ----

    def rank_funding_opportunities(self, markets: List[PerpMarket]) -> List[PerpMarket]:
        # Filter: positive funding, liquid market, decent volume
        eligible = [
            m for m in markets
            if m.funding_rate_8h > 0                  # contango only
            and m.volume_24h_usd > 1_000_000          # $1M+ daily vol
            and m.annualized_basis > MIN_FUNDING_APY   # 8%+ annualized
        ]
        # Rank by risk-adjusted yield: basis / (vol proxy from OI change)
        return sorted(eligible, key=lambda m: m.annualized_basis, reverse=True)

    def compute_skew_zscore(self, symbol: str, current_skew: float) -> float:
        history = self.skew_history.setdefault(symbol, [])
        history.append(current_skew)
        if len(history) > 720:  # 30 days of hourly data
            history.pop(0)
        if len(history) < 48:   # need 2 days minimum
            return 0.0
        mean = sum(history) / len(history)
        std  = math.sqrt(sum((x-mean)**2 for x in history) / len(history))
        return (current_skew - mean) / std if std > 0 else 0.0

    def execute_basis_trade(self, market: PerpMarket, size_usd: float):
        log.info(f"Opening basis trade: short {market.symbol} perp, "
                  f"buy spot | basis={market.annualized_basis:.1%}")
        # Short the perp (collect funding)
        perp_result = self.place_perp_order(market.symbol, "sell", size_usd)
        # Buy equivalent spot via Purple Flea wallet transfer to DEX
        # (spot hedging via wallet API or external DEX aggregator)
        log.info(f"Basis trade opened: {perp_result}")
        self.positions[market.symbol] = size_usd

    async def run(self):
        while True:
            try:
                # 1. Scan all perp markets for funding opportunities
                markets = self.get_all_perp_markets()
                top_funding = self.rank_funding_opportunities(markets)

                log.info(f"Top funding opportunities:")
                for m in top_funding[:5]:
                    log.info(f"  {m.symbol}: {m.annualized_basis:.1%} APY | "
                              f"funding={m.funding_rate_8h*100:.4f}%/8h")

                # 2. Open new basis trades if capital available
                current_deployed = sum(self.positions.values())
                available = 100_000 - current_deployed   # $100k total budget
                for m in top_funding[:3]:              # top 3 markets
                    if m.symbol not in self.positions and available > 10_000:
                        size = min(MAX_POSITION_USD, available / 3)
                        self.execute_basis_trade(m, size)
                        available -= size

                # 3. Check skew data for options signals
                vol_surfaces = self.get_vol_surface("BTC")
                if vol_surfaces:
                    latest = vol_surfaces[-1]
                    z = self.compute_skew_zscore("BTC", latest.skew_25d)
                    log.info(f"BTC IV: {latest.atm_iv:.1%}  skew_z={z:.2f}")
                    if z > SKEW_Z_THRESHOLD:
                        log.info("Skew elevated: consider sell risk-reversal on Deribit")
                    elif z < -SKEW_Z_THRESHOLD:
                        log.info("Skew compressed: consider buy risk-reversal on Deribit")

            except Exception as e:
                log.error(f"Agent cycle error: {e}")

            await asyncio.sleep(REBALANCE_MINS * 60)


if __name__ == "__main__":
    agent = DerivativesAgent()
    asyncio.run(agent.run())

Derivatives Risk Framework for Agents

Derivatives amplify both returns and losses. An agent running a multi-strategy derivatives portfolio needs systematic risk limits across multiple dimensions:

Risk DimensionMetricSuggested LimitAction on Breach
Total deltaNet BTC equivalent±5 BTCHedge excess delta with spot/perp
Total vegaUSD change per 1% IV move±$1,000Close or hedge option positions
Gamma exposureUSD change in delta per 1% move±$500Reduce gamma via position close
Max drawdownPeak-to-trough portfolio loss-15%Halt all new positions; review
Funding costMonthly funding paid (if backwardation)<2% monthlyClose basis trade if funding reverses
Liquidation distance% move to reach liquidation price>30%Reduce leverage or add margin

Getting Started

Purple Flea provides the infrastructure for derivatives agents to get started quickly:

  • Register your agent to access the Trading API with 275 perp markets.
  • Use the Faucet to claim free credits for paper trading derivatives strategies.
  • Read the Trading API docs for order types, margin modes, and funding rate endpoints.
  • Combine with the Wallet API for spot hedging on multi-chain assets.
275 Markets Available Now

Purple Flea's Hyperliquid integration gives agents access to 275 perpetual markets with low fees and deep liquidity. Ideal for running the basis trades, calendar spreads, and cross-asset spreads described in this guide.

Conclusion

Crypto derivatives represent the most complex and potentially most lucrative strategy space for autonomous AI agents. The key insight is that agents have structural advantages over human traders in derivatives: they can monitor dozens of markets simultaneously, hedge delta in real time, track IV and skew across full option chains, and execute multi-leg strategies atomically without hesitation.

The taxonomy covered here—futures, perpetuals, options, and structured products—gives agents a vocabulary and framework for building systematic strategies. Basis trading and funding harvest are the most accessible starting points (consistent positive expectancy with manageable risk). Calendar spreads and skew trading require more infrastructure but offer less crowded edges. Gamma scalping and complex multi-leg options strategies are the frontier for well-capitalized agents with robust infrastructure.

Use Purple Flea's 275-market perp API as the foundation for linear derivatives strategies, and Deribit's public API for options data. The Python agent above provides a working scaffold for your own derivatives manager. Start with paper trading using the Faucet, then deploy real capital as the strategy proves out.

Volatility Surface Trading for Agents

The volatility surface is a 3D map of implied volatility across strike prices and expiry dates. Agents that can model and trade the vol surface have access to some of the most consistent edges in crypto derivatives — edges that human traders rarely exploit systematically due to the monitoring overhead.

Understanding IV Surface Structure

A crypto options vol surface has two primary dimensions: moneyness (the ratio of strike to spot price) and time to expiry. The surface exhibits characteristic shapes that agents can exploit:

  • Volatility smile: IV is higher for deep OTM puts and calls versus ATM options. Crypto smiles are typically more pronounced than equity skews due to fat-tail risk appetite.
  • Term structure: Near-term IV is typically higher than long-dated IV (backwardation) during risk-off periods, and lower during calm markets (contango).
  • Skew: In crypto, put skew (OTM puts carrying higher IV than OTM calls) inverts frequently around bullish narratives, creating tradeable dislocations.

Python: Vol Surface Builder

import numpy as np
from scipy.interpolate import RectBivariateSpline
from dataclasses import dataclass
from typing import List, Dict, Tuple

@dataclass
class OptionQuote:
    strike: float
    expiry_days: int
    iv: float          # implied volatility (decimal)
    option_type: str   # "call" or "put"
    delta: float

class VolSurface:
    """
    Build and query an implied volatility surface from option quotes.
    Uses 2D spline interpolation across strike and expiry dimensions.
    """

    def __init__(self, spot: float):
        self.spot = spot
        self.quotes: List[OptionQuote] = []
        self._surface = None
        self._strikes = None
        self._expiries = None

    def add_quotes(self, quotes: List[OptionQuote]):
        self.quotes = quotes
        self._build_surface()

    def _build_surface(self):
        """Interpolate vol surface from discrete option quotes."""
        # Extract unique strikes and expiries
        strikes = sorted(set(q.strike for q in self.quotes))
        expiries = sorted(set(q.expiry_days for q in self.quotes))

        # Build IV matrix
        iv_matrix = np.zeros((len(strikes), len(expiries)))
        quote_map = {(q.strike, q.expiry_days): q.iv for q in self.quotes}

        for i, s in enumerate(strikes):
            for j, e in enumerate(expiries):
                iv_matrix[i, j] = quote_map.get((s, e), np.nan)

        # Fill missing values with column means
        col_means = np.nanmean(iv_matrix, axis=0)
        for j in range(iv_matrix.shape[1]):
            mask = np.isnan(iv_matrix[:, j])
            iv_matrix[mask, j] = col_means[j]

        self._strikes = np.array(strikes)
        self._expiries = np.array(expiries)
        self._surface = RectBivariateSpline(
            self._strikes, self._expiries, iv_matrix, kx=2, ky=2
        )

    def get_iv(self, strike: float, expiry_days: int) -> float:
        """Interpolate IV for any strike/expiry combination."""
        if self._surface is None:
            raise RuntimeError("Surface not built — add quotes first")
        return float(self._surface(strike, expiry_days))

    def atm_iv(self, expiry_days: int) -> float:
        """Return ATM implied volatility for given expiry."""
        return self.get_iv(self.spot, expiry_days)

    def skew(self, expiry_days: int, delta_otm: float = 0.25) -> float:
        """
        25-delta skew: IV(25d put) - IV(25d call).
        Positive skew = puts more expensive than calls.
        """
        put_strike = self.spot * (1 - delta_otm)
        call_strike = self.spot * (1 + delta_otm)
        put_iv = self.get_iv(put_strike, expiry_days)
        call_iv = self.get_iv(call_strike, expiry_days)
        return put_iv - call_iv

    def term_structure_slope(self) -> float:
        """
        Measure term structure slope: positive = contango (longer-dated IV higher).
        """
        if self._expiries is None or len(self._expiries) < 2:
            return 0.0
        short_iv = self.atm_iv(self._expiries[0])
        long_iv = self.atm_iv(self._expiries[-1])
        return (long_iv - short_iv) / (self._expiries[-1] - self._expiries[0])

    def find_rich_strikes(self, expiry_days: int, threshold_iv: float = 0.05) -> List[dict]:
        """
        Identify strikes where IV is significantly above the smooth surface.
        These are candidates for selling (richness > threshold).
        """
        rich = []
        for s in np.linspace(self.spot * 0.7, self.spot * 1.3, 50):
            market_iv = self.get_iv(s, expiry_days)
            atm = self.atm_iv(expiry_days)
            moneyness = (s / self.spot) - 1
            expected_iv = atm + abs(moneyness) * 0.3  # simple smile approximation
            richness = market_iv - expected_iv
            if richness > threshold_iv:
                rich.append({"strike": round(s, 0), "iv": market_iv, "richness": richness})
        return sorted(rich, key=lambda x: x["richness"], reverse=True)

Practical Vol Surface Strategies

Three edge cases agents should monitor continuously:

  • IV vs RV divergence: When 30-day ATM IV exceeds realized volatility by more than 10 vol points consistently, systematic short vol positions (via strangles) carry positive expectancy over time.
  • Skew inversions: When 25-delta calls become more expensive than 25-delta puts (negative skew), this signals speculative call buying — a potential short-term bullish signal and a relative value opportunity to sell calls and buy puts.
  • Term structure kink: When 7-day IV > 30-day IV by more than 20 vol points, calendar spreads (buy long-dated, sell short-dated) tend to revert profitably.

Advanced Funding Rate Harvesting

Funding rate harvesting is a market-neutral strategy that systematically captures the difference between perpetual futures funding rates and spot borrowing rates. When perpetual markets are in sustained contango (positive funding), short perp + long spot generates risk-free carry.

Multi-Market Funding Aggregation

import asyncio
import aiohttp
from dataclasses import dataclass, field
from typing import Dict, List, Optional
from datetime import datetime

@dataclass
class FundingOpportunity:
    market: str
    exchange: str
    funding_rate: float     # 8h rate
    annualized: float       # funding_rate * 3 * 365
    oi: float               # open interest in USD
    spot_borrow_rate: float # AAVE/Compound borrow rate annualized
    net_carry: float        # annualized - spot_borrow_rate

class FundingHarvester:
    """
    Multi-exchange funding rate monitor with carry calculation.
    Identifies best funding harvest opportunities across markets.
    """

    EXCHANGES = {
        "hyperliquid": "https://api.hyperliquid.xyz/info",
        "purple_flea":  "https://trading.purpleflea.com/api/v1/funding",
    }

    def __init__(self, min_annualized: float = 15.0, min_oi: float = 1_000_000):
        self.min_annualized = min_annualized
        self.min_oi = min_oi
        self.opportunities: List[FundingOpportunity] = []

    async def fetch_hyperliquid_funding(self, session: aiohttp.ClientSession) -> List[dict]:
        """Fetch funding rates from Hyperliquid."""
        payload = {"type": "metaAndAssetCtxs"}
        async with session.post(
            "https://api.hyperliquid.xyz/info",
            json=payload,
            timeout=aiohttp.ClientTimeout(total=15)
        ) as resp:
            data = await resp.json()

        meta, asset_ctxs = data[0], data[1]
        results = []
        for i, asset in enumerate(meta.get("universe", [])):
            ctx = asset_ctxs[i] if i < len(asset_ctxs) else {}
            funding = float(ctx.get("funding", 0))
            oi = float(ctx.get("openInterest", 0)) * float(ctx.get("markPx", 0))
            results.append({
                "market": asset["name"] + "-PERP",
                "exchange": "hyperliquid",
                "funding_rate": funding,
                "oi": oi
            })
        return results

    async def fetch_purple_flea_funding(self, session: aiohttp.ClientSession) -> List[dict]:
        """Fetch funding rates from Purple Flea Trading API."""
        try:
            async with session.get(
                "https://trading.purpleflea.com/api/v1/funding",
                timeout=aiohttp.ClientTimeout(total=15)
            ) as resp:
                data = await resp.json()
            return [
                {
                    "market": m.get("symbol", ""),
                    "exchange": "purple_flea",
                    "funding_rate": m.get("fundingRate", 0),
                    "oi": m.get("openInterest", 0)
                }
                for m in data.get("markets", [])
            ]
        except Exception:
            return []

    async def scan(self, spot_borrow_rate: float = 0.05) -> List[FundingOpportunity]:
        """Scan all exchanges for funding harvest opportunities."""
        async with aiohttp.ClientSession() as session:
            tasks = [
                self.fetch_hyperliquid_funding(session),
                self.fetch_purple_flea_funding(session),
            ]
            results = await asyncio.gather(*tasks, return_exceptions=True)

        all_markets = []
        for r in results:
            if isinstance(r, list):
                all_markets.extend(r)

        opportunities = []
        for m in all_markets:
            fr = m.get("funding_rate", 0)
            oi = m.get("oi", 0)
            annualized = fr * 3 * 365 * 100  # 8h rate -> annual %

            if annualized >= self.min_annualized and oi >= self.min_oi:
                net_carry = annualized - spot_borrow_rate * 100
                if net_carry > 0:
                    opportunities.append(FundingOpportunity(
                        market=m["market"],
                        exchange=m["exchange"],
                        funding_rate=fr,
                        annualized=annualized,
                        oi=oi,
                        spot_borrow_rate=spot_borrow_rate * 100,
                        net_carry=net_carry
                    ))

        self.opportunities = sorted(opportunities, key=lambda x: x.net_carry, reverse=True)
        return self.opportunities

    def top_opportunities(self, n: int = 5) -> List[FundingOpportunity]:
        return self.opportunities[:n]

# Run the harvester
async def main():
    harvester = FundingHarvester(min_annualized=20.0)
    opps = await harvester.scan(spot_borrow_rate=0.06)  # 6% USDC borrow cost
    print(f"Found {len(opps)} funding opportunities:")
    for o in harvester.top_opportunities(5):
        print(f"  {o.exchange}/{o.market}: {o.annualized:.1f}% annualized | Net carry: {o.net_carry:.1f}%")

asyncio.run(main())

Risk Factors in Funding Harvest

Despite its market-neutral framing, funding harvest carries several risks agents must monitor:

  • Liquidation risk: The short perp leg can be liquidated if spot price rises sharply and margin isn't topped up. Agents should maintain at least 30% buffer margin above liquidation price.
  • Funding rate reversal: Positive funding doesn't persist indefinitely. When rate turns negative, the agent pays funding rather than receiving it. Set automatic exit conditions when funding flips negative for two consecutive periods.
  • Spot-perp basis divergence: In periods of extreme volatility, the perp mark price can deviate significantly from spot. This creates mark-to-market losses on the perp leg even when net delta is zero.
  • Counterparty risk: Exchange insolvency (as seen with FTX) can cause loss of both legs. Spread across at least 2–3 exchanges and maintain off-exchange custody of spot holdings where possible.

Full Portfolio Greeks Tracking

When running multiple options positions simultaneously, portfolio-level Greeks determine the overall exposure to price movement (delta), convexity (gamma), time decay (theta), and volatility (vega). Agents must aggregate these continuously to understand net risk.

import math
from dataclasses import dataclass
from typing import List, Dict

@dataclass
class OptionsPosition:
    symbol: str
    option_type: str     # "call" or "put"
    strike: float
    expiry_days: int
    quantity: float      # positive = long, negative = short
    spot: float
    iv: float            # implied volatility (decimal)
    r: float = 0.05      # risk-free rate

    def d1(self) -> float:
        T = self.expiry_days / 365
        return (math.log(self.spot / self.strike) +
                (self.r + 0.5 * self.iv**2) * T) / (self.iv * math.sqrt(T))

    def d2(self) -> float:
        T = self.expiry_days / 365
        return self.d1() - self.iv * math.sqrt(T)

    def _norm_cdf(self, x: float) -> float:
        return (1 + math.erf(x / math.sqrt(2))) / 2

    def _norm_pdf(self, x: float) -> float:
        return math.exp(-0.5 * x**2) / math.sqrt(2 * math.pi)

    def delta(self) -> float:
        d1 = self.d1()
        if self.option_type == "call":
            return self._norm_cdf(d1)
        else:
            return self._norm_cdf(d1) - 1

    def gamma(self) -> float:
        T = self.expiry_days / 365
        return self._norm_pdf(self.d1()) / (self.spot * self.iv * math.sqrt(T))

    def theta(self) -> float:  # per day
        T = self.expiry_days / 365
        d1, d2 = self.d1(), self.d2()
        term1 = -(self.spot * self._norm_pdf(d1) * self.iv) / (2 * math.sqrt(T))
        if self.option_type == "call":
            return (term1 - self.r * self.strike * math.exp(-self.r * T) * self._norm_cdf(d2)) / 365
        else:
            return (term1 + self.r * self.strike * math.exp(-self.r * T) * self._norm_cdf(-d2)) / 365

    def vega(self) -> float:  # per 1% change in IV
        T = self.expiry_days / 365
        return self.spot * self._norm_pdf(self.d1()) * math.sqrt(T) / 100

class DerivativesPortfolio:
    """
    Track and manage portfolio-level Greeks across all options and perp positions.
    """

    def __init__(self):
        self.options_positions: List[OptionsPosition] = []
        self.perp_positions: Dict[str, float] = {}  # symbol -> net delta

    def add_option(self, pos: OptionsPosition):
        self.options_positions.append(pos)

    def add_perp(self, symbol: str, net_delta: float):
        self.perp_positions[symbol] = self.perp_positions.get(symbol, 0) + net_delta

    def portfolio_greeks(self) -> dict:
        """Aggregate portfolio-level Greeks."""
        total_delta = 0.0
        total_gamma = 0.0
        total_theta = 0.0
        total_vega = 0.0

        for pos in self.options_positions:
            q = pos.quantity
            total_delta += q * pos.delta()
            total_gamma += q * pos.gamma()
            total_theta += q * pos.theta()
            total_vega += q * pos.vega()

        # Add perp deltas
        for sym, delta in self.perp_positions.items():
            total_delta += delta

        return {
            "delta": round(total_delta, 4),
            "gamma": round(total_gamma, 6),
            "theta_per_day": round(total_theta, 2),
            "vega_per_1pct_iv": round(total_vega, 2),
            "positions": len(self.options_positions),
            "perp_positions": len(self.perp_positions),
        }

    def delta_hedge_qty(self, hedge_asset_delta: float = 1.0) -> float:
        """
        Calculate quantity of hedge asset (perp or spot) needed to neutralize delta.
        """
        greeks = self.portfolio_greeks()
        return -greeks["delta"] / hedge_asset_delta

    def gamma_scalp_pnl(self, spot_move: float) -> float:
        """
        Estimate P&L from gamma scalping over a given spot move.
        P&L ≈ 0.5 * Gamma * (dS)^2
        """
        greeks = self.portfolio_greeks()
        return 0.5 * greeks["gamma"] * spot_move**2

    def risk_report(self) -> str:
        g = self.portfolio_greeks()
        lines = [
            "=== Portfolio Greeks Report ===",
            f"Net Delta:     {g['delta']:+.4f}",
            f"Net Gamma:     {g['gamma']:+.6f}",
            f"Daily Theta:   ${g['theta_per_day']:+.2f}",
            f"Vega (1% IV):  ${g['vega_per_1pct_iv']:+.2f}",
            f"Option Positions: {g['positions']}",
            f"Perp Positions:   {g['perp_positions']}",
            f"",
            f"Delta hedge: {self.delta_hedge_qty():.2f} units needed",
            f"Gamma scalp P&L (1% move): ${self.gamma_scalp_pnl(self.options_positions[0].spot * 0.01 if self.options_positions else 0):.2f}",
        ]
        return "\n".join(lines)

# Example: Delta-neutral strangle portfolio
portfolio = DerivativesPortfolio()
spot = 65000.0

# Long strangle: buy OTM call + OTM put
portfolio.add_option(OptionsPosition("BTC", "call", 70000, 30, quantity=0.5, spot=spot, iv=0.65))
portfolio.add_option(OptionsPosition("BTC", "put",  60000, 30, quantity=0.5, spot=spot, iv=0.72))

# Delta-hedge the net position with a perp short
greeks = portfolio.portfolio_greeks()
hedge_qty = portfolio.delta_hedge_qty()
portfolio.add_perp("BTC-PERP", hedge_qty)

print(portfolio.risk_report())

Dynamic Delta Hedging Frequency

The key question for gamma scalpers is: how often should you re-hedge? The answer depends on gamma magnitude and transaction costs:

  • High gamma positions (short-dated near-ATM options): re-hedge every 15–30 minutes or when delta moves beyond ±0.05
  • Low gamma positions (long-dated or deep OTM): re-hedge once daily or when delta moves beyond ±0.10
  • Cost consideration: Each re-hedge incurs spread + taker fee (typically 0.03–0.05% on liquid perps). At $50k position, this is $15–$25/trade. Hedge frequency must be justified by gamma income.

Purple Flea for Derivatives Agents

Purple Flea provides the financial layer that derivatives agents need beyond just trade execution:

📈
Trading API

275+ perp markets for linear derivatives strategies and delta hedging

trading.purpleflea.com
💧
Faucet

Free $1 USDC for new agents to test derivatives strategies with zero risk

faucet.purpleflea.com
🔒
Escrow

Trustless settlement for structured products and OTC derivatives between agents

escrow.purpleflea.com
💳
Wallet

Multi-chain wallet with programmatic access for on-chain option settlement

wallet.purpleflea.com
New to derivatives? Start with the Purple Flea Faucet to get $1 USDC free — enough to experiment with small positions on our 275-market perp API. Build intuition for funding rates, basis, and Greeks before scaling up.