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

Return an overall account health score from 0-100, where lower values mean higher liquidation risk.

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

Collateral, margin requirement, leverage

Get total account collateral value in quote units (typically USD precision).

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 ↗
ParameterTypeRequired
marginCategory
MarginCategory
No
strict
boolean
No
includeOpenOrders
boolean
No
liquidationBuffer
any
No
perpMarketIndex
number
No
Returns
BN

Get the required margin for the account under initial or maintenance rules.

// 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 ↗

Signature 1

ParameterTypeRequired
marginCategory
MarginCategory
Yes
liquidationBuffer
any
No
strict
boolean
No
includeOpenOrders
boolean
No
enteringHighLeverage
boolean
No
Returns
BN

Signature 2

ParameterTypeRequired
marginCategory
MarginCategory
The category of margin to calculate ('Initial' or 'Maintenance').
Yes
liquidationBuffer
any
Optional buffer amount to consider during liquidation scenarios.
No
strict
boolean
Optional flag to enforce strict margin calculations.
No
includeOpenOrders
boolean
Optional flag to include open orders in the margin calculation.
No
enteringHighLeverage
boolean
Optional flag indicating if the user is entering high leverage mode.
No
perpMarketIndex
number
Optional index of the perpetual market. Required if marginType is 'Isolated'.
No
Returns
BN

Get currently available collateral that can be used for new positions or withdrawals.

const free = driftClient.getUser().getFreeCollateral(); console.log(convertToNumber(free, QUOTE_PRECISION)); // USD available
Method User.getFreeCollateralReference ↗
ParameterTypeRequired
marginCategory
MarginCategory
No
enterHighLeverageMode
boolean
No
perpMarketIndex
number
No
Returns
BN

Get current account leverage as a scaled value (convert to human-readable x leverage).

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 ↗
ParameterTypeRequired
includeOpenOrders
boolean
No
perpMarketIndex
number
No
Returns
BN

Unrealized PnL

Get unrealized PnL across open positions (optionally including funding effects).

// 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 ↗
ParameterTypeRequired
withFunding
boolean
No
marketIndex
number
No
withWeightMarginCategory
MarginCategory
No
strict
boolean
No
liquidationBuffer
any
No
Returns
BN

Get unrealized funding PnL only, separated from price-movement PnL.

// Funding PnL only (accumulated funding payments) const fundingPnl = driftClient.getUser().getUnrealizedFundingPNL(); console.log(convertToNumber(fundingPnl, QUOTE_PRECISION)); // USD
Method User.getUnrealizedFundingPNLReference ↗
ParameterTypeRequired
marketIndex
number
No
Returns
BN

Entry price helper

Compute the effective entry price for a perp position from its cumulative trade data.

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 ↗
ParameterTypeRequired
userPosition
PerpPosition
Yes

Precision: PRICE_PRECISION (10^6)

Returns
BN

Settle perp PnL

Realize and settle a user’s perp PnL for a specific market into spot balances.

const user = driftClient.getUser(); await driftClient.settlePNL(user.userAccountPublicKey, user.getUserAccount(), 0);
Method DriftClient.settlePNLReference ↗
ParameterTypeRequired
settleeUserAccountPublicKey
PublicKey
Yes
settleeUserAccount
UserAccount
Yes
marketIndex
number
Yes
txParams
TxParams
No
optionalIxs
TransactionInstruction[]
No
revenueShareEscrowMap
RevenueShareEscrowMap
No
Returns
Promise<string>
Last updated on