On-Chain Options for AI Agents: Dopex, Lyra, Hegic, and Decentralized Options Protocols

Decentralized options protocols have matured significantly since 2021, offering AI agents access to structured derivatives, volatility trading, and delta hedging without centralized counterparties. This research guide compares the leading on-chain options protocols — Dopex SSOV, Lyra's AMM-based model, Hegic's pooled liquidity, and Premia's peer-to-pool design — and shows how to build a Python options trading agent that uses the Purple Flea trading API to hedge synthetic options exposures with perpetual swaps.

How On-Chain Options Differ from CEX Options

Centralized exchange options (Deribit, OKX, Binance) operate on traditional market maker models where the exchange maintains an order book and traders interact with human or algorithmic market makers. Settlement is handled by the exchange, and options can be closed at any time via the order book.

On-chain options have fundamentally different mechanics:

Feature CEX Options (Deribit) On-Chain Options
Counterparty Market makers / exchange Smart contract / liquidity pool
Settlement Cash settlement by exchange Automatic on-chain at expiry
Custody Exchange holds collateral Collateral in smart contract
Pricing Order book / market makers AMM, pooled IV, or peer-to-pool
Expiries Daily, weekly, monthly Protocol-defined epochs (weekly/monthly)
Strikes Many granular strikes Limited strikes per epoch
Slippage Low (liquid markets) Higher (pool liquidity constrained)
API access REST/WebSocket Smart contract calls (web3)
Counterparty risk Exchange solvency risk Smart contract bug risk

For AI agents, on-chain options offer permissionless access (no KYC, no account), composability (options can be held as NFTs or ERC-20s), and programmable settlement — advantages that outweigh the liquidity and latency trade-offs for many strategies.

Dopex: Single Staking Option Vaults (SSOV)

Dopex (Decentralized Options Exchange) pioneered the Single Staking Option Vault (SSOV) model. In an SSOV, users deposit a single asset (e.g., ETH, DPX, GOHM) and the protocol writes covered calls or cash-secured puts on that asset for the current epoch (typically monthly). Buyers purchase these options by paying premiums that are distributed to depositors.

SSOV Mechanics

  1. Depositors lock collateral for the epoch. ETH depositors in an ETH SSOV write covered calls.
  2. Strike selection — The protocol offers 3–5 preset strikes per epoch, typically 10–30% OTM.
  3. Option buyers purchase calls or puts by paying a premium priced using Black-Scholes with the protocol's implied volatility.
  4. At epoch end, in-the-money options are settled and depositors receive premiums plus any remaining collateral.

Dopex also introduced Atlantic Options — perpetual options with no fixed expiry that use the collateral backing the option as transferable margin, enabling composable option strategies.

SSOV for AI Agents: Yield Strategy

Agents can act as SSOV depositors to earn yield from option premiums. This is equivalent to a systematic covered call writing strategy — profitable in low-volatility, sideways or mildly bullish markets, but caps upside if the asset rallies strongly above the strike.

"""
Dopex SSOV depositor strategy via web3.py.
Deposits ETH into SSOV to earn option premium yield.
"""

from web3 import Web3
import json

# Arbitrum RPC
w3 = Web3(Web3.HTTPProvider("https://arb1.arbitrum.io/rpc"))

# Dopex ETH Monthly SSOV contract (Arbitrum)
SSOV_ADDRESS = "0x..."  # Fetch from Dopex docs
SSOV_ABI = json.loads('[...]')  # Simplified

def get_epoch_strikes(ssov_contract) -> list[int]:
    """Get available strikes for current epoch."""
    epoch = ssov_contract.functions.currentEpoch().call()
    strikes = ssov_contract.functions.getEpochStrikes(epoch).call()
    return strikes

def deposit_to_ssov(
    ssov_contract,
    strike_index: int,
    amount_eth: float,
    sender_address: str,
    private_key: str
) -> str:
    """Deposit ETH into SSOV at specified strike index."""
    amount_wei = w3.to_wei(amount_eth, 'ether')

    tx = ssov_contract.functions.deposit(
        strike_index,
        sender_address
    ).build_transaction({
        'from': sender_address,
        'value': amount_wei,
        'gas': 300_000,
        'nonce': w3.eth.get_transaction_count(sender_address)
    })

    signed = w3.eth.account.sign_transaction(tx, private_key)
    tx_hash = w3.eth.send_raw_transaction(signed.rawTransaction)
    return tx_hash.hex()

def buy_call_option(
    ssov_contract,
    strike_index: int,
    amount: int,         # Number of options (in wei-equivalent)
    epoch: int,
    sender_address: str,
    private_key: str
) -> str:
    """Buy a call option from the SSOV."""
    # Get required premium
    premium = ssov_contract.functions.calculatePremium(
        strike_index, amount, epoch
    ).call()

    tx = ssov_contract.functions.purchase(
        strike_index,
        amount,
        sender_address
    ).build_transaction({
        'from': sender_address,
        'value': premium,
        'gas': 400_000,
        'nonce': w3.eth.get_transaction_count(sender_address)
    })

    signed = w3.eth.account.sign_transaction(tx, private_key)
    tx_hash = w3.eth.send_raw_transaction(signed.rawTransaction)
    return tx_hash.hex()

Lyra: AMM-Based Options

Lyra Finance uses an Automated Market Maker specifically designed for options pricing. Unlike Dopex's vault model, Lyra's AMM dynamically quotes both calls and puts at any strike and expiry within a supported market, using a Black-Scholes model with a skew adjustment to manage pool risk.

How Lyra's AMM Works

The Lyra AMM maintains a Market Maker Vault (MMV) — a pool of sUSD (Synthetix USD) that backs all option positions. When a trader buys an option:

  1. The AMM calculates the Black-Scholes fair value.
  2. A skew ratio adjustment is applied based on the current net delta of the pool (to incentivize trades that reduce pool risk).
  3. A vega utilization fee is added when the pool's total vega exposure is high.
  4. The premium flows into the MMV; the pool underwrites the option.

Lyra Greeks: Understanding Pool Risk

The Lyra AMM hedges its net delta automatically by trading perpetuals on Synthetix. This makes Lyra's pool approximately delta-neutral, but exposed to gamma and vega risk. For AI agents trading against Lyra, this means:

Research Note: Lyra V2

Lyra V2 migrated to a hybrid order book + AMM model on its own app-chain, offering tighter spreads and more granular strike selection. AI agents interacting with Lyra V2 can use the REST API directly rather than pure on-chain calls for faster order execution.

Hegic: Pooled Liquidity Options

Hegic takes a simpler approach: a single liquidity pool backs all options written on the platform. Buyers pay a premium; the pool receives the premium and underwrites the potential payout. There is no order book, no epoch structure, no strike selection — buyers specify any strike and any expiry up to 30 days.

Hegic Pricing Formula

Hegic prices options using a simplified Black-Scholes model. For a call option:

Premium = IV × √(T/365) × S × N(d1) − K × e^(−r·T) × N(d2)

where S = current spot price, K = strike, T = time to expiry in years, IV = implied volatility from Chainlink price feeds, N = standard normal CDF.

Hegic for Agents: Flexible Expiry Strategy

Hegic's main advantage for AI agents is the freedom to specify exact strike and expiry. An agent can buy a 72-hour put option at exactly 5% below current price as a portfolio hedge — something not possible with epoch-based protocols like Dopex.

"""
Hegic options buyer via web3.py.
Buys a short-dated ATM call option as directional bet.
"""

from web3 import Web3
from eth_account import Account
import math

w3 = Web3(Web3.HTTPProvider("https://arb1.arbitrum.io/rpc"))

# Hegic Operational Treasury (Arbitrum)
HEGIC_FACADE = "0x..."
HEGIC_ABI = [...]

def black_scholes_premium(
    S: float, K: float, T: float,
    sigma: float, r: float = 0.05,
    option_type: str = "call"
) -> float:
    """Pure Python Black-Scholes option pricing."""
    from scipy.stats import norm
    d1 = (math.log(S / K) + (r + 0.5 * sigma**2) * T) / (sigma * math.sqrt(T))
    d2 = d1 - sigma * math.sqrt(T)
    if option_type == "call":
        return S * norm.cdf(d1) - K * math.exp(-r * T) * norm.cdf(d2)
    else:
        return K * math.exp(-r * T) * norm.cdf(-d2) - S * norm.cdf(-d1)

def buy_hegic_option(
    spot_price: float,
    strike_pct: float,       # e.g. 1.0 = ATM, 1.05 = 5% OTM call
    duration_hours: int,
    amount_eth: float,
    option_type: str,        # "call" or "put"
    private_key: str
) -> dict:
    """
    Buy a Hegic option.
    Returns tx details.
    """
    account = Account.from_key(private_key)
    facade = w3.eth.contract(address=HEGIC_FACADE, abi=HEGIC_ABI)

    strike = int(spot_price * strike_pct * 1e8)  # Chainlink 8-decimal format
    period = duration_hours * 3600
    amount_wei = w3.to_wei(amount_eth, 'ether')

    # Estimate premium
    option_type_int = 1 if option_type == "call" else 2
    premium = facade.functions.getOptionPrice(
        option_type_int, period, amount_wei, strike
    ).call()

    tx = facade.functions.buyOption(
        option_type_int,
        period,
        amount_wei,
        strike,
        account.address
    ).build_transaction({
        'from': account.address,
        'value': premium,
        'gas': 500_000,
        'nonce': w3.eth.get_transaction_count(account.address)
    })

    signed = w3.eth.account.sign_transaction(tx, private_key)
    tx_hash = w3.eth.send_raw_transaction(signed.rawTransaction)

    return {
        "tx_hash": tx_hash.hex(),
        "strike": strike / 1e8,
        "premium_eth": w3.from_wei(premium, 'ether'),
        "expires_at": duration_hours
    }

Premia: Peer-to-Pool Options

Premia V3 introduced a peer-to-pool model where LPs provide liquidity in specific strike-expiry ranges, and buyers interact directly with this concentrated liquidity. This is conceptually similar to Uniswap V3 liquidity ranges, but for options instead of token swaps.

Premia V3 Architecture

Protocol Comparison Table

Protocol Model Chains Strike Flexibility Expiry Best For
Dopex SSOV Vault / epoch Arbitrum 3–5 preset strikes Monthly epochs Premium yield farming
Lyra V2 AMM + order book Arbitrum, Base Many granular strikes Weekly / monthly Active options trading
Hegic Pooled liquidity Arbitrum, Ethereum Any strike 1–30 days (custom) Short-term directional bets
Premia V3 Peer-to-pool Arbitrum, Base Strike-specific pools Weekly / monthly LP yield on specific strikes
Opyn (Squeeth) Power perpetual Ethereum, Arbitrum N/A (perpetual) Perpetual Convex ETH² exposure

Black-Scholes for On-Chain Option Pricing

Understanding Black-Scholes is essential for evaluating whether on-chain options are fairly priced. The key inputs are: spot price (S), strike (K), time to expiry (T), implied volatility (IV), and risk-free rate (r).

import math
from typing import Tuple

def norm_cdf(x: float) -> float:
    """Standard normal CDF using Abramowitz & Stegun approximation."""
    a1, a2, a3, a4, a5 = 0.319381530, -0.356563782, 1.781477937, -1.821255978, 1.330274429
    p = 0.2316419
    t = 1.0 / (1.0 + p * abs(x))
    poly = t * (a1 + t * (a2 + t * (a3 + t * (a4 + t * a5))))
    cdf = 1.0 - (1.0 / math.sqrt(2 * math.pi)) * math.exp(-0.5 * x * x) * poly
    return cdf if x >= 0 else 1.0 - cdf

def black_scholes(
    S: float, K: float, T: float,
    sigma: float, r: float = 0.05
) -> Tuple[float, float, dict]:
    """
    Black-Scholes pricing + Greeks.
    Returns (call_price, put_price, greeks_dict).
    """
    if T <= 0:
        call = max(S - K, 0)
        put = max(K - S, 0)
        return call, put, {}

    sqrt_T = math.sqrt(T)
    d1 = (math.log(S / K) + (r + 0.5 * sigma**2) * T) / (sigma * sqrt_T)
    d2 = d1 - sigma * sqrt_T

    Nd1 = norm_cdf(d1)
    Nd2 = norm_cdf(d2)
    Nm_d1 = norm_cdf(-d1)
    Nm_d2 = norm_cdf(-d2)

    discount = math.exp(-r * T)
    pdf_d1 = math.exp(-0.5 * d1 * d1) / math.sqrt(2 * math.pi)

    call = S * Nd1 - K * discount * Nd2
    put = K * discount * Nm_d2 - S * Nm_d1

    greeks = {
        "delta_call": Nd1,
        "delta_put": Nd1 - 1,
        "gamma": pdf_d1 / (S * sigma * sqrt_T),
        "theta_call": -(S * pdf_d1 * sigma / (2 * sqrt_T)) / 365 - r * K * discount * Nd2,
        "vega": S * pdf_d1 * sqrt_T / 100,   # per 1% IV change
        "rho_call": K * T * discount * Nd2 / 100,
        "implied_vol": sigma
    }

    return call, put, greeks

# Example: ETH $2000 call, $2200 strike, 30 days, 80% IV
call, put, greeks = black_scholes(
    S=2000, K=2200, T=30/365, sigma=0.80
)
print(f"Call: ${call:.2f} | Put: ${put:.2f}")
print(f"Delta: {greeks['delta_call']:.3f} | Gamma: {greeks['gamma']:.5f}")
print(f"Vega: ${greeks['vega']:.2f}/1% IV | Theta: ${greeks['theta_call']:.2f}/day")

Delta Hedging with Purple Flea Trading API

When an AI agent buys on-chain options (long gamma strategy), it needs to delta-hedge the position to isolate the convexity exposure. Delta hedging means maintaining a perpetual futures position equal in size to −Delta × Notional, so that small moves in the underlying are neutralized and the agent only profits from realized volatility exceeding implied volatility.

The Purple Flea trading API provides access to 275 perpetual markets on Hyperliquid at up to 50x leverage, making it the ideal hedge instrument for on-chain options positions.

Delta Hedge Implementation

import asyncio
import httpx
import time
import math

PURPLE_FLEA_BASE = "https://purpleflea.com/api"

class DeltaHedgeAgent:
    """
    Maintains delta-neutral position:
    - Long ETH call on-chain (positive delta)
    - Short ETH perpetual via Purple Flea (negative delta hedge)
    """

    def __init__(self, api_key: str, agent_id: str):
        self.api_key = api_key
        self.agent_id = agent_id
        self.headers = {
            "Authorization": f"Bearer {api_key}",
            "X-Agent-ID": agent_id
        }
        self.current_hedge_size = 0.0
        self.option_position = None

    async def get_spot_price(self, symbol: str = "ETH") -> float:
        async with httpx.AsyncClient() as client:
            r = await client.get(
                f"{PURPLE_FLEA_BASE}/trading/price",
                headers=self.headers,
                params={"symbol": f"{symbol}-PERP"}
            )
            return r.json()["mark_price"]

    async def get_perp_position(self, symbol: str = "ETH-PERP") -> dict:
        async with httpx.AsyncClient() as client:
            r = await client.get(
                f"{PURPLE_FLEA_BASE}/trading/positions",
                headers=self.headers,
                params={"symbol": symbol}
            )
            positions = r.json().get("positions", [])
            for pos in positions:
                if pos["symbol"] == symbol:
                    return pos
            return {"size": 0.0, "side": "none"}

    async def set_hedge(self, target_short_eth: float, symbol: str = "ETH-PERP"):
        """
        Set perpetual short to target size in ETH.
        Adjusts existing position if needed.
        """
        current_pos = await self.get_perp_position(symbol)
        current_short = -current_pos["size"] if current_pos["side"] == "short" else current_pos["size"]

        delta_needed = target_short_eth - current_short
        if abs(delta_needed) < 0.001:  # below dust threshold
            return

        side = "sell" if delta_needed > 0 else "buy"
        size = abs(delta_needed)

        async with httpx.AsyncClient() as client:
            r = await client.post(
                f"{PURPLE_FLEA_BASE}/trading/order",
                headers=self.headers,
                json={
                    "symbol": symbol,
                    "side": side,
                    "size": size,
                    "order_type": "market",
                    "reduce_only": (side == "buy")
                }
            )
            order = r.json()
            print(f"Hedge adjusted: {side} {size:.4f} ETH | Fill: ${order.get('fill_price', 'pending'):.2f}")
            self.current_hedge_size = target_short_eth

    def compute_option_delta(
        self,
        spot: float,
        strike: float,
        expiry_hours: float,
        iv: float,
        option_type: str = "call"
    ) -> float:
        """Compute Black-Scholes delta for current option position."""
        T = expiry_hours / 8760  # fraction of year

        if T <= 0:
            return 1.0 if (spot > strike and option_type == "call") else 0.0

        d1 = (math.log(spot / strike) + (0.05 + 0.5 * iv**2) * T) / (iv * math.sqrt(T))
        # Simplified norm_cdf
        from scipy.stats import norm
        delta = norm.cdf(d1) if option_type == "call" else norm.cdf(d1) - 1
        return delta

    async def rebalance(self, option_notional_eth: float = 1.0):
        """Main rebalance loop: compute delta and adjust hedge."""
        spot = await self.get_spot_price("ETH")

        if self.option_position is None:
            print("No option position tracked — skipping hedge")
            return

        strike = self.option_position["strike"]
        expiry_hours = self.option_position["expiry_hours"]
        iv = self.option_position["iv"]
        option_type = self.option_position["type"]

        delta = self.compute_option_delta(spot, strike, expiry_hours, iv, option_type)
        target_hedge = delta * option_notional_eth  # short this much in perp

        print(f"Spot: ${spot:.2f} | Strike: ${strike:.2f} | Delta: {delta:.4f} | Target short: {target_hedge:.4f} ETH")
        await self.set_hedge(target_hedge)

    def set_option_position(self, strike: float, expiry_hours: float, iv: float, option_type: str = "call"):
        """Register the option position to hedge."""
        self.option_position = {
            "strike": strike,
            "expiry_hours": expiry_hours,
            "iv": iv,
            "type": option_type
        }

async def run_delta_hedge_agent():
    agent = DeltaHedgeAgent(
        api_key="your-purple-flea-api-key",
        agent_id="delta-hedge-001"
    )

    # Bought 1 ETH call: $2200 strike, 72hr expiry, 80% IV
    agent.set_option_position(strike=2200, expiry_hours=72, iv=0.80, option_type="call")

    print("Delta hedge agent running...")
    while True:
        try:
            await agent.rebalance(option_notional_eth=1.0)
        except Exception as e:
            print(f"Rebalance error: {e}")
        await asyncio.sleep(60)  # Rebalance every 60 seconds

if __name__ == "__main__":
    asyncio.run(run_delta_hedge_agent())

Volatility Trading Strategies for Agents

Long Gamma (Long Volatility)

Buy options and delta-hedge continuously. Profitable when realized volatility exceeds implied volatility. Best in periods of calm markets pricing in low IV before a large move. The Python agent above implements this strategy.

Short Gamma (SSOV Depositing)

Deposit into Dopex SSOV or Premia pools to write options and collect premiums. Profitable when realized volatility is lower than implied volatility (markets overpricing fear). Common in the days after a spike.

Volatility Surface Arbitrage

Compare implied volatility across different protocols for the same underlying. If Hegic is pricing 30-day ETH IV at 75% while Dopex SSOV's 30-day call premium implies 85% IV, an agent can buy Hegic options and sell SSOV calls to capture the 10% IV spread with delta-hedged neutrality.

Calendar Spread

Buy a longer-dated option and sell a shorter-dated option at the same strike. The position profits from the time value decay of the short option and from volatility mean-reversion in the term structure.

Risk Considerations for On-Chain Options Agents

Critical: Smart Contract and Liquidity Risk

On-chain options protocols have been targeted by exploits. Always check audit status, TVL trends, and insurance fund health before deploying significant capital. Use the Purple Flea faucet to test with small amounts first.

Hedge On-Chain Options with Purple Flea Perps

Access 275 perpetual markets at up to 50x leverage for delta hedging your on-chain options positions. Register your agent, get free credits from the faucet, and start trading in minutes.

Register Your Agent

Conclusion

On-chain options represent one of the most powerful tools in an AI agent's financial toolkit. The combination of permissionless access, programmable settlement, and composability with other DeFi primitives makes them uniquely suited to automated trading strategies.

The most profitable agents combine multiple protocols: buying cheap Hegic puts as portfolio insurance, depositing idle capital into Dopex SSOV to earn yield, and delta-hedging all net exposure through the Purple Flea trading API's low-latency perpetual markets. This full stack — on-chain options + perp hedging + automated rebalancing — is only feasible for AI agents operating 24/7.