COVERED CALL API

Write Covered Calls Automatically with AI

AI agents generate steady premium income by systematically writing covered calls on BTC, ETH, SOL, BNB, MATIC, and XMR holdings. Delta-guided strike selection, automatic roll-up and roll-down logic, 2–5% monthly premium income — zero manual intervention required.

2–5%
Monthly Premium
Weekly
Opportunities
6
Supported Assets
Auto
Roll Logic

How Covered Call Writing Works

A covered call means you hold the underlying asset and sell someone else the right to buy it at a higher price. You keep the premium regardless of outcome.

💵

Step 1: Hold the Asset

Your agent must hold the underlying asset in its Purple Flea wallet. ETH, BTC, SOL, BNB, MATIC, or XMR. You can only write calls against assets you actually own — this is what makes it "covered."

Step 2: Sell the Call

Your agent calls POST /options/write. The API selects a strike at 0.20–0.35 delta (OTM), prices it using Black-Scholes with real-time IV from Deribit, and sells it on-chain. Premium lands in your wallet instantly.

Step 3: Wait for Expiry

Most expirations are weekly (Friday 08:00 UTC). If the market stays below the strike, the call expires worthless and you keep both the premium and your underlying. Repeat next Friday.

Step 4: Auto-Roll

If the call is about to be exercised (price approaching strike), the agent's roll logic kicks in automatically. Roll up (same expiry, higher strike) or roll out (same strike, next expiry). The API handles the mechanics.

Choosing the Right Strike Delta

Delta determines how aggressive your call writing is. Lower delta = more OTM = lower premium but lower assignment risk. 0.20–0.35 is the sweet spot for most agents.

Delta Moneyness Monthly Premium Assignment Prob. Best When Risk Profile
0.10 Deep OTM (~15% above spot) 0.5–1.2% ~10% High IV, very bullish market Conservative
0.20 OTM (~8% above spot) 1.5–2.8% ~20% Neutral to slightly bullish Low Risk
0.30 OTM (~5% above spot) 2.5–4.0% ~30% Sideways to mildly bullish Optimal
0.35 Slightly OTM (~3% above) 3.5–5.0% ~35% Sideways market, high IV rank Moderate
0.45 Near ATM (~1% above) 4.5–6.5% ~45% Bearish short-term view Aggressive

* Premium percentages are monthly, annualized to 30–78% APY at aggressive deltas. Assignment means your asset is sold at the strike — still profitable if strike > cost basis.

Monthly Premium by Asset

Premium income varies by asset volatility. Higher-vol assets like SOL and BNB yield more premium at the same delta than BTC and ETH. Trailing 90-day averages at 0.30 delta.

Bitcoin (BTC)
2.4%
Monthly at 0.30 delta
Weekly expiry Fri 08:00 UTC
Ethereum (ETH)
3.1%
Monthly at 0.30 delta
Weekly + biweekly available
Solana (SOL)
4.6%
Monthly at 0.30 delta
Higher vol = higher premium
BNB Chain (BNB)
3.8%
Monthly at 0.30 delta
PancakeSwap options liquidity
Polygon (MATIC)
4.2%
Monthly at 0.30 delta
High beta, rich premium
Monero (XMR)
5.1%
Monthly at 0.30 delta
Highest vol in the set

Covered Call API Endpoints

RESTful JSON API. Authenticate with header X-API-Key: pf_live_...

GET
/options/calls
List available call options to write for a given asset. Returns strikes (by delta), expiry dates, current IV, bid/ask spread, and estimated premium in USD. Filter by asset, delta range, and expiry.
POST
/options/write
Write (sell) a covered call. Specify asset, quantity, strike, expiry, and optional delta_target. The API validates your collateral, executes the write, and returns a position_id, premium earned in USD, and breakeven price.
GET
/options/premium-calc
Calculate theoretical premium for any strike/expiry combination without executing. Uses Black-Scholes with real-time IV from Deribit. Returns premium, delta, gamma, theta, vega, and RoR (return on collateral).
GET
/portfolio/coverage
Show which of your holdings are "covered" (have active calls written against them) vs uncovered. Returns coverage ratio, aggregate premium income YTD, and next expiry dates across all positions.
POST
/options/roll
Roll an existing covered call to a new strike or expiry. Supports roll-up (higher strike same expiry), roll-out (same strike next expiry), and roll-up-and-out. Returns net debit/credit for the roll transaction.
POST
/options/close
Buy back an open covered call before expiry. Use when buying to close is cheaper than rolling, or to take profits on theta decay. Returns P&L vs original premium received.

Automatic Roll-Up and Roll-Down

The CoveredCallAgent monitors your open positions and rolls automatically based on configurable triggers. No manual monitoring needed.

1

Monitor Delta in Real Time

The agent polls /portfolio/coverage every hour. When the delta of an open call crosses the roll_trigger_delta threshold (default: 0.70), it initiates a roll.

2

Determine Roll Direction

If the asset has rallied above strike: roll up (buy back, sell new call at higher strike). If the asset has fallen and the call is nearly worthless: buy to close, write new call at current delta target. Never let a call expire in-the-money without action.

3

Check Roll Economics

Only roll if the net credit (new premium minus buyback cost) is positive, OR if rolling out in time provides enough additional premium to justify the extended duration. The API returns a roll_pnl_estimate before execution.

4

Execute and Log

Execute the roll via POST /options/roll. All actions are logged to /portfolio/history for tax reporting and performance analysis. The agent maintains a running P&L across all writes, rolls, and expirations.

CoveredCallAgent Class

Drop-in Python class for automated covered call writing with roll-up and roll-down logic. Requires a funded Purple Flea wallet with BTC or ETH balance.

covered_call_agent.py Python
import requests
import time
from dataclasses import dataclass
from typing import Optional

BASE    = "https://purpleflea.com/api/v1"
API_KEY = "pf_live_your_key_here"
HDR     = {"X-API-Key": API_KEY}

@dataclass
class CallPosition:
    position_id:    str
    asset:          str
    strike:         float
    expiry:         str
    premium_usd:    float
    quantity:       float
    current_delta:  float = 0.30

class CoveredCallAgent:
    """
    Writes covered calls on BTC/ETH holdings.
    Automatically rolls when delta exceeds threshold.
    """

    def __init__(
        self,
        asset: str           = "ETH",
        target_delta: float  = 0.30,
        roll_delta: float    = 0.70,  # roll if delta exceeds this
        quantity: float      = 1.0,   # units of asset to cover
    ):
        self.asset        = asset
        self.target_delta = target_delta
        self.roll_delta   = roll_delta
        self.quantity     = quantity
        self.positions    = []
        self.total_premium= 0.0

    def get_best_call(self) -> Optional[dict]:
        """Find the best call to write at our target delta."""
        r = requests.get(f"{BASE}/options/calls", headers=HDR, params={
            "asset":       self.asset,
            "delta_min":   self.target_delta - 0.05,
            "delta_max":   self.target_delta + 0.05,
            "expiry_type": "weekly"
        })
        calls = r.json()["calls"]
        if not calls:
            return None
        # Pick highest premium-to-delta ratio
        return max(calls, key=lambda c: c["premium_usd"] / c["delta"])

    def write_call(self, call: dict) -> CallPosition:
        """Execute the covered call write."""
        r = requests.post(f"{BASE}/options/write", headers=HDR, json={
            "asset":    self.asset,
            "strike":   call["strike"],
            "expiry":   call["expiry"],
            "quantity": self.quantity
        })
        data = r.json()
        pos  = CallPosition(
            position_id  = data["position_id"],
            asset        = self.asset,
            strike       = call["strike"],
            expiry       = call["expiry"],
            premium_usd  = data["premium_usd"],
            quantity     = self.quantity
        )
        self.total_premium += pos.premium_usd
        print(f"Wrote {asset} call | strike=${pos.strike:,.0f} | exp={pos.expiry} | premium=${pos.premium_usd:.2f}")
        return pos

    def monitor_and_roll(self, pos: CallPosition):
        """Check current delta and roll if needed."""
        r = requests.get(f"{BASE}/portfolio/coverage", headers=HDR,
                        params={"position_id": pos.position_id})
        live_delta = r.json()["current_delta"]
        print(f"Position {pos.position_id}: current delta={live_delta:.2f}")

        if live_delta >= self.roll_delta:
            print(f"Delta {live_delta:.2f} >= threshold {self.roll_delta} → rolling up")
            roll_r = requests.post(f"{BASE}/options/roll", headers=HDR, json={
                "position_id":  pos.position_id,
                "roll_type":    "roll_up",
                "new_delta":    self.target_delta
            })
            roll_data = roll_r.json()
            print(f"Rolled → new strike=${roll_data['new_strike']:,.0f} | net_credit=${roll_data['net_credit']:.2f}")
            self.total_premium += roll_data["net_credit"]

    def run(self, check_interval_sec: int = 3600):
        """Main loop: write calls, monitor, roll as needed."""
        print(f"CoveredCallAgent starting | asset={self.asset} | delta={self.target_delta}")
        while True:
            if not self.positions:
                call = self.get_best_call()
                if call:
                    pos = self.write_call(call)
                    self.positions.append(pos)
            else:
                for pos in self.positions:
                    self.monitor_and_roll(pos)
            print(f"Total premium collected: ${self.total_premium:.2f}")
            time.sleep(check_interval_sec)

if __name__ == "__main__":
    agent = CoveredCallAgent(asset="ETH", target_delta=0.30, quantity=2.0)
    agent.run()

When to Deploy Covered Call Writing

High IV Rank (50+)

When implied volatility rank exceeds 50, options are "expensive." This is the best time to be a seller. Premium is 30–50% higher than normal — use 0.25–0.30 delta to capture rich income while staying OTM.

After a Rally

If your BTC/ETH holding is up 20%+, write calls to lock in some profit potential above current prices. You cap additional upside but pocket significant premium to reduce your cost basis further.

Sideways Markets

When the agent's trend model shows neutral momentum, covered calls turn dormant capital into active income. The asset sits still and premium decays to you — pure theta income with no directional bet needed.

Yield on Long-Term Holdings

Long-term agents holding XMR for privacy or BTC as a reserve asset can write monthly covered calls to compound returns without selling. This compounds the holding's effective APY by 25–60% annually.

START EARNING

Turn Your Holdings Into an Income Machine

Get your API key, load the CoveredCallAgent, and start collecting weekly premiums on your crypto holdings. Free USDC available via the faucet to get started.