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% healthyMethod User.getHealthReference ↗| Name | Type | Default |
|---|---|---|
perpMarketIndex | 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 ↗| Name | Type | Default |
|---|---|---|
marginCategory | MarginCategory | |
strict | boolean | |
includeOpenOrders | boolean | |
liquidationBuffer | any | |
perpMarketIndex | number |
// getMarginRequirement(marginCategory, strict?)
// marginCategory: 'Initial' (for new positions) or 'Maintenance' (for liquidation)
const req = driftClient.getUser().getMarginRequirement('Initial');
console.log(convertToNumber(req, QUOTE_PRECISION)); // USDMethod User.getMarginRequirementReference ↗const free = driftClient.getUser().getFreeCollateral();
console.log(convertToNumber(free, QUOTE_PRECISION)); // USD availableMethod User.getFreeCollateralReference ↗| Name | Type | Default |
|---|---|---|
marginCategory | MarginCategory | |
enterHighLeverageMode | boolean | |
perpMarketIndex | number |
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 ↗| Name | Type | Default |
|---|---|---|
includeOpenOrders | boolean | |
perpMarketIndex | number |
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 ↗| Name | Type | Default |
|---|---|---|
withFunding | boolean | |
marketIndex | number | |
withWeightMarginCategory | MarginCategory | |
strict | boolean | |
liquidationBuffer | any |
// Funding PnL only (accumulated funding payments)
const fundingPnl = driftClient.getUser().getUnrealizedFundingPNL();
console.log(convertToNumber(fundingPnl, QUOTE_PRECISION)); // USDMethod User.getUnrealizedFundingPNLReference ↗| Name | Type | Default |
|---|---|---|
marketIndex | number |
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 ↗| Name | Type | Default |
|---|---|---|
userPosition | PerpPosition |
Settle perp PnL
const user = driftClient.getUser();
await driftClient.settlePNL(user.userAccountPublicKey, user.getUserAccount(), 0);Method DriftClient.settlePNLReference ↗| Name | Type | Default |
|---|---|---|
settleeUserAccountPublicKey | PublicKey | |
settleeUserAccount | UserAccount | |
marketIndex | number | |
txParams | TxParams | |
optionalIxs | TransactionInstruction[] | |
revenueShareEscrowMap | RevenueShareEscrowMap |