1
zj
119 mins ago effab9619e17b97ac98b035eaa64ba99b27f5dc6
trading-order-service/src/main/java/com/yami/trading/service/contract/ContractOrderCalculationServiceImpl.java
@@ -1,17 +1,16 @@
package com.yami.trading.service.contract;
import com.yami.trading.bean.contract.domain.ContractOrder;
import com.yami.trading.bean.contract.domain.ContractOrderProfit;
import com.yami.trading.bean.data.domain.Realtime;
import com.yami.trading.bean.item.domain.Item;
import com.yami.trading.bean.model.Wallet;
import com.yami.trading.bean.syspara.domain.Syspara;
import com.yami.trading.common.constants.ContractRedisKeys;
import com.yami.trading.common.util.RedisUtil;
import com.yami.trading.common.util.ThreadUtils;
import com.yami.trading.service.WalletService;
import com.yami.trading.service.data.DataService;
import com.yami.trading.service.item.ItemService;
import com.yami.trading.service.syspara.SysparaService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.logging.log4j.LogManager;
@@ -21,13 +20,12 @@
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
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;
import java.util.Date;
import java.util.List;
@Slf4j
@@ -51,31 +49,10 @@
    private DataService dataService;
    @Autowired
    private WalletService walletService;
    @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) {
@@ -97,11 +74,9 @@
            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);
                .add(defaultZero(order.getDeposit()));
        BigDecimal priceOffset = baseEquity.divide(volume, 10, RoundingMode.HALF_UP);
        if (ContractOrder.DIRECTION_BUY.equalsIgnoreCase(order.getDirection())) {
            return tradeAvgPrice.subtract(priceOffset);
@@ -119,7 +94,7 @@
        if (thresholdRatio.compareTo(BigDecimal.ZERO) <= 0) {
            return tradeAvgPrice;
        }
        BigDecimal availableDeposit = defaultZero(order.getDeposit()).subtract(estimateAccruedFundingFee(order));
        BigDecimal availableDeposit = defaultZero(order.getDeposit());
        if (availableDeposit.compareTo(BigDecimal.ZERO) <= 0) {
            return tradeAvgPrice;
        }
@@ -195,11 +170,10 @@
        BigDecimal point = close.subtract(order.getTradeAvgPrice()).abs().divide(order.getPips(), 10, RoundingMode.HALF_UP);
        // 根据偏 差点数和手数算出盈亏金额
        BigDecimal amount = order.getPipsAmount().multiply(point).multiply(order.getVolume());
        if (order.getDirection().equalsIgnoreCase(ContractOrder.DIRECTION_BUY)) {
            return amount;
        } else {
            return amount.negate();
        }
        BigDecimal pricePnl = order.getDirection().equalsIgnoreCase(ContractOrder.DIRECTION_BUY)
                ? amount : amount.negate();
        BigDecimal funding = contractOrderService.calculateAccruedFundingPnl(order, close, new Date());
        return pricePnl.add(funding);
    }
@@ -230,11 +204,10 @@
         * 根据偏 差点数和手数算出盈亏金额
         */
        BigDecimal amount = order.getPipsAmount().multiply(point).multiply(order.getVolume());
        if (order.getDirection().equalsIgnoreCase(ContractOrder.DIRECTION_BUY)) {
            return amount;
        } else {
            return amount.negate();
        }
        BigDecimal pricePnl = order.getDirection().equalsIgnoreCase(ContractOrder.DIRECTION_BUY)
                ? amount : amount.negate();
        BigDecimal funding = contractOrderService.calculateAccruedFundingPnl(order, close, new Date());
        return pricePnl.add(funding);
    }
@@ -262,28 +235,7 @@
            pips = new BigDecimal("0.01");
        }
        /**
         * 根据价格变化百分比和保证金计算盈亏金额
         */
        BigDecimal priceChangeRatio = currentPrice.subtract(order.getTradeAvgPrice())
            .divide(order.getTradeAvgPrice(), 6, RoundingMode.DOWN);
        BigDecimal margin = order.getTradeAvgPrice().multiply(order.getVolume()); // 这是用户当前持仓对应的投资金额
        BigDecimal profitAmount = margin.multiply(priceChangeRatio);
        if (ContractOrder.DIRECTION_BUY.equals(order.getDirection())) {
            order.setProfit(profitAmount.setScale(6,RoundingMode.DOWN));
        } else{
            order.setProfit(profitAmount.setScale(6,RoundingMode.DOWN).negate());
        }
        /**
         * 多次平仓价格不对,后续修
         */
        order.setCloseAvgPrice(currentPrice);
        this.contractOrderService.updateByIdBuffer(order);
        applyMarkPriceToOrder(order, currentPrice);
        /**
         * 止盈价
@@ -332,7 +284,8 @@
                return;
            }
        }
        BigDecimal profit1 = contractOrderService.getCacheProfit(order.getUuid()).getProfit();
        ContractOrderProfit cp = contractOrderService.getCacheProfit(order.getUuid());
        BigDecimal profit1 = cp != null ? cp.getProfit() : defaultZero(order.getProfit());
        if (order_close_line_type == 1) {
            Wallet wallet = this.walletService.findByUserId(order.getPartyId().toString());
            Integer decimal = itemService.getDecimal(order.getSymbol());
@@ -389,4 +342,36 @@
        this.order_close_line_type = order_close_line_type;
    }
    private void applyMarkPriceToOrder(ContractOrder order, BigDecimal currentPrice) {
        BigDecimal priceChangeRatio = currentPrice.subtract(order.getTradeAvgPrice())
                .divide(order.getTradeAvgPrice(), 6, RoundingMode.DOWN);
        BigDecimal margin = order.getTradeAvgPrice().multiply(order.getVolume());
        BigDecimal profitAmount = margin.multiply(priceChangeRatio);
        BigDecimal priceProfit;
        if (ContractOrder.DIRECTION_BUY.equals(order.getDirection())) {
            priceProfit = profitAmount.setScale(6, RoundingMode.DOWN);
        } else {
            priceProfit = profitAmount.setScale(6, RoundingMode.DOWN).negate();
        }
        BigDecimal fundingPnl = contractOrderService.calculateAccruedFundingPnl(order, currentPrice, new Date());
        order.setProfit(priceProfit.add(fundingPnl));
        order.setCloseAvgPrice(currentPrice);
        this.contractOrderService.updateByIdBuffer(order);
    }
    @Override
    public void refreshMarkPriceProfit(ContractOrder order) {
        if (order == null || !ContractOrder.STATE_SUBMITTED.equals(order.getState())) {
            return;
        }
        if (defaultZero(order.getVolume()).compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }
        List<Realtime> list = this.dataService.realtime(order.getSymbol());
        if (list.isEmpty()) {
            return;
        }
        applyMarkPriceToOrder(order, BigDecimal.valueOf(list.get(0).getClose()));
    }
}