Skip to Content

PnL & Risk

How it works

Drift calculates your account’s risk using a health metric (0-100) derived from total collateral vs margin requirements. Health 100 = no margin used, health 0 = liquidation eligible.

PnL (Profit and Loss) comes in two forms: unrealized (mark-to-market value of open positions) and realized (settled when positions close). Unrealized PnL is calculated by comparing your position’s entry price to the current oracle price. For perps, you also have funding PnL from periodic funding rate payments between longs and shorts.

Free collateral is the amount of collateral not currently backing positions, it’s what you can withdraw or use to open new positions. Margin requirements increase with position size and vary by market. Leverage is calculated as notional position value divided by total collateral. These metrics update in real-time as prices and positions change.

SDK Usage

These helpers are commonly used for risk checks, dashboards, and liquidation logic.

User health

const user = driftClient.getUser(); const health = user.getHealth(); // returns number 0-100 console.log(health); // e.g. 85 means 85% healthy
Method User.getHealthReference ↗
Parameters:
NameTypeDefault
perpMarketIndexnumber
Returns:
number

Collateral, margin requirement, leverage

import { QUOTE_PRECISION, convertToNumber } from "@drift-labs/sdk"; // getTotalCollateral returns BN in QUOTE_PRECISION (1e6) // marginCategory defaults to 'Initial'; pass 'Maintenance' for liquidation checks const total = driftClient.getUser().getTotalCollateral(); console.log(convertToNumber(total, QUOTE_PRECISION)); // e.g. 1500.50 (USD)
Method User.getTotalCollateralReference ↗
Parameters:
NameTypeDefault
marginCategoryMarginCategory
strictboolean
includeOpenOrdersboolean
liquidationBufferany
perpMarketIndexnumber
Returns:
BN
// getMarginRequirement(marginCategory, strict?) // marginCategory: 'Initial' (for new positions) or 'Maintenance' (for liquidation) const req = driftClient.getUser().getMarginRequirement('Initial'); console.log(convertToNumber(req, QUOTE_PRECISION)); // USD
Method User.getMarginRequirementReference ↗
Parameters:
NameTypeDefault
marginCategoryMarginCategory
liquidationBufferany
strictboolean
includeOpenOrdersboolean
enteringHighLeverageboolean
Returns:
BN
const free = driftClient.getUser().getFreeCollateral(); console.log(convertToNumber(free, QUOTE_PRECISION)); // USD available
Method User.getFreeCollateralReference ↗
Parameters:
NameTypeDefault
marginCategoryMarginCategory
enterHighLeverageModeboolean
perpMarketIndexnumber
Returns:
BN
import { TEN_THOUSAND } from "@drift-labs/sdk"; // getLeverage() returns BN scaled by 10000 (e.g. 2x = BN(20000)) const lev = driftClient.getUser().getLeverage(); console.log(lev.toNumber() / TEN_THOUSAND.toNumber()); // e.g. 2.5 (2.5x leverage)
Method User.getLeverageReference ↗
Parameters:
NameTypeDefault
includeOpenOrdersboolean
perpMarketIndexnumber
Returns:
BN

Unrealized PnL

// Returns BN in QUOTE_PRECISION. Positive = profit, negative = loss. // Pass withWeightMarginCategory to apply asset/liability weights. const pnl = driftClient.getUser().getUnrealizedPNL(true); // withFunding=true console.log(convertToNumber(pnl, QUOTE_PRECISION)); // e.g. -25.50 (USD)
Method User.getUnrealizedPNLReference ↗
Parameters:
NameTypeDefault
withFundingboolean
marketIndexnumber
withWeightMarginCategoryMarginCategory
strictboolean
liquidationBufferany
Returns:
BN
// Funding PnL only (accumulated funding payments) const fundingPnl = driftClient.getUser().getUnrealizedFundingPNL(); console.log(convertToNumber(fundingPnl, QUOTE_PRECISION)); // USD
Method User.getUnrealizedFundingPNLReference ↗
Parameters:
NameTypeDefault
marketIndexnumber
Returns:
BN

Entry price helper

import { calculateEntryPrice, PRICE_PRECISION, convertToNumber } from "@drift-labs/sdk"; const position = driftClient.getUser().getPerpPosition(0); if (position) { const entryPrice = calculateEntryPrice(position); // BN in PRICE_PRECISION console.log(convertToNumber(entryPrice, PRICE_PRECISION)); // e.g. 150.25 }
Function calculateEntryPriceReference ↗
Parameters:
NameTypeDefault
userPositionPerpPosition
Returns:
BN

Precision: PRICE_PRECISION (10^6)

Settle perp PnL

const user = driftClient.getUser(); await driftClient.settlePNL(user.userAccountPublicKey, user.getUserAccount(), 0);
Method DriftClient.settlePNLReference ↗
Parameters:
NameTypeDefault
settleeUserAccountPublicKeyPublicKey
settleeUserAccountUserAccount
marketIndexnumber
txParamsTxParams
optionalIxsTransactionInstruction[]
revenueShareEscrowMapRevenueShareEscrowMap
Returns:
Promise<string>
Last updated on