Real-time health factor monitoring, automated collateral top-up, and sub-50ms alerts across 275 markets. Built for AI agents that cannot afford to be margin-called at 3am.
Liquidation is the forced closure of a leveraged position when your collateral can no longer cover your losses. For AI agents running 24/7, a single market spike can trigger a cascade that wipes out weeks of gains in seconds.
Your health factor (HF) is the ratio of your collateral value to your borrowed or leveraged exposure. When it drops to 1.0, your position is liquidated — the exchange forcibly closes it and takes a liquidation penalty.
Most agents get liquidated because they:
The margin mode you choose fundamentally changes how liquidation risk propagates across your portfolio.
Each position has its own dedicated collateral pool. Liquidation on one position cannot affect others. Maximum loss equals the margin allocated to that position.
All positions share one collateral pool. Profits from winning positions offset losing ones — but a large loss can drain collateral and trigger simultaneous liquidations across all open positions.
Purple Flea classifies every position into one of four risk zones based on health factor. Alerts are dispatched the moment a position crosses a zone boundary.
| Zone | Health Factor | Action Recommended | Purple Flea Response |
|---|---|---|---|
| Safe | HF > 2.0 | No action required | Periodic status push every 60s |
| Warning | 1.4 < HF ≤ 2.0 | Consider adding collateral or reducing size | Alert dispatched; optional auto top-up triggered |
| Danger | 1.05 < HF ≤ 1.4 | Add collateral immediately or close position | Priority alert (<50ms); auto top-up from wallet reserve; optional kill switch |
| Liquidated | HF ≤ 1.05 | Position force-closed by exchange | Liquidation webhook; portfolio reconciliation triggered |
Set custom HF warning and danger thresholds per position or per market. Your risk tolerance, your rules.
Health factors are polled every 100ms. Alerts are pushed via webhook within 50ms of a threshold crossing being detected.
Monitor all 275 markets from a single API call. No polling loop needed — subscribe once and receive a real-time stream.
Fetch real-time health factors, subscribe to liquidation alerts, and query position risk across all your open trades with simple REST endpoints.
Returns all open positions with current health factor, margin mode, leverage, and unrealized PnL.
Returns detailed health metrics for a specific position including liquidation price, maintenance margin, and current collateral.
Register a webhook URL to receive real-time liquidation risk alerts. Supports per-position and portfolio-level thresholds.
Programmatically add collateral to a specific position from your wallet balance. Used by the auto top-up system.
import requests API_KEY = "pf_live_your_key_here" BASE = "https://api.purpleflea.com" def get_at_risk_positions(threshold=1.4): r = requests.get( f"{BASE}/api/v1/trading/positions", headers={"Authorization": f"Bearer {API_KEY}"} ) r.raise_for_status() positions = r.json()["positions"] return [ p for p in positions if p["health_factor"] < threshold ] at_risk = get_at_risk_positions() for pos in at_risk: print(f"{pos['market']} — HF: {pos['health_factor']}")
When a position enters the Warning zone, Purple Flea can automatically transfer funds from your agent wallet to top up the position's margin — no human intervention required.
The monitoring service detects an HF below your configured warning level (default: 1.6).
The system calculates the minimum collateral needed to restore HF to your target safe level (default: 2.0).
Available balance in your Purple Flea wallet is queried. If reserve is insufficient, a kill-switch is queued instead.
The transfer and margin top-up execute in the same API call. HF is re-read within 200ms to confirm the position is back in the safe zone.
A collateral_topped_up event is logged with amount, timestamp, and new HF. Your webhook receives the payload within 50ms.
{
"enabled": true,
"warning_threshold": 1.6,
"danger_threshold": 1.2,
"target_health_factor": 2.0,
"max_topup_per_event": "500 USDC",
"max_topup_per_day": "2000 USDC",
"reserve_minimum": "100 USDC",
"fallback_to_kill_switch": true,
"notify_webhook": "https://your-agent/hooks/topup"
}
When wallet reserves are exhausted or HF drops into the danger zone faster than top-up can respond, the kill switch triggers an immediate close of one or more positions to halt further losses.
Triggers a market-order close on the specified position (or all positions in cross margin mode) the moment danger thresholds are breached.
Kill-switch orders bypass the normal order queue and execute with highest priority to minimize slippage during high-volatility events.
Close only the most at-risk position, close all positions above a leverage threshold, or nuke the entire portfolio. Your agent decides.
Optionally re-enter positions at smaller sizes once market volatility drops below a configurable ATR threshold.
{
"scope": "most_at_risk", // "most_at_risk" | "all" | "above_leverage"
"leverage_threshold": 10, // used when scope = "above_leverage"
"reason": "auto_danger_zone",
"dry_run": false // set true to simulate without executing
}
LiquidationGuard classDrop this into your agent to get continuous position monitoring, automatic collateral top-up, and kill-switch protection — all in a single asynchronous loop.
import asyncio import aiohttp import logging from dataclasses import dataclass, field from typing import Optional logger = logging.getLogger("liquidation_guard") @dataclass class GuardConfig: api_key: str warning_hf: float = 1.6 danger_hf: float = 1.2 target_hf: float = 2.0 max_topup_usdc: float = 500.0 reserve_minimum_usdc: float = 100.0 poll_interval_sec: float = 5.0 webhook_url: Optional[str] = None class LiquidationGuard: """ Monitors all open positions on Purple Flea and automatically tops up collateral or triggers kill-switch when health factor drops below configured thresholds. """ BASE_URL = "https://api.purpleflea.com/api/v1" def __init__(self, config: GuardConfig): self.config = config self.headers = { "Authorization": f"Bearer {config.api_key}", "Content-Type": "application/json" } self._running = False async def _get_positions(self, session): async with session.get( f"{self.BASE_URL}/trading/positions", headers=self.headers ) as r: data = await r.json() return data.get("positions", []) async def _get_wallet_balance(self, session) -> float: async with session.get( f"{self.BASE_URL}/wallet/balance", headers=self.headers ) as r: data = await r.json() return float(data.get("usdc_balance", 0)) async def _top_up(self, session, position_id: str, amount_usdc: float): async with session.post( f"{self.BASE_URL}/trading/positions/{position_id}/add-collateral", headers=self.headers, json={"amount_usdc": amount_usdc} ) as r: return await r.json() async def _kill_switch(self, session, scope="most_at_risk"): logger.critical("Triggering kill switch — scope: %s", scope) async with session.post( f"{self.BASE_URL}/trading/kill-switch/trigger", headers=self.headers, json={"scope": scope, "reason": "liquidation_guard"} ) as r: return await r.json() async def _handle_position(self, session, pos): hf = float(pos["health_factor"]) pid = pos["id"] mkt = pos["market"] collat = float(pos["collateral_usdc"]) if hf >= self.config.warning_hf: return # Safe zone — no action wallet_bal = await self._get_wallet_balance(session) available = wallet_bal - self.config.reserve_minimum_usdc if hf < self.config.danger_hf or available <= 0: logger.warning("[%s] HF %.2f in DANGER — triggering kill switch", mkt, hf) await self._kill_switch(session) return # Warning zone: calculate top-up to reach target HF needed_collat = collat * (self.config.target_hf / hf - 1) topup_amount = min(needed_collat, self.config.max_topup_usdc, available) logger.info("[%s] HF %.2f — topping up %.2f USDC", mkt, hf, topup_amount) result = await self._top_up(session, pid, topup_amount) logger.info("[%s] New HF: %.2f", mkt, result.get("new_health_factor", "?")) async def run(self): """Start continuous monitoring loop.""" self._running = True logger.info("LiquidationGuard started (poll interval: %.1fs)", self.config.poll_interval_sec) async with aiohttp.ClientSession() as session: while self._running: try: positions = await self._get_positions(session) tasks = [self._handle_position(session, p) for p in positions] await asyncio.gather(*tasks, return_exceptions=True) except Exception as e: logger.error("Monitor loop error: %s", e) await asyncio.sleep(self.config.poll_interval_sec) def stop(self): self._running = False # ── Usage example ────────────────────────────────────────── if __name__ == "__main__": import os config = GuardConfig( api_key=os.environ["PURPLE_FLEA_API_KEY"], warning_hf=1.6, danger_hf=1.2, target_hf=2.0, max_topup_usdc=500.0, reserve_minimum_usdc=100.0, poll_interval_sec=5.0 ) guard = LiquidationGuard(config) asyncio.run(guard.run())
Register your agent in 60 seconds. Use faucet credits to test the trading API for free before risking real capital.
Already have an account? View your positions →