DEV Community
Monitoring Perpetual Futures Liquidation Risk in Python: Mark Price, Margin State, and Data Freshness
Disclosure: AI assistance was used in preparing this technical article. The code is an illustrative monitoring example, not a production liquidation engine or a live exchange integration. A derivatives trading system can receive three different prices for the same contract: Last traded price. Index price. Mark price. All three may be valid, but they are not interchangeable. A common engineering mistake is to use the last traded price for every downstream calculation, including unrealized profit and loss, margin monitoring, stop-loss simulation, and liquidation-risk estimation. That can produce incorrect risk states. This article develops a minimal monitoring approach that preserves the meanings of different price fields and treats the exchange's account-level margin data as separate inputs. 1. Define the failure scenario Consider a hypothetical BTCUSDT perpetual long position. Field Value Last price 100,100 Index price 99,900 Mark price 99,850 Estimated liquidation level 99,900 The last traded price remains above the estimated liquidation level. The mark price is below it. For a contract whose liquidation risk depends on the mark price and applicable maintenance margin requirements, those values describe different potential risk conclusions. The correct engineering response is not to assume that the last-price chart is wrong. It is to identify which field the exchange uses for each function and which account conditions are needed to evaluate the position. 2. Maintain separate market and account data A reliable risk snapshot should contain at least: Market data Instrument and exchange identifiers. Last traded price. Index price. Mark price. Source event timestamps. Local receipt timestamps. Position data Contract type and size. Entry or average position cost. Margin mode. Funding-related adjustments. Applicable maintenance margin tier. Account data Margin balance or equivalent risk-account equity. Maintenance margin requirement. Exchange-reported risk ratio. Relevant restrictions and pending orders. Not every account mode provides a meaningful single liquidation price. For example, cross-margin arrangements may depend on other positions and collateral in the same account. The implementation should therefore prefer official account-level risk fields where available. A locally estimated liquidation level can be retained as a diagnostic, but it should not override the exchange's actual account state. 3. Build a small monitoring function The following Python example distinguishes the prices, checks data freshness, and compares illustrative margin-account values. It does not attempt to reproduce Binance, Bybit, or OKX liquidation formulas. from dataclasses import dataclass
from datetime import datetime, timezone, timedelta
import math
@dataclass(frozen=True)
class RiskSnapshot:
instrument: str
last_price: float
index_price: float
mark_price: float
margin_balance: float
maintenance_margin: float
mark_timestamp: datetime
def inspect_risk(snapshot, observed_at, max_age_seconds=5):
values = [
snapshot.last_price,
snapshot.index_price,
snapshot.mark_price,
snapshot.margin_balance,
snapshot.maintenance_margin,
]
if not all(math.isfinite(v) for v in values):
raise ValueError("Non-finite numerical input.")
if min(
snapshot.last_price,
snapshot.index_price,
snapshot.mark_price
) <= 0:
raise ValueError("Prices must be positive.")
if snapshot.maintenance_margin < 0:
raise ValueError("Invalid maintenance margin.")
if snapshot.mark_timestamp.tzinfo is None:
raise ValueError("Timestamp must be timezone-aware.")
if observed_at.tzinfo is None:
raise ValueError("Observation time must be timezone-aware.")
age = observed_at - snapshot.mark_timestamp
if age < timedelta(seconds=0) or age > timedelta(
seconds=max_age_seconds
):
return {
"s...
Powered by Readybot.io
External Link
Platform
You are about to visit:
https://example.comThis will open in a new tab. Make sure you trust this link.