| | |
| | | package com.xcong.excoin.modules.contract.service.impl; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.IdUtil; |
| | | 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.member.entity.MemberWalletContractEntity; |
| | | import com.xcong.excoin.modules.platform.entity.PlatformTradeSettingEntity; |
| | | import com.xcong.excoin.rabbit.pricequeue.OrderModel; |
| | | import com.xcong.excoin.rabbit.pricequeue.whole.HoldOrderDataModel; |
| | | import com.xcong.excoin.rabbit.pricequeue.whole.WholePriceDataModel; |
| | | import com.xcong.excoin.utils.*; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @author wzy |
| | |
| | | } |
| | | } |
| | | } |
| | | }catch (Exception e) { |
| | | } catch (Exception e) { |
| | | log.error("平仓异常", e); |
| | | } |
| | | |
| | |
| | | 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())); |
| | | LogRecordUtils.insertFollowerNotice(memberEntity.getId(), NoticeConstant.CLOSE_ORDER_TITLE, StrUtil.format(NoticeConstant.CLOSE_ORDER_CONTENT, contractOrderEntity.getSymbol(), contractOrderEntity.getClosingPrice(), profitOrLoss.setScale(8, BigDecimal.ROUND_DOWN), traderInfoEntity.getNickname())); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | MemberEntity memberEntity = memberDao.selectById(holdOrderEntity.getMemberId()); |
| | | |
| | | MemberWalletContractEntity walletContract = memberWalletContractDao.findWalletContractByMemberIdAndSymbol(holdOrderEntity.getMemberId(), CoinTypeConvert.convertContractTypeToCoin(symbol)); |
| | | MemberWalletContractEntity walletContract = memberWalletContractDao.findWalletContractByMemberIdAndSymbol(holdOrderEntity.getMemberId(), CoinTypeEnum.USDT.name()); |
| | | if (walletContract != null) { |
| | | BigDecimal lotNumber = cacheSettingUtils.getSymbolSku(symbol); |
| | | // 盈亏 |
| | |
| | | contractOrderEntity.setClosingType(closingType); |
| | | contractOrderEntity.setSymbolCnt(closeCnt); |
| | | contractOrderEntity.setRewardAmount(profitOrLoss); |
| | | contractOrderEntity.setBondAmount(bondAmount); |
| | | 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()); |
| | |
| | | log.info("totalMoney : {}", total); |
| | | |
| | | memberWalletContractDao.increaseWalletContractBalanceById(changeAmount, total, null, walletContract.getId()); |
| | | |
| | | ThreadPoolUtils.sendWholePrice(memberEntity.getId()); |
| | | |
| | | ThreadPoolUtils.sendWholeForceClosingPrice(holdOrderEntity.getSymbol(), memberEntity); |
| | | // 计算佣金 |
| | |
| | | String symbol = entrustOrder.getSymbol(); |
| | | |
| | | MemberEntity memberEntity = memberDao.selectById(memberId); |
| | | MemberWalletContractEntity walletContract = memberWalletContractDao.findWalletContractByMemberIdAndSymbol(memberId, CoinTypeConvert.convertContractTypeToCoin(symbol)); |
| | | MemberWalletContractEntity walletContract = memberWalletContractDao.findWalletContractByMemberIdAndSymbol(memberId, CoinTypeEnum.USDT.name()); |
| | | |
| | | BigDecimal lotNumber = cacheSettingUtils.getSymbolSku(symbol); |
| | | |
| | |
| | | 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; |
| | | // 平多 |
| | |
| | | memberWalletContractDao.increaseWalletContractBalanceById(changeAmount, total, null, walletContract.getId()); |
| | | |
| | | contractEntrustOrderDao.deleteById(entrustOrder.getId()); |
| | | |
| | | ThreadPoolUtils.sendWholePrice(memberEntity.getId()); |
| | | |
| | | ThreadPoolUtils.sendWholeForceClosingPrice(holdOrderEntity.getSymbol(), memberEntity); |
| | | // 计算佣金 |
| | | ThreadPoolUtils.calReturnMoney(memberEntity.getId(), fee, contractOrderEntity, AgentReturnEntity.ORDER_TYPE_CLOSE); |
| | | } |
| | | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @Override |
| | | public void wholeBombOrder(WholePriceDataModel wholePriceData) { |
| | | MemberWalletContractEntity wallet = memberWalletContractDao.findWalletContractByMemberIdAndSymbol(wholePriceData.getMemberId(), CoinTypeEnum.USDT.name()); |
| | | MemberEntity memberEntity = memberDao.selectById(wholePriceData.getMemberId()); |
| | | List<HoldOrderDataModel> list = wholePriceData.getList(); |
| | | if (CollUtil.isNotEmpty(list)) { |
| | | String batchNo = IdUtil.randomUUID(); |
| | | for (HoldOrderDataModel holdOrderDataModel : list) { |
| | | ContractHoldOrderEntity holdOrderEntity = contractHoldOrderDao.selectById(holdOrderDataModel.getId()); |
| | | if (holdOrderEntity == null) { |
| | | log.info("持仓不存在:{}", holdOrderDataModel.getId()); |
| | | redisUtils.del(AppContants.WHOLE_BOMB_PREFIX + wholePriceData.getMemberId()); |
| | | continue; |
| | | } |
| | | |
| | | // holdOrderEntity.setForceClosingPrice(getForceSetPrice(wholePriceData, holdOrderEntity, holdOrderDataModel.getSymbol())); |
| | | contractHoldOrderDao.deleteById(holdOrderDataModel.getId()); |
| | | |
| | | ContractOrderEntity contractOrderEntity = ContractHoldOrderEntityMapper.INSTANCE.holdOrderToOrder(holdOrderEntity); |
| | | |
| | | if (holdOrderEntity.getOpeningType() == ContractHoldOrderEntity.OPENING_TYPE_MORE) { |
| | | contractOrderEntity.setClosingType(4); |
| | | } else { |
| | | contractOrderEntity.setClosingType(5); |
| | | } |
| | | |
| | | BigDecimal rewardRatio = holdOrderDataModel.getRewardAmount().divide(holdOrderEntity.getBondAmount().subtract(holdOrderEntity.getOpeningFeeAmount()), 8, BigDecimal.ROUND_DOWN); |
| | | contractOrderEntity.setRewardRatio(rewardRatio); |
| | | contractOrderEntity.setRewardAmount(holdOrderDataModel.getRewardAmount().add(contractOrderEntity.getHoldBond().negate())); |
| | | contractOrderEntity.setClosingPrice(holdOrderDataModel.getClosingPrice()); |
| | | contractOrderEntity.setForceClosingPrice(holdOrderDataModel.getClosingPrice()); |
| | | |
| | | // 订单状态转换 |
| | | 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.setBatchNo(batchNo); |
| | | contractOrderDao.insert(contractOrderEntity); |
| | | } |
| | | |
| | | List<ContractEntrustOrderEntity> entrustOrder = contractEntrustOrderDao.selectEntrustOrderListByMemberId(wholePriceData.getMemberId()); |
| | | BigDecimal totalAmount = BigDecimal.ZERO; |
| | | if (CollUtil.isNotEmpty(entrustOrder)) { |
| | | for (ContractEntrustOrderEntity contractEntrustOrderEntity : entrustOrder) { |
| | | totalAmount = totalAmount.add(contractEntrustOrderEntity.getEntrustAmount()); |
| | | } |
| | | } |
| | | |
| | | memberWalletContractDao.increaseWalletContractBalanceById(wallet.getAvailableBalance().negate(), wallet.getTotalBalance().subtract(totalAmount).negate(), null, wallet.getId()); |
| | | |
| | | redisUtils.del(AppContants.WHOLE_BOMB_PREFIX + wholePriceData.getMemberId()); |
| | | } else { |
| | | log.info("参数有误:{}", memberEntity.getId()); |
| | | } |
| | | } |
| | | |
| | | @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)) { |
| | | BigDecimal maxLess = BigDecimal.ZERO; |
| | | ContractOrderEntity maxLessEntity = null; |
| | | BigDecimal totalProfitOrLess = BigDecimal.ZERO; |
| | | 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 = 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("无当前持仓"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 1 2 3 |
| | | * 开仓价 - (权益 - 其他币种成本)/当前币种成本 * (开仓价 * 1/杠杆) |
| | | * |
| | | * @param dataModel |
| | | * @param holdOrder |
| | | * @return |
| | | */ |
| | | private BigDecimal getForceSetPrice(WholePriceDataModel dataModel, ContractHoldOrderEntity holdOrder, String currentSymbol) { |
| | | Long memberId = holdOrder.getMemberId(); |
| | | List<ContractHoldOrderEntity> holdOrderEntities = contractHoldOrderDao.selectHoldOrderListForWholeByMemberIdAndSymbol(memberId, null); |
| | | List<String> symbols = contractHoldOrderDao.selectWholeHoldOrderSymbolsByMemberId(memberId); |
| | | |
| | | BigDecimal result = BigDecimal.ZERO; |
| | | if (CollUtil.isNotEmpty(holdOrderEntities)) { |
| | | |
| | | for (String symbol : symbols) { |
| | | // 其他币种成本 |
| | | BigDecimal totalBondAmount = BigDecimal.ZERO; |
| | | // 当前币种保证金 |
| | | BigDecimal symbolBondAmount = BigDecimal.ZERO; |
| | | |
| | | // 开仓均价 |
| | | BigDecimal openPrice = BigDecimal.ZERO; |
| | | // 杠杆 |
| | | int leverRatio = 0; |
| | | boolean isAloneLess = true; |
| | | for (ContractHoldOrderEntity holdOrderEntity : holdOrderEntities) { |
| | | BigDecimal bondAmount = holdOrderEntity.getBondAmount().subtract(holdOrderEntity.getOpeningFeeAmount()); |
| | | |
| | | if (symbol.equalsIgnoreCase(holdOrderEntity.getSymbol())) { |
| | | if (holdOrderEntity.getOpeningType() == ContractHoldOrderEntity.OPENING_TYPE_MORE) { |
| | | isAloneLess = false; |
| | | } |
| | | symbolBondAmount = symbolBondAmount.add(bondAmount.subtract(holdOrderEntity.getOpeningFeeAmount())); |
| | | |
| | | if (openPrice.compareTo(BigDecimal.ZERO) == 0) { |
| | | openPrice = holdOrderEntity.getOpeningPrice(); |
| | | } else { |
| | | openPrice = openPrice.add(holdOrderEntity.getOpeningPrice()).divide(BigDecimal.valueOf(2), 8, BigDecimal.ROUND_DOWN); |
| | | } |
| | | leverRatio = holdOrderEntity.getLeverRatio(); |
| | | } else { |
| | | totalBondAmount = totalBondAmount.add(holdOrderEntity.getBondAmount().subtract(holdOrderEntity.getOpeningFeeAmount())); |
| | | } |
| | | |
| | | } |
| | | |
| | | BigDecimal equity = dataModel.getEquity(); |
| | | BigDecimal sub = equity.subtract(totalBondAmount); |
| | | |
| | | if (sub.compareTo(symbolBondAmount) <= 0) { |
| | | BigDecimal multi = BigDecimal.valueOf(10); |
| | | BigDecimal divide = equity.divide(equity.add(multi), 8, BigDecimal.ROUND_DOWN); |
| | | sub = symbolBondAmount.multiply(divide); |
| | | } |
| | | |
| | | BigDecimal divide = sub.divide(symbolBondAmount, 8, BigDecimal.ROUND_DOWN); |
| | | BigDecimal divide2 = openPrice.divide(BigDecimal.valueOf(leverRatio), 8, BigDecimal.ROUND_DOWN); |
| | | |
| | | BigDecimal forcePrice = BigDecimal.ZERO; |
| | | if (isAloneLess) { |
| | | forcePrice = openPrice.add(divide.multiply(divide2)); |
| | | } else { |
| | | forcePrice = openPrice.subtract(divide.multiply(divide2)); |
| | | } |
| | | |
| | | if (symbol.equalsIgnoreCase(currentSymbol)) { |
| | | result = forcePrice; |
| | | } |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | } |