From befbf57e4112d07003bff18102f556a1e5a154de Mon Sep 17 00:00:00 2001
From: zj <1772600164@qq.com>
Date: Wed, 22 Apr 2026 10:53:37 +0800
Subject: [PATCH] 1

---
 trading-order-service/src/main/java/com/yami/trading/service/contract/ContractOrderService.java |  153 +++++++++++++++++++++++++++++++++-----------------
 1 files changed, 100 insertions(+), 53 deletions(-)

diff --git a/trading-order-service/src/main/java/com/yami/trading/service/contract/ContractOrderService.java b/trading-order-service/src/main/java/com/yami/trading/service/contract/ContractOrderService.java
index ff6eec0..cea79b3 100644
--- a/trading-order-service/src/main/java/com/yami/trading/service/contract/ContractOrderService.java
+++ b/trading-order-service/src/main/java/com/yami/trading/service/contract/ContractOrderService.java
@@ -16,10 +16,10 @@
 import com.yami.trading.bean.contract.domain.ContractOrder;
 import com.yami.trading.bean.contract.domain.ContractOrderProfit;
 import com.yami.trading.bean.contract.dto.ContractOrderDTO;
+import com.yami.trading.bean.contract.dto.TraderOwnClosedAggDTO;
 import com.yami.trading.bean.contract.query.ContractOrderQuery;
 import com.yami.trading.bean.data.domain.Realtime;
 import com.yami.trading.bean.item.domain.Item;
-import com.yami.trading.bean.model.FollowWallet;
 import com.yami.trading.bean.model.User;
 import com.yami.trading.bean.model.Wallet;
 import com.yami.trading.bean.syspara.domain.Syspara;
@@ -31,12 +31,12 @@
 import com.yami.trading.common.constants.ContractRedisKeys;
 import com.yami.trading.common.constants.RedisKeys;
 import com.yami.trading.common.constants.TipConstants;
+import com.yami.trading.common.util.Arith;
 import com.yami.trading.common.util.DateUtils;
 import com.yami.trading.common.util.RandomUtil;
 import com.yami.trading.common.util.RedisUtil;
 import com.yami.trading.common.util.StringUtils;
 import com.yami.trading.dao.contract.ContractOrderMapper;
-import com.yami.trading.service.FollowWalletService;
 import com.yami.trading.service.WalletService;
 import com.yami.trading.service.item.ItemService;
 import com.yami.trading.service.syspara.SysparaService;
@@ -69,6 +69,7 @@
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
@@ -142,10 +143,6 @@
 
     @Autowired
     private WalletService walletService;
-
-    @Autowired
-    private FollowWalletService followWalletService;
-
 
     @Autowired
     private UserService userService;
@@ -240,6 +237,89 @@
         queryWrapper.orderByDesc("create_time");
         return list(queryWrapper);
     }
+
+    /**
+     * 仅查询交易员本人持仓(排除其作为跟单用户产生的跟单订单)。
+     */
+    public List<ContractOrder> findSubmittedTraderOwn(String partyId, String symbol) {
+        QueryWrapper<ContractOrder> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq(StrUtil.isNotBlank(partyId), "party_id", partyId);
+        queryWrapper.eq(StrUtil.isNotBlank(symbol), "symbol", symbol);
+        queryWrapper.eq("state", ContractOrder.STATE_SUBMITTED);
+        // 交易员本人持仓:排除明确的跟单单(follow=1),并兼容历史数据 follow 为空
+        queryWrapper.and(w -> w.ne("follow", ContractOrder.ORDER_FOLLOW).or().isNull("follow"));
+        queryWrapper.orderByDesc("create_time");
+        return list(queryWrapper);
+    }
+
+	/**
+	 * 交易员本人、已平仓、非跟单单:全品种已实现盈亏合计(与 T_TRADER.profit 相比以合约表为准)。
+	 */
+	public BigDecimal sumClosedProfitTraderOwn(String partyId) {
+		if (StrUtil.isBlank(partyId)) {
+			return BigDecimal.ZERO;
+		}
+		Map<String, TraderOwnClosedAggDTO> m = mapClosedTraderOwnAggByPartyIds(Collections.singletonList(partyId));
+		TraderOwnClosedAggDTO row = m.get(partyId);
+		if (row == null || row.getClosedProfitSum() == null) {
+			return BigDecimal.ZERO;
+		}
+		return row.getClosedProfitSum();
+	}
+
+	/**
+	 * 交易员本人、已平仓、非跟单单:全品种开仓保证金 deposit_open 合计(与当前持仓 deposit 同一口径,用于收益率分母)。
+	 */
+	public BigDecimal sumClosedDepositOpenTraderOwn(String partyId) {
+		if (StrUtil.isBlank(partyId)) {
+			return BigDecimal.ZERO;
+		}
+		Map<String, TraderOwnClosedAggDTO> m = mapClosedTraderOwnAggByPartyIds(Collections.singletonList(partyId));
+		TraderOwnClosedAggDTO row = m.get(partyId);
+		if (row == null || row.getClosedMarginSum() == null) {
+			return BigDecimal.ZERO;
+		}
+		return row.getClosedMarginSum();
+	}
+
+	public Map<String, TraderOwnClosedAggDTO> mapClosedTraderOwnAggByPartyIds(List<String> partyIds) {
+		if (partyIds == null || partyIds.isEmpty()) {
+			return Collections.emptyMap();
+		}
+		List<String> distinct = partyIds.stream().filter(StrUtil::isNotBlank).distinct().collect(Collectors.toList());
+		if (distinct.isEmpty()) {
+			return Collections.emptyMap();
+		}
+		List<TraderOwnClosedAggDTO> rows = getBaseMapper().sumClosedTraderOwnAggByPartyIds(distinct);
+		if (rows == null || rows.isEmpty()) {
+			return Collections.emptyMap();
+		}
+		return rows.stream()
+				.filter(r -> r != null && StrUtil.isNotBlank(r.getPartyId()))
+				.collect(Collectors.toMap(TraderOwnClosedAggDTO::getPartyId, r -> r, (a, b) -> a));
+	}
+
+	/**
+	 * 累计收益/收益率:历史已实现盈亏(合约表全品种)+ 偏差;历史分母优先用已平仓保证金合计(与当前持仓保证金一致),否则回退 T_TRADER.order_amount。
+	 */
+	public double historyProfitForTraderTotalYield(Trader entity) {
+		if (entity == null || StrUtil.isBlank(entity.getPartyId())) {
+			return 0D;
+		}
+		double closed = sumClosedProfitTraderOwn(entity.getPartyId()).doubleValue();
+		return Arith.add(closed, entity.getDeviationProfit());
+	}
+
+	public double historyAmountBasisForTraderTotalYield(Trader entity) {
+		if (entity == null) {
+			return 0D;
+		}
+		BigDecimal marginSum = sumClosedDepositOpenTraderOwn(entity.getPartyId());
+		if (marginSum != null && marginSum.compareTo(BigDecimal.ZERO) > 0) {
+			return Arith.add(marginSum.doubleValue(), entity.getDeviationOrderAmount());
+		}
+		return Arith.add(entity.getOrderAmount(), entity.getDeviationOrderAmount());
+	}
 
 
     public List<ContractOrder> findSubmitted(String partyId, String symbol, String direction, String startTime, String endTime, String symbolType) {
@@ -413,31 +493,12 @@
         order.setFundingFee(defaultZero(order.getFundingFee()).add(fundingPnlChunk));
 //        Item item = itemService.findBySymbol(symbol);
 //        profit = exchangeRateService.getUsdtByType(profit, item.getType());
-        if (ContractOrder.ORDER_FOLLOW == order.getFollow()) { // 跟单订单
-//		if (profit > 0) {
-            FollowWallet wallet = followWalletService.findByUserId(order.getPartyId());
-            BigDecimal amount_before = wallet.getMoney();
-
-//		wallet.setMoney(Arith.add(wallet.getMoney(), profit));
-
-            if (wallet.getMoney().add(profit).compareTo(BigDecimal.ZERO) < 0) {
-                profit = wallet.getMoney().negate();
-            }
-
-            followWalletService.updateMoney(order.getSymbol(), partyId, profit, BigDecimal.ZERO,
-                    Constants.MONEYLOG_CATEGORY_CONTRACT, Constants.WALLET_USDT, Constants.MONEYLOG_CONTENT_CONTRACT_CLOSE, "平仓,平仓合约数[" + volume + "],订单号[" + order.getOrderNo() + "]");
-        } else {
-            //		if (profit > 0) {
-            Wallet wallet = walletService.findByUserId(order.getPartyId());
-            BigDecimal amount_before = wallet.getMoney();
-
-//		wallet.setMoney(Arith.add(wallet.getMoney(), profit));
-            if (wallet.getMoney().add(profit).compareTo(BigDecimal.ZERO) < 0) {
-                profit = wallet.getMoney().negate();
-            }
-            walletService.updateMoney(order.getSymbol(), partyId, profit, BigDecimal.ZERO,
-                    Constants.MONEYLOG_CATEGORY_CONTRACT, Constants.WALLET_USDT, Constants.MONEYLOG_CONTENT_CONTRACT_CLOSE, "平仓,平仓合约数[" + volume + "],订单号[" + order.getOrderNo() + "]");
+        Wallet wallet = walletService.findByUserId(order.getPartyId());
+        if (wallet.getMoney().add(profit).compareTo(BigDecimal.ZERO) < 0) {
+            profit = wallet.getMoney().negate();
         }
+        walletService.updateMoney(order.getSymbol(), partyId, profit, BigDecimal.ZERO,
+                Constants.MONEYLOG_CATEGORY_CONTRACT, Constants.WALLET_USDT, Constants.MONEYLOG_CONTENT_CONTRACT_CLOSE, "平仓,平仓合约数[" + volume + "],订单号[" + order.getOrderNo() + "]");
 //        List<Realtime> list = this.dataService.realtime(order.getSymbol());
 //        // 平仓时候把当前价格先更新回去
 //        if (list.size() != 0) {
@@ -450,6 +511,10 @@
         }
 
         update(order);
+
+        if (ContractOrder.STATE_CREATED.equals(order.getState())) {
+            traderFollowUserOrderService.syncFollowUserOrderLinkAfterContractClose(order);
+        }
 
         /**
          * 交易员带单,用户跟单
@@ -676,29 +741,7 @@
         BigDecimal realizedProfit = originProfit.multiply(closeRatio).setScale(8, RoundingMode.HALF_UP);
         BigDecimal profit = releasedDeposit.add(realizedProfit);
 
-        if (ContractOrder.ORDER_FOLLOW == order.getFollow()) { // 跟单还得减去利息收益
-            BigDecimal orderAmount = order.getUnitAmount().multiply(order.getTradeAvgPrice()).multiply(order.getLeverRate()); //订单总金额
-            TraderFollowUserOrder traderFollowUserOrder = traderFollowUserOrderService.findByPartyIdAndOrderNo(order.getPartyId(), order.getOrderNo());
-            if (null != traderFollowUserOrder) {
-                TraderFollowUser traderFollowUser = traderFollowUserService.findByPartyIdAndTrader_partyId(order.getPartyId(), traderFollowUserOrder.getTraderPartyId());
-                if (StringUtils.isNotEmpty(traderFollowUser.getDaysSetting())) {
-                    TraderDaysSetting traderDaysSetting = traderDaysSettingService.selectById(traderFollowUser.getDaysSetting());
-                    if (null != traderDaysSetting) { // 借款利率
-                        int days = 0;
-                        try {
-                            days = daysBetween(order.getCreateTime(), new Date());
-                        } catch (ParseException e) {
-//                            throw new RuntimeException(e);
-                            log.error(e.getMessage());
-                        }
-                        if (days < 0) {
-                            days = 0;
-                        }
-                    }
-                }
-            }
-
-        }
+        // 跟单利息功能已下线,此处不再做历史利率扣减
 
         order.setAmountClose(order.getAmountClose().add(profit));
         BigDecimal remainVolume = currentVolume.subtract(volume);
@@ -1093,6 +1136,10 @@
         return data;
     }
 
+    public List<Map<String, Object>> buildDataFromOrders(List<ContractOrder> list) {
+        return bulidData(list);
+    }
+
     public Map<String, Object> bulidOne(ContractOrder order) {
         Map<String, Object> map = new HashMap<String, Object>();
         map.put("order_no", order.getOrderNo());

--
Gitblit v1.9.3