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 pnlPercent the profit and loss represented as a percentage
|
||||||
* @param leverage TODO
|
* @param leverage TODO
|
||||||
* @param entryPrice the entry price of the position, denominated in USDC
|
* @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 marketPrice the current spot price of the token
|
||||||
* @param collateral the amount of USD representing the collateral for this position
|
* @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)
|
* @param totalFees the total amount of fees (TODO: is that including pending/due fees)
|
||||||
@@ -37,6 +38,7 @@ public record JupiterPerpsPosition(
|
|||||||
BigDecimal pnlPercent,
|
BigDecimal pnlPercent,
|
||||||
BigDecimal leverage,
|
BigDecimal leverage,
|
||||||
ΩUSDCPriceΩ entryPrice,
|
ΩUSDCPriceΩ entryPrice,
|
||||||
|
ΩUSDCPriceΩ liquidationPrice,
|
||||||
ΩUSDCPriceΩ marketPrice,
|
ΩUSDCPriceΩ marketPrice,
|
||||||
ΩUSDCAmountΩ collateral,
|
ΩUSDCAmountΩ collateral,
|
||||||
ΩUSDCAmountΩ totalFees,
|
ΩUSDCAmountΩ totalFees,
|
||||||
|
|||||||
+80
-3
@@ -1,6 +1,7 @@
|
|||||||
package com.r35157.libs.jupiter.perps.impl.anchoridl;
|
package com.r35157.libs.jupiter.perps.impl.anchoridl;
|
||||||
|
|
||||||
import com.r35157.libs.jupiter.perps.JupiterPerpsPosition;
|
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.jupiter.perps.JupiterPerpsService;
|
||||||
import com.r35157.libs.solana.SolanaAccountInfo;
|
import com.r35157.libs.solana.SolanaAccountInfo;
|
||||||
import com.r35157.libs.solana.SolanaBlockChain;
|
import com.r35157.libs.solana.SolanaBlockChain;
|
||||||
@@ -114,12 +115,34 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
|||||||
|
|
||||||
ΩSPLMintAddressΩ mintAddress = custodyAccountInfo.mintAddress();
|
Ω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());
|
.subtract(perpsPositionInfo.cumulativeInterestSnapshot());
|
||||||
|
|
||||||
ΩUSDCAmountΩ positionSize = perpsPositionInfo.positionSize();
|
ΩUSDCAmountΩ positionSize = perpsPositionInfo.positionSize();
|
||||||
ΩUSDCAmountΩ borrowFeesDue = calculateBorrowFeesDue(positionInterest, positionSize);
|
ΩUSDCAmountΩ borrowFeesDue = calculateBorrowFeesDue(positionInterest, positionSize);
|
||||||
ΩUSDCAmountΩ closeFeePending = calculateCloseFeePending(positionSize);
|
ΩUSDCAmountΩ closeFeePending = calculateCloseFeePending(positionSize);
|
||||||
|
ΩUSDCPriceΩ liquidationPrice = calculateLiquidationPrice(
|
||||||
|
perpsPositionInfo.direction(),
|
||||||
|
perpsPositionInfo.entryPrice(),
|
||||||
|
perpsPositionInfo.collateral(),
|
||||||
|
closeFeePending,
|
||||||
|
borrowFeesDue,
|
||||||
|
positionSize
|
||||||
|
);
|
||||||
|
|
||||||
ΩUSDCAmountΩ value = ZERO; // TODO - Dummy
|
ΩUSDCAmountΩ value = ZERO; // TODO - Dummy
|
||||||
ΩUSDCAmountΩ pnl = ZERO; // TODO - Dummy
|
ΩUSDCAmountΩ pnl = ZERO; // TODO - Dummy
|
||||||
@@ -142,6 +165,7 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
|||||||
pnlPercent,
|
pnlPercent,
|
||||||
leverage,
|
leverage,
|
||||||
perpsPositionInfo.entryPrice(),
|
perpsPositionInfo.entryPrice(),
|
||||||
|
liquidationPrice,
|
||||||
marketPrice,
|
marketPrice,
|
||||||
perpsPositionInfo.collateral(),
|
perpsPositionInfo.collateral(),
|
||||||
totalFees,
|
totalFees,
|
||||||
@@ -161,7 +185,7 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
|||||||
.multiply(size)
|
.multiply(size)
|
||||||
.divide(
|
.divide(
|
||||||
BigDecimal.valueOf(RATE_POWER),
|
BigDecimal.valueOf(RATE_POWER),
|
||||||
6,
|
USDC_DECIMALS,
|
||||||
RoundingMode.CEILING
|
RoundingMode.CEILING
|
||||||
);
|
);
|
||||||
return fees;
|
return fees;
|
||||||
@@ -172,19 +196,72 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
|||||||
.multiply(BigDecimal.valueOf(CLOSE_FEE_BPS))
|
.multiply(BigDecimal.valueOf(CLOSE_FEE_BPS))
|
||||||
.divide(
|
.divide(
|
||||||
BigDecimal.valueOf(BASIS_POINTS_DIVISOR),
|
BigDecimal.valueOf(BASIS_POINTS_DIVISOR),
|
||||||
6,
|
USDC_DECIMALS,
|
||||||
RoundingMode.CEILING
|
RoundingMode.CEILING
|
||||||
);
|
);
|
||||||
|
|
||||||
return fee;
|
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 long RATE_POWER = 1_000_000_000L;
|
||||||
private static final int CLOSE_FEE_BPS = 6;
|
private static final int CLOSE_FEE_BPS = 6;
|
||||||
private static final int BASIS_POINTS_DIVISOR = 10_000;
|
private static final int BASIS_POINTS_DIVISOR = 10_000;
|
||||||
private static final ΩJupiterPerpsProgramIdΩ JUPITER_PERPS_PROGRAM_ID =
|
private static final ΩJupiterPerpsProgramIdΩ JUPITER_PERPS_PROGRAM_ID =
|
||||||
"PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu";
|
"PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu";
|
||||||
private static final int POSITION_OWNER_OFFSET = 8;
|
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 SolanaBlockChain solanaBlockChain;
|
||||||
private final AnchorIdlJupiterPerpsPositionDecoder positionDecoder;
|
private final AnchorIdlJupiterPerpsPositionDecoder positionDecoder;
|
||||||
|
|||||||
Reference in New Issue
Block a user