| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | import java.math.RoundingMode; |
| | | import java.text.ParseException; |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.Duration; |
| | | import java.time.Instant; |
| | | import java.time.ZoneId; |
| | | import java.time.ZonedDateTime; |
| | | 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; |
| | |
| | | import java.util.concurrent.ConcurrentMap; |
| | | import java.util.concurrent.Executors; |
| | | import java.util.concurrent.ScheduledExecutorService; |
| | | import java.util.concurrent.ThreadLocalRandom; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.stream.Collectors; |
| | | |
| | |
| | | @Transactional |
| | | @Slf4j |
| | | public class ContractOrderService extends ServiceImpl<ContractOrderMapper, ContractOrder> { |
| | | |
| | | /** |
| | | * 资金费结算间隔(分钟):从当地日界 0:00 起每 N 分钟为一个结算点。 |
| | | * 240 即每 4 小时一档(0、4、8、12、16、20 点)。 |
| | | */ |
| | | private static final int FUNDING_SETTLEMENT_INTERVAL_MINUTES = 240; |
| | | |
| | | private Logger logger = LogManager.getLogger(ContractOrderService.class); |
| | | |
| | |
| | | private WalletService walletService; |
| | | |
| | | @Autowired |
| | | private FollowWalletService followWalletService; |
| | | |
| | | |
| | | @Autowired |
| | | private UserService userService; |
| | | @Autowired |
| | | private TipService tipService; |
| | |
| | | private ContractApplyOrderService contractApplyOrderService; |
| | | @Autowired |
| | | private SysparaService sysparaService; |
| | | |
| | | @Autowired |
| | | @Lazy |
| | | private ContractOrderCalculationService contractOrderCalculationService; |
| | | |
| | | public IPage<ContractOrderDTO> listRecordCur(Page page, ContractOrderQuery query) { |
| | | if (query.getStartTime() != null) { |
| | |
| | | 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) { |
| | |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 收益 |
| | | */ |
| | | contractOrderCalculationService.refreshMarkPriceProfit(order); |
| | | |
| | | BigDecimal volume = order.getVolume(); |
| | | BigDecimal fundingFee = this.calculateFundingFee(order, volume, new Date()); |
| | | BigDecimal profit = settle(order, order.getVolume()).subtract(fundingFee); |
| | | order.setAmountClose(order.getAmountClose().subtract(fundingFee)); |
| | | order.setFundingFee(defaultZero(order.getFundingFee()).add(fundingFee)); |
| | | if (volume.compareTo(BigDecimal.ZERO) <= 0) { |
| | | return null; |
| | | } |
| | | |
| | | ContractOrderProfit cache = getCacheProfit(order.getUuid()); |
| | | BigDecimal markPrice = order.getTradeAvgPrice(); |
| | | if (cache != null && cache.getCloseAvgPrice() != null |
| | | && cache.getCloseAvgPrice().compareTo(BigDecimal.ZERO) > 0) { |
| | | markPrice = cache.getCloseAvgPrice(); |
| | | } |
| | | BigDecimal fundingPnlChunk = calculateAccruedFundingPnl(order, markPrice, new Date()); |
| | | |
| | | String symbol = order.getSymbol(); |
| | | Item item = itemService.findBySymbol(symbol); |
| | | BigDecimal closeFee = calculateCloseTradingFee(item, markPrice, volume); |
| | | |
| | | BigDecimal profit = settle(order, volume).subtract(closeFee); |
| | | |
| | | order.setFee(defaultZero(order.getFee()).add(closeFee)); |
| | | order.setAmountClose(order.getAmountClose().subtract(closeFee)); |
| | | 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) { |
| | |
| | | } |
| | | |
| | | update(order); |
| | | |
| | | if (ContractOrder.STATE_CREATED.equals(order.getState())) { |
| | | traderFollowUserOrderService.syncFollowUserOrderLinkAfterContractClose(order); |
| | | } |
| | | |
| | | /** |
| | | * 交易员带单,用户跟单 |
| | |
| | | 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); |
| | |
| | | return profit; |
| | | } |
| | | |
| | | private BigDecimal calculateFundingFee(ContractOrder order, BigDecimal closeVolume, Date closeTime) { |
| | | if (order == null || closeVolume == null || closeTime == null) { |
| | | /** |
| | | * 累计资金费带来的盈亏(正数表示用户获利):多仓为 -合约价值×费率×次数,空仓为 +合约价值×费率×次数。 |
| | | * 费率来自 syspara funding_fee;结算锚点为系统默认时区、从当天 0:00 起每 {@link #FUNDING_SETTLEMENT_INTERVAL_MINUTES} 分钟一档。 |
| | | */ |
| | | public BigDecimal calculateAccruedFundingPnl(ContractOrder order, BigDecimal markPrice, Date asOf) { |
| | | if (order == null || markPrice == null || asOf == null || order.getCreateTime() == null) { |
| | | return BigDecimal.ZERO; |
| | | } |
| | | if (closeVolume.compareTo(BigDecimal.ZERO) <= 0 |
| | | || order.getVolumeOpen() == null |
| | | || order.getVolumeOpen().compareTo(BigDecimal.ZERO) <= 0 |
| | | || order.getCreateTime() == null) { |
| | | BigDecimal vol = defaultZero(order.getVolume()); |
| | | if (vol.compareTo(BigDecimal.ZERO) <= 0 || markPrice.compareTo(BigDecimal.ZERO) <= 0) { |
| | | return BigDecimal.ZERO; |
| | | } |
| | | |
| | | long holdHours = Duration.between(order.getCreateTime().toInstant(), closeTime.toInstant()).toHours(); |
| | | long settlementPeriods = holdHours / 4; |
| | | if (settlementPeriods <= 0) { |
| | | long periods = countFundingSettlementPoints( |
| | | order.getCreateTime().toInstant(), |
| | | asOf.toInstant(), |
| | | ZoneId.systemDefault(), |
| | | FUNDING_SETTLEMENT_INTERVAL_MINUTES); |
| | | if (periods <= 0) { |
| | | return BigDecimal.ZERO; |
| | | } |
| | | BigDecimal notional = markPrice.multiply(vol); |
| | | BigDecimal rate = getContractFundingRate(); |
| | | BigDecimal signed = ContractOrder.DIRECTION_BUY.equalsIgnoreCase(order.getDirection()) |
| | | ? rate.negate() : rate; |
| | | return notional.multiply(signed).multiply(BigDecimal.valueOf(periods)).setScale(8, RoundingMode.HALF_UP); |
| | | } |
| | | |
| | | BigDecimal fundingRateTotal = BigDecimal.ZERO; |
| | | for (int i = 0; i < settlementPeriods; i++) { |
| | | double periodRate = ThreadLocalRandom.current().nextDouble(-0.001D, 0.0010000001D); |
| | | fundingRateTotal = fundingRateTotal.add(BigDecimal.valueOf(periodRate)); |
| | | } |
| | | |
| | | BigDecimal currentVolume = defaultZero(order.getVolume()); |
| | | if (currentVolume.compareTo(BigDecimal.ZERO) <= 0) { |
| | | public BigDecimal getContractFundingRate() { |
| | | try { |
| | | Syspara p = sysparaService.find("funding_fee"); |
| | | if (p == null || StringUtils.isEmptyString(p.getSvalue())) { |
| | | return BigDecimal.ZERO; |
| | | } |
| | | return new BigDecimal(p.getSvalue().trim()); |
| | | } catch (Exception e) { |
| | | log.warn("parse funding_fee syspara failed", e); |
| | | return BigDecimal.ZERO; |
| | | } |
| | | } |
| | | |
| | | BigDecimal closeRatio = closeVolume.divide(currentVolume, 10, RoundingMode.HALF_UP); |
| | | BigDecimal borrowedBase = getCurrentBorrowedAmount(order).multiply(closeRatio); |
| | | return borrowedBase.multiply(fundingRateTotal).setScale(8, RoundingMode.HALF_UP); |
| | | /** |
| | | * 平仓手续费:手续费率×平仓价×数量(与开仓计费规则一致:U 本位用 unitPercentage,否则 unitFee×价×量)。 |
| | | */ |
| | | public BigDecimal calculateCloseTradingFee(Item item, BigDecimal closePrice, BigDecimal closeVolume) { |
| | | if (item == null || closePrice == null || closeVolume == null |
| | | || closeVolume.compareTo(BigDecimal.ZERO) <= 0) { |
| | | return BigDecimal.ZERO; |
| | | } |
| | | Syspara syspara = sysparaService.find("u_standard_contract"); |
| | | if (ObjectUtils.isNotEmpty(syspara) && "1".equals(syspara.getSvalue())) { |
| | | return closePrice.multiply(closeVolume).multiply(BigDecimal.valueOf(item.getUnitPercentage())) |
| | | .setScale(8, RoundingMode.HALF_UP); |
| | | } |
| | | return BigDecimal.valueOf(item.getUnitFee()).multiply(closePrice).multiply(closeVolume) |
| | | .setScale(8, RoundingMode.HALF_UP); |
| | | } |
| | | |
| | | private static ZonedDateTime nextFundingSettlementStrictlyAfter(ZonedDateTime t, int intervalMinutes) { |
| | | int step = intervalMinutes <= 0 ? 240 : intervalMinutes; |
| | | ZonedDateTime tTrunc = t.withSecond(0).withNano(0); |
| | | ZonedDateTime dayStart = tTrunc.toLocalDate().atStartOfDay(tTrunc.getZone()); |
| | | long minutesFromDayStart = ChronoUnit.MINUTES.between(dayStart, tTrunc); |
| | | long slotIndex = minutesFromDayStart / step; |
| | | ZonedDateTime slotStart = dayStart.plusMinutes(slotIndex * step); |
| | | ZonedDateTime next = slotStart; |
| | | while (!next.isAfter(t)) { |
| | | next = next.plusMinutes(step); |
| | | } |
| | | return next; |
| | | } |
| | | |
| | | private static long countFundingSettlementPoints(Instant open, Instant end, ZoneId zone, int intervalMinutes) { |
| | | if (open == null || end == null || !end.isAfter(open)) { |
| | | return 0; |
| | | } |
| | | int step = intervalMinutes <= 0 ? 240 : intervalMinutes; |
| | | ZonedDateTime zEnd = end.atZone(zone); |
| | | ZonedDateTime cursor = nextFundingSettlementStrictlyAfter(open.atZone(zone), step); |
| | | long cnt = 0; |
| | | while (!cursor.isAfter(zEnd)) { |
| | | cnt++; |
| | | cursor = cursor.plusMinutes(step); |
| | | } |
| | | return cnt; |
| | | } |
| | | |
| | | private BigDecimal defaultZero(BigDecimal value) { |
| | |
| | | */ |
| | | return applyOrder; |
| | | } |
| | | BigDecimal preVolume = order.getVolume(); |
| | | contractOrderCalculationService.refreshMarkPriceProfit(order); |
| | | |
| | | BigDecimal volume; |
| | | if (applyOrder.getVolume().compareTo(order.getVolume()) > 0) { |
| | | volume = order.getVolume(); |
| | | } else { |
| | | volume = applyOrder.getVolume(); |
| | | } |
| | | /** |
| | | * 平仓退回的金额 |
| | | */ |
| | | BigDecimal fundingFee = this.calculateFundingFee(order, volume, new Date()); |
| | | BigDecimal profit = this.settle(order, volume); |
| | | BigDecimal netProfit = profit.subtract(fundingFee); |
| | | order.setAmountClose(order.getAmountClose().subtract(fundingFee)); |
| | | order.setFundingFee(defaultZero(order.getFundingFee()).add(fundingFee)); |
| | | BigDecimal markPrice = BigDecimal.valueOf(realtime.getClose()); |
| | | ContractOrderProfit cache = getCacheProfit(order.getUuid()); |
| | | if (cache != null && cache.getCloseAvgPrice() != null |
| | | && cache.getCloseAvgPrice().compareTo(BigDecimal.ZERO) > 0) { |
| | | markPrice = cache.getCloseAvgPrice(); |
| | | } |
| | | BigDecimal fundingAccruedTotal = calculateAccruedFundingPnl(order, markPrice, new Date()); |
| | | BigDecimal fundingPnlChunk = fundingAccruedTotal.multiply(volume.divide(preVolume, 10, RoundingMode.HALF_UP)) |
| | | .setScale(8, RoundingMode.HALF_UP); |
| | | |
| | | Item item = itemService.findBySymbol(order.getSymbol()); |
| | | BigDecimal closeFee = calculateCloseTradingFee(item, markPrice, volume); |
| | | |
| | | BigDecimal profit = this.settle(order, volume).subtract(closeFee); |
| | | BigDecimal netProfit = profit; |
| | | |
| | | order.setFee(defaultZero(order.getFee()).add(closeFee)); |
| | | order.setAmountClose(order.getAmountClose().subtract(closeFee)); |
| | | order.setFundingFee(defaultZero(order.getFundingFee()).add(fundingPnlChunk)); |
| | | update(order); |
| | | Wallet wallet = this.walletService.findByUserId(order.getPartyId()); |
| | | BigDecimal amount_before = wallet.getMoney(); |
| | |
| | | |
| | | |
| | | applyOrder.setVolume(applyOrder.getVolume().subtract(volume)); |
| | | applyOrder.setFundingFee(defaultZero(applyOrder.getFundingFee()).add(fundingFee)); |
| | | applyOrder.setFundingFee(defaultZero(applyOrder.getFundingFee()).add(fundingPnlChunk)); |
| | | if (applyOrder.getVolume().compareTo(BigDecimal.ZERO) <= 0) { |
| | | applyOrder.setState(ContractApplyOrder.STATE_CREATED); |
| | | } |
| | |
| | | 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()); |