Skip to main content

Overview

The position management module provides functions for calculating position metrics, unrealized PnL, funding payments, and other position-related data.

Position Calculation Functions

calculatePositionPNL

Calculates the unrealized PnL for a perpetual position. Formula: BaseAssetAmount × (Avg Exit Price - Avg Entry Price)
import { calculatePositionPNL } from '@drift-labs/sdk';

const pnl = calculatePositionPNL(
  perpMarket,
  perpPosition,
  true, // include funding
  oraclePriceData
);

console.log('Position PnL:', pnl.toString());
Parameters:
market
PerpMarketAccount
required
The perpetual market account.
perpPosition
PerpPosition
required
The user’s perpetual position.
withFunding
boolean
default:"false"
Whether to include unrealized funding payment PnL in the result.
oraclePriceData
OraclePriceData
required
Oracle price data containing the current price.
Returns: BN - Position PnL in QUOTE_PRECISION (1e6)

calculateBaseAssetValue

Calculates the market value of closing the entire position.
import { calculateBaseAssetValue } from '@drift-labs/sdk';

const positionValue = calculateBaseAssetValue(
  perpMarket,
  perpPosition,
  mmOraclePriceData,
  true, // use spread
  false, // don't skip AMM update
  latestSlot
);
Parameters:
market
PerpMarketAccount
required
The perpetual market account.
userPosition
PerpPosition
required
The user’s position.
mmOraclePriceData
MMOraclePriceData
required
Market maker oracle price data.
useSpread
boolean
default:"true"
Whether to apply AMM spread to the calculation.
skipUpdate
boolean
default:"false"
Whether to skip AMM updates before calculation.
latestSlot
BN
Latest slot for accurate AMM state.
Returns: BN - Base asset value in QUOTE_PRECISION (1e6)

calculateClaimablePnl

Calculates the claimable (settleable) PnL for a position, accounting for pool limitations.
import { calculateClaimablePnl } from '@drift-labs/sdk';

const claimable = calculateClaimablePnl(
  perpMarket,
  spotMarket, // quote spot market
  perpPosition,
  oraclePriceData
);
Parameters:
market
PerpMarketAccount
required
The perpetual market account.
spotMarket
SpotMarketAccount
required
The quote spot market account (usually USDC).
perpPosition
PerpPosition
required
The user’s perpetual position.
oraclePriceData
OraclePriceData
required
Oracle price data.
Returns: BN - Claimable PnL in QUOTE_PRECISION (1e6)

Funding Calculations

calculateUnsettledFundingPnl

Calculates the unsettled funding payment PnL for a position.
import { calculateUnsettledFundingPnl } from '@drift-labs/sdk';

const fundingPnl = calculateUnsettledFundingPnl(
  perpMarket,
  perpPosition
);

console.log('Unsettled funding:', fundingPnl.toString());
Parameters:
market
PerpMarketAccount
required
The perpetual market account.
perpPosition
PerpPosition
required
The user’s perpetual position.
Returns: BN - Unsettled funding PnL in QUOTE_PRECISION (1e6)

calculateFeesAndFundingPnl

Returns total fees and funding PnL for a position.
import { calculateFeesAndFundingPnl } from '@drift-labs/sdk';

const totalFeesFunding = calculateFeesAndFundingPnl(
  perpMarket,
  perpPosition,
  true // include unsettled funding
);
Parameters:
market
PerpMarketAccount
required
The perpetual market account.
perpPosition
PerpPosition
required
The user’s perpetual position.
includeUnsettled
boolean
default:"true"
Whether to include unsettled funding in the result.
Returns: BN - Total fees and funding PnL in QUOTE_PRECISION (1e6)

Price Calculations

calculateBreakEvenPrice

Calculates the break-even price for a position (entry price + fees + funding).
import { calculateBreakEvenPrice } from '@drift-labs/sdk';

const breakEven = calculateBreakEvenPrice(perpPosition);
console.log('Break-even price:', breakEven.toString());
Parameters:
userPosition
PerpPosition
required
The user’s perpetual position.
Returns: BN - Break-even price in PRICE_PRECISION (1e6)

calculateEntryPrice

Calculates the average entry price for a position.
import { calculateEntryPrice } from '@drift-labs/sdk';

const entryPrice = calculateEntryPrice(perpPosition);
console.log('Entry price:', entryPrice.toString());
Parameters:
userPosition
PerpPosition
required
The user’s perpetual position.
Returns: BN - Average entry price in PRICE_PRECISION (1e6)

calculateCostBasis

Calculates the cost basis of a position.
import { calculateCostBasis } from '@drift-labs/sdk';

const costBasis = calculateCostBasis(
  perpPosition,
  true // include settled PnL
);
Parameters:
userPosition
PerpPosition
required
The user’s perpetual position.
includeSettledPnl
boolean
default:"false"
Whether to include settled PnL in the calculation.
Returns: BN - Cost basis in PRICE_PRECISION (1e10)

Position State Functions

findDirectionToClose

Determines the direction needed to close a position.
import { findDirectionToClose, PositionDirection } from '@drift-labs/sdk';

const closeDirection = findDirectionToClose(perpPosition);
// Returns PositionDirection.SHORT for long positions
// Returns PositionDirection.LONG for short positions
Parameters:
userPosition
PerpPosition
required
The user’s perpetual position.
Returns: PositionDirection - Direction to close the position

positionCurrentDirection

Returns the current direction of a position.
import { positionCurrentDirection } from '@drift-labs/sdk';

const direction = positionCurrentDirection(perpPosition);
Parameters:
userPosition
PerpPosition
required
The user’s perpetual position.
Returns: PositionDirection - Current position direction

positionIsAvailable

Checks if a position slot is available (no position or orders).
import { positionIsAvailable } from '@drift-labs/sdk';

const isAvailable = positionIsAvailable(perpPosition);
if (isAvailable) {
  console.log('Position slot is available');
}
Parameters:
position
PerpPosition
required
The perpetual position to check.
Returns: boolean - True if position slot is available

positionIsBeingLiquidated

Checks if a position is currently being liquidated.
import { positionIsBeingLiquidated } from '@drift-labs/sdk';

const isLiquidating = positionIsBeingLiquidated(perpPosition);
if (isLiquidating) {
  console.log('Position is being liquidated!');
}
Parameters:
position
PerpPosition
required
The perpetual position to check.
Returns: boolean - True if position has BeingLiquidated or Bankruptcy flag set

isEmptyPosition

Checks if a position is empty (no base asset and no open orders).
import { isEmptyPosition } from '@drift-labs/sdk';

const isEmpty = isEmptyPosition(perpPosition);
Parameters:
userPosition
PerpPosition
required
The user’s perpetual position.
Returns: boolean - True if position is empty

hasOpenOrders

Checks if a position has any open orders.
import { hasOpenOrders } from '@drift-labs/sdk';

const hasOrders = hasOpenOrders(perpPosition);
if (hasOrders) {
  console.log('Position has open orders');
}
Parameters:
position
PerpPosition
required
The position to check.
Returns: boolean - True if position has open orders

PerpPosition Type

The PerpPosition type contains all data for a perpetual position:
baseAssetAmount
BN
Current base asset amount held (positive for long, negative for short).
lastCumulativeFundingRate
BN
Last cumulative funding rate when position was updated.
marketIndex
number
Index of the perpetual market.
quoteAssetAmount
BN
Current quote asset amount (cost basis).
quoteEntryAmount
BN
Quote amount at entry (before fees and funding).
quoteBreakEvenAmount
BN
Quote amount including fees and funding (break-even point).
openOrders
number
Number of open orders for this position.
openBids
BN
Total size of open bid orders.
openAsks
BN
Total size of open ask orders.
settledPnl
BN
Settled PnL for this position.
lpShares
BN
LP shares if user is providing liquidity.
maxMarginRatio
number
Maximum margin ratio for this position.
lastQuoteAssetAmountPerLp
BN
Last quote asset amount per LP share.
perLpBase
number
Base asset per LP (i8).
positionFlag
number
Position status flags.PositionFlag values:
  • PositionFlag.IsolatedPosition (1) - Isolated margin position
  • PositionFlag.BeingLiquidated (2) - Position is being liquidated
  • PositionFlag.Bankruptcy (4) - Position is bankrupt
isolatedPositionScaledBalance
BN
Scaled balance for isolated positions.

Example: Position Dashboard

import {
  calculatePositionPNL,
  calculateBreakEvenPrice,
  calculateEntryPrice,
  calculateUnsettledFundingPnl,
  convertToNumber,
  PRICE_PRECISION,
  QUOTE_PRECISION,
} from '@drift-labs/sdk';

function displayPositionMetrics(
  perpMarket: PerpMarketAccount,
  position: PerpPosition,
  oraclePriceData: OraclePriceData
) {
  const pnl = calculatePositionPNL(
    perpMarket,
    position,
    true,
    oraclePriceData
  );
  
  const entryPrice = calculateEntryPrice(position);
  const breakEvenPrice = calculateBreakEvenPrice(position);
  const fundingPnl = calculateUnsettledFundingPnl(perpMarket, position);
  
  console.log('Position Metrics:');
  console.log('  Entry Price:', convertToNumber(entryPrice, PRICE_PRECISION));
  console.log('  Break-Even:', convertToNumber(breakEvenPrice, PRICE_PRECISION));
  console.log('  Unrealized PnL:', convertToNumber(pnl, QUOTE_PRECISION));
  console.log('  Funding PnL:', convertToNumber(fundingPnl, QUOTE_PRECISION));
  console.log('  Position Size:', position.baseAssetAmount.toString());
}

See Also

  • OrderParams - Configure and place orders
  • DLOB - Decentralized Limit Order Book

Build docs developers (and LLMs) love