24: Calculate and expose liquidationPrice in JupiterPerpsPosition
This commit is contained in:
@@ -20,6 +20,7 @@ import java.math.BigDecimal;
|
||||
* @param pnlPercent the profit and loss represented as a percentage
|
||||
* @param leverage TODO
|
||||
* @param entryPrice the entry price of the position, denominated in USDC
|
||||
* @param liquidationPrice the estimated liquidation price of the position, denominated in USDC
|
||||
* @param marketPrice the current spot price of the token
|
||||
* @param collateral the amount of USD representing the collateral for this position
|
||||
* @param totalFees the total amount of fees (TODO: is that including pending/due fees)
|
||||
@@ -37,6 +38,7 @@ public record JupiterPerpsPosition(
|
||||
BigDecimal pnlPercent,
|
||||
BigDecimal leverage,
|
||||
ΩUSDCPriceΩ entryPrice,
|
||||
ΩUSDCPriceΩ liquidationPrice,
|
||||
ΩUSDCPriceΩ marketPrice,
|
||||
ΩUSDCAmountΩ collateral,
|
||||
ΩUSDCAmountΩ totalFees,
|
||||
|
||||
+80
-3
@@ -1,6 +1,7 @@
|
||||
package com.r35157.libs.jupiter.perps.impl.anchoridl;
|
||||
|
||||
import com.r35157.libs.jupiter.perps.JupiterPerpsPosition;
|
||||
import com.r35157.libs.jupiter.perps.JupiterPerpsPositionDirection;
|
||||
import com.r35157.libs.jupiter.perps.JupiterPerpsService;
|
||||
import com.r35157.libs.solana.SolanaAccountInfo;
|
||||
import com.r35157.libs.solana.SolanaBlockChain;
|
||||
@@ -114,12 +115,34 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
||||
|
||||
ΩSPLMintAddressΩ mintAddress = custodyAccountInfo.mintAddress();
|
||||
|
||||
ΩJupiterPostionInterestΩ positionInterest = custodyAccountInfo.currentCumulativeInterestRate()
|
||||
ΩJupiterPerpsCollateralCustodyAccountAddressΩ collateralCustodyAccountAddress =
|
||||
perpsPositionInfo.collateralCustodyAccountAddress();
|
||||
|
||||
ΩJupiterCustodyAccountInfoEncodedΩ encodedCollateralCustodyAccountInfo =
|
||||
solanaBlockChain.getAccountInfo(collateralCustodyAccountAddress);
|
||||
|
||||
if (encodedCollateralCustodyAccountInfo == null) {
|
||||
String errorMsg = "Jupiter Perps collateral custody account does not exist: " + collateralCustodyAccountAddress;
|
||||
throw new IllegalArgumentException(errorMsg);
|
||||
}
|
||||
|
||||
JupiterCustodyAccountInfo collateralCustodyAccountInfo =
|
||||
custodyDecoder.decode(encodedCollateralCustodyAccountInfo);
|
||||
|
||||
ΩJupiterPostionInterestΩ positionInterest = collateralCustodyAccountInfo.currentCumulativeInterestRate()
|
||||
.subtract(perpsPositionInfo.cumulativeInterestSnapshot());
|
||||
|
||||
ΩUSDCAmountΩ positionSize = perpsPositionInfo.positionSize();
|
||||
ΩUSDCAmountΩ borrowFeesDue = calculateBorrowFeesDue(positionInterest, positionSize);
|
||||
ΩUSDCAmountΩ closeFeePending = calculateCloseFeePending(positionSize);
|
||||
ΩUSDCPriceΩ liquidationPrice = calculateLiquidationPrice(
|
||||
perpsPositionInfo.direction(),
|
||||
perpsPositionInfo.entryPrice(),
|
||||
perpsPositionInfo.collateral(),
|
||||
closeFeePending,
|
||||
borrowFeesDue,
|
||||
positionSize
|
||||
);
|
||||
|
||||
ΩUSDCAmountΩ value = ZERO; // TODO - Dummy
|
||||
ΩUSDCAmountΩ pnl = ZERO; // TODO - Dummy
|
||||
@@ -142,6 +165,7 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
||||
pnlPercent,
|
||||
leverage,
|
||||
perpsPositionInfo.entryPrice(),
|
||||
liquidationPrice,
|
||||
marketPrice,
|
||||
perpsPositionInfo.collateral(),
|
||||
totalFees,
|
||||
@@ -161,7 +185,7 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
||||
.multiply(size)
|
||||
.divide(
|
||||
BigDecimal.valueOf(RATE_POWER),
|
||||
6,
|
||||
USDC_DECIMALS,
|
||||
RoundingMode.CEILING
|
||||
);
|
||||
return fees;
|
||||
@@ -172,19 +196,72 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
||||
.multiply(BigDecimal.valueOf(CLOSE_FEE_BPS))
|
||||
.divide(
|
||||
BigDecimal.valueOf(BASIS_POINTS_DIVISOR),
|
||||
6,
|
||||
USDC_DECIMALS,
|
||||
RoundingMode.CEILING
|
||||
);
|
||||
|
||||
return fee;
|
||||
}
|
||||
|
||||
private static ΩUSDCPriceΩ calculateLiquidationPrice(
|
||||
JupiterPerpsPositionDirection direction,
|
||||
ΩUSDCPriceΩ price,
|
||||
ΩUSDCAmountΩ collateral,
|
||||
ΩUSDCAmountΩ closeFeePending,
|
||||
ΩUSDCAmountΩ borrowFeesDue,
|
||||
ΩUSDCAmountΩ positionSize
|
||||
) {
|
||||
ΩUSDCAmountΩ minimumCollateral = positionSize.divide(
|
||||
BigDecimal.valueOf(MAX_LEVERAGE),
|
||||
USDC_DECIMALS,
|
||||
RoundingMode.CEILING
|
||||
);
|
||||
|
||||
ΩUSDCAmountΩ maxLoss = minimumCollateral
|
||||
.add(closeFeePending)
|
||||
.add(borrowFeesDue);
|
||||
|
||||
ΩUSDCAmountΩ maxPriceDiffAmount = maxLoss
|
||||
.subtract(collateral)
|
||||
.abs();
|
||||
|
||||
ΩUSDCPriceΩ maxPriceDiff = maxPriceDiffAmount
|
||||
.multiply(price)
|
||||
.divide(
|
||||
positionSize,
|
||||
USDC_DECIMALS,
|
||||
RoundingMode.CEILING
|
||||
);
|
||||
|
||||
boolean maxLossExceedsCollateral = maxLoss.compareTo(collateral) > 0;
|
||||
|
||||
if (direction == JupiterPerpsPositionDirection.LONG) {
|
||||
if (maxLossExceedsCollateral) {
|
||||
return price.add(maxPriceDiff);
|
||||
}
|
||||
|
||||
return price.subtract(maxPriceDiff);
|
||||
}
|
||||
|
||||
if (direction == JupiterPerpsPositionDirection.SHORT) {
|
||||
if (maxLossExceedsCollateral) {
|
||||
return price.subtract(maxPriceDiff);
|
||||
}
|
||||
|
||||
return price.add(maxPriceDiff);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unsupported Jupiter Perps position direction: " + direction);
|
||||
}
|
||||
|
||||
private static final long RATE_POWER = 1_000_000_000L;
|
||||
private static final int CLOSE_FEE_BPS = 6;
|
||||
private static final int BASIS_POINTS_DIVISOR = 10_000;
|
||||
private static final ΩJupiterPerpsProgramIdΩ JUPITER_PERPS_PROGRAM_ID =
|
||||
"PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu";
|
||||
private static final int POSITION_OWNER_OFFSET = 8;
|
||||
private static final int MAX_LEVERAGE = 500;
|
||||
private static final int USDC_DECIMALS = 6;
|
||||
|
||||
private final SolanaBlockChain solanaBlockChain;
|
||||
private final AnchorIdlJupiterPerpsPositionDecoder positionDecoder;
|
||||
|
||||
Reference in New Issue
Block a user