From f658569891db433854221b80f0a9fa99608cff64 Mon Sep 17 00:00:00 2001
From: zj <1772600164@qq.com>
Date: Fri, 03 Apr 2026 18:22:34 +0800
Subject: [PATCH] 1
---
trading-order-service/src/main/java/com/yami/trading/service/contract/ContractOrderCalculationServiceImpl.java | 130 +++++++++++++++++++++++++++++++------------
1 files changed, 93 insertions(+), 37 deletions(-)
diff --git a/trading-order-service/src/main/java/com/yami/trading/service/contract/ContractOrderCalculationServiceImpl.java b/trading-order-service/src/main/java/com/yami/trading/service/contract/ContractOrderCalculationServiceImpl.java
index fda90c8..43d9b73 100644
--- a/trading-order-service/src/main/java/com/yami/trading/service/contract/ContractOrderCalculationServiceImpl.java
+++ b/trading-order-service/src/main/java/com/yami/trading/service/contract/ContractOrderCalculationServiceImpl.java
@@ -24,6 +24,7 @@
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
+import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
@@ -53,6 +54,83 @@
@Resource
private SysparaService sysparaService;
private Logger logger = LogManager.getLogger(ContractOrderCalculationServiceImpl.class);
+
+ private BigDecimal defaultZero(BigDecimal value) {
+ return value == null ? BigDecimal.ZERO : value;
+ }
+
+ private BigDecimal estimateAccruedFundingFee(ContractOrder order) {
+ if (order == null || order.getCreateTime() == null) {
+ return BigDecimal.ZERO;
+ }
+ BigDecimal borrowedAmount = defaultZero(order.getBorrowedAmount());
+ if (borrowedAmount.compareTo(BigDecimal.ZERO) <= 0) {
+ return BigDecimal.ZERO;
+ }
+ long holdHours = Duration.between(order.getCreateTime().toInstant(), Instant.now()).toHours();
+ long settlementPeriods = holdHours / 4;
+ if (settlementPeriods <= 0) {
+ return BigDecimal.ZERO;
+ }
+ BigDecimal conservativeRate = new BigDecimal("0.001");
+ return borrowedAmount.multiply(conservativeRate)
+ .multiply(BigDecimal.valueOf(settlementPeriods))
+ .setScale(8, RoundingMode.HALF_UP);
+ }
+
+ private BigDecimal calculateType1ForceClosePrice(ContractOrder order, Wallet wallet) {
+ BigDecimal volume = defaultZero(order.getVolume());
+ BigDecimal tradeAvgPrice = defaultZero(order.getTradeAvgPrice());
+ if (volume.compareTo(BigDecimal.ZERO) <= 0) {
+ return BigDecimal.ZERO;
+ }
+
+ List<ContractOrder> list = contractOrderService.findSubmitted(order.getPartyId(), null, null, null, null, null);
+ BigDecimal otherEquity = BigDecimal.ZERO;
+ for (ContractOrder contractOrder : list) {
+ if (ContractOrder.STATE_SUBMITTED.equals(contractOrder.getState())) {
+ contractOrderService.wrapProfit(contractOrder);
+ }
+ if (order.getUuid().equals(contractOrder.getUuid())) {
+ continue;
+ }
+ otherEquity = otherEquity.add(defaultZero(contractOrder.getProfit()).add(defaultZero(contractOrder.getDeposit())));
+ }
+
+ BigDecimal accruedFundingFee = estimateAccruedFundingFee(order);
+ BigDecimal baseEquity = defaultZero(wallet.getMoney())
+ .add(otherEquity)
+ .add(defaultZero(order.getDeposit()))
+ .subtract(accruedFundingFee);
+ BigDecimal priceOffset = baseEquity.divide(volume, 10, RoundingMode.HALF_UP);
+ if (ContractOrder.DIRECTION_BUY.equalsIgnoreCase(order.getDirection())) {
+ return tradeAvgPrice.subtract(priceOffset);
+ }
+ return tradeAvgPrice.add(priceOffset);
+ }
+
+ private BigDecimal calculateType2ForceClosePrice(ContractOrder order) {
+ BigDecimal volume = defaultZero(order.getVolume());
+ BigDecimal tradeAvgPrice = defaultZero(order.getTradeAvgPrice());
+ if (volume.compareTo(BigDecimal.ZERO) <= 0) {
+ return BigDecimal.ZERO;
+ }
+ BigDecimal thresholdRatio = order_close_line.divide(new BigDecimal(100), 10, RoundingMode.HALF_UP);
+ if (thresholdRatio.compareTo(BigDecimal.ZERO) <= 0) {
+ return tradeAvgPrice;
+ }
+ BigDecimal availableDeposit = defaultZero(order.getDeposit()).subtract(estimateAccruedFundingFee(order));
+ if (availableDeposit.compareTo(BigDecimal.ZERO) <= 0) {
+ return tradeAvgPrice;
+ }
+ BigDecimal requiredLoss = availableDeposit.divide(thresholdRatio, 10, RoundingMode.HALF_UP);
+ BigDecimal priceOffset = requiredLoss.divide(volume, 10, RoundingMode.HALF_UP);
+ if (ContractOrder.DIRECTION_BUY.equalsIgnoreCase(order.getDirection())) {
+ return tradeAvgPrice.subtract(priceOffset);
+ }
+ return tradeAvgPrice.add(priceOffset);
+ }
+
@Override
public void saveCalculation(String order_no) {
try {
@@ -70,6 +148,7 @@
Realtime realtime = list.get(0);
BigDecimal close = new BigDecimal(realtime.getClose());
+ settle(order, "watch", close);
BigDecimal add = order.getTradeAvgPrice().add(order.getPips());
BigDecimal subtract = order.getTradeAvgPrice().subtract(order.getPips());
@@ -186,11 +265,10 @@
/**
* 根据价格变化百分比和保证金计算盈亏金额
*/
+ BigDecimal priceChangeRatio = currentPrice.subtract(order.getTradeAvgPrice())
+ .divide(order.getTradeAvgPrice(), 6, RoundingMode.DOWN);
- BigDecimal priceChangeRatio = currentPrice.subtract(order.getTradeAvgPrice())
- .divide(order.getTradeAvgPrice(), 6, RoundingMode.DOWN);
-
- BigDecimal margin = order.getUnitAmount().multiply(order.getVolumeOpen()); // 这是用户实际的投资金额
+ BigDecimal margin = order.getTradeAvgPrice().multiply(order.getVolume()); // 这是用户当前持仓对应的投资金额
BigDecimal profitAmount = margin.multiply(priceChangeRatio);
@@ -256,53 +334,24 @@
}
BigDecimal profit1 = contractOrderService.getCacheProfit(order.getUuid()).getProfit();
if (order_close_line_type == 1) {
- /**
- * 收益
- */
- BigDecimal profit = BigDecimal.ZERO;
-
Wallet wallet = this.walletService.findByUserId(order.getPartyId().toString());
- // 计算所有除自己以外的profit
- BigDecimal profitExptThis = profit.subtract(profit1).subtract(order.getDeposit());
- /**
- * profitAll+wallet<=0
- * profitAll<=wallet 强平
- * p1 +E (p2~pn) <=wallet
- * (currentPrice-tradavg)*pipAmount*volume/pips + depost1 <=wallet-E(p2~pn)
- */
- BigDecimal left = wallet.getMoney().negate().subtract(profitExptThis).subtract(order.getDeposit());
- BigDecimal pipsAmount = order.getPipsAmount();
- if(pipsAmount.doubleValue() <= 0.00){
- pipsAmount = new BigDecimal("0.01");
- }
- BigDecimal overLine = (left.multiply(pips).divide(pipsAmount, 10, RoundingMode.HALF_UP)
- .divide(order.getVolume(), 10, RoundingMode.HALF_UP));
Integer decimal = itemService.getDecimal(order.getSymbol());
- BigDecimal forceClose = BigDecimal.ZERO;
- // 买多,从买价跌多少
- if (order.getDirection().equalsIgnoreCase(ContractOrder.DIRECTION_BUY)) {
- forceClose = order.getTradeAvgPrice().add(overLine).setScale(decimal, RoundingMode.HALF_UP);
- //买跌,涨到多少
- } else {
- forceClose = order.getTradeAvgPrice().subtract(overLine).setScale(decimal, RoundingMode.HALF_UP);
- }
+ BigDecimal forceClose = calculateType1ForceClosePrice(order, wallet).setScale(decimal, RoundingMode.HALF_UP);
if (forceClose.compareTo(BigDecimal.ZERO) < 0) {
forceClose = BigDecimal.ZERO;
}
order.setForceClosePrice(forceClose.toPlainString());
this.contractOrderService.updateByIdBuffer(order);
List<ContractOrder> list = contractOrderService.findSubmitted(order.getPartyId(), null, null, null, null, null);
+ BigDecimal totalEquity = defaultZero(wallet.getMoney());
for(ContractOrder contractOrder :list) {
if(ContractOrder.STATE_SUBMITTED.equals(contractOrder.getState())){
contractOrderService.wrapProfit(contractOrder);
}
+ totalEquity = totalEquity.add(defaultZero(contractOrder.getProfit()).add(defaultZero(contractOrder.getDeposit())));
}
- for (int i = 0; i < list.size(); i++) {
- ContractOrder close_line = list.get(i);
- profit = profit.add(close_line.getProfit().add(close_line.getDeposit()));
- }
- if (profit.add(wallet.getMoney()).compareTo(BigDecimal.ZERO) <= 0) {
+ if (totalEquity.compareTo(BigDecimal.ZERO) <= 0) {
/**
* 触发全仓强平
*/
@@ -310,6 +359,13 @@
}
} else {
+ Integer decimal = itemService.getDecimal(order.getSymbol());
+ BigDecimal forceClose = calculateType2ForceClosePrice(order).setScale(decimal, RoundingMode.HALF_UP);
+ if (forceClose.compareTo(BigDecimal.ZERO) < 0) {
+ forceClose = BigDecimal.ZERO;
+ }
+ order.setForceClosePrice(forceClose.toPlainString());
+ this.contractOrderService.updateByIdBuffer(order);
BigDecimal divide = order.getDeposit().divide(profit1.abs(), 10, RoundingMode.HALF_UP);
if (profit1.compareTo(BigDecimal.ZERO) < 0 && divide.compareTo(order_close_line.divide(new BigDecimal(100), 10, RoundingMode.HALF_UP)) <= 0) {
/**
--
Gitblit v1.9.3