package com.yami.trading.service.contract; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.yami.trading.bean.contract.domain.ContractApplyOrder; import com.yami.trading.bean.contract.dto.ContractApplyOrderDTO; import com.yami.trading.bean.contract.dto.ContractOrderDTO; import com.yami.trading.bean.contract.query.ContractApplyOrderQuery; 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.User; import com.yami.trading.bean.model.UserData; import com.yami.trading.bean.model.Wallet; import com.yami.trading.common.constants.Constants; import com.yami.trading.common.constants.ContractRedisKeys; import com.yami.trading.common.constants.TipConstants; import com.yami.trading.common.exception.YamiShopBindException; 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.service.StrongLevelCalculationService; import com.yami.trading.service.data.DataService; import com.yami.trading.service.system.TipService; import com.yami.trading.service.user.UserDataService; import com.yami.trading.service.user.UserService; import com.yami.trading.service.WalletService; import com.yami.trading.service.item.ItemService; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yami.trading.bean.contract.domain.ContractOrder; import com.yami.trading.dao.contract.ContractOrderMapper; import org.springframework.web.bind.annotation.RequestParam; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.*; import java.util.stream.Collectors; /** * 非按金额订单Service * * @author lucas * @version 2023-03-29 */ @Service @Transactional public class ContractOrderService extends ServiceImpl { private final ConcurrentMap map = new ConcurrentHashMap<>(); private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); public ContractOrderService(){ executorService.scheduleAtFixedRate(this::flush, 1, 1, TimeUnit.SECONDS); } public void flush() { List items = new ArrayList<>(map.values()); if (!items.isEmpty()) { getBaseMapper().batchUpdateBuffer(items); } } @Qualifier("dataService") @Autowired @Lazy private DataService dataService; @Autowired private ItemService itemService; @Autowired private WalletService walletService; @Autowired private UserService userService; @Autowired private TipService tipService; @Autowired private UserDataService userDataService; @Autowired @Lazy private ContractApplyOrderService contractApplyOrderService; @Autowired private StrongLevelCalculationService strongLevelCalculationService; public IPage listRecord(Page page, ContractOrderQuery query) { return baseMapper.listRecord(page, query); } /** * 持仓单 * * @param partyId * @param symbol * @param direction * @return */ public List findSubmitted(String partyId, String symbol, String direction) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(StrUtil.isNotBlank(partyId), "party_id", partyId); queryWrapper.eq(StrUtil.isNotBlank(symbol), "symbol", symbol); queryWrapper.eq(StrUtil.isNotBlank(direction), "direction", direction); queryWrapper.eq("state", "submitted"); queryWrapper.orderByDesc("create_time"); return list(queryWrapper); } public List findSubmitted(String partyId, List symbols) { symbols.add("-1"); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("party_id", partyId); queryWrapper.in("symbol", symbols); queryWrapper.eq("state", "submitted"); queryWrapper.orderByDesc("create_time"); return list(queryWrapper); } public List findSubmitted(String partyId, String symbol, String direction, String startTime, String endTime, String symbolType) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(StrUtil.isNotBlank(partyId), "party_id", partyId); // queryWrapper.eq(StrUtil.isNotBlank(symbol), "symbol", symbol); queryWrapper.eq(StrUtil.isNotBlank(direction), "direction", direction); queryWrapper.eq("state", "submitted"); List symbols = itemService.findByType(symbolType).stream().map(Item::getSymbol).collect(Collectors.toList()); symbols.add("-1"); if (StringUtils.isNotEmpty(symbolType) && StringUtils.isEmptyString(symbol)) { queryWrapper.in(StringUtils.isNotEmpty(symbolType), "symbol", symbols); } queryWrapper.ge(StringUtils.isNotEmpty(startTime), "date_format(create_time,'%Y-%m-%d')", startTime); queryWrapper.le(StringUtils.isNotEmpty(endTime), "date_format(create_time,'%Y-%m-%d')", endTime); queryWrapper.orderByDesc("create_time"); return list(queryWrapper); } public List> findSubmittedRedis(String partyId, String symbol, String startTime, String endTime, String symbolType) { List list = findSubmitted(partyId, symbol, null, startTime, endTime, symbolType); return this.bulidData(list); } public List> findSubmittedRedis(String partyId, String symbol) { List list = findSubmitted(partyId, symbol, null); return this.bulidData(list); } public List> getPaged(int pageNo, int pageSize, String partyId, String symbol, String type, String queryDate) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(StrUtil.isNotBlank(partyId), "party_id", partyId); queryWrapper.eq(StrUtil.isNotBlank(symbol), "symbol", symbol); if ("orders".equals(type)) { queryWrapper.eq("state", "submitted"); queryWrapper.eq(StringUtils.isNotEmpty(queryDate), "date_format(create_time,'%Y-%m-%d')", queryDate); } else if ("hisorders".equals(type)) { queryWrapper.eq("state", "created"); queryWrapper.eq(StringUtils.isNotEmpty(queryDate), "date_format(create_time,'%Y-%m-%d')", queryDate); } queryWrapper.orderByDesc("create_time"); Date date = DateUtils.addDay(new Date(), -1); Page page = new Page(pageNo, pageSize); List list = baseMapper.selectPage(page, queryWrapper).getRecords(); List> data = this.bulidData(list); return data; } public Long getOrdersCount(String type, String partyId, String symbol, String symbolType) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(StrUtil.isNotBlank(partyId), "party_id", partyId); queryWrapper.eq(StrUtil.isNotBlank(symbol), "symbol", symbol); if ("orders".equals(type)) { queryWrapper.eq("state", "submitted"); } else if ("hisorders".equals(type)) { queryWrapper.eq("state", "created"); } List symbols = itemService.findByType(symbolType).stream().map(Item::getSymbol).collect(Collectors.toList()); symbols.add("-1"); if (StringUtils.isNotEmpty(symbolType) && StringUtils.isEmptyString(symbol)) { queryWrapper.in(StringUtils.isNotEmpty(symbolType), "symbol", symbols); } return count(queryWrapper); } public List findSubmitted() { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("state", ContractOrder.STATE_SUBMITTED); return list(queryWrapper); } public ContractOrder findByOrderNoRedis(String orderNo) { return RedisUtil.get(ContractRedisKeys.CONTRACT_ORDERNO + orderNo); } public ContractOrder findByOrderNo(String orderNo) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("order_no", orderNo); queryWrapper.last("limit 1"); List list = list(queryWrapper); if (CollectionUtil.isEmpty(list)) { return null; } return list.get(0); } public List> getPaged(int pageNo, int pageSize, String partyId, String symbol, String type, String startTime, String endTime, String symbolType) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(StrUtil.isNotBlank(partyId), "party_id", partyId); // queryWrapper.eq(StrUtil.isNotBlank(symbol), "symbol", symbol); if ("orders".equals(type)) { queryWrapper.eq("state", "submitted"); } else if ("hisorders".equals(type)) { queryWrapper.eq("state", "created"); } List symbols = itemService.findByType(symbolType).stream().map(Item::getSymbol).collect(Collectors.toList()); symbols.add("-1"); if (StringUtils.isNotEmpty(symbolType) && StringUtils.isEmptyString(symbol)) { queryWrapper.in(StringUtils.isNotEmpty(symbolType), "symbol", symbols); } queryWrapper.ge(StrUtil.isNotBlank(startTime), "create_time", startTime + " 00:00:00"); queryWrapper.le(StrUtil.isNotBlank(endTime), "create_time", endTime + " 23:59:59"); queryWrapper.orderByDesc("create_time"); Page page = new Page(pageNo, pageSize); List list = baseMapper.selectPage(page, queryWrapper).getRecords(); List> data = this.bulidData(list); return data; } /** * 平仓,按订单进行平仓 */ private final Object lock = new Object(); @Transactional public ContractOrder saveClose(String partyId, String orderNo,String describe) { /* * 平仓 */ synchronized (lock) { ContractOrder order = this.findByOrderNo(orderNo); if (order == null || !ContractOrder.STATE_SUBMITTED.equals(order.getState()) || !partyId.equals(order.getPartyId()) || order.getVolume().compareTo(BigDecimal.ZERO) <= 0) { /** * 状态已改变,退出处理 */ return null; } /** * 收益 */ BigDecimal volume = order.getVolume(); BigDecimal profit = settle(order, order.getVolume()); Wallet wallet = walletService.findByUserId(order.getPartyId()); if (wallet.getMoney().add(profit).compareTo(BigDecimal.ZERO) < 0) { // 如果结果是负数,就归零 if (wallet.getMoney().compareTo(BigDecimal.ZERO) < 0) { profit = BigDecimal.ZERO; } } walletService.updateMoney(order.getSymbol(), partyId, profit, BigDecimal.ZERO, Constants.MONEYLOG_CATEGORY_CONTRACT, Constants.WALLET_USDT, Constants.MONEYLOG_CONTENT_CONTRACT_CLOSE, describe+"平仓,平仓合约数[" + volume + "],订单号[" + order.getOrderNo() + "]"); order.setState(ContractOrder.STATE_CREATED); order.setVolume(BigDecimal.ZERO); order.setDeposit(BigDecimal.ZERO); order.setCloseTime(DateUtil.currentSeconds()); order.setCloseTimeTs(DateUtil.currentSeconds()); update(order); /** * 合约产品平仓后添加当前流水setWithdraw_limit_now_amount */ User party = userService.getById(order.getPartyId()); party.setWithdrawLimitNowAmount(party.getWithdrawLimitNowAmount().add(order.getDepositOpen())); userService.updateById(party); if (ObjectUtils.isEmpty(order.getCloseAvgPrice())) { order.setCloseAvgPrice(BigDecimal.ZERO); } return order; } } /** * 全仓强平 */ private final Object allCloseLock = new Object(); @Transactional public void allClose(String partyId) { synchronized (allCloseLock) { /* * 平仓 */ //所有订单 List list = list(new LambdaQueryWrapper<>(ContractOrder.class) .eq(ContractOrder::getState, ContractOrder.STATE_SUBMITTED) .eq(ContractOrder::getPartyId, partyId) ); //计算所有亏损 BigDecimal finalProfit = BigDecimal.ZERO; // 初始化为 0 String symbol = null; String orderNo = null; String volume = null; for (ContractOrder order : list) { /** * 计算收益 */ BigDecimal earnings = settle(order, order.getVolume()); finalProfit = finalProfit.add(earnings); order.setState(ContractOrder.STATE_CREATED); order.setVolume(BigDecimal.ZERO); order.setDeposit(BigDecimal.ZERO); order.setCloseTime(DateUtil.currentSeconds()); order.setCloseTimeTs(DateUtil.currentSeconds()); update(order); /** * 合约产品平仓后添加当前流水setWithdraw_limit_now_amount */ User party = userService.getById(order.getPartyId()); party.setWithdrawLimitNowAmount(party.getWithdrawLimitNowAmount().add(order.getDepositOpen())); userService.updateById(party); if (ObjectUtils.isEmpty(order.getCloseAvgPrice())) { order.setCloseAvgPrice(BigDecimal.ZERO); } if (StringUtils.isNotEmpty(symbol)) { symbol += "," + order.getSymbol(); } else { symbol = order.getSymbol(); } if (StringUtils.isNotEmpty(orderNo)) { orderNo += "," + order.getOrderNo(); } else { orderNo = order.getOrderNo(); } if (StringUtils.isNotEmpty(volume)) { volume += "," + "订单号:" + order.getOrderNo() + "数量:" + order.getVolumeOpen(); } else { volume = "订单号:" + order.getOrderNo() + "数量:" + order.getVolumeOpen(); } } walletService.updateMoney(symbol, partyId, finalProfit, BigDecimal.ZERO, Constants.MONEYLOG_CATEGORY_CONTRACT, Constants.WALLET_USDT, Constants.MONEYLOG_CONTENT_CONTRACT_CLOSE, "强制平仓,平仓合约数" + list.size() + "[" + volume + "],订单号[" + orderNo + "]"); } } /** * 前台发起的,直接不缓存 * updateByIdBuffer 只是更新利润强平价格的,不要处理state状态更新 * * @param entity * @return */ @Transactional(propagation = Propagation.NOT_SUPPORTED) public void updateByIdBuffer(ContractOrder entity) { map.put(entity.getUuid(), entity); } public void update(ContractOrder order) { // 强制刷新 updateById(order); // this.getHibernateTemplate().merge(order); RedisUtil.set(ContractRedisKeys.CONTRACT_ORDERNO + order.getOrderNo(), order); if (ContractOrder.STATE_SUBMITTED.equals(order.getState())) { Map map = RedisUtil.get(ContractRedisKeys.CONTRACT_SUBMITTED_ORDER_PARTY_ID + order.getPartyId()); if (null == map) { map = new ConcurrentHashMap<>(); } ContractOrder orderOld = map.get(order.getOrderNo()); map.put(order.getOrderNo(), order); RedisUtil.set(ContractRedisKeys.CONTRACT_SUBMITTED_ORDER_PARTY_ID + order.getPartyId(), map); // 获取单个订单的合约总资产、总保证金、总未实现盈利 Map contractAssetsOrder = this.walletService.getMoneyContractByOrder(order); Map contractAssetsOrderOld = this.walletService.getMoneyContractByOrder(orderOld); BigDecimal contractAssets = RedisUtil.get(ContractRedisKeys.CONTRACT_ASSETS_PARTY_ID + order.getPartyId().toString()); if (contractAssets == null) { contractAssets = BigDecimal.ZERO; } BigDecimal contractAssetsDeposit = RedisUtil.get(ContractRedisKeys.CONTRACT_ASSETS_DEPOSIT_PARTY_ID + order.getPartyId().toString()); if (contractAssetsDeposit == null) { contractAssetsDeposit = BigDecimal.ZERO; } BigDecimal contractAssetsProfit = RedisUtil.get(ContractRedisKeys.CONTRACT_ASSETS_PROFIT_PARTY_ID + order.getPartyId().toString()); if (contractAssetsProfit == null) { contractAssetsProfit = BigDecimal.ZERO; } RedisUtil.set(ContractRedisKeys.CONTRACT_ASSETS_PARTY_ID + order.getPartyId().toString(), contractAssets.add(contractAssetsOrder.get("money_contract")).subtract(contractAssetsOrderOld.get("money_contract"))); RedisUtil.set(ContractRedisKeys.CONTRACT_ASSETS_DEPOSIT_PARTY_ID + order.getPartyId().toString(), contractAssetsDeposit.add(contractAssetsOrder.get("money_contract_deposit")).subtract(contractAssetsOrderOld.get("money_contract_deposit"))); RedisUtil.set(ContractRedisKeys.CONTRACT_ASSETS_PROFIT_PARTY_ID + order.getPartyId().toString(), contractAssetsProfit.add(contractAssetsOrder.get("money_contract_profit")).subtract(contractAssetsOrderOld.get("money_contract_profit"))); } else if (ContractOrder.STATE_CREATED.equals(order.getState())) { // 平仓后,移除持仓列表 Map map = RedisUtil.get(ContractRedisKeys.CONTRACT_SUBMITTED_ORDER_PARTY_ID + order.getPartyId().toString()); ContractOrder orderOld = null; if (map != null && !map.isEmpty()) { orderOld = map.get(order.getOrderNo()); map.remove(order.getOrderNo()); } RedisUtil.set(ContractRedisKeys.CONTRACT_SUBMITTED_ORDER_PARTY_ID + order.getPartyId().toString(), map); // 获取单个订单的合约总资产、总保证金、总未实现盈利 Map contractAssetsOrderOld = walletService.getMoneyContractByOrder(orderOld); BigDecimal contractAssets = RedisUtil.get(ContractRedisKeys.CONTRACT_ASSETS_PARTY_ID + order.getPartyId().toString()); if (contractAssets == null) { contractAssets = BigDecimal.ZERO; } BigDecimal contractAssetsDeposit = RedisUtil.get(ContractRedisKeys.CONTRACT_ASSETS_DEPOSIT_PARTY_ID + order.getPartyId().toString()); if (contractAssetsDeposit == null) { contractAssetsDeposit = BigDecimal.ZERO; } BigDecimal contractAssetsProfit = RedisUtil.get(ContractRedisKeys.CONTRACT_ASSETS_PROFIT_PARTY_ID + order.getPartyId().toString()); if (contractAssetsProfit == null) { contractAssetsProfit = BigDecimal.ZERO; } RedisUtil.set(ContractRedisKeys.CONTRACT_ASSETS_PARTY_ID + order.getPartyId().toString(), contractAssets.subtract(contractAssetsOrderOld.get("money_contract"))); RedisUtil.set(ContractRedisKeys.CONTRACT_ASSETS_DEPOSIT_PARTY_ID + order.getPartyId().toString(), contractAssetsDeposit.subtract(contractAssetsOrderOld.get("money_contract_deposit"))); RedisUtil.set(ContractRedisKeys.CONTRACT_ASSETS_PROFIT_PARTY_ID + order.getPartyId().toString(), contractAssetsProfit.subtract(contractAssetsOrderOld.get("money_contract_profit"))); // 平仓则纪录数据(委托平仓,订单直接平仓) this.userDataService.saveClose(order); User party = userService.getById(order.getPartyId()); if (Constants.SECURITY_ROLE_MEMBER.equals(party.getRoleName())) { tipService.deleteTip(order.getUuid().toString()); } } } /** * 收益结算,平仓时计算 * * @param closevolume 平仓的张数 */ public BigDecimal settle(ContractOrder order, BigDecimal volume) { /** * 偏差点位 */ List list = this.dataService.realtime(order.getSymbol()); if (list.size() == 0) { order.getProfit(); } Realtime realtime = list.get(0); BigDecimal close = realtime.getClose(); BigDecimal point = close.subtract(order.getTradeAvgPrice()); BigDecimal profit = point.multiply(new BigDecimal("0.01")).multiply(order.getVolumeOpen()).setScale(4, BigDecimal.ROUND_DOWN);; BigDecimal rentalProfit = order.getDeposit().add(profit); BigDecimal rate = volume.divide(order.getVolumeOpen(), 2, RoundingMode.HALF_UP); order.setAmountClose(order.getAmountClose().add(profit)); order.setVolume(order.getVolume().subtract(volume)); order.setDeposit(order.getDeposit().subtract(order.getDepositOpen().multiply(rate))); if (order.getVolume().compareTo(BigDecimal.ZERO) <= 0) { order.setState(ContractOrder.STATE_CREATED); order.setCloseTime(DateUtil.currentSeconds()); order.setCloseTimeTs(DateUtil.currentSeconds()); } return rentalProfit; } public void saveOpen(ContractApplyOrder applyOrder, Realtime realtime) { Item item = this.itemService.findBySymbol(applyOrder.getSymbol()); ContractOrder order = new ContractOrder(); order.setPartyId(applyOrder.getPartyId()); order.setSymbol(applyOrder.getSymbol()); String orderNo = com.yami.trading.common.util.DateUtil.formatDate(new Date(), "yyMMddHHmmss") + RandomUtil.getRandomNum(8); order.setOrderNo(orderNo); order.setDirection(applyOrder.getDirection()); order.setLeverRate(applyOrder.getLeverRate()); order.setOrderPriceType(applyOrder.getOrderPriceType()); order.setTradeAvgPrice(applyOrder.getPrice()); order.setStopPriceProfit(applyOrder.getStopPriceProfit()); order.setStopPriceLoss(applyOrder.getStopPriceLoss()); order.setPips(item.getPips()); order.setPipsAmount(item.getPipsAmount()); if(applyOrder.getOrderPriceType().equals("opponent")){//市价单,创建订单在计算和扣款 BigDecimal unitAmount = applyOrder.getPrice().multiply(BigDecimal.valueOf(item.getFaceValue())); unitAmount = unitAmount.setScale(4, RoundingMode.DOWN); BigDecimal deposit = unitAmount.multiply(applyOrder.getVolumeOpen()).divide(order.getLeverRate(), 4, RoundingMode.DOWN); order.setUnitAmount(unitAmount); order.setDepositOpen(deposit); order.setDeposit(deposit); if (order.getLeverRate() != null) { /** * 加上杠杆 */ // 设置订单数量 order.setVolume(applyOrder.getVolumeOpen()); BigDecimal fee = order.getDeposit().multiply(order.getLeverRate()).multiply(item.getUnitFee()); fee = fee.setScale(4, RoundingMode.DOWN); // 保留两位小数 order.setFee(fee); } order.setVolumeOpen(applyOrder.getVolumeOpen()); walletService.updateMoney(order.getSymbol(), order.getPartyId(), BigDecimal.ZERO.subtract(order.getDeposit()), BigDecimal.ZERO , Constants.MONEYLOG_CATEGORY_CONTRACT, Constants.WALLET_USDT, Constants.MONEYLOG_CONTENT_CONTRACT_OPEN, "委托单,订单号[" + order.getOrderNo() + "]" ); walletService.updateMoney(order.getSymbol(), order.getPartyId(), BigDecimal.ZERO.subtract(order.getFee()), BigDecimal.ZERO , Constants.MONEYLOG_CATEGORY_CONTRACT, Constants.WALLET_USDT, Constants.MONEYLOG_CONTENT_FEE, "委托单,订单号[" + order.getOrderNo() + "]" ); } double faceValue = 0.01; // 合约面值(固定面值不能调整) double maintenanceMarginRate = 0.004; // 维持保证金率(固定不变) //"buy":买(多) "sell":卖(空) if(order.getDirection().equals("buy")){ double forceClosePrice = strongLevelCalculationService.calculateLiquidationPrice(order.getDepositOpen().doubleValue(), faceValue, order.getVolumeOpen().doubleValue(), order.getTradeAvgPrice().doubleValue() , maintenanceMarginRate, item.getUnitFee().doubleValue()); order.setForceClosePrice(BigDecimal.valueOf(forceClosePrice).toString()); }else{ double forceClosePrice = strongLevelCalculationService.calculateEmptyLiquidationPrice(order.getDepositOpen().doubleValue(), faceValue, order.getVolumeOpen().doubleValue(), order.getTradeAvgPrice().doubleValue() , maintenanceMarginRate, item.getUnitFee().doubleValue()); order.setForceClosePrice(BigDecimal.valueOf(forceClosePrice).toString()); } save(order); RedisUtil.set(ContractRedisKeys.CONTRACT_ORDERNO + order.getOrderNo(), order); Map map = RedisUtil .get(ContractRedisKeys.CONTRACT_SUBMITTED_ORDER_PARTY_ID + order.getPartyId().toString()); if (map == null) { map = new ConcurrentHashMap(); } map.put(order.getOrderNo(), order); RedisUtil.set(ContractRedisKeys.CONTRACT_SUBMITTED_ORDER_PARTY_ID + order.getPartyId().toString(), map); // 获取单个订单的合约总资产、总保证金、总未实现盈利 Map contractAssetsOrder = this.walletService.getMoneyContractByOrder(order); BigDecimal contractAssets = RedisUtil.get(ContractRedisKeys.CONTRACT_ASSETS_PARTY_ID + order.getPartyId().toString()); if (contractAssets == null) { contractAssets = BigDecimal.ZERO; } BigDecimal contractAssetsDeposit = RedisUtil.get(ContractRedisKeys.CONTRACT_ASSETS_DEPOSIT_PARTY_ID + order.getPartyId().toString()); if (contractAssetsDeposit == null) { contractAssetsDeposit = BigDecimal.ZERO; } BigDecimal contractAssetsProfit = RedisUtil.get(ContractRedisKeys.CONTRACT_ASSETS_PROFIT_PARTY_ID + order.getPartyId().toString()); if (contractAssetsProfit == null) { contractAssetsProfit = BigDecimal.ZERO; } RedisUtil.set(ContractRedisKeys.CONTRACT_ASSETS_PARTY_ID + order.getPartyId().toString(), contractAssets.add(contractAssetsOrder.get("money_contract"))); RedisUtil.set(ContractRedisKeys.CONTRACT_ASSETS_DEPOSIT_PARTY_ID + order.getPartyId().toString(), contractAssetsDeposit.add(contractAssetsOrder.get("money_contract_deposit"))); RedisUtil.set(ContractRedisKeys.CONTRACT_ASSETS_PROFIT_PARTY_ID + order.getPartyId().toString(), contractAssetsProfit.add(contractAssetsOrder.get("money_contract_profit"))); /** * 进入市场 */ applyOrder.setVolume(BigDecimal.ZERO); applyOrder.setState(ContractApplyOrder.STATE_CREATED); contractApplyOrderService.updateById(applyOrder); User party = this.userService.getById(order.getPartyId()); if (Constants.SECURITY_ROLE_MEMBER.equals(party.getRoleName())) { tipService.saveTip(order.getUuid().toString(), TipConstants.CONTRACT_ORDER); } } public ContractApplyOrder saveClose(ContractApplyOrder applyOrder, Realtime realtime, String order_no) { ContractOrder order = this.findByOrderNo(order_no); if (order == null || !ContractOrder.STATE_SUBMITTED.equals(order.getState()) || order.getVolume().compareTo(BigDecimal.ZERO) <= 0) { /** * 状态已改变,退出处理 */ return applyOrder; } BigDecimal volume; if (applyOrder.getVolume().compareTo(order.getVolume()) > 0) { volume = order.getVolume(); } else { volume = applyOrder.getVolume(); } /** * 平仓退回的金额 */ BigDecimal profit = this.settle(order, volume); update(order); Wallet wallet = this.walletService.findByUserId(order.getPartyId()); if (wallet.getMoney().add(profit).compareTo(BigDecimal.ZERO) < 0) { profit = wallet.getMoney().negate(); } walletService.updateMoney(order.getSymbol(), order.getPartyId(), profit, BigDecimal.ZERO, Constants.MONEYLOG_CATEGORY_CONTRACT, Constants.WALLET_USDT, Constants.MONEYLOG_CONTENT_CONTRACT_CLOSE, "平仓,平仓合约数[" + volume + "],订单号[" + order.getOrderNo() + "]"); applyOrder.setVolume(applyOrder.getVolume().subtract(volume)); if (applyOrder.getVolume().compareTo(BigDecimal.ZERO) <= 0) { applyOrder.setState(ContractApplyOrder.STATE_CREATED); } contractApplyOrderService.updateById(applyOrder); return applyOrder; } public boolean lock(String order_no) { return ContractLock.add(order_no); } public void unlock(String order_no) { ContractLock.remove(order_no); } private List> bulidData(List list) { List> data = new ArrayList(); for (int i = 0; i < list.size(); i++) { ContractOrder order = list.get(i); Map map = bulidOne(order); data.add(map); } return data; } public Map bulidOne(ContractOrder order) { Map map = new HashMap(); map.put("order_no", order.getOrderNo()); Item bySymbol = itemService.findBySymbol(order.getSymbol()); String name = "---"; if(bySymbol != null){ name = bySymbol.getName(); } map.put("name", name); map.put("symbol", order.getSymbol()); map.put("create_time", DateUtils.format(order.getCreateTime(), DateUtils.DF_yyyyMMddHHmmss)); map.put("create_time_ts", order.getCreateTimeTs()); if (order.getCloseTime() != null) { map.put("close_time", order.getCloseTime()); } else { map.put("close_time", ""); } String orderPriceType = order.getOrderPriceType(); if (StringUtils.isEmptyString(orderPriceType)) { orderPriceType = "opponent"; } map.put("order_price_type", orderPriceType); map.put("direction", order.getDirection()); map.put("lever_rate", order.getLeverRate()); map.put("trade_avg_price", order.getTradeAvgPrice()); map.put("close_avg_price", order.getCloseAvgPrice()); if (order.getStopPriceProfit() != null) { map.put("stop_price_profit", order.getStopPriceProfit().setScale(4, RoundingMode.HALF_UP)); }else{ map.put("stop_price_profit", order.getStopPriceProfit()); } if (order.getStopPriceLoss() != null) { map.put("stop_price_loss", order.getStopPriceLoss().setScale(4, RoundingMode.HALF_UP)); }else{ map.put("stop_price_loss", order.getStopPriceLoss()); } map.put("state", order.getState()); map.put("amount", order.getVolume().multiply(order.getUnitAmount())); map.put("amount_open", order.getVolumeOpen().multiply(order.getUnitAmount())); map.put("fee", order.getFee()); map.put("deposit", order.getDeposit()); map.put("deposit_open", order.getDepositOpen()); map.put("change_ratio", order.getChangeRatio()); if(order.getProfit()!=null){ map.put("profit", order.getProfit().setScale(4, RoundingMode.HALF_UP)); }else{ map.put("profit", order.getProfit()); } map.put("volume", order.getVolume()); map.put("volume_open", order.getVolumeOpen()); map.put("force_close_rice", order.getForceClosePrice()); return map; } /** * 根据用户批量赎回订单 * * @param partyId */ public void saveCloseRemoveAllByPartyId(String partyId) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("party_id", partyId); List orders = list(queryWrapper); List findSubmittedContractOrders = findSubmitted(partyId, null, null); if (!CollectionUtils.isEmpty(findSubmittedContractOrders)) { for (ContractOrder order : orders) { if (ContractOrder.STATE_SUBMITTED.equals(order.getState())) { saveClose(order.getPartyId().toString(), order.getOrderNo(),null); } RedisUtil.del(ContractRedisKeys.CONTRACT_ORDERNO + order.getOrderNo()); } RedisUtil.del(ContractRedisKeys.CONTRACT_SUBMITTED_ORDER_PARTY_ID + partyId); RedisUtil.del(ContractRedisKeys.CONTRACT_ASSETS_PARTY_ID + partyId); RedisUtil.del(ContractRedisKeys.CONTRACT_ASSETS_DEPOSIT_PARTY_ID + partyId); RedisUtil.del(ContractRedisKeys.CONTRACT_ASSETS_PROFIT_PARTY_ID + partyId); } } }