From 3b51e28456fc8c3ca03a27df70645b82c1a1530b Mon Sep 17 00:00:00 2001 From: Helius <wangdoubleone@gmail.com> Date: Tue, 08 Sep 2020 18:00:30 +0800 Subject: [PATCH] modify --- src/main/java/com/xcong/excoin/modules/contract/service/impl/RabbitOrderServiceImpl.java | 453 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 433 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/xcong/excoin/modules/contract/service/impl/RabbitOrderServiceImpl.java b/src/main/java/com/xcong/excoin/modules/contract/service/impl/RabbitOrderServiceImpl.java index ebba922..3d1476a 100644 --- a/src/main/java/com/xcong/excoin/modules/contract/service/impl/RabbitOrderServiceImpl.java +++ b/src/main/java/com/xcong/excoin/modules/contract/service/impl/RabbitOrderServiceImpl.java @@ -1,33 +1,51 @@ package com.xcong.excoin.modules.contract.service.impl; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import com.xcong.excoin.common.contants.AppContants; import com.xcong.excoin.common.enumerates.CoinTypeEnum; import com.xcong.excoin.common.enumerates.OrderClosingTypeEnum; import com.xcong.excoin.common.system.service.CommonService; +import com.xcong.excoin.modules.coin.entity.MemberAccountFlowEntity; +import com.xcong.excoin.modules.contract.dao.ContractEntrustOrderDao; import com.xcong.excoin.modules.contract.dao.ContractHoldOrderDao; import com.xcong.excoin.modules.contract.dao.ContractOrderDao; +import com.xcong.excoin.modules.contract.entity.ContractEntrustOrderEntity; import com.xcong.excoin.modules.contract.entity.ContractHoldOrderEntity; import com.xcong.excoin.modules.contract.entity.ContractOrderEntity; import com.xcong.excoin.modules.contract.mapper.ContractHoldOrderEntityMapper; import com.xcong.excoin.modules.contract.service.RabbitOrderService; +import com.xcong.excoin.modules.documentary.common.NoticeConstant; +import com.xcong.excoin.modules.documentary.dao.FollowFollowerOrderRelationDao; +import com.xcong.excoin.modules.documentary.dao.FollowFollowerProfitDao; +import com.xcong.excoin.modules.documentary.dao.FollowTraderInfoDao; +import com.xcong.excoin.modules.documentary.dao.FollowTraderProfitDetailDao; +import com.xcong.excoin.modules.documentary.entity.FollowFollowerOrderRelationEntity; +import com.xcong.excoin.modules.documentary.entity.FollowFollowerProfitEntity; +import com.xcong.excoin.modules.documentary.entity.FollowTraderInfoEntity; +import com.xcong.excoin.modules.documentary.entity.FollowTraderProfitDetailEntity; +import com.xcong.excoin.modules.documentary.service.FollowOrderOperationService; import com.xcong.excoin.modules.member.dao.MemberDao; +import com.xcong.excoin.modules.member.dao.MemberSettingDao; import com.xcong.excoin.modules.member.dao.MemberWalletContractDao; import com.xcong.excoin.modules.member.entity.AgentReturnEntity; import com.xcong.excoin.modules.member.entity.MemberEntity; +import com.xcong.excoin.modules.member.entity.MemberSettingEntity; import com.xcong.excoin.modules.member.entity.MemberWalletContractEntity; import com.xcong.excoin.modules.platform.entity.PlatformTradeSettingEntity; -import com.xcong.excoin.utils.CacheSettingUtils; -import com.xcong.excoin.utils.CoinTypeConvert; -import com.xcong.excoin.utils.RedisUtils; -import com.xcong.excoin.utils.ThreadPoolUtils; +import com.xcong.excoin.rabbit.pricequeue.OrderModel; +import com.xcong.excoin.utils.*; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; /** * @author wzy @@ -39,46 +57,67 @@ @Resource private MemberDao memberDao; - @Resource private OrderWebsocketServiceImpl orderWebsocketService; - @Resource private ContractHoldOrderDao contractHoldOrderDao; - @Resource private ContractOrderDao contractOrderDao; - @Resource private CommonService commonService; - @Resource private MemberWalletContractDao memberWalletContractDao; - @Resource private CacheSettingUtils cacheSettingUtils; - @Resource private RedisUtils redisUtils; + @Resource + private MemberSettingDao memberSettingDao; + @Resource + private FollowFollowerOrderRelationDao followFollowerOrderRelationDao; + @Resource + private FollowOrderOperationService followOrderOperationService; + @Resource + private FollowTraderInfoDao followTraderInfoDao; + @Resource + private FollowTraderProfitDetailDao followTraderProfitDetailDao; + @Resource + private FollowFollowerProfitDao followFollowerProfitDao; + @Resource + private ContractEntrustOrderDao contractEntrustOrderDao; @Transactional(rollbackFor = Exception.class) @Override public void cancelHoldOrder(List<Long> ids) { if (CollUtil.isNotEmpty(ids)) { - if (ids.size() == 1) { - ContractHoldOrderEntity holdOrderEntity = contractHoldOrderDao.selectById(ids.get(0)); - cancelHoldOrderMethod(holdOrderEntity); - } else { - List<ContractHoldOrderEntity> holdOrderEntities = contractHoldOrderDao.selectBatchIds(ids); - if (CollUtil.isNotEmpty(holdOrderEntities)) { - for (ContractHoldOrderEntity holdOrder : holdOrderEntities) { - cancelHoldOrderMethod(holdOrder); + try { + if (ids.size() == 1) { + ContractHoldOrderEntity holdOrderEntity = contractHoldOrderDao.selectById(ids.get(0)); + + // 判断仓位类型是否逐仓 + if (holdOrderEntity.getPositionType() == ContractEntrustOrderEntity.POSITION_TYPE_ADD) { + // 逐仓平仓 + cancelHoldOrderMethod(holdOrderEntity); + } else { + // 全仓模式平仓 + closingWholeOrder(holdOrderEntity); + } + } else { + List<ContractHoldOrderEntity> holdOrderEntities = contractHoldOrderDao.selectBatchIds(ids); + if (CollUtil.isNotEmpty(holdOrderEntities)) { + for (ContractHoldOrderEntity holdOrder : holdOrderEntities) { + cancelHoldOrderMethod(holdOrder); + } } } + } catch (Exception e) { + log.error("平仓异常", e); } + } } + @Transactional(rollbackFor = Exception.class) public void cancelHoldOrderMethod(ContractHoldOrderEntity holdOrderEntity) { String symbol = holdOrderEntity.getSymbol(); // 获取最新价 @@ -96,14 +135,18 @@ BigDecimal profitOrLoss = BigDecimal.ZERO; Integer orderType = null; Integer closingType = null; + + MemberSettingEntity memberSettingEntity = memberSettingDao.selectMemberSettingByMemberId(memberEntity.getId()); // 开多 if (ContractHoldOrderEntity.OPENING_TYPE_MORE == holdOrderEntity.getOpeningType()) { + newPrice = newPrice.multiply(BigDecimal.ONE.subtract(memberSettingEntity.getClosingSpread().divide(BigDecimal.valueOf(10000), 4, BigDecimal.ROUND_DOWN))); // (最新价-开仓价)*规格*张数 profitOrLoss = newPrice.subtract(holdOrderEntity.getOpeningPrice()).multiply(lotNumber).multiply(new BigDecimal(holdOrderEntity.getSymbolCnt())); orderType = ContractOrderEntity.ORDER_TYPE_CLOSE_MORE; closingType = OrderClosingTypeEnum.CLOSE_MORE.getValue(); // 开空 } else { + newPrice = newPrice.multiply(BigDecimal.ONE.add(memberSettingEntity.getClosingSpread().divide(BigDecimal.valueOf(10000), 4, BigDecimal.ROUND_DOWN))); // (开仓价-最新价)*规格*张数 profitOrLoss = holdOrderEntity.getOpeningPrice().subtract(newPrice).multiply(lotNumber).multiply(new BigDecimal(holdOrderEntity.getSymbolCnt())); orderType = ContractOrderEntity.ORDER_TYPE_CLOSE_LESS; @@ -122,6 +165,23 @@ // 盈亏比例(回报率) BigDecimal rewardRatio = profitOrLoss.divide(holdOrderEntity.getBondAmount().subtract(holdOrderEntity.getOpeningFeeAmount()), 8, BigDecimal.ROUND_DOWN); + FollowTraderInfoEntity traderInfoEntity = null; + // 判断当前订单是否为跟单 + if (ContractOrderEntity.CONTRACTTYPE_DOCUMENTARY == holdOrderEntity.getContractType()) { + // 若不为交易员,则计算跟随者订单返利 + if (!MemberEntity.IS_TRADER_Y.equals(memberEntity.getIsTrader())) { + traderInfoEntity = followTraderInfoDao.selectTraderInfoByOrderId(holdOrderEntity.getId()); + if (profitOrLoss.compareTo(BigDecimal.ZERO) > 0) { + // 计算需返利给交易员的金额 + BigDecimal returnMoney = profitOrLoss.multiply(traderInfoEntity.getProfitRatio()); + profitOrLoss = profitOrLoss.subtract(returnMoney); + MemberWalletContractEntity traderWallet = memberWalletContractDao.findWalletContractByMemberIdAndSymbol(traderInfoEntity.getMemberId(), CoinTypeEnum.USDT.name()); + memberWalletContractDao.increaseWalletContractBalanceById(returnMoney, returnMoney, null, traderWallet.getId()); + insertReturnProfitDetail(traderInfoEntity.getMemberId(), memberEntity.getId(), returnMoney, holdOrderEntity.getOrderNo()); + } + } + } + ContractOrderEntity contractOrderEntity = ContractHoldOrderEntityMapper.INSTANCE.holdOrderToOrder(holdOrderEntity); contractOrderEntity.setId(null); contractOrderEntity.setOrderType(orderType); @@ -135,11 +195,364 @@ // 计算盈利或亏损后可用金额和总金额应该增加或减少的 BigDecimal addMoney = holdOrderEntity.getBondAmount().subtract(holdOrderEntity.getOpeningFeeAmount()).add(profitOrLoss); - memberWalletContractDao.increaseWalletContractBalanceById(addMoney, profitOrLoss.subtract(contractOrderEntity.getOpeningFeeAmount()), null, walletContract.getId()); + + // 流水 + LogRecordUtils.insertMemberAccountFlow(memberEntity.getId(), addMoney, walletContract.getAvailableBalance().add(addMoney), holdOrderEntity.getSymbol(), "平仓", "平仓"); + // 计算佣金 ThreadPoolUtils.calReturnMoney(memberEntity.getId(), contractOrderEntity.getClosingFeeAmount(), contractOrderEntity, AgentReturnEntity.ORDER_TYPE_CLOSE); + + // 判断当前持仓是否为跟单订单 + if (ContractOrderEntity.CONTRACTTYPE_DOCUMENTARY == holdOrderEntity.getContractType()) { + updateFollowOrderRelation(holdOrderEntity.getId(), contractOrderEntity.getId()); + + // 若为交易员,则平仓跟随者订单 + if (MemberEntity.IS_TRADER_Y.equals(memberEntity.getIsTrader())) { + followOrderOperationService.closingFollowOrders(holdOrderEntity.getOrderNo()); + } else { + followFollowerProfitDao.updateFollowerProfitByTradeMemberId(holdOrderEntity.getBondAmount().subtract(holdOrderEntity.getOpeningFeeAmount()), profitOrLoss, traderInfoEntity.getMemberId(), memberEntity.getId()); + LogRecordUtils.insertFollowerNotice(memberEntity.getId(), NoticeConstant.CLOSE_ORDER_TITLE, StrUtil.format(NoticeConstant.CLOSE_ORDER_CONTENT, contractOrderEntity.getSymbol(), contractOrderEntity.getClosingPrice(), profitOrLoss, traderInfoEntity.getNickname())); + } + } } } + + /** + * 更新跟单订单关系 + * + * @param oldOrderId 当前持仓ID + * @param newOrderId 历史订单ID + */ + public void updateFollowOrderRelation(Long oldOrderId, Long newOrderId) { + FollowFollowerOrderRelationEntity orderRelationEntity = followFollowerOrderRelationDao.selectNowOneByorderId(oldOrderId); + if (orderRelationEntity != null) { + orderRelationEntity.setOrderId(newOrderId); + orderRelationEntity.setOrderType(FollowFollowerOrderRelationEntity.ORDER_TYPE_HISTORY); + followFollowerOrderRelationDao.updateById(orderRelationEntity); + } + } + + /** + * 插入跟单返利明细 + * + * @param memberId 交易员会员ID + * @param followMemberId 跟随者会员ID + * @param amount 返利金额 + * @param orderNo 订单编号 + */ + public void insertReturnProfitDetail(Long memberId, Long followMemberId, BigDecimal amount, String orderNo) { + FollowTraderProfitDetailEntity profitDetailEntity = new FollowTraderProfitDetailEntity(); + profitDetailEntity.setMemberId(memberId); + profitDetailEntity.setFollowMemberId(followMemberId); + profitDetailEntity.setAmount(amount); + profitDetailEntity.setOrderNo(orderNo); + followTraderProfitDetailDao.insert(profitDetailEntity); + } + + /** + * 全仓模式平仓逻辑 + */ + public void closingWholeOrder(ContractHoldOrderEntity holdOrderEntity) { + String symbol = holdOrderEntity.getSymbol(); + // 获取最新价 + BigDecimal newPrice = new BigDecimal(redisUtils.getString(CoinTypeConvert.convertToKey(symbol))); + + MemberEntity memberEntity = memberDao.selectById(holdOrderEntity.getMemberId()); + + MemberWalletContractEntity walletContract = memberWalletContractDao.findWalletContractByMemberIdAndSymbol(holdOrderEntity.getMemberId(), CoinTypeEnum.USDT.name()); + if (walletContract != null) { + BigDecimal lotNumber = cacheSettingUtils.getSymbolSku(symbol); + // 盈亏 + BigDecimal profitOrLoss = BigDecimal.ZERO; + Integer orderType = null; + Integer closingType = null; + + // 获取平仓张数 + Integer closeCnt = (Integer) redisUtils.get(AppContants.CLOSING_ORDER_PREFIX + holdOrderEntity.getId()); + + MemberSettingEntity memberSettingEntity = memberSettingDao.selectMemberSettingByMemberId(memberEntity.getId()); + // 开多 + if (ContractHoldOrderEntity.OPENING_TYPE_MORE == holdOrderEntity.getOpeningType()) { + newPrice = newPrice.multiply(BigDecimal.ONE.subtract(memberSettingEntity.getClosingSpread().divide(BigDecimal.valueOf(10000), 4, BigDecimal.ROUND_DOWN))); + // (最新价-开仓价)*规格*张数 + profitOrLoss = newPrice.subtract(holdOrderEntity.getOpeningPrice()).multiply(lotNumber).multiply(new BigDecimal(closeCnt)); + orderType = ContractOrderEntity.ORDER_TYPE_CLOSE_MORE; + closingType = OrderClosingTypeEnum.CLOSE_MORE.getValue(); + // 开空 + } else { + newPrice = newPrice.multiply(BigDecimal.ONE.add(memberSettingEntity.getClosingSpread().divide(BigDecimal.valueOf(10000), 4, BigDecimal.ROUND_DOWN))); + // (开仓价-最新价)*规格*张数 + profitOrLoss = holdOrderEntity.getOpeningPrice().subtract(newPrice).multiply(lotNumber).multiply(new BigDecimal(closeCnt)); + orderType = ContractOrderEntity.ORDER_TYPE_CLOSE_LESS; + closingType = OrderClosingTypeEnum.CLOSE_LESS.getValue(); + } + + if (memberEntity.getIsProfit() == MemberEntity.IS_PROFIT_Y) { + PlatformTradeSettingEntity tradeSettingEntity = cacheSettingUtils.getTradeSetting(); + if (profitOrLoss.compareTo(BigDecimal.ZERO) > -1) { + profitOrLoss = profitOrLoss.multiply(BigDecimal.ONE.subtract(tradeSettingEntity.getProfitParam())); + } else { + profitOrLoss = profitOrLoss.multiply(BigDecimal.ONE.add(tradeSettingEntity.getProfitParam())); + } + } + log.info("profitOrLoss:{}", profitOrLoss); + + // 保证金 + BigDecimal bondAmount = CalculateUtil.getBondAmount(holdOrderEntity.getOpeningPrice(), lotNumber, closeCnt, holdOrderEntity.getLeverRatio()); + + log.info("bondAmount:{}", bondAmount); + // 平仓手续费 TODO 可能需要修复手续费 + BigDecimal fee = BigDecimal.ZERO; + + if (holdOrderEntity.getSymbolCntSale() != 0) { + BigDecimal totalFeeAmount = contractOrderDao.selectWholeFeeAmountByOrderNo(holdOrderEntity.getOrderNo()); + fee = totalFeeAmount.divide(BigDecimal.valueOf(holdOrderEntity.getSymbolCnt()), 8, BigDecimal.ROUND_DOWN).multiply(BigDecimal.valueOf(closeCnt)); + } else { + fee = holdOrderEntity.getOpeningFeeAmount(); + } + log.info("fee:{}", fee); + ContractOrderEntity contractOrderEntity = ContractHoldOrderEntityMapper.INSTANCE.holdOrderToOrder(holdOrderEntity); + contractOrderEntity.setId(null); + contractOrderEntity.setClosingPrice(newPrice); + contractOrderEntity.setOrderType(orderType); + contractOrderEntity.setClosingType(closingType); + contractOrderEntity.setSymbolCnt(closeCnt); + contractOrderEntity.setRewardAmount(profitOrLoss); + contractOrderEntity.setBondAmount(bondAmount.add(fee)); + contractOrderEntity.setClosingFeeAmount(fee); + contractOrderEntity.setClosingTime(new Date()); + contractOrderDao.insert(contractOrderEntity); + + if (holdOrderEntity.getSymbolCntSale() != 0) { + holdOrderEntity.setOpeningFeeAmount(holdOrderEntity.getOpeningFeeAmount().subtract(fee)); + holdOrderEntity.setBondAmount(holdOrderEntity.getBondAmount().subtract(bondAmount)); + BigDecimal rewardAmount = holdOrderEntity.getRewardAmount() == null ? BigDecimal.ZERO : holdOrderEntity.getRewardAmount(); + holdOrderEntity.setRewardAmount(rewardAmount.add(profitOrLoss)); + contractHoldOrderDao.updateById(holdOrderEntity); + } else { + contractHoldOrderDao.deleteById(holdOrderEntity.getId()); + + // 若平掉所有张数,若存在委托平仓,则删除委托平仓记录 + List<ContractEntrustOrderEntity> entrustOrders = contractEntrustOrderDao.selectEntrustOrderByOrderNo(holdOrderEntity.getOrderNo()); + if (CollUtil.isNotEmpty(entrustOrders)) { + for (ContractEntrustOrderEntity entrustOrder : entrustOrders) { + contractEntrustOrderDao.deleteById(entrustOrder.getId()); + } + } + } + + BigDecimal changeAmount = profitOrLoss.add(bondAmount); + log.info("changeAmount : {}", changeAmount); + + BigDecimal total = profitOrLoss.subtract(fee); + log.info("totalMoney : {}", total); + + memberWalletContractDao.increaseWalletContractBalanceById(changeAmount, total, null, walletContract.getId()); + + ThreadPoolUtils.sendWholeForceClosingPrice(holdOrderEntity.getSymbol(), memberEntity); + // 计算佣金 + ThreadPoolUtils.calReturnMoney(memberEntity.getId(), fee, contractOrderEntity, AgentReturnEntity.ORDER_TYPE_CLOSE); + + } + } + + @Override + public void entrustCloseOrder(List<OrderModel> list) { + if (CollUtil.isNotEmpty(list)) { + List<Long> ids = new ArrayList<>(); + list.forEach(model -> ids.add(model.getOrderId())); + List<ContractEntrustOrderEntity> contractEntrustOrderEntities = contractEntrustOrderDao.selectEntrustOrderListByIds(ids); + + if (CollUtil.isNotEmpty(contractEntrustOrderEntities)) { + for (ContractEntrustOrderEntity entrustOrderEntity : contractEntrustOrderEntities) { + closeOrder(entrustOrderEntity); + } + } else { + log.info("平仓委托单未找到"); + } + } + } + + private void closeOrder(ContractEntrustOrderEntity entrustOrder) { + log.info("执行平仓委托"); + + Long memberId = entrustOrder.getMemberId(); + int orderType = entrustOrder.getEntrustType() == ContractEntrustOrderEntity.ENTRUST_TYPE_CLOSE_MORE ? ContractHoldOrderEntity.OPENING_TYPE_MORE : ContractHoldOrderEntity.OPENING_TYPE_LESS; + String symbol = entrustOrder.getSymbol(); + + MemberEntity memberEntity = memberDao.selectById(memberId); + MemberWalletContractEntity walletContract = memberWalletContractDao.findWalletContractByMemberIdAndSymbol(memberId, CoinTypeEnum.USDT.name()); + + BigDecimal lotNumber = cacheSettingUtils.getSymbolSku(symbol); + + BigDecimal newPrice = entrustOrder.getEntrustPrice(); + int closeCnt = entrustOrder.getSymbolCnt(); + + ContractHoldOrderEntity holdOrderEntity = contractHoldOrderDao.selectWholeHoldOrderByOrderType(memberId, orderType, symbol); + + List<Object> types = redisUtils.lGet(AppContants.RABBIT_TYPE + holdOrderEntity.getId(), 0, -1); + if (types.contains(9) || types.contains(10) || types.contains(11) || types.contains(12)) { + log.info("存在止盈/止损 orderId : {}, types : {}", holdOrderEntity.getId(), JSONObject.toJSONString(types)); + return; + } + + BigDecimal profitOrLoss; + int closingType; + // 平多 + if (entrustOrder.getEntrustType() == ContractEntrustOrderEntity.ENTRUST_TYPE_CLOSE_MORE) { + profitOrLoss = newPrice.subtract(holdOrderEntity.getOpeningPrice()).multiply(lotNumber).multiply(new BigDecimal(closeCnt)); + closingType = OrderClosingTypeEnum.CLOSE_MORE.getValue(); + + // 平空 + } else { + profitOrLoss = newPrice.subtract(holdOrderEntity.getOpeningPrice()).multiply(lotNumber).multiply(new BigDecimal(closeCnt)); + closingType = OrderClosingTypeEnum.CLOSE_LESS.getValue(); + } + + if (memberEntity.getIsProfit() == MemberEntity.IS_PROFIT_Y) { + PlatformTradeSettingEntity tradeSettingEntity = cacheSettingUtils.getTradeSetting(); + if (profitOrLoss.compareTo(BigDecimal.ZERO) > -1) { + profitOrLoss = profitOrLoss.multiply(BigDecimal.ONE.subtract(tradeSettingEntity.getProfitParam())); + } else { + profitOrLoss = profitOrLoss.multiply(BigDecimal.ONE.add(tradeSettingEntity.getProfitParam())); + } + } + log.info("profitOrLoss:{}", profitOrLoss); + + // 保证金 + BigDecimal bondAmount = CalculateUtil.getBondAmount(holdOrderEntity.getOpeningPrice(), lotNumber, closeCnt, holdOrderEntity.getLeverRatio()); + + log.info("bondAmount:{}", bondAmount); + // 平仓手续费 TODO 可能需要修复手续费 + BigDecimal fee = BigDecimal.ZERO; + + if (holdOrderEntity.getSymbolCntSale() != 0) { + fee = holdOrderEntity.getOpeningFeeAmount().divide(BigDecimal.valueOf(holdOrderEntity.getSymbolCnt()), 8, BigDecimal.ROUND_DOWN).multiply(BigDecimal.valueOf(closeCnt)); + } else { + fee = holdOrderEntity.getOpeningFeeAmount(); + } + + log.info("fee:{}", fee); + ContractOrderEntity contractOrderEntity = ContractHoldOrderEntityMapper.INSTANCE.holdOrderToOrder(holdOrderEntity); + contractOrderEntity.setId(null); + contractOrderEntity.setEntrustOpeningPrice(newPrice); + contractOrderEntity.setEntrustTime(new Date()); + contractOrderEntity.setClosingPrice(newPrice); + contractOrderEntity.setOrderType(orderType); + contractOrderEntity.setClosingType(closingType); + contractOrderEntity.setSymbolCnt(closeCnt); + contractOrderEntity.setRewardAmount(profitOrLoss); + contractOrderEntity.setBondAmount(bondAmount); + contractOrderEntity.setClosingFeeAmount(fee); + contractOrderDao.insert(contractOrderEntity); + + if (holdOrderEntity.getSymbolCntSale() - closeCnt != 0) { + holdOrderEntity.setSymbolCntSale(holdOrderEntity.getSymbolCntSale() - closeCnt); + holdOrderEntity.setOpeningFeeAmount(holdOrderEntity.getOpeningFeeAmount().subtract(fee)); + holdOrderEntity.setBondAmount(holdOrderEntity.getBondAmount().subtract(bondAmount)); + contractHoldOrderDao.updateById(holdOrderEntity); + } else { + contractHoldOrderDao.deleteById(holdOrderEntity.getId()); + } + + BigDecimal changeAmount = profitOrLoss.add(bondAmount); + log.info("changeAmount : {}", changeAmount); + + BigDecimal total = profitOrLoss.subtract(fee); + log.info("totalMoney : {}", total); + + memberWalletContractDao.increaseWalletContractBalanceById(changeAmount, total, null, walletContract.getId()); + + contractEntrustOrderDao.deleteById(entrustOrder.getId()); + ThreadPoolUtils.sendWholeForceClosingPrice(holdOrderEntity.getSymbol(), memberEntity); + // 计算佣金 + ThreadPoolUtils.calReturnMoney(memberEntity.getId(), fee, contractOrderEntity, AgentReturnEntity.ORDER_TYPE_CLOSE); + } + + + @Transactional(rollbackFor = Exception.class) + @Override + public void wholeBombOrder(List<OrderModel> list) { + for (OrderModel orderModel : list) { + MemberEntity memberEntity = memberDao.selectById(orderModel.getMemberId()); + Long memberId = memberEntity.getId(); + List<ContractHoldOrderEntity> holdOrderEntities = contractHoldOrderDao.selectHoldOrderListForWholeByMemberIdAndSymbol(memberId, null); + MemberWalletContractEntity wallet = memberWalletContractDao.findWalletContractByMemberIdAndSymbol(memberId, CoinTypeEnum.USDT.name()); + + Map<Object, Object> value = redisUtils.hmget(AppContants.WHOLE_BOMB_PREFIX + memberId); + if (CollUtil.isNotEmpty(holdOrderEntities)) { + PlatformTradeSettingEntity tradeSetting = cacheSettingUtils.getTradeSetting(); + for (ContractHoldOrderEntity holdOrderEntity : holdOrderEntities) { + // 删除次仓订单 + contractHoldOrderDao.deleteById(holdOrderEntity.getId()); + BigDecimal lotNumber = cacheSettingUtils.getSymbolSku(holdOrderEntity.getSymbol()); + String symbolPrice = (String) value.get(holdOrderEntity.getSymbol()); + log.info("symbolPrice : {}, symbol : {}", symbolPrice, holdOrderEntity.getSymbol()); + BigDecimal currentPrice = new BigDecimal(symbolPrice); + // 单个订单盈利 +// BigDecimal profitOrLess = BigDecimal.ZERO; +// // 开多 +// if (ContractHoldOrderEntity.OPENING_TYPE_MORE == holdOrderEntity.getOpeningType()) { +// profitOrLess = currentPrice.subtract(holdOrderEntity.getOpeningPrice()).multiply(new BigDecimal(holdOrderEntity.getSymbolCntSale())).multiply(lotNumber); +// // 开空 +// } else { +// profitOrLess = holdOrderEntity.getOpeningPrice().subtract(currentPrice).multiply(new BigDecimal(holdOrderEntity.getSymbolCntSale())).multiply(lotNumber); +// } +// +// if (MemberEntity.IS_PROFIT_Y == memberEntity.getIsProfit()) { +// if (profitOrLess.compareTo(BigDecimal.ZERO) > 0) { +// profitOrLess = profitOrLess.multiply(BigDecimal.ONE.subtract(tradeSetting.getForceParam())); +// } else { +// profitOrLess = profitOrLess.multiply(BigDecimal.ONE.add(tradeSetting.getForceParam())); +// } +// } + BigDecimal profitOrLess = CalculateUtil.calOrderProfitOrLess(holdOrderEntity.getOpeningType(), currentPrice, holdOrderEntity.getOpeningPrice(), lotNumber, holdOrderEntity.getSymbolCntSale(), memberEntity.getIsProfit()); + log.info("profitOrLess ---> {}", profitOrLess); + ContractOrderEntity contractOrderEntity = ContractHoldOrderEntityMapper.INSTANCE.holdOrderToOrder(holdOrderEntity); + + // 查询是否满足爆仓条件 + if (holdOrderEntity.getOpeningType() == ContractHoldOrderEntity.OPENING_TYPE_MORE) { + contractOrderEntity.setClosingType(4); + } else { + contractOrderEntity.setClosingType(5); + } + + // 盈亏比例(回报率) + BigDecimal rewardRatio = profitOrLess.divide(holdOrderEntity.getBondAmount().subtract(holdOrderEntity.getOpeningFeeAmount()), 8, BigDecimal.ROUND_DOWN); + contractOrderEntity.setId(null); + contractOrderEntity.setRewardRatio(rewardRatio); + contractOrderEntity.setRewardAmount(profitOrLess); + contractOrderEntity.setClosingPrice(currentPrice); + contractOrderEntity.setForceClosingPrice(currentPrice); + + // 订单状态转换 + if (ContractOrderEntity.ORDER_TYPE_OPEN_MORE == contractOrderEntity.getOrderType()) { + contractOrderEntity.setOrderType(ContractOrderEntity.ORDER_TYPE_CLOSE_MORE); + } else { + contractOrderEntity.setOrderType(ContractOrderEntity.ORDER_TYPE_CLOSE_LESS); + } + contractOrderEntity.setClosingTime(new Date()); + contractOrderEntity.setClosingFeeAmount(holdOrderEntity.getOpeningFeeAmount()); + + contractOrderDao.insert(contractOrderEntity); + } + + List<ContractEntrustOrderEntity> entrustOrder = contractEntrustOrderDao.selectEntrustOrderListByMemberId(memberId); + BigDecimal totalAmount = BigDecimal.ZERO; + if (CollUtil.isNotEmpty(entrustOrder)) { + for (ContractEntrustOrderEntity contractEntrustOrderEntity : entrustOrder) { + totalAmount.add(contractEntrustOrderEntity.getEntrustAmount()); + } + } + + memberWalletContractDao.increaseWalletContractBalanceById(wallet.getAvailableBalance().negate(), wallet.getTotalBalance().subtract(totalAmount).negate(), null, wallet.getId()); + + redisUtils.del(AppContants.WHOLE_BOMB_PREFIX + memberId); + } else { + log.info("无当前持仓"); + } + } + } } -- Gitblit v1.9.1