The Crypto Options Landscape
Crypto options have matured dramatically. What was once a thin, illiquid market dominated by over-the-counter desks is now a multi-billion-dollar ecosystem with competitive venues, standardized contracts, and publicly available Greeks. AI agents have an asymmetric edge here: options require constant Greeks monitoring, delta hedging at precise intervals, and the ability to scan hundreds of strikes and expiries simultaneously — tasks that are trivial for an agent and exhausting for a human trader.
Major venues and their characteristics
| Venue | Type | Assets | Notable Feature | API? |
|---|---|---|---|---|
| Deribit | Centralized | BTC, ETH, SOL, others | Largest OI; DVOL index; Black-Scholes IV surface API | Yes (REST + WS) |
| Lyra Finance | Decentralized | ETH, BTC, SOL | On-chain AMM pricing; liquidation-resistant LPs | Yes (v2 SDK) |
| Premia Finance | Decentralized | ETH, BTC, ARB, LINK | CLOB-style on-chain; discrete strike pools | Yes (v3 API) |
| Hegic | Decentralized | ETH, BTC | Single-sided LP; no counterparty selection | Limited |
| Aevo Options | Centralized L2 | ETH, BTC, SOL, AEVO | High-throughput L2; combined perp + options book | Yes (REST + WS) |
| Ribbon Finance | Decentralized | ETH, BTC, AVAX | Automated DOV (options vault) strategies | Vault-level |
For agent-driven strategies, Deribit remains the primary venue due to its deep liquidity, comprehensive API, and the DVOL volatility index. Aevo is the leading choice for agents wanting to combine perpetual and options positions on one platform. DeFi venues like Lyra and Premia offer composability advantages but require on-chain gas budget management.
Agent advantage: Deribit's API returns pre-computed Greeks (delta, gamma, theta, vega, rho) on every options quote. An agent can scan the entire BTC options surface — all strikes, all expiries — in a single API call, compute aggregate portfolio Greeks in milliseconds, and rebalance delta in near real-time. A human doing the same would need an entire trading desk.
Options Greeks for Agents: What They Are and Why Agents Automate Them
Greeks quantify how an option's price changes with respect to various inputs. For systematic agents, each Greek represents both a risk dimension to manage and a potential signal to trade.
Delta (Δ)
Rate of change of option price with respect to the underlying. A call at 0.50 delta moves $0.50 for every $1 move in BTC. Agents hedge delta by taking an offsetting position in the perpetual or spot.
Gamma (Γ)
Rate of change of delta with respect to the underlying. High gamma means delta shifts rapidly near expiry. Long gamma agents profit from large moves; short gamma agents profit from calm markets but bleed on big moves.
Theta (Θ)
Time decay — how much option value erodes per day, all else equal. Negative for option buyers (time works against them), positive for sellers. Agents running short options positions track theta as daily income.
Vega (ν)
Sensitivity to implied volatility changes. A vega of 0.05 means a 1-point IV increase adds $0.05 to the option value. Agents trade vega when they have a directional view on volatility (DVOL above/below fair value).
Rho and second-order Greeks
Rho (interest rate sensitivity) is typically minor in crypto but becomes relevant when on-chain borrowing rates spike. Vanna (change in delta with respect to IV) and Volga (change in vega with respect to IV) are second-order Greeks that matter for large books and volatility surface arbitrage. Most agents start with the four primary Greeks and add Vanna tracking once their books grow above ~$50K notional.
Automated Greeks tracking: Python implementation
import requests, json from dataclasses import dataclass, field from typing import List, Dict import math DERIBIT_BASE = "https://www.deribit.com/api/v2" @dataclass class OptionPosition: instrument: str # e.g. "BTC-28MAR25-80000-C" size: float # positive = long, negative = short delta: float gamma: float theta: float vega: float mark_price: float underlying_price: float @dataclass class PortfolioGreeks: net_delta: float = 0.0 net_gamma: float = 0.0 net_theta: float = 0.0 # daily USD theta net_vega: float = 0.0 # per 1-vol-point positions: List[OptionPosition] = field(default_factory=list) def fetch_option_greeks(instrument_name: str) -> dict: """Fetch mark price + greeks for a single option from Deribit.""" resp = requests.get( f"{DERIBIT_BASE}/public/get_order_book", params={"instrument_name": instrument_name, "depth": 1} ) data = resp.json()["result"] greeks = data.get("greeks", {}) return { "delta": greeks.get("delta", 0.0), "gamma": greeks.get("gamma", 0.0), "theta": greeks.get("theta", 0.0), "vega": greeks.get("vega", 0.0), "mark_price": data.get("mark_price", 0.0), "underlying": data.get("underlying_price", 0.0), "iv": data.get("mark_iv", 0.0), } def build_portfolio_greeks(positions_raw: List[Dict]) -> PortfolioGreeks: """ positions_raw: [{"instrument": "BTC-28MAR25-80000-C", "size": -1.0}, ...] Returns aggregated portfolio Greeks. """ portfolio = PortfolioGreeks() for p in positions_raw: g = fetch_option_greeks(p["instrument"]) pos = OptionPosition( instrument = p["instrument"], size = p["size"], delta = g["delta"], gamma = g["gamma"], theta = g["theta"], vega = g["vega"], mark_price = g["mark_price"], underlying_price= g["underlying"], ) portfolio.positions.append(pos) portfolio.net_delta += pos.delta * pos.size portfolio.net_gamma += pos.gamma * pos.size portfolio.net_theta += pos.theta * pos.size # theta is per-day USD portfolio.net_vega += pos.vega * pos.size return portfolio # Example usage positions = [ {"instrument": "BTC-28MAR25-80000-C", "size": -2.0}, # short 2 calls {"instrument": "BTC-28MAR25-75000-P", "size": -2.0}, # short 2 puts ] book = build_portfolio_greeks(positions) print(f"Net Delta: {book.net_delta:.4f} BTC") print(f"Net Gamma: {book.net_gamma:.6f} per $1 move") print(f"Net Theta: ${book.net_theta:.2f} / day") print(f"Net Vega: ${book.net_vega:.2f} per 1-vol-pt")
This scanner runs every few minutes in the agent's main loop. When net delta drifts beyond a threshold (e.g., ±0.05 BTC equivalent), the agent automatically submits a offsetting trade on Purple Flea's perpetual market to re-center the book.
Covered Call Strategies: Generating Yield on Spot Holdings
A covered call is the simplest income-generating options strategy: an agent holds spot BTC (or ETH, SOL) and sells an out-of-the-money call against it. If the price stays below the strike at expiry, the call expires worthless and the agent keeps the premium as yield. If the price exceeds the strike, the agent delivers the coins at the agreed price — still profitable, but with capped upside.
Why covered calls are natural for AI agents
The systematic covered call program — sometimes called a "buy-write" — is nearly impossible to manage consistently as a human trader. An agent handles all of it automatically:
- Strike selection: Target a delta of 0.20–0.30 (roughly 20–30% probability of expiring in-the-money) for a balance between premium income and upside participation.
- Expiry selection: Weekly to bi-weekly expiries capture the theta decay "sweet spot" where time decay accelerates but IV premium is still meaningful.
- Roll management: If the underlying approaches the strike, the agent automatically rolls the call up and out — buying back the current call and selling a higher-strike, further-dated call.
- Premium accounting: All premium received is logged and annualized. A well-run covered call program on BTC during moderate-IV environments typically generates 15–40% annualized yield on the notional.
import requests, time from datetime import datetime, timedelta DERIBIT = "https://www.deribit.com/api/v2" DERIBIT_KEY = "your_deribit_api_key" DERIBIT_SECRET = "your_deribit_secret" def get_btc_instruments(): """Fetch all live BTC options instruments.""" resp = requests.get(f"{DERIBIT}/public/get_instruments", params={"currency": "BTC", "kind": "option", "expired": "false"}) return resp.json()["result"] def get_spot_price(): resp = requests.get(f"{DERIBIT}/public/get_index_price", params={"index_name": "btc_usd"}) return resp.json()["result"]["index_price"] def find_covered_call_strike(instruments, spot_price, target_delta=0.25, days_out=7): """ Find the call closest to target_delta with ~days_out days to expiry. Returns the best instrument or None. """ target_expiry = datetime.utcnow() + timedelta(days=days_out) candidates = [] for inst in instruments: if inst["option_type"] != "call": continue exp_ts = inst["expiration_timestamp"] / 1000 exp_dt = datetime.utcfromtimestamp(exp_ts) days_to_exp = (exp_dt - datetime.utcnow()).days if not (5 <= days_to_exp <= 14): continue book = requests.get(f"{DERIBIT}/public/get_order_book", params={"instrument_name": inst["instrument_name"], "depth": 1}).json()["result"] greeks = book.get("greeks", {}) delta = greeks.get("delta", 1.0) bid = book.get("best_bid_price", 0) iv = book.get("mark_iv", 0) if bid < 0.001: # skip illiquid strikes continue candidates.append({ "instrument": inst["instrument_name"], "delta": delta, "bid": bid, "iv": iv, "days": days_to_exp, "strike": inst["strike"], "delta_dist": abs(delta - target_delta), }) if not candidates: return None candidates.sort(key=lambda x: x["delta_dist"]) return candidates[0] # --- Main covered call loop --- spot = get_spot_price() instruments = get_btc_instruments() best_call = find_covered_call_strike(instruments, spot) if best_call: annual_yield = (best_call["bid"] * spot) / spot * (365 / best_call["days"]) * 100 print(f"Best covered call: {best_call['instrument']}") print(f" Delta: {best_call['delta']:.3f}") print(f" Bid (BTC): {best_call['bid']:.4f}") print(f" IV: {best_call['iv']:.1f}%") print(f" Annualized yield: ~{annual_yield:.1f}%")
Roll discipline: The most common mistake in covered call programs is failing to roll when the underlying surges. Set an automatic trigger: if spot moves within 2% of the short strike, initiate a roll to a strike at least 5% above current spot with at least 7 days added to expiry. Never let a covered call expire deep in-the-money without a roll decision — it forces delivery of the spot holdings at a below-market price.
Cash-Secured Puts: Acquiring Assets at Lower Prices
The mirror image of the covered call is the cash-secured put. An agent holds USDC collateral and sells an out-of-the-money put at a target purchase price. Two outcomes are possible:
- Spot stays above strike: The put expires worthless, the agent keeps the premium. Effectively earned yield on the USDC collateral.
- Spot falls below strike: The put is exercised (or assigned), the agent acquires BTC at the strike price — which is partially offset by the premium received. The effective cost basis is
strike - premium_received.
For an agent that wants to accumulate BTC on dips, this is a superior strategy to placing a limit buy order. The limit buy generates no income while waiting; the cash-secured put generates premium income regardless of whether spot reaches the target level.
Annualized returns on cash-secured puts
| Scenario (BTC at $85K) | Strike | Premium (BTC) | Days | Ann. Yield on USDC |
|---|---|---|---|---|
| Conservative (-5% OTM) | $80,750 | 0.0030 | 7 | ~18.5% |
| Moderate (-10% OTM) | $76,500 | 0.0018 | 7 | ~11.2% |
| Aggressive (-3% OTM) | $82,450 | 0.0055 | 7 | ~33.8% |
| Longer dated (-8% OTM) | $78,200 | 0.0060 | 21 | ~11.0% |
Note that shorter-dated puts have higher annualized yields due to accelerated theta decay, but more aggressive short-dated puts also carry higher delta risk if BTC makes a sudden move. A well-run cash-secured put agent sizes each put so that assignment on all open puts would not exceed the USDC balance — hence "cash-secured."
Volatility Trading: Straddles and Strangles Before Major Events
Options are volatility instruments as much as directional instruments. When an agent has a view that realized volatility will exceed implied volatility — regardless of direction — the correct trade is a long straddle or strangle.
When to go long volatility in crypto
- ETF announcement dates or macro Fed decisions where the market often underprices the tail move
- On-chain governance votes for major protocols (e.g., Ethereum hardforks, major DAO decisions)
- Quarterly CME options expiries — "max pain" dynamics can cause violent repricing
- Low DVOL periods: When BTC DVOL falls below 45, historical realized vol is often higher than implied over the next two weeks
- Exchange listing events for smaller assets that trade on Purple Flea's perp markets
Straddle vs. strangle mechanics
A straddle buys an at-the-money (ATM) call and an ATM put at the same strike. Maximum loss is the combined premium paid; profits when spot moves significantly in either direction. A strangle buys an OTM call and OTM put at different strikes, with lower premium cost but requiring a larger move to profit.
const axios = require('axios'); const DERIBIT = 'https://www.deribit.com/api/v2'; async function findAtmStraddle(currency = 'BTC', targetDays = 7) { // Step 1: Get spot price const indexResp = await axios.get(`${DERIBIT}/public/get_index_price`, { params: { index_name: `${currency.toLowerCase()}_usd` } }); const spot = indexResp.data.result.index_price; // Step 2: Get all options const instResp = await axios.get(`${DERIBIT}/public/get_instruments`, { params: { currency, kind: 'option', expired: 'false' } }); const instruments = instResp.data.result; // Step 3: Filter to target expiry window const now = Date.now(); const targetMs = targetDays * 86400000; const nearExpiry = instruments.filter(i => { const msToExp = i.expiration_timestamp - now; return msToExp > 3 * 86400000 && msToExp < 14 * 86400000; }); // Step 4: Find ATM strike (closest to spot) const strikes = [...new Set(nearExpiry.map(i => i.strike))].sort((a,b) => a-b); const atmStrike = strikes.reduce((prev, curr) => Math.abs(curr - spot) < Math.abs(prev - spot) ? curr : prev); // Step 5: Fetch call and put books at ATM strike const callName = nearExpiry.find(i => i.strike === atmStrike && i.option_type === 'call')?.instrument_name; const putName = nearExpiry.find(i => i.strike === atmStrike && i.option_type === 'put')?.instrument_name; const [callBook, putBook] = await Promise.all([ axios.get(`${DERIBIT}/public/get_order_book`, { params: { instrument_name: callName, depth: 1 } }), axios.get(`${DERIBIT}/public/get_order_book`, { params: { instrument_name: putName, depth: 1 } }), ]); const callAsk = callBook.data.result.best_ask_price; const putAsk = putBook.data.result.best_ask_price; const callIV = callBook.data.result.mark_iv; const putIV = putBook.data.result.mark_iv; const straddelCost = (callAsk + putAsk) * spot; // in USD const avgIV = (callIV + putIV) / 2; // Breakeven: spot must move +/- straddle_cost / spot from strike const breakevenPct = ((callAsk + putAsk) / 2) * 100; console.log(`ATM Straddle Analysis: ${callName} + ${putName}`); console.log(` Spot: $${spot.toLocaleString()}`); console.log(` ATM Strike: $${atmStrike.toLocaleString()}`); console.log(` Call ask (BTC): ${callAsk.toFixed(4)}`); console.log(` Put ask (BTC): ${putAsk.toFixed(4)}`); console.log(` Total cost: $${straddelCost.toFixed(0)}`); console.log(` Avg IV: ${avgIV.toFixed(1)}%`); console.log(` Breakeven move: ±${breakevenPct.toFixed(2)}%`); return { callName, putName, cost: straddelCost, iv: avgIV, breakevenPct }; } findAtmStraddle('BTC', 7).catch(console.error);
The breakeven percentage is critical: if DVOL prices the weekly straddle at ±4.5% and the agent estimates a ±7% move (based on a macro catalyst), the straddle is underpriced and the purchase is justified. If the agent's move estimate is only ±3%, the implied volatility is too rich and selling the straddle (short volatility) is the better play.
Iron Condor in Crypto: Selling Volatility in Ranging Markets
The iron condor is the premium-selling strategy for range-bound markets. It combines a short strangle (sell OTM call + sell OTM put) with a long strangle at wider strikes to cap maximum loss. The agent collects premium as long as spot remains between the two short strikes at expiry.
Iron condor structure
- Sell OTM call at strike C1 (e.g., +8% from spot)
- Buy OTM call at strike C2 (e.g., +12% from spot) — limits upside loss
- Sell OTM put at strike P1 (e.g., -8% from spot)
- Buy OTM put at strike P2 (e.g., -12% from spot) — limits downside loss
Maximum profit = net premium received (when spot expires between P1 and C1). Maximum loss = wing width minus premium received. In crypto, wings are typically sized at 4–6% per wing given the asset's historical move distribution.
When is an iron condor appropriate? After a large realized volatility event (e.g., a +25% BTC week), implied volatility is often elevated while the market consolidates. The IV mean-reversion creates a positive theta environment for iron condors — the agent collects accelerating decay as expiry approaches and IV compresses back to baseline.
Iron condor P&L at expiry
| BTC at Expiry | P&L Scenario | Outcome |
|---|---|---|
| Below P2 (e.g., below $74K) | Max loss = wing width - premium | Max loss hit |
| Between P2 and P1 ($74K–$78K) | Partial loss (put spread absorbs) | Partial loss |
| Between P1 and C1 ($78K–$91K) | All options expire worthless | Full premium collected |
| Between C1 and C2 ($91K–$95K) | Partial loss (call spread absorbs) | Partial loss |
| Above C2 (above $95K) | Max loss = wing width - premium | Max loss hit |
A key advantage for agents: the iron condor's Greeks profile (short gamma, short vega, long theta) means the agent automatically benefits from low realized volatility and time passage — no directional view needed, just a range estimate. The agent monitors gamma continuously and closes the position early if realized vol accelerates above a pre-set threshold.
Perpetual vs. Options for Hedging: A Comparison
When an agent holds a spot BTC position and wants to hedge downside, two primary instruments are available: put options and short perpetual futures. The choice matters significantly for cost, flexibility, and Greek profile.
| Dimension | Put Option Hedge | Short Perpetual Hedge |
|---|---|---|
| Cost structure | Upfront premium (known max cost) | Funding rate (variable, ongoing) |
| Upside participation | Retained above strike | Fully offset (delta = -1 if fully hedged) |
| Downside protection | Full below strike (after breakeven) | Full below entry (dollar-for-dollar) |
| Delta behavior | Dynamic (gamma-adjusted with moves) | Constant -1 per unit short |
| Best environment | High-fear, elevated IV spike periods | Persistently positive funding (longs pay) |
| Purple Flea usage | Deribit puts + PF spot wallet | PF perp short + PF spot wallet |
The sophisticated agent uses both simultaneously. The base hedge is a short perpetual on Purple Flea (cheap to maintain when funding is negative, i.e., when shorts collect funding from longs). When DVOL spikes above 75–80 (suggesting the market prices in extreme fear), the agent switches the marginal hedge to a short-dated put that allows upside participation if the panic reverses.
Delta-neutral hedging loop with Purple Flea perps
import requests PF_BASE = "https://purpleflea.com/api/v1" PF_API_KEY = "your_pf_api_key" def get_pf_perp_position(symbol="BTC-USDC"): """Fetch current PF perpetual position for BTC.""" resp = requests.get(f"{PF_BASE}/trading/positions", headers={"Authorization": f"Bearer {PF_API_KEY}"}) positions = resp.json().get("positions", []) for p in positions: if p["symbol"] == symbol: return p["size"] # negative = short, positive = long return 0.0 def place_pf_perp_order(symbol, side, size, order_type="market"): """Place a perp order on Purple Flea to adjust delta hedge.""" payload = { "symbol": symbol, "side": side, # "buy" or "sell" "size": size, "type": order_type, } resp = requests.post(f"{PF_BASE}/trading/order", headers={"Authorization": f"Bearer {PF_API_KEY}"}, json=payload) return resp.json() def rebalance_delta(options_net_delta: float, hedge_threshold: float = 0.05): """ options_net_delta: the options book's net delta in BTC. A positive net_delta means the book is net long delta — we need to short perps to bring the total portfolio delta to zero. hedge_threshold: minimum |delta| before placing a hedge trade. """ current_perp_pos = get_pf_perp_position("BTC-USDC") # total portfolio delta = options_delta + perp_position total_delta = options_net_delta + current_perp_pos if abs(total_delta) < hedge_threshold: print(f"Delta within threshold ({total_delta:.4f} BTC). No trade.") return None # required adjustment: -total_delta on perps adj_size = abs(total_delta) adj_side = "sell" if total_delta > 0 else "buy" print(f"Rebalancing: {adj_side} {adj_size:.4f} BTC perp on PF") result = place_pf_perp_order("BTC-USDC", adj_side, adj_size) print(f"Order result: {result}") return result # Example: options book has net delta of +0.30 BTC # Agent will sell 0.30 BTC perp on Purple Flea to delta-neutral rebalance_delta(options_net_delta=0.30, hedge_threshold=0.05)
This loop runs every 15–30 minutes during active markets. The agent's options book accumulates theta (daily income from short options) while the perpetual hedge on Purple Flea ensures the total portfolio remains delta-neutral — capturing volatility premium without directional risk.
Implied Volatility Surface Analysis
The implied volatility (IV) surface maps out the implied volatility of every option in the market across two dimensions: strike (or moneyness) and time to expiry. The shape of this surface contains rich information about market expectations and risk premiums.
Key features of the IV surface
- Volatility smile (or smirk): Options typically show higher IV at extreme strikes than at-the-money. In crypto, the skew often leans towards put options (downside strikes have higher IV), reflecting demand for crash protection.
- Term structure: Near-term IV is often higher than long-term IV (backwardation) when fear is elevated — and the reverse (contango) during calm markets. The shape of this curve tells agents whether short-dated or long-dated vol is more attractively priced.
- ATM volatility level: The absolute level of at-the-money IV is the primary signal for whether options are cheap or expensive relative to historical realized volatility.
- Skew (25-delta risk reversal): The difference in IV between 25-delta puts and 25-delta calls. Extreme negative skew (puts much more expensive than calls) signals hedging demand and potential capitulation lows.
import requests, json from collections import defaultdict def build_iv_surface(currency="BTC"): """ Build a simplified IV surface: {expiry_date: {strike: iv}} Returns a nested dict and a summary of ATM IVs per expiry. """ DERIBIT = "https://www.deribit.com/api/v2" spot_resp = requests.get(f"{DERIBIT}/public/get_index_price", params={"index_name": f"{currency.lower()}_usd"}) spot = spot_resp.json()["result"]["index_price"] inst_resp = requests.get(f"{DERIBIT}/public/get_instruments", params={"currency": currency, "kind": "option", "expired": "false"}) instruments = inst_resp.json()["result"] surface = defaultdict(dict) # surface[expiry][strike] = iv atm_ivs = {} # atm_ivs[expiry] = atm_iv # Batch fetch using get_book_summary_by_currency summary_resp = requests.get(f"{DERIBIT}/public/get_book_summary_by_currency", params={"currency": currency, "kind": "option"}) summaries = summary_resp.json()["result"] inst_map = {i["instrument_name"]: i for i in instruments} for s in summaries: name = s.get("instrument_name", "") iv = s.get("mark_iv", 0.0) if iv == 0.0 or name not in inst_map: continue inst = inst_map[name] strike = inst["strike"] expiry = name.split("-")[1] # e.g. "28MAR25" surface[expiry][strike] = iv # Compute ATM IV per expiry (closest strike to spot) for expiry, strike_ivs in surface.items(): atm = min(strike_ivs.keys(), key=lambda k: abs(k - spot)) atm_ivs[expiry] = strike_ivs[atm] # Print term structure print("=== IV Term Structure (ATM) ===") for exp in sorted(atm_ivs.keys()): print(f" {exp:10s} ATM IV: {atm_ivs[exp]:.1f}%") return surface, atm_ivs surface, atm_ivs = build_iv_surface("BTC")
Term Structure Trading: Calendar Spreads
A calendar spread exploits differences in the rate of time decay between two options at the same strike but different expiries. The classic calendar spread buys a longer-dated option and sells a shorter-dated option at the same strike — profiting when the front-month option decays faster than the back-month option.
Crypto calendar spread setup
In crypto, the most actionable calendar spread is the volatility term structure play: when near-term IV is temporarily elevated (e.g., due to an upcoming event or fear spike), sell the front-week option and buy the back-month option at the same strike. As the front-week IV reverts to normal after the event passes, the short leg decays rapidly while the long leg retains its value.
| Calendar Spread Type | When to Use | Max Profit | Max Loss |
|---|---|---|---|
| Long calendar (buy back, sell front) | Near-term IV spike relative to back month | Premium differential at convergence | Net debit paid |
| Short calendar (sell back, buy front) | Back-month IV elevated; anticipate near-term move | Net credit received | Potentially unlimited (back-month long gamma) |
| Diagonal calendar | Directional + term structure view combined | Strike difference + premium | Net debit |
Identifying calendar spread opportunities
def find_calendar_opportunities(surface, atm_ivs, spread_threshold=8.0): """ Finds expiry pairs where front-month ATM IV is significantly higher than back-month ATM IV (long calendar opportunity). spread_threshold: minimum front-back IV spread in vol points. """ expiries = sorted(atm_ivs.keys()) opportunities = [] for i in range(len(expiries) - 1): front = expiries[i] back = expiries[i + 1] iv_front = atm_ivs[front] iv_back = atm_ivs[back] spread = iv_front - iv_back if spread >= spread_threshold: opportunities.append({ "front_expiry": front, "back_expiry": back, "iv_front": iv_front, "iv_back": iv_back, "spread_pts": spread, "type": "long_calendar", }) opportunities.sort(key=lambda x: -x["spread_pts"]) for opp in opportunities[:3]: print(f"Calendar: sell {opp['front_expiry']} ({opp['iv_front']:.1f}%) / " f"buy {opp['back_expiry']} ({opp['iv_back']:.1f}%) — spread {opp['spread_pts']:.1f} vol pts") return opportunities find_calendar_opportunities(surface, atm_ivs, spread_threshold=6.0)
DVOL: Using the Deribit Volatility Index as a Signal
DVOL is Deribit's bitcoin volatility index — the crypto equivalent of the VIX for equities. It measures the 30-day forward-looking implied volatility derived from the BTC options surface and is expressed as an annualized percentage. DVOL is one of the most powerful signals available to an agent running options strategies.
DVOL signal framework
| DVOL Level | Market Regime | Recommended Agent Posture |
|---|---|---|
| < 40 | Extreme complacency | Long vol: buy straddles, long calendar, buy protection |
| 40–55 | Normal low-vol regime | Theta strategies: covered calls, cash-secured puts |
| 55–75 | Moderate volatility | Iron condors, selective covered calls with wider strikes |
| 75–100 | Elevated fear | Reduce short vol exposure; begin buying back short options |
| > 100 | Crisis / capitulation | Long vol only; sell puts for cash-secured acquisition if conviction is high |
const axios = require('axios'); async function getDvol(currency = 'BTC') { const resp = await axios.get('https://www.deribit.com/api/v2/public/get_volatility_index_data', { params: { currency, start_timestamp: Date.now() - 300000, // last 5 minutes end_timestamp: Date.now(), resolution: '60', // 1-minute candles } }); const candles = resp.data.result.data; if (!candles.length) return null; const latest = candles[candles.length - 1]; return latest[4]; // close value } function getStrategyMode(dvol) { if (dvol < 40) return { mode: 'long_vol', action: 'Buy straddles / long calendars' }; if (dvol < 55) return { mode: 'theta_farm', action: 'Covered calls + cash-secured puts' }; if (dvol < 75) return { mode: 'condor', action: 'Iron condors + wide strangles' }; if (dvol < 100) return { mode: 'reduce_short', action: 'Close short vol; switch to delta hedge' }; return { mode: 'crisis', action: 'Long vol only; no naked short options' }; } async function main() { const dvol = await getDvol('BTC'); const strategy = getStrategyMode(dvol); console.log(`BTC DVOL: ${dvol.toFixed(1)}`); console.log(`Mode: ${strategy.mode}`); console.log(`Action: ${strategy.action}`); // An agent would pass strategy.mode to its position-sizing and // entry-criteria modules to adjust behavior accordingly. } main();
Automated Options Strategies: Systematic Covered Calls and Delta Hedging Bots
Systematic options programs are one of the highest-value applications of AI agents in crypto. A well-designed options bot outperforms human traders not because it has better judgment, but because it is consistent — it never skips a roll, never forgets to rebalance delta, never lets theta decay go unmonitored over a weekend.
Architecture of a production options agent
- Data layer: Fetches live options chain from Deribit (REST + WebSocket for real-time updates), spot price from a reference oracle, and DVOL from the volatility index endpoint. Caches data locally with a 10-second TTL.
- Greek aggregation engine: Computes portfolio-level delta, gamma, theta, vega every 60 seconds. Stores a rolling 24-hour history to detect abnormal Greek drift.
- Strategy selector: Based on DVOL level and term structure shape, selects the active strategy: theta farming (DVOL 40–55), iron condors (DVOL 55–75), or long vol (DVOL below 40 or above 100).
- Execution engine: Splits large options orders into smaller slices to minimize market impact. Uses limit orders with a maximum 0.5% slippage tolerance; cancels and reprices after 60 seconds if unfilled.
- Delta hedge module: Sends delta rebalancing orders to Purple Flea's perpetual market (BTC-USDC perp, 0.05%/0.1% taker/maker fees). Rebalances when net delta exceeds ±0.05 BTC or when a large spot move occurs (>1% in 5 minutes).
- Risk circuit breakers: Hard limits: max portfolio vega = $500 per 1-vol-point, max portfolio gamma = 0.01 BTC per $1 move, max single-position size = 20% of portfolio. Violations trigger an immediate position reduction.
Purple Flea integration: The delta hedge module uses Purple Flea's perpetual trading API at https://purpleflea.com/api/v1/trading/order. With 275 markets and 0.05% maker fee, BTC-USDC is one of the cheapest places to run continuous delta hedging. Funding rates on Purple Flea perps also contribute carry income or cost that the agent factors into its total position P&L calculation.
Automated covered call program — full agent loop
import requests, time, logging from datetime import datetime, timezone logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s") log = logging.getLogger("covered_call_agent") DERIBIT = "https://www.deribit.com/api/v2" PF_BASE = "https://purpleflea.com/api/v1" PF_HEADERS = {"Authorization": "Bearer your_pf_api_key"} BTC_SPOT_HOLDINGS = 1.0 # agent holds 1 BTC spot TARGET_DELTA = 0.25 # sell 25-delta calls ROLL_TRIGGER = 0.45 # roll if short call delta exceeds 0.45 def check_existing_short_calls(): """Return list of active short call positions on Deribit.""" # (requires Deribit auth — omitted for brevity) return [] def should_roll(position): g = fetch_option_greeks(position["instrument"]) return g["delta"] > ROLL_TRIGGER def run_covered_call_cycle(): log.info("--- Covered call cycle starting ---") spot = get_spot_price() log.info(f"BTC spot: ${spot:,.0f}") existing = check_existing_short_calls() if existing: for pos in existing: if should_roll(pos): log.warning(f"Rolling {pos['instrument']} — delta too high") # close existing + open new further-dated call # (Deribit order placement omitted — requires auth) log.info("Existing short calls checked; no new position needed.") return # No existing position — find and sell a new call instruments = get_btc_instruments() best_call = find_covered_call_strike(instruments, spot, target_delta=TARGET_DELTA, days_out=7) if not best_call: log.warning("No suitable call found this cycle.") return ann_yield = best_call["bid"] * (365 / best_call["days"]) * 100 log.info(f"Selling {best_call['instrument']} | delta={best_call['delta']:.3f} | " f"IV={best_call['iv']:.1f}% | annualized={ann_yield:.1f}%") # Submit sell order on Deribit (auth + order placement omitted) # After sell, rebalance delta on Purple Flea perp options_delta = -BTC_SPOT_HOLDINGS * best_call["delta"] rebalance_delta(options_net_delta=options_delta) log.info("Cycle complete.") # Run every 4 hours while True: try: run_covered_call_cycle() except Exception as e: log.error(f"Cycle error: {e}") time.sleep(4 * 3600)
Fetching Options Chains and Calculating Greeks: JavaScript SDK Example
Not all agents run on Python. The following JavaScript example shows how to fetch a full options chain, filter for tradeable strikes, and compute a custom Black-Scholes delta without relying on the API's pre-computed values — useful for validating data or pricing non-standard instruments.
const axios = require('axios'); // Cumulative standard normal distribution (Abramowitz & Stegun approximation) function normCdf(x) { const a1 = 0.254829592, a2 = -0.284496736, a3 = 1.421413741; const a4 = -1.453152027, a5 = 1.061405429, p = 0.3275911; const sign = x < 0 ? -1 : 1; x = Math.abs(x); const t = 1.0 / (1.0 + p * x); const y = 1.0 - (((((a5*t + a4)*t + a3)*t + a2)*t + a1)*t * Math.exp(-x*x)); return 0.5 * (1.0 + sign * y); } function bsGreeks(S, K, T, r, sigma, type = 'call') { // S=spot, K=strike, T=years to expiry, r=rate, sigma=IV decimal const d1 = (Math.log(S/K) + (r + sigma*sigma/2)*T) / (sigma * Math.sqrt(T)); const d2 = d1 - sigma * Math.sqrt(T); const nd1 = normCdf(d1); const phi = Math.exp(-d1*d1/2) / Math.sqrt(2 * Math.PI); const delta = type === 'call' ? nd1 : nd1 - 1; const gamma = phi / (S * sigma * Math.sqrt(T)); const theta = (-(S * phi * sigma) / (2 * Math.sqrt(T)) - r * K * Math.exp(-r*T) * normCdf(type === 'call' ? d2 : -d2)) / 365; const vega = S * phi * Math.sqrt(T) / 100; // per 1-vol-point return { delta, gamma, theta, vega }; } async function fetchAndAnalyzeChain(currency = 'BTC', targetExpiry = null) { const DERIBIT = 'https://www.deribit.com/api/v2'; const [idxResp, sumResp] = await Promise.all([ axios.get(`${DERIBIT}/public/get_index_price`, { params: { index_name: `${currency.toLowerCase()}_usd` } }), axios.get(`${DERIBIT}/public/get_book_summary_by_currency`, { params: { currency, kind: 'option' } }), ]); const spot = idxResp.data.result.index_price; const chain = sumResp.data.result; const r = 0.05; // risk-free rate estimate const results = chain .filter(o => !targetExpiry || o.instrument_name.includes(targetExpiry)) .filter(o => o.mark_iv > 0 && o.open_interest > 0) .map(o => { const parts = o.instrument_name.split('-'); const strike = parseFloat(parts[2]); const type = parts[3] === 'C' ? 'call' : 'put'; const T = (o.creation_timestamp ? Math.max(0.001, (o.expiration_timestamp - Date.now()) / (365 * 86400000)) : 7/365); const sigma = o.mark_iv / 100; const g = bsGreeks(spot, strike, T, r, sigma, type); return { instrument: o.instrument_name, type, strike, T: (T * 365).toFixed(1), iv: o.mark_iv.toFixed(1), bid: o.best_bid_price, ask: o.best_ask_price, delta: g.delta.toFixed(4), gamma: g.gamma.toFixed(6), theta: g.theta.toFixed(4), vega: g.vega.toFixed(4), oi: o.open_interest, }; }); // Print top 10 by open interest results.sort((a, b) => b.oi - a.oi).slice(0, 10).forEach(r => console.log(JSON.stringify(r, null, 2)) ); return results; } fetchAndAnalyzeChain('BTC').catch(console.error);
Risk Management: Max Loss, Greeks Limits, and Liquidity Risk
Options positions can experience non-linear losses. A short straddle that appears to collect $500/week in theta can lose $5,000 in a single day if BTC moves 15%. Rigorous risk management is non-negotiable for any agent running options books.
Greeks limits framework
Define hard limits for each Greek at the portfolio level. When any limit is breached, the agent automatically initiates a reduction trade before placing any new positions:
| Greek | Meaning of Limit | Example Limit | Breach Action |
|---|---|---|---|
| Net Delta | Directional exposure in BTC equivalent | ±0.10 BTC | Rebalance via PF perp |
| Net Gamma | How quickly delta changes; loss in a fast move | -0.005 BTC/$1 | Buy back front-month options |
| Net Theta | Daily time decay (income if short, cost if long) | Min -$50/day | Add short options if theta too negative |
| Net Vega | P&L sensitivity to 1% IV change | -$300/vol-pt | Reduce short options notional |
Liquidity risk in crypto options
The most underappreciated risk in crypto options is liquidity risk — the inability to exit a position at a reasonable price during a market crisis. When BTC drops 20% in an hour, all bid-ask spreads widen catastrophically, put options become nearly untradeable, and the agent may be forced to hold through a loss that would otherwise be manageable.
- Only trade strikes with open interest above 50 contracts. Illiquid strikes have 3–5% bid-ask spreads in normal conditions and widen to 20%+ during stress.
- Pre-compute exit costs. Before entering any position, calculate the cost to exit at current mid minus two bid-ask spread widths. This is your realistic exit cost in stress.
- Never hold short options through major catalysts without a defined stop. If a scheduled macro event is within 48 hours, either close short options or buy protective wings.
- Maintain a liquidity reserve on Purple Flea. Keep at least 20% of options collateral in USDC on Purple Flea's wallet API, instantly deployable for delta hedging via perps regardless of options market liquidity.
from dataclasses import dataclass from typing import List @dataclass class RiskLimits: max_abs_delta: float = 0.10 # BTC min_gamma: float = -0.005 # BTC per $1 min_theta_daily:float = -50.0 # USD per day max_abs_vega: float = 300.0 # USD per 1 vol point def check_risk_limits(portfolio: PortfolioGreeks, limits: RiskLimits) -> List[str]: """Returns a list of breach messages. Empty = within limits.""" breaches = [] if abs(portfolio.net_delta) > limits.max_abs_delta: breaches.append( f"DELTA BREACH: {portfolio.net_delta:.4f} BTC (limit ±{limits.max_abs_delta})") if portfolio.net_gamma < limits.min_gamma: breaches.append( f"GAMMA BREACH: {portfolio.net_gamma:.6f} (limit {limits.min_gamma})") if portfolio.net_theta < limits.min_theta_daily: breaches.append( f"THETA BREACH: ${portfolio.net_theta:.2f}/day (limit ${limits.min_theta_daily})") if abs(portfolio.net_vega) > limits.max_abs_vega: breaches.append( f"VEGA BREACH: ${portfolio.net_vega:.2f}/vol-pt (limit ±${limits.max_abs_vega})") return breaches def risk_monitor_loop(positions_raw, limits=None): if limits is None: limits = RiskLimits() portfolio = build_portfolio_greeks(positions_raw) breaches = check_risk_limits(portfolio, limits) if breaches: for b in breaches: print(f"[RISK ALERT] {b}") # Trigger automatic delta rebalance if delta breached if any("DELTA" in b for b in breaches): rebalance_delta(portfolio.net_delta, hedge_threshold=0.02) else: print(f"[RISK OK] delta={portfolio.net_delta:.4f} gamma={portfolio.net_gamma:.6f} " f"theta=${portfolio.net_theta:.2f}/day vega=${portfolio.net_vega:.2f}/vol-pt") return portfolio, breaches
Max Loss Scenarios: Stress Testing Your Options Book
Every agent running a short-options strategy should stress-test its book against historical worst-case crypto moves before committing real capital. The following scenarios represent historically observed extremes:
| Scenario | BTC Move | IV Move | Impact on Short Straddle | Impact on Iron Condor |
|---|---|---|---|---|
| March 2020 crash | -50% in 48h | +80 vol pts | -8 to -15x premium | Max loss on put wing |
| Nov 2022 FTX collapse | -25% in 72h | +40 vol pts | -4 to -7x premium | Max loss on put wing |
| Oct 2021 ATH rally | +35% in 14d | -5 vol pts | -5 to -10x premium (call loss) | Max loss on call wing |
| Typical ranging week | ±3% | ±5 vol pts | Full premium captured | Full premium captured |
Critical sizing rule: Size short options positions so that the max loss scenario (full wing loss on iron condor, or 10x premium loss on a straddle) never exceeds 5% of total portfolio capital in a single expiry cycle. If running multiple expiry cycles simultaneously, ensure non-correlated sizing so a correlated crash does not simultaneously hit all short-gamma positions.
Putting It All Together: A Multi-Strategy Options Agent
A production-grade AI options agent does not run a single strategy — it dynamically allocates across strategies based on market conditions, available capital, and risk budget. The architecture below describes a complete multi-strategy options agent that integrates with both Deribit options and Purple Flea perpetuals:
- Boot sequence: Agent registers with Purple Flea (or loads existing API key), claims USDC from the faucet if new, and establishes WebSocket connections to Deribit market data streams.
- DVOL read: Fetch DVOL and determine strategy mode (theta farm, condor, long vol). This mode persists until the next hourly DVOL check.
- Portfolio scan: Fetch all existing options positions from Deribit, compute portfolio Greeks, check risk limits.
- Position management: Roll any positions approaching expiry or strike. Close positions that have captured >70% of max theoretical theta profit (locking in gains early rather than gambling the last 30% against gamma risk).
- New position entry: If capital is available and risk limits allow, enter new positions per the active strategy mode.
- Delta rebalancing: Calculate net portfolio delta, submit rebalancing order to Purple Flea perp market if delta exceeds ±0.05 BTC. Log the funding rate paid/received.
- Sleep: Wait 15 minutes, then repeat from step 2.
Run your options strategies with Purple Flea
Purple Flea provides the perpetual trading backbone for your delta hedging: 275 markets, 0.05% maker fee, live funding rates, and a wallet API for multi-asset collateral management. Register an agent and claim $1 USDC to start.
Register free →Summary: Crypto Options for AI Agents
Options are one of the most powerful instruments available to AI agents in crypto, precisely because they require the kind of systematic, tireless, multi-dimensional analysis that agents excel at. The key takeaways from this guide:
- Greeks automation is table stakes. Any agent running options must continuously track delta, gamma, theta, and vega at the portfolio level. Manual Greeks monitoring is impractical beyond a handful of positions.
- DVOL is your primary strategy selector. Use the DVOL level to determine whether you are in a theta-farming regime (DVOL 40–55), a condor regime (55–75), or a long-vol regime (<40 or >100). Ignore this signal and you will sell volatility into spikes and buy it at peaks.
- Perpetuals and options complement each other. Use Deribit options for premium collection and volatility exposure; use Purple Flea perpetuals for continuous delta hedging. The combination creates a true market-neutral options book.
- Liquidity risk is the silent killer. Only trade liquid strikes (OI > 50 contracts), maintain a USDC reserve for emergency hedging, and never hold naked short options through major known catalysts.
- Size conservatively. Max loss on any single expiry cycle should not exceed 5% of total portfolio. The edge in options comes from consistency across many cycles, not from maximizing size on any single trade.
- Roll before assignment. Automated roll triggers at defined delta thresholds prevent the largest single sources of unplanned loss in covered call and cash-secured put programs.
The agent that runs these strategies systematically — never missing a rebalance, never skipping a roll, always checking DVOL before entry — will outperform a human trader running the same book not because of superior judgment, but because of superior execution consistency. That consistency is the core competitive advantage of AI agents in financial markets.
Related: The Crypto Carry Trade for AI Agents · Perpetual Futures: Complete Agent Guide · Risk Management for Trading Agents · Purple Flea Trading API