Perpetual Futures Guide for AI Agents
Everything an autonomous agent needs to understand perpetual futures: how they differ from dated contracts, why funding rates exist and how to harvest them, open interest as a sentiment signal, liquidation cascade dynamics, and a production Python bot framework built on the Purple Flea trading API.
Perpetuals vs Dated Futures
Traditional futures contracts expire on a fixed date. At expiration the contract settles at the spot price and all positions are closed. Traders who want ongoing exposure must "roll" into the next contract โ a friction-laden process that creates basis risk and transaction costs. Perpetual futures solve this elegantly: they never expire. A perpetual position can be held indefinitely, and the instrument tracks spot price through a clever economic mechanism called the funding rate.
For AI agents, perpetuals are operationally superior to dated futures. There is no calendar management, no roll logic, and no gap risk at expiry. An agent can open a position and hold it across any time horizon without ever touching another contract. This simplicity makes perpetuals the default derivative instrument for most algorithmic strategies.
| Dimension | Dated Futures | Perpetual Futures |
|---|---|---|
| Expiry | Fixed date (quarterly or monthly) | None โ perpetual |
| Settlement | Mark price or delivery at expiry | Continuous funding payments |
| Roll cost | Slippage + spread on roll trade | Funding rate (can be positive or negative) |
| Price anchoring | Converges to spot at expiry | Funding rate enforces convergence continuously |
| Basis risk | High near expiry | Low โ usually within 0.1% of spot |
| Liquidity | Fragmented across expiries | Concentrated in single instrument |
| Agent suitability | Medium โ requires roll logic | High โ set-and-forget exposure |
Mark Price and Index Price
Two prices matter for perpetuals: the mark price and the index price. The index price is a weighted median of spot prices across multiple exchanges โ it represents the "true" fair value. The mark price is a smoothed version of the perpetual's own order book, used exclusively for liquidation calculations and unrealized PnL. Using the mark price for liquidations (rather than the last trade price) prevents manipulators from triggering liquidations with a single small trade.
The basis rate is the exponential moving average of (Perp Price - Index Price) / Index Price
over a short window (typically 30โ60 seconds). When basis is positive, longs pay shorts; when negative,
shorts pay longs.
Funding Rate Mechanics
The funding rate is the economic heartbeat of a perpetual futures market. Every 8 hours (on most venues) a payment is exchanged between longs and shorts proportional to their position size and the funding rate. This creates a constant gravitational pull between the perpetual price and spot.
The Funding Rate Formula
The canonical funding rate formula used across most perpetual venues decomposes into an interest component and a premium component:
Where:
- Interest Rate = (Quote borrow rate โ Base borrow rate) / funding intervals per day. For BTC/USDC with typical rates, this is around 0.01% per 8-hour period.
- Premium Index = (Max(0, Impact Bid โ Mark) โ Max(0, Mark โ Impact Ask)) / Index. The impact bid/ask are the average fill prices for a standardized notional.
- The
clampfunction limits how far the interest and premium can diverge, preventing runaway rates in highly directional markets.
Payment Timing and Calculation
Funding is calculated continuously and exchanged at the funding timestamp (00:00, 08:00, 16:00 UTC on most exchanges). The amount paid or received per unit of time is:
Most venues accrue funding continuously but only realize it at the interval timestamp. If you close a position 1 minute before the funding timestamp, you forfeit the accrued funding for that entire 8-hour period. Always check accrued funding before sizing exit decisions.
A positive funding rate means the perpetual is trading above spot (longs are bullish, paying shorts). A negative rate means perpetual is below spot (shorts are dominant, paying longs). Extreme funding rates (above 0.1% per 8h, or >100% annualized) are a strong contrarian signal โ they indicate crowded positioning and historically precede mean-reversion moves.
Funding Rate Harvesting Strategy
When funding rates are significantly positive, a delta-neutral agent can harvest the rate by:
- Going short the perpetual (to receive positive funding)
- Going long spot (to hedge the delta, creating a delta-neutral position)
- Net P&L = funding received โ hedging costs (borrow, spread, rebalance slippage)
This is called a cash-and-carry trade adapted for perpetuals. The key risk is that funding rates can flip, and if your hedge isn't perfect, you carry residual delta exposure. In practice, agents use dynamic delta rebalancing to maintain the neutral position as prices move.
Open Interest Analysis
Open interest (OI) is the total number of outstanding perpetual contracts (denominated in base asset or USD). Unlike volume, which resets each day, OI is cumulative โ it tells you how much capital is committed to open positions right now. Interpreting OI changes alongside price gives agents a powerful lens into market conviction.
| Price | OI Change | Interpretation | Signal Strength |
|---|---|---|---|
| Rising | Rising | New longs entering โ bullish confirmation | Strong |
| Rising | Falling | Shorts covering โ less conviction, near exhaustion | Medium |
| Falling | Rising | New shorts entering โ bearish confirmation | Strong |
| Falling | Falling | Longs capitulating โ potential capitulation bottom | Medium |
OI Extremes and Liquidation Risk
Extremely elevated OI relative to historical norms signals that the market is over-leveraged. A sudden price move can trigger a cascade of liquidations, amplifying the move. The metric to watch is OI / Market Cap โ ratios above 3โ5% for large-cap assets historically correlate with elevated liquidation cascade risk.
When both OI and funding rates spike simultaneously, the market is in "maximum bullish leverage" territory. This combination has preceded virtually every major deleveraging event in crypto history. Reduce long exposure or add short hedges.
Basis Trading: Perps vs Spot
The basis is the difference between the perpetual price and the spot price, expressed as a percentage:
In a healthy bull market, basis is slightly positive (0.01โ0.05%). Extreme positive basis (>0.5%) indicates excessive demand for leveraged long exposure. Negative basis (perpetual trading below spot) is rarer and typically indicates heavy bearish positioning or spot premium on certain venues.
Basis Mean Reversion Trades
Basis tends to mean-revert. When it spikes, funding rate payments force it back toward zero. A systematic basis-trading agent monitors the rolling z-score of basis and fades extremes:
- Basis z-score > +2.0: short perp, long spot (basis compression trade)
- Basis z-score < -2.0: long perp, short spot (basis expansion trade)
- Exit when basis z-score crosses zero
Expected holding time is typically 2โ48 hours. The main risk is trend continuation โ if the market continues to move strongly in one direction, basis can remain elevated for days. Always size these trades with defined max loss.
Liquidation Cascade Dynamics
Liquidation cascades are one of crypto's most distinctive market microstructure phenomena. When a leveraged position is liquidated, the exchange takes over the position and closes it in the market, causing price impact. If that price impact triggers more liquidations, a self-reinforcing cascade begins.
Liquidation Mechanics
A position is liquidated when its margin ratio falls below the maintenance margin rate (typically 0.4โ0.5% for BTC). The liquidation price for a long position is:
For a 10x leveraged long entered at $100,000: initial margin = 10%, maintenance = 0.5%, liquidation at $100,000 ร (1 โ 0.10 + 0.005) = $90,500. If price drops to $90,500, the position is forcibly closed at market, regardless of the trader's wishes.
Cascade Conditions and Agent Response
Cascades form when there is a dense cluster of liquidation prices at a level that would be hit by normal price moves. Liquidation heatmaps (available via on-chain analytics) show where these clusters are. Smart agents use this information in two ways:
- Avoidance: Don't set stops or liquidation prices near high-density liquidation clusters โ your stop will be hit by cascade flow.
- Exploitation: Small agents can fade the cascade by buying into liquidation-driven drops, provided they have firepower and the cascade is identifiable (OI dropping rapidly = cascade underway).
During cascades, bid-side liquidity can disappear entirely for 2โ5 second windows. Market orders placed during this window can fill at catastrophically bad prices. Always use limit orders with a defined maximum slippage tolerance during high-volatility periods.
Position Sizing with Leverage
Leverage amplifies both gains and losses proportionally. The core insight for agents: leverage should be determined by your stop loss distance, not by a fixed number. The correct framework is:
If your account is $10,000, you risk 1% per trade ($100), and your stop is 2% from entry, the correct position size is $100 / 0.02 = $5,000 notional. With a $10,000 account, that's 0.5x leverage โ very conservative. Most agents cap position leverage at 5x to maintain meaningful buffer against cascades and funding spikes.
Kelly Criterion for Perp Agents
The Kelly Criterion gives the theoretically optimal bet fraction to maximize long-run geometric growth. For a binary outcome strategy (win or lose):
Where p = win probability, q = 1-p, W = avg win size, L = avg loss size. Kelly is notoriously aggressive โ most practitioners use half-Kelly or quarter-Kelly to reduce variance. For AI agents with uncertain win-rate estimates, quarter-Kelly is recommended as a starting point.
Purple Flea Perpetuals API
The Purple Flea trading API exposes perpetual futures endpoints under /v1/perp/. All
requests require a valid API key in the X-API-Key header.
import requests
BASE = "https://purpleflea.com/api/v1"
KEY = "pf_live_<your_key>"
# Get available perpetual instruments
resp = requests.get(
f"{BASE}/perp/instruments",
headers={"X-API-Key": KEY}
)
instruments = resp.json()["instruments"]
for inst in instruments[:5]:
print(f"{inst['symbol']:20s} tick={inst['tick_size']} max_lev={inst['max_leverage']}x")
# Get current and predicted funding rates
resp = requests.get(
f"{BASE}/perp/funding",
params={"symbol": "BTC-PERP"},
headers={"X-API-Key": KEY}
)
data = resp.json()
print(f"Current funding rate : {data['current_rate']*100:.4f}% per 8h")
print(f"Predicted next rate : {data['predicted_rate']*100:.4f}% per 8h")
print(f"Annualized rate : {data['current_rate']*3*365*100:.2f}%")
print(f"Next funding at : {data['next_funding_ts']}")
# Open a long position
order_body = {
"symbol": "BTC-PERP",
"side": "buy", # "buy" = long, "sell" = short
"order_type": "limit",
"quantity": 0.01, # in base asset (BTC)
"price": 95000,
"leverage": 5,
"reduce_only": False,
"time_in_force": "GTC"
}
resp = requests.post(
f"{BASE}/perp/orders",
json=order_body,
headers={"X-API-Key": KEY, "Content-Type": "application/json"}
)
order = resp.json()
print(f"Order ID: {order['order_id']} Status: {order['status']}")
# List all open perpetual positions
resp = requests.get(
f"{BASE}/perp/positions",
headers={"X-API-Key": KEY}
)
positions = resp.json()["positions"]
for pos in positions:
print(
f"{pos['symbol']:20s} side={pos['side']:5s} "
f"size={pos['size']} entry={pos['entry_price']:.2f} "
f"pnl={pos['unrealized_pnl']:+.4f} "
f"liq={pos['liquidation_price']:.2f}"
)
Python Perpetual Trading Bot
The following production-grade Python classes implement a complete perpetual trading agent with funding rate harvesting, risk management, and position lifecycle management.
"""
Purple Flea Perpetual Futures Bot
Implements funding rate harvesting with delta-neutral hedging.
"""
import time
import logging
import requests
from dataclasses import dataclass, field
from typing import Optional
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
log = logging.getLogger("perp-bot")
BASE_URL = "https://purpleflea.com/api/v1"
@dataclass
class FundingHarvester:
api_key: str
symbol: str = "BTC-PERP"
spot_symbol: str = "BTC-SPOT"
# Minimum annualized rate to enter a harvest position (e.g., 50% = 0.50)
min_ann_rate: float = 0.50
# Size in USD notional to deploy per harvest opportunity
notional_usd: float = 1000.0
leverage: int = 3
_session: requests.Session = field(default_factory=requests.Session, repr=False)
def __post_init__(self):
self._session.headers.update({
"X-API-Key": self.api_key,
"Content-Type": "application/json"
})
def _get(self, path: str, **params) -> dict:
r = self._session.get(f"{BASE_URL}{path}", params=params)
r.raise_for_status()
return r.json()
def _post(self, path: str, body: dict) -> dict:
r = self._session.post(f"{BASE_URL}{path}", json=body)
r.raise_for_status()
return r.json()
def get_funding(self) -> tuple[float, float]:
"""Return (current_rate_8h, annualized_rate)."""
data = self._get("/perp/funding", symbol=self.symbol)
rate_8h = data["current_rate"]
ann = rate_8h * 3 * 365 # 3 intervals/day ร 365 days
return rate_8h, ann
def get_mark_price(self) -> float:
data = self._get("/perp/ticker", symbol=self.symbol)
return float(data["mark_price"])
def get_spot_price(self) -> float:
data = self._get("/spot/ticker", symbol=self.spot_symbol)
return float(data["last_price"])
def get_open_position(self) -> Optional[dict]:
positions = self._get("/perp/positions")["positions"]
for p in positions:
if p["symbol"] == self.symbol:
return p
return None
def place_perp_order(self, side: str, notional: float) -> dict:
mark = self.get_mark_price()
qty = round(notional / mark, 6)
return self._post("/perp/orders", {
"symbol": self.symbol,
"side": side,
"order_type": "market",
"quantity": qty,
"leverage": self.leverage,
"reduce_only": False
})
def close_perp_position(self) -> Optional[dict]:
pos = self.get_open_position()
if not pos:
return None
close_side = "sell" if pos["side"] == "long" else "buy"
return self._post("/perp/orders", {
"symbol": self.symbol,
"side": close_side,
"order_type": "market",
"quantity": abs(float(pos["size"])),
"reduce_only": True
})
def run_once(self):
rate_8h, ann_rate = self.get_funding()
log.info(f"Funding: {rate_8h*100:.4f}%/8h Annualized: {ann_rate*100:.2f}%")
pos = self.get_open_position()
if pos is None:
if ann_rate >= self.min_ann_rate:
log.info(f"Opening harvest short: rate={ann_rate*100:.2f}% >= min={self.min_ann_rate*100:.0f}%")
# Short perp to receive positive funding
order = self.place_perp_order("sell", self.notional_usd)
log.info(f"Perp short opened: {order}")
# NOTE: In production, simultaneously place a spot long hedge here
else:
log.info("Rate below threshold, no position.")
else:
# Position exists โ check if rate is still favorable
if ann_rate < self.min_ann_rate * 0.5: # Exit at half the entry threshold
log.info(f"Rate dropped below exit threshold ({ann_rate*100:.2f}%), closing.")
result = self.close_perp_position()
log.info(f"Position closed: {result}")
else:
accrued = self._get("/perp/accrued-funding", symbol=self.symbol)
log.info(
f"Holding position. Size={pos['size']} "
f"PnL={pos['unrealized_pnl']:+.4f} "
f"Accrued={accrued.get('amount', 0):+.6f}"
)
def run(self, poll_seconds: int = 300):
log.info(f"Starting funding harvester for {self.symbol}")
while True:
try:
self.run_once()
except Exception as e:
log.error(f"Error in run_once: {e}", exc_info=True)
time.sleep(poll_seconds)
# โโ Risk Manager โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
@dataclass
class PerpRiskManager:
"""Enforces position limits and liquidation buffer rules."""
max_leverage: float = 5.0
max_notional_usd: float = 10_000.0
min_liquidation_buffer: float = 0.10 # 10% buffer from liquidation
max_funding_exposure_ann: float = 1.0 # Don't hold if rate > 100% ann against you
def check_leverage(self, requested: float) -> float:
if requested > self.max_leverage:
log.warning(f"Leverage {requested}x exceeds max {self.max_leverage}x, capping.")
return self.max_leverage
return requested
def check_notional(self, requested: float) -> float:
if requested > self.max_notional_usd:
log.warning(f"Notional ${requested} exceeds max ${self.max_notional_usd}, capping.")
return self.max_notional_usd
return requested
def check_liquidation_buffer(self, mark: float, liq_price: float, side: str) -> bool:
if side == "long":
buffer = (mark - liq_price) / mark
else:
buffer = (liq_price - mark) / mark
if buffer < self.min_liquidation_buffer:
log.error(f"Liquidation buffer {buffer:.2%} below minimum {self.min_liquidation_buffer:.2%}!")
return False
return True
def should_close_on_funding(self, ann_rate: float, side: str) -> bool:
"""Close if funding is working strongly against the position."""
if side == "long" and ann_rate < -self.max_funding_exposure_ann:
log.warning(f"Funding rate {ann_rate:.2%} ann too negative for long, close recommended.")
return True
if side == "short" and ann_rate > self.max_funding_exposure_ann:
log.warning(f"Funding rate {ann_rate:.2%} ann too positive for short, close recommended.")
return True
return False
# โโ Entrypoint โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
if __name__ == "__main__":
import os
API_KEY = os.environ.get("PURPLEFLEA_API_KEY", "pf_live_<your_key>")
bot = FundingHarvester(
api_key=API_KEY,
symbol="BTC-PERP",
min_ann_rate=0.50, # Enter when annualized rate > 50%
notional_usd=1000.0,
leverage=3
)
risk = PerpRiskManager(max_leverage=5.0, max_notional_usd=5000.0)
bot.run(poll_seconds=300)
Liquidation Cascade Detector
"""
Detects liquidation cascades by monitoring OI and price divergence velocity.
"""
import time, requests
from collections import deque
class CascadeDetector:
def __init__(self, api_key: str, symbol: str = "BTC-PERP",
window: int = 20, oi_drop_threshold: float = 0.03,
price_drop_threshold: float = 0.02):
self.headers = {"X-API-Key": api_key}
self.symbol = symbol
self.oi_history = deque(maxlen=window)
self.price_history = deque(maxlen=window)
self.oi_drop = oi_drop_threshold # 3% OI drop in one interval
self.price_drop = price_drop_threshold # 2% price drop in one interval
def sample(self):
base = f"https://purpleflea.com/api/v1"
oi_data = requests.get(f"{base}/perp/oi", params={"symbol": self.symbol},
headers=self.headers).json()
px_data = requests.get(f"{base}/perp/ticker", params={"symbol": self.symbol},
headers=self.headers).json()
self.oi_history.append(float(oi_data["open_interest_usd"]))
self.price_history.append(float(px_data["mark_price"]))
def is_cascade(self) -> bool:
if len(self.oi_history) < 2:
return False
oi_change = (self.oi_history[-1] - self.oi_history[-2]) / self.oi_history[-2]
px_change = (self.price_history[-1] - self.price_history[-2]) / self.price_history[-2]
# Cascade = OI dropping fast AND price moving fast in same direction
if oi_change < -self.oi_drop and abs(px_change) > self.price_drop:
return True
return False
def monitor(self, interval: int = 30):
while True:
self.sample()
if self.is_cascade():
oi_chg = (self.oi_history[-1]-self.oi_history[-2])/self.oi_history[-2]*100
px_chg = (self.price_history[-1]-self.price_history[-2])/self.price_history[-2]*100
print(f"[ALERT] CASCADE DETECTED โ OI: {oi_chg:+.2f}% Price: {px_chg:+.2f}%")
time.sleep(interval)
Summary and Agent Checklist
Perpetual futures are the most powerful instrument available to autonomous trading agents โ but they require careful engineering. Use this checklist before going live:
- Confirm you understand the funding rate formula and can predict the next funding period payment
- Set a maximum leverage cap in your risk manager (recommend 5x for most strategies)
- Monitor liquidation buffer continuously โ never let it fall below 10%
- Check OI + funding rate together before entering large positions
- Implement cascade detection to pause trading during liquidation events
- Backtest funding harvesting strategies over at least 12 months of data
- Use quarter-Kelly sizing until your strategy has 100+ out-of-sample trades
- Never place market orders during high-volatility cascades โ use limit orders only
Ready to trade perps? Get your API key at purpleflea.com/api-keys and explore the full API reference at purpleflea.com/docs. New agents can claim free funds at faucet.purpleflea.com to experiment without risk.
Related: Wallet Architecture for Production AI Agents ยท Market Regime Detection for AI Agents ยท Agent System Prompt Guide