Run autonomous market making with AI agents on Purple Flea. Post bid and ask orders, earn the spread, and collect liquidity rebates — on 275 perpetual markets via Hyperliquid integration. Your agent becomes the market.
A market maker provides liquidity to an order book by simultaneously posting a bid (buy limit order below market) and an ask (sell limit order above market). When both orders fill, the market maker captures the bid-ask spread as profit. On Hyperliquid, market makers also receive a maker rebate of -0.025% per filled limit order — meaning the exchange pays the market maker for providing liquidity.
The challenge is inventory risk: if the market moves sharply in one direction, the market maker accumulates a directional position that can generate losses exceeding spread income. Professional market makers manage this with delta hedging — using offsetting positions to neutralize directional exposure after fills become asymmetric.
Purple Flea's market making API handles the mechanics: posting quotes, cancelling stale orders, tracking inventory, and triggering hedges when exposure exceeds your configured threshold. Your agent provides the signal — the spread width and market selection — the API handles the execution loop.
The gap between your buy limit and sell limit orders. At 5bps on a $100 order, each complete round trip earns $0.05. Volume is the multiplier — $1M/day at 5bps = $500/day gross before rebates.
Hyperliquid pays -0.025% of notional to the liquidity provider on every limit order fill. At $1M volume, that is $250/day in rebates — on top of spread income.
When more bids fill than asks (or vice versa), the market maker holds a directional position. This "inventory" can generate losses if the market moves against it. Managed with delta hedging.
Quotes must be updated as the mid price moves, otherwise filled orders create adverse inventory. The API's built-in refresh loop cancels and reposts quotes every configurable interval.
| Endpoint | Description |
|---|---|
| POST/v1/mm/quote | Post a pair of limit bid and ask orders at specified prices and sizes. Returns order IDs for both. Optionally set auto_refresh: true to have the API manage the refresh loop server-side. |
| POST/v1/mm/cancel | Cancel all pending market maker orders for the authenticated agent on a specified symbol. Call this before refreshing quotes to avoid duplicate orders accumulating in the book. |
| GET/v1/mm/inventory | Current inventory position accumulated from asymmetric fills: net long or short delta, average entry price, and unrealized inventory PnL. Used to determine when to trigger a delta hedge. |
| POST/v1/mm/hedge | Execute a market order to neutralize current inventory. Specify hedge_pct (0–1) to partially or fully hedge. Typically triggered when net delta exceeds a threshold like $500 notional. |
| GET/v1/mm/pnl | Decomposed PnL for the market making session: gross spread income, maker rebates earned, inventory PnL (realized + unrealized), fees paid, and net total. Filterable by time window. |
The class below implements a basic symmetric market maker: it posts equal-size bid and ask orders at a fixed spread around the mid price, refreshes every 5 seconds, and hedges when inventory exceeds a delta threshold. This is a minimal but functional starting point.
import time, requests PF_BASE = "https://purpleflea.com" HEADERS = { "Authorization": "Bearer pf_live_YOUR_KEY", "Content-Type": "application/json", } class SimpleMarketMaker: def __init__(self, symbol: str, spread_bps: float = 5, order_size: float = 100): self.symbol = symbol self.spread_bps = spread_bps # 5 bps = 0.05% self.order_size = order_size # Order size in USD per side self.hedge_threshold = order_size * 3 # Hedge at 3x order size self.session_pnl = 0.0 def get_mid_price(self) -> float: r = requests.get( f"{PF_BASE}/v1/markets/{self.symbol}/price", headers=HEADERS ).json() return (r["best_bid"] + r["best_ask"]) / 2 def cancel_all_orders(self): requests.post( f"{PF_BASE}/v1/mm/cancel", json={"symbol": self.symbol}, headers=HEADERS ) def refresh_quotes(self, mid: float): half_spread = mid * (self.spread_bps / 10000) / 2 bid_price = round(mid - half_spread, 2) ask_price = round(mid + half_spread, 2) result = requests.post( f"{PF_BASE}/v1/mm/quote", json={ "symbol": self.symbol, "bid_price": bid_price, "bid_size": self.order_size, "ask_price": ask_price, "ask_size": self.order_size, "time_in_force": "GTC" }, headers=HEADERS ).json() print(f" Quotes: BID ${bid_price:,.2f} / ASK ${ask_price:,.2f} | " f"Spread: {self.spread_bps}bps | IDs: {result['bid_id'][:8]}…/{result['ask_id'][:8]}…") def hedge_inventory_if_needed(self): inv = requests.get( f"{PF_BASE}/v1/mm/inventory", params={"symbol": self.symbol}, headers=HEADERS ).json() net_delta_usd = abs(inv["net_delta_usd"]) if net_delta_usd > self.hedge_threshold: hedge_result = requests.post( f"{PF_BASE}/v1/mm/hedge", json={"symbol": self.symbol, "hedge_pct": 1.0}, headers=HEADERS ).json() print(f" HEDGED: ${net_delta_usd:,.0f} delta at ${hedge_result['fill_price']:,.2f}") def run(self, interval_seconds=5, max_iterations=720): """Run market maker for up to max_iterations * interval_seconds""" print(f"Starting market maker: {self.symbol} | {self.spread_bps}bps spread | ${self.order_size}/side") for i in range(max_iterations): try: mid = self.get_mid_price() self.cancel_all_orders() self.refresh_quotes(mid) self.hedge_inventory_if_needed() # Log running PnL every 60 iterations (5 min) if i % 60 == 0: pnl = requests.get( f"{PF_BASE}/v1/mm/pnl", params={"symbol": self.symbol}, headers=HEADERS ).json() print(f" PnL: Spread=${pnl['spread_income']:+.2f} " f"Rebates=${pnl['rebates']:+.2f} Inventory=${pnl['inventory_pnl']:+.2f} " f"Net=${pnl['net_pnl']:+.2f}") time.sleep(interval_seconds) except Exception as e: print(f" Error: {e} — pausing 30s") time.sleep(30) self.cancel_all_orders() print("Market maker stopped. All orders cancelled.") # Run BTC-PERP market maker with 5bps spread, $100 per side if __name__ == "__main__": mm = SimpleMarketMaker(symbol="BTC-PERP", spread_bps=5, order_size=100) mm.run(interval_seconds=5)
Market making without risk controls can generate catastrophic losses during fast market moves. Purple Flea's market making API includes configurable guardrails that activate before significant damage occurs.
Configure a hard limit on net delta exposure via the max_inventory_usd parameter on POST /v1/mm/quote. When this limit is reached, the API automatically stops posting new quotes on the side that would increase inventory further, and posts only the hedging side.
Set a max_spread_bps threshold. If the market's own bid-ask spread widens beyond this threshold — a signal of increased volatility or low liquidity — the market maker pauses quoting until the spread compresses back below the threshold. This prevents quoting into a disorderly market.
Configure auto_hedge_threshold_usd on the quote endpoint. When net inventory exceeds this threshold, the API automatically fires a market order to neutralize the delta. The hedge execution cost is included in the /v1/mm/pnl response under hedge_cost.
Optionally pass session_stop_loss_usd to the quote endpoint. If the session's net PnL (spread + rebates + inventory) falls below this negative threshold, the API cancels all orders and stops the session, preventing runaway losses from a single volatile session.
Market making income scales with volume. The math below shows expected gross income at a 5bps spread with 100% fill rate — real fill rates depend on market conditions and competition. Use it as a ceiling estimate rather than a guarantee.
Note: These figures assume 100% fill rate on both sides, which is optimistic. Real fill rates for tight spreads on liquid markets like BTC-PERP typically range from 40–80% depending on spread width and queue position. Adjust your spread width to find the fill rate / spread income tradeoff that works for your capital.
All market making endpoints are available as MCP tools. An LLM-powered orchestrator agent can call these tools to manage a market making sub-agent — dynamically adjusting spread width based on volatility signals or pausing quoting during news events.
Register your agent, claim $1 from the faucet to test with, and start your first market making session in under 10 minutes. Scale up as you tune your spread and fill rate parameters.