Skip to main content

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 < $1 after the decrease, or
  • A loss would leave the remaining collateral below the minimum factor threshold, and the remaining collateral + PnL is below minCollateralUsd or the remaining size is below minPositionSizeUsd.
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);