decrease
This module provides utilities for calculating decrease position amounts, fees, and next position values when closing or reducing trading positions. It handles complex calculations including PnL realization, fee deductions, collateral adjustments, and swap requirements.
Methods
The decrease trade module exports functions for computing position close amounts, determining full-close conditions, calculating collateral costs, and projecting the next position state. Import any function directly from @gmx-io/sdk/utils/trade.
getDecreasePositionAmounts
getDecreasePositionAmounts(p: {
marketInfo: MarketInfo;
collateralToken: TokenData;
isLong: boolean;
position: PositionInfoLoaded | undefined;
closeSizeUsd: bigint;
keepLeverage: boolean;
triggerPrice?: bigint;
fixedAcceptablePriceImpactBps?: bigint;
acceptablePriceImpactBuffer?: number;
userReferralInfo: UserReferralInfo | undefined;
minCollateralUsd: bigint;
minPositionSizeUsd: bigint;
uiFeeFactor: bigint;
isLimit?: boolean;
limitPrice?: bigint;
triggerOrderType?: DecreasePositionAmounts["triggerOrderType"];
isSetAcceptablePriceImpactEnabled: boolean;
receiveToken?: TokenData;
}): DecreasePositionAmounts
Computes a complete DecreasePositionAmounts result for a Market Decrease, Limit Decrease, Stop-Loss, or Take-Profit order. The result includes all pricing, fee, PnL, collateral, and receive-amount fields needed to build the on-chain order.
When position is undefined or has zero size, only the fee and price fields are computed; amounts relating to PnL and collateral are left at zero.
When receiveToken is omitted, it defaults to collateralToken.
import { getDecreasePositionAmounts } from "@gmx-io/sdk/utils/trade";
const decreaseAmounts = getDecreasePositionAmounts({
marketInfo,
collateralToken: usdcToken,
isLong: true,
position: currentPosition,
closeSizeUsd: 1000n * 10n ** 30n, // close $1000 of position
keepLeverage: false,
userReferralInfo: undefined,
minCollateralUsd: 5000n * 10n ** 30n,
minPositionSizeUsd: 1000n * 10n ** 30n,
uiFeeFactor: 0n,
isSetAcceptablePriceImpactEnabled: true,
});
console.log("Receive token amount:", decreaseAmounts.receiveTokenAmount);
console.log("Receive USD:", decreaseAmounts.receiveUsd);
console.log("Realized PnL:", decreaseAmounts.realizedPnl);
console.log("Position fee:", decreaseAmounts.positionFeeUsd);
console.log("Acceptable price:", decreaseAmounts.acceptablePrice);
getIsFullClose
getIsFullClose(p: {
position: PositionInfoLoaded;
sizeDeltaUsd: bigint;
indexPrice: bigint;
remainingCollateralUsd: bigint;
minCollateralUsd: bigint;
minPositionSizeUsd: bigint;
}): boolean
Returns true when the decrease must be treated as a full close. This happens when:
- The remaining position size would be
< $1after the decrease, or - A loss would leave the remaining collateral below the minimum factor threshold, and the remaining collateral + PnL is below
minCollateralUsdor the remaining size is belowminPositionSizeUsd.
import { getIsFullClose } from "@gmx-io/sdk/utils/trade";
const isFullClose = getIsFullClose({
position: currentPosition,
sizeDeltaUsd: 500n * 10n ** 30n,
indexPrice: currentPosition.markPrice,
remainingCollateralUsd: 100n * 10n ** 30n,
minCollateralUsd: 5000n * 10n ** 30n,
minPositionSizeUsd: 1000n * 10n ** 30n,
});
getMinCollateralUsdForLeverage
getMinCollateralUsdForLeverage(position: PositionInfoLoaded, openInterestDelta: bigint): bigint
Returns the minimum collateral required to keep the current position's leverage within the market's allowed range, given an open interest change.
import { getMinCollateralUsdForLeverage } from "@gmx-io/sdk/utils/trade";
const minCollateral = getMinCollateralUsdForLeverage(
currentPosition,
-1000n * 10n ** 30n // OI decreasing by $1000
);
payForCollateralCost
payForCollateralCost(p: {
initialCostUsd: bigint;
collateralToken: TokenData;
collateralPrice: bigint;
outputAmount: bigint;
remainingCollateralAmount: bigint;
}): {
outputAmount: bigint;
remainingCollateralAmount: bigint;
paidOutputAmount: bigint;
paidRemainingCollateralAmount: bigint;
}
Deducts initialCostUsd from outputAmount first, then from remainingCollateralAmount. Returns the updated balances and the amounts paid from each source.
import { payForCollateralCost } from "@gmx-io/sdk/utils/trade";
const result = payForCollateralCost({
initialCostUsd: 100n * 10n ** 30n,
collateralToken: usdcToken,
collateralPrice: 1n * 10n ** 30n, // $1 per USDC
outputAmount: 50_000_000n, // 50 USDC (6 decimals)
remainingCollateralAmount: 1_000_000_000n,
});
// result.paidOutputAmount — deducted from output
// result.paidRemainingCollateralAmount — deducted from remaining collateral
estimateCollateralCost
estimateCollateralCost(baseUsd: bigint, collateralToken: TokenData, collateralPrice: bigint): {
amount: bigint;
usd: bigint;
}
Converts baseUsd to the collateral token's amount using collateralToken.prices.minPrice, then converts back to USD using collateralPrice. Used to estimate costs denominated in the collateral token.
import { estimateCollateralCost } from "@gmx-io/sdk/utils/trade";
const { amount, usd } = estimateCollateralCost(
50n * 10n ** 30n, // $50
usdcToken,
1n * 10n ** 30n // $1 per USDC
);
// amount: token units of the cost
// usd: cost in USD at collateralPrice
getTotalFeesUsdForDecrease
getTotalFeesUsdForDecrease(p: {
positionFeeUsd: bigint;
borrowingFeeUsd: bigint;
fundingFeeUsd: bigint;
swapProfitFeeUsd: bigint;
swapUiFeeUsd: bigint;
uiFeeUsd: bigint;
pnlUsd: bigint;
totalPendingImpactDeltaUsd: bigint;
}): bigint
Returns the total cost that must be covered by the position's output. Only negative contributions are counted: a negative pnlUsd (loss) and a negative totalPendingImpactDeltaUsd (adverse price impact) are added as absolute values.
import { getTotalFeesUsdForDecrease } from "@gmx-io/sdk/utils/trade";
const totalCost = getTotalFeesUsdForDecrease({
positionFeeUsd: 10n * 10n ** 30n,
borrowingFeeUsd: 5n * 10n ** 30n,
fundingFeeUsd: 2n * 10n ** 30n,
swapProfitFeeUsd: 1n * 10n ** 30n,
swapUiFeeUsd: 0n,
uiFeeUsd: 0n,
pnlUsd: -10n * 10n ** 30n, // $10 loss is added to total cost
totalPendingImpactDeltaUsd: -5n * 10n ** 30n, // negative impact is added
});
// totalCost = 10 + 5 + 2 + 1 + 10 + 5 = $33
getNextPositionValuesForDecreaseTrade
getNextPositionValuesForDecreaseTrade(p: {
existingPosition?: PositionInfo;
marketInfo: MarketInfo;
collateralToken: TokenData;
sizeDeltaUsd: bigint;
sizeDeltaInTokens: bigint;
realizedPnl: bigint;
estimatedPnl: bigint;
collateralDeltaUsd: bigint;
collateralDeltaAmount: bigint;
payedRemainingCollateralUsd: bigint;
payedRemainingCollateralAmount: bigint;
proportionalPendingImpactDeltaUsd: bigint;
showPnlInLeverage: boolean;
isLong: boolean;
minCollateralUsd: bigint;
userReferralInfo: UserReferralInfo | undefined;
}): NextPositionValues
Computes the projected position state after a decrease: remaining size, collateral, leverage, PnL percentage, and liquidation price. Use this to populate UI previews before order submission.
import { getNextPositionValuesForDecreaseTrade } from "@gmx-io/sdk/utils/trade";
const nextValues = getNextPositionValuesForDecreaseTrade({
existingPosition: currentPosition,
marketInfo,
collateralToken: usdcToken,
sizeDeltaUsd: decreaseAmounts.sizeDeltaUsd,
sizeDeltaInTokens: decreaseAmounts.sizeDeltaInTokens,
realizedPnl: decreaseAmounts.realizedPnl,
estimatedPnl: decreaseAmounts.estimatedPnl,
collateralDeltaUsd: decreaseAmounts.collateralDeltaUsd,
collateralDeltaAmount: decreaseAmounts.collateralDeltaAmount,
payedRemainingCollateralUsd: decreaseAmounts.payedRemainingCollateralUsd,
payedRemainingCollateralAmount: decreaseAmounts.payedRemainingCollateralAmount,
proportionalPendingImpactDeltaUsd: decreaseAmounts.proportionalPendingImpactDeltaUsd,
showPnlInLeverage: true,
isLong: true,
minCollateralUsd: 5000n * 10n ** 30n,
userReferralInfo: undefined,
});
console.log("Next size:", nextValues.nextSizeUsd);
console.log("Next leverage:", nextValues.nextLeverage);
console.log("Next liq price:", nextValues.nextLiqPrice);