import BN from 'bn.js' ; import { AMM_RESERVE_PRECISION , AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO , AMM_TO_QUOTE_PRECISION_RATIO , FUNDING_PAYMENT_PRECISION , MARK_PRICE_PRECISION , ONE , PRICE_TO_QUOTE_PRECISION , ZERO , } from '../constants/numericConstants' ; import { Market , PositionDirection , UserPosition } from '../types' ; import { calculateAmmReservesAfterSwap , getSwapDirection } from './amm' ; param market param userPosition returns export function calculateBaseAssetValue ( market , userPosition ) { if ( userPosition . baseAssetAmount . eq ( ZERO ) ) { return ZERO ; } const directionToClose = userPosition . baseAssetAmount . gt ( ZERO ) ? PositionDirection . SHORT : PositionDirection . LONG ; const [ newQuoteAssetReserve , _ ] = calculateAmmReservesAfterSwap ( market . amm , 'base' , userPosition . baseAssetAmount . abs ( ) , getSwapDirection ( 'base' , directionToClose ) ) ; switch ( directionToClose ) { case PositionDirection . SHORT : return market . amm . quoteAssetReserve . sub ( newQuoteAssetReserve ) . mul ( market . amm . pegMultiplier ) . div ( AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO ) ; case PositionDirection . LONG : return newQuoteAssetReserve . sub ( market . amm . quoteAssetReserve ) . mul ( market . amm . pegMultiplier ) . div ( AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO ) ; } } param market param marketPosition param withFunding returns export function calculatePositionPNL ( market , marketPosition , withFunding = false ) { if ( marketPosition . baseAssetAmount . eq ( ZERO ) ) { return ZERO ; } const baseAssetValue = calculateBaseAssetValue ( market , marketPosition ) ; let pnl ; if ( marketPosition . baseAssetAmount . gt ( ZERO ) ) { pnl = baseAssetValue . sub ( marketPosition . quoteAssetAmount ) ; } else { pnl = marketPosition . quoteAssetAmount . sub ( baseAssetValue ) . sub ( ONE ) ; } if ( withFunding ) { const fundingRatePnL = calculatePositionFundingPNL ( market , marketPosition ) . div ( PRICE_TO_QUOTE_PRECISION ) ; pnl = pnl . add ( fundingRatePnL ) ; } return pnl ; } param market param marketPosition returns export function calculatePositionFundingPNL ( market , marketPosition ) { if ( marketPosition . baseAssetAmount . eq ( ZERO ) ) { return ZERO ; } let ammCumulativeFundingRate ; if ( marketPosition . baseAssetAmount . gt ( ZERO ) ) { ammCumulativeFundingRate = market . amm . cumulativeFundingRateLong ; } else { ammCumulativeFundingRate = market . amm . cumulativeFundingRateShort ; } const perPositionFundingRate = ammCumulativeFundingRate . sub ( marketPosition . lastCumulativeFundingRate ) . mul ( marketPosition . baseAssetAmount ) . div ( AMM_RESERVE_PRECISION ) . div ( FUNDING_PAYMENT_PRECISION ) . mul ( new BN ( - 1 ) ) ; return perPositionFundingRate ; } param userPosition returns export function calculateEntryPrice ( userPosition ) { if ( userPosition . baseAssetAmount . eq ( ZERO ) ) { return ZERO ; } return userPosition . quoteAssetAmount . mul ( MARK_PRICE_PRECISION ) . mul ( AMM_TO_QUOTE_PRECISION_RATIO ) . div ( userPosition . baseAssetAmount ) . abs ( ) ; }