The position calculation utilities provide comprehensive functions for calculating position values, profit and loss, funding payments, and other position-related metrics.
Position Value Functions
calculateBaseAssetValue
Calculates the market value of closing an entire position using AMM reserves.
calculateBaseAssetValue(
market: PerpMarketAccount,
userPosition: PerpPosition,
mmOraclePriceData: MMOraclePriceData,
useSpread?: boolean,
skipUpdate?: boolean,
latestSlot?: BN
): BN
market
PerpMarketAccount
required
The perpetual market account
mmOraclePriceData
MMOraclePriceData
required
The oracle price data
Whether to include spread in calculation
Whether to skip AMM updates
The latest slot for calculations
Base asset value in QUOTE_PRECISION
Usage Example
import { calculateBaseAssetValue } from '@drift-labs/sdk';
const market = driftClient.getPerpMarketAccount(0);
const position = user.getPerpPosition(0);
const oracleData = driftClient.getOracleDataForPerpMarket(0);
const value = calculateBaseAssetValue(
market,
position,
oracleData,
true // use spread
);
console.log('Position value:', convertToNumber(value, QUOTE_PRECISION));
PnL Calculation Functions
calculatePositionPNL
Calculates position PnL as: BaseAssetAmount * (Avg Exit Price - Avg Entry Price).
calculatePositionPNL(
market: PerpMarketAccount,
perpPosition: PerpPosition,
withFunding?: boolean,
oraclePriceData: Pick<OraclePriceData, 'price'>
): BN
market
PerpMarketAccount
required
The perpetual market account
Whether to include unrealized funding payment PnL
oraclePriceData
Pick<OraclePriceData, 'price'>
required
Oracle price data
Position PnL in QUOTE_PRECISION
Usage Example
import { calculatePositionPNL } from '@drift-labs/sdk';
const market = driftClient.getPerpMarketAccount(0);
const position = user.getPerpPosition(0);
const oracleData = driftClient.getOracleDataForPerpMarket(0);
// PnL without funding
const pnl = calculatePositionPNL(market, position, false, oracleData);
console.log('PnL:', convertToNumber(pnl, QUOTE_PRECISION));
// PnL with funding
const pnlWithFunding = calculatePositionPNL(market, position, true, oracleData);
console.log('PnL with funding:', convertToNumber(pnlWithFunding, QUOTE_PRECISION));
calculateClaimablePnl
Calculates the claimable (realizable) PnL for a position, accounting for pool limits.
calculateClaimablePnl(
market: PerpMarketAccount,
spotMarket: SpotMarketAccount,
perpPosition: PerpPosition,
oraclePriceData: Pick<OraclePriceData, 'price'>
): BN
market
PerpMarketAccount
required
The perpetual market account
spotMarket
SpotMarketAccount
required
The spot market account
oraclePriceData
Pick<OraclePriceData, 'price'>
required
Oracle price data
Claimable PnL in QUOTE_PRECISION
Funding Calculation Functions
calculateUnsettledFundingPnl
Returns unsettled funding PnL for a position.
calculateUnsettledFundingPnl(
market: PerpMarketAccount,
perpPosition: PerpPosition
): BN
market
PerpMarketAccount
required
The perpetual market account
Unsettled funding PnL in QUOTE_PRECISION
Usage Example
import { calculateUnsettledFundingPnl } from '@drift-labs/sdk';
const market = driftClient.getPerpMarketAccount(0);
const position = user.getPerpPosition(0);
const fundingPnl = calculateUnsettledFundingPnl(market, position);
console.log('Unsettled funding:', convertToNumber(fundingPnl, QUOTE_PRECISION));
calculateFeesAndFundingPnl
Returns total fees and funding PnL for a position.
calculateFeesAndFundingPnl(
market: PerpMarketAccount,
perpPosition: PerpPosition,
includeUnsettled?: boolean
): BN
market
PerpMarketAccount
required
The perpetual market account
Whether to include unsettled funding
Total fees and funding PnL in QUOTE_PRECISION
Price Calculation Functions
calculateBreakEvenPrice
Calculates the break-even price for a position.
calculateBreakEvenPrice(
userPosition: PerpPosition
): BN
Break-even price in PRICE_PRECISION (10^6)
Usage Example
import { calculateBreakEvenPrice } from '@drift-labs/sdk';
const position = user.getPerpPosition(0);
const breakEvenPrice = calculateBreakEvenPrice(position);
console.log('Break-even price:', convertToNumber(breakEvenPrice, PRICE_PRECISION));
calculateEntryPrice
Calculates the entry price for a position.
calculateEntryPrice(
userPosition: PerpPosition
): BN
Entry price in PRICE_PRECISION (10^6)
calculateCostBasis
Calculates the cost basis for a position.
calculateCostBasis(
userPosition: PerpPosition,
includeSettledPnl?: boolean
): BN
Whether to include settled PnL in calculation
Cost basis in PRICE_PRECISION (10^10)
Position Status Functions
positionIsAvailable
Checks if a position slot is available (empty and not being liquidated).
positionIsAvailable(
position: PerpPosition
): boolean
True if position is available
positionIsBeingLiquidated
Checks if a position is currently being liquidated.
positionIsBeingLiquidated(
position: PerpPosition
): boolean
True if position is being liquidated or bankrupt
isEmptyPosition
Checks if a position is empty (no base amount and no open orders).
isEmptyPosition(
userPosition: PerpPosition
): boolean
True if position is empty
hasOpenOrders
Checks if a position has open orders.
hasOpenOrders(
position: PerpPosition
): boolean
True if position has open orders, bids, or asks
Direction Helper Functions
findDirectionToClose
Determines the direction needed to close a position.
findDirectionToClose(
userPosition: PerpPosition
): PositionDirection
SHORT if position is long, LONG if position is short
positionCurrentDirection
Returns the current direction of a position.
positionCurrentDirection(
userPosition: PerpPosition
): PositionDirection
LONG if baseAssetAmount >= 0, SHORT otherwise
Usage Example
import {
findDirectionToClose,
positionCurrentDirection,
PositionDirection
} from '@drift-labs/sdk';
const position = user.getPerpPosition(0);
const currentDir = positionCurrentDirection(position);
const closeDir = findDirectionToClose(position);
console.log('Current direction:', currentDir === PositionDirection.LONG ? 'LONG' : 'SHORT');
console.log('Direction to close:', closeDir === PositionDirection.LONG ? 'LONG' : 'SHORT');