| | |
| | | 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.MemberWalletCoinEnum; |
| | | 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.coin.entity.MemberAccountMoneyChange; |
| | | import com.xcong.excoin.modules.contract.dao.ContractEntrustOrderDao; |
| | | import com.xcong.excoin.modules.contract.dao.ContractHoldOrderDao; |
| | | import com.xcong.excoin.modules.contract.dao.ContractOrderDao; |
| | |
| | | if (ids.size() == 1) { |
| | | ContractHoldOrderEntity holdOrderEntity = contractHoldOrderDao.selectById(ids.get(0)); |
| | | |
| | | // 判断仓位类型是否逐仓 |
| | | if (holdOrderEntity.getPositionType() == ContractEntrustOrderEntity.POSITION_TYPE_ADD) { |
| | | // 逐仓平仓 |
| | | cancelHoldOrderMethod(holdOrderEntity); |
| | | if (holdOrderEntity != null) { |
| | | // 判断仓位类型是否逐仓 |
| | | if (holdOrderEntity.getPositionType() == ContractEntrustOrderEntity.POSITION_TYPE_ADD) { |
| | | // 逐仓平仓 |
| | | cancelHoldOrderMethod(holdOrderEntity); |
| | | } else { |
| | | // 全仓模式平仓 |
| | | closingWholeOrder(holdOrderEntity); |
| | | } |
| | | } else { |
| | | // 全仓模式平仓 |
| | | closingWholeOrder(holdOrderEntity); |
| | | log.info("持仓订单为空: {}", ids.get(0)); |
| | | } |
| | | } else { |
| | | List<ContractHoldOrderEntity> holdOrderEntities = contractHoldOrderDao.selectBatchIds(ids); |
| | | if (CollUtil.isNotEmpty(holdOrderEntities)) { |
| | | for (ContractHoldOrderEntity holdOrder : holdOrderEntities) { |
| | | cancelHoldOrderMethod(holdOrder); |
| | | // 判断仓位类型是否逐仓 |
| | | if (holdOrder.getPositionType() == ContractEntrustOrderEntity.POSITION_TYPE_ADD) { |
| | | // 逐仓平仓 |
| | | cancelHoldOrderMethod(holdOrder); |
| | | } else { |
| | | // 全仓模式平仓 |
| | | closingWholeOrder(holdOrder); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | MemberWalletContractEntity traderWallet = memberWalletContractDao.findWalletContractByMemberIdAndSymbol(traderInfoEntity.getMemberId(), CoinTypeEnum.USDT.name()); |
| | | memberWalletContractDao.increaseWalletContractBalanceById(returnMoney, returnMoney, null, traderWallet.getId()); |
| | | insertReturnProfitDetail(traderInfoEntity.getMemberId(), memberEntity.getId(), returnMoney, holdOrderEntity.getOrderNo()); |
| | | //增加返佣提醒 |
| | | // String orderNo = holdOrderEntity.getOrderNo(); |
| | | // LogRecordUtils.insertFollowerNotice(traderInfoEntity.getMemberId(), |
| | | // NoticeConstant.RETURN_MONEY_TITLE, |
| | | // StrUtil.format(NoticeConstant.RETURN_MONEY_CONTENT, |
| | | // orderNo, |
| | | // holdOrderEntity.getSymbol(), |
| | | // returnMoney.setScale(2, BigDecimal.ROUND_HALF_UP).toString())); |
| | | // //带单返利的记录要在资产页面的其他记录 |
| | | // LogRecordUtils.insertMemberAccountMoneyChange( |
| | | // traderInfoEntity.getMemberId(), |
| | | // StrUtil.format(NoticeConstant.RETURN_MONEY_CONTENT_MAMC, |
| | | // orderNo, |
| | | // holdOrderEntity.getSymbol(), |
| | | // returnMoney.setScale(2, BigDecimal.ROUND_HALF_UP).toString()), |
| | | // returnMoney.setScale(2, BigDecimal.ROUND_HALF_UP), |
| | | // MemberWalletCoinEnum.WALLETCOINCODE.getValue(), |
| | | // MemberAccountMoneyChange.STATUS_SUCCESS_INTEGER, |
| | | // MemberAccountMoneyChange.TYPE_WALLET_AGENT); |
| | | } |
| | | } |
| | | } |
| | |
| | | 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())); |
| | | //followFollowerProfitDao.updateFollowerProfitByTradeMemberId(holdOrderEntity.getBondAmount(), profitOrLoss, traderInfoEntity.getMemberId(), memberEntity.getId()); |
| | | LogRecordUtils.insertFollowerNotice(memberEntity.getId(), NoticeConstant.CLOSE_ORDER_TITLE, StrUtil.format(NoticeConstant.CLOSE_ORDER_CONTENT, contractOrderEntity.getSymbol(), contractOrderEntity.getClosingPrice().setScale(2, BigDecimal.ROUND_HALF_UP).toString(), profitOrLoss.setScale(2, BigDecimal.ROUND_HALF_UP).toString(), traderInfoEntity.getNickname())); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | // 获取平仓张数 |
| | | Integer closeCnt = (Integer) redisUtils.get(AppContants.CLOSING_ORDER_PREFIX + holdOrderEntity.getId()); |
| | | // 无法从redis中获取平仓张数,说明来自一键平仓 |
| | | if (closeCnt == null) { |
| | | closeCnt = holdOrderEntity.getSymbolCntSale(); |
| | | holdOrderEntity.setSymbolCntSale(0); |
| | | } |
| | | |
| | | MemberSettingEntity memberSettingEntity = memberSettingDao.selectMemberSettingByMemberId(memberEntity.getId()); |
| | | // 开多 |
| | |
| | | } |
| | | log.info("profitOrLoss:{}", profitOrLoss); |
| | | |
| | | BigDecimal rewardRatio = profitOrLoss.divide(holdOrderEntity.getBondAmount().subtract(holdOrderEntity.getOpeningFeeAmount()), 4, BigDecimal.ROUND_DOWN); |
| | | // 保证金 |
| | | BigDecimal bondAmount = CalculateUtil.getBondAmount(holdOrderEntity.getOpeningPrice(), lotNumber, closeCnt, holdOrderEntity.getLeverRatio()); |
| | | |
| | |
| | | contractOrderEntity.setClosingType(closingType); |
| | | contractOrderEntity.setSymbolCnt(closeCnt); |
| | | contractOrderEntity.setRewardAmount(profitOrLoss); |
| | | contractOrderEntity.setRewardRatio(rewardRatio); |
| | | contractOrderEntity.setBondAmount(bondAmount.add(fee)); |
| | | contractOrderEntity.setClosingFeeAmount(fee); |
| | | contractOrderEntity.setClosingTime(new Date()); |
| | |
| | | contractOrderEntity.setEntrustOpeningPrice(newPrice); |
| | | contractOrderEntity.setEntrustTime(new Date()); |
| | | contractOrderEntity.setClosingPrice(newPrice); |
| | | contractOrderEntity.setOrderType(orderType); |
| | | contractOrderEntity.setTradeType(ContractOrderEntity.TRADE_TYPE_LIMIT_PRICE); |
| | | contractOrderEntity.setOrderType(entrustOrder.getEntrustType()); |
| | | contractOrderEntity.setClosingType(closingType); |
| | | contractOrderEntity.setSymbolCnt(closeCnt); |
| | | contractOrderEntity.setRewardAmount(profitOrLoss); |
| | | contractOrderEntity.setBondAmount(bondAmount); |
| | | contractOrderEntity.setClosingTime(new Date()); |
| | | contractOrderEntity.setClosingFeeAmount(fee); |
| | | contractOrderDao.insert(contractOrderEntity); |
| | | |
| | |
| | | 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)); |
| | | // holdOrderEntity.setForceClosingPrice(getForceSetPrice(wholePriceData, holdOrderEntity, holdOrderDataModel.getSymbol())); |
| | | contractHoldOrderDao.deleteById(holdOrderDataModel.getId()); |
| | | |
| | | ContractOrderEntity contractOrderEntity = ContractHoldOrderEntityMapper.INSTANCE.holdOrderToOrder(holdOrderEntity); |
| | |
| | | |
| | | BigDecimal rewardRatio = holdOrderDataModel.getRewardAmount().divide(holdOrderEntity.getBondAmount().subtract(holdOrderEntity.getOpeningFeeAmount()), 8, BigDecimal.ROUND_DOWN); |
| | | contractOrderEntity.setRewardRatio(rewardRatio); |
| | | contractOrderEntity.setRewardAmount(holdOrderDataModel.getRewardAmount().add(contractOrderEntity.getBondAmount().subtract(contractOrderEntity.getOpeningFeeAmount()).negate())); |
| | | 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_LESS); |
| | | } |
| | | contractOrderEntity.setClosingTime(new Date()); |
| | | |
| | | contractOrderEntity.setBatchNo(batchNo); |
| | | contractOrderDao.insert(contractOrderEntity); |
| | | } |
| | | |
| | |
| | | BigDecimal totalAmount = BigDecimal.ZERO; |
| | | if (CollUtil.isNotEmpty(entrustOrder)) { |
| | | for (ContractEntrustOrderEntity contractEntrustOrderEntity : entrustOrder) { |
| | | totalAmount.add(contractEntrustOrderEntity.getEntrustAmount()); |
| | | 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()); |
| | | } |
| | |
| | | * @param holdOrder |
| | | * @return |
| | | */ |
| | | private BigDecimal getForceSetPrice(WholePriceDataModel dataModel, ContractHoldOrderEntity holdOrder) { |
| | | return holdOrder.getOpeningPrice().subtract(holdOrder.getOpeningPrice().multiply(BigDecimal.ONE.divide(new BigDecimal(holdOrder.getLeverRatio()), 8, BigDecimal.ROUND_DOWN))); |
| | | 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; |
| | | } |
| | | } |