New file |
| | |
| | | package com.xcong.excoin.modules.documentary.service.impl; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.xcong.excoin.common.enumerates.CoinTypeEnum; |
| | | import com.xcong.excoin.common.enumerates.RabbitPriceTypeEnum; |
| | | import com.xcong.excoin.common.response.Result; |
| | | import com.xcong.excoin.common.system.service.CommonService; |
| | | 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.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.FollowFollowerSettingDao; |
| | | import com.xcong.excoin.modules.documentary.dao.FollowTraderInfoDao; |
| | | import com.xcong.excoin.modules.documentary.entity.FollowFollowerProfitEntity; |
| | | import com.xcong.excoin.modules.documentary.entity.FollowFollowerSettingEntity; |
| | | import com.xcong.excoin.modules.documentary.entity.FollowTraderInfoEntity; |
| | | import com.xcong.excoin.modules.documentary.service.FollowOrderOperationService; |
| | | import com.xcong.excoin.modules.member.dao.MemberDao; |
| | | 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.MemberWalletContractEntity; |
| | | import com.xcong.excoin.modules.platform.entity.PlatformTradeSettingEntity; |
| | | import com.xcong.excoin.rabbit.pricequeue.OrderModel; |
| | | import com.xcong.excoin.rabbit.producer.OrderProducer; |
| | | import com.xcong.excoin.utils.CacheSettingUtils; |
| | | import com.xcong.excoin.utils.CalculateUtil; |
| | | import com.xcong.excoin.utils.LogRecordUtils; |
| | | import com.xcong.excoin.utils.ThreadPoolUtils; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author helius |
| | | */ |
| | | @Slf4j |
| | | @Service |
| | | public class FollowOrderOperationServiceImpl implements FollowOrderOperationService { |
| | | |
| | | @Resource |
| | | private ContractHoldOrderDao contractHoldOrderDao; |
| | | @Resource |
| | | private FollowFollowerSettingDao followFollowerSettingDao; |
| | | @Resource |
| | | private CacheSettingUtils cacheSettingUtils; |
| | | @Resource |
| | | private FollowFollowerOrderRelationDao followFollowerOrderRelationDao; |
| | | @Resource |
| | | private MemberWalletContractDao memberWalletContractDao; |
| | | @Resource |
| | | private MemberDao memberDao; |
| | | @Resource |
| | | private CommonService commonService; |
| | | @Resource |
| | | private ContractOrderDao contractOrderDao; |
| | | @Resource |
| | | private OrderProducer producer; |
| | | @Resource |
| | | private FollowTraderInfoDao followTraderInfoDao; |
| | | |
| | | @Override |
| | | public void addFollowerOrder(Long id) { |
| | | // 查询交易员订单 |
| | | ContractHoldOrderEntity holdOrderEntity = contractHoldOrderDao.selectById(id); |
| | | |
| | | List<FollowFollowerSettingEntity> followerSettings = followFollowerSettingDao.selectAllFollowerSettingByTradeMemberId(holdOrderEntity.getMemberId()); |
| | | // 开仓价 |
| | | BigDecimal openPrice = holdOrderEntity.getOpeningPrice(); |
| | | PlatformTradeSettingEntity tradeSettingEntity = cacheSettingUtils.getTradeSetting(); |
| | | |
| | | // 交易员信息 |
| | | FollowTraderInfoEntity followTraderInfoEntity = followTraderInfoDao.selectTraderInfoByMemberId(holdOrderEntity.getMemberId()); |
| | | |
| | | // 点差 |
| | | BigDecimal lotNumber = cacheSettingUtils.getSymbolSku(holdOrderEntity.getSymbol()); |
| | | Long tradeMemberId = holdOrderEntity.getMemberId(); |
| | | if (CollUtil.isNotEmpty(followerSettings)) { |
| | | for (FollowFollowerSettingEntity followerSetting : followerSettings) { |
| | | // 当前持仓张数 |
| | | Integer holdingCnt = followFollowerOrderRelationDao.selectFollowerHoldingSymbolCnt(tradeMemberId, followerSetting.getMemberId()); |
| | | |
| | | // 跟单张数 根据跟随者设置,若为固定张数,则为其固定张数,若为固定比例,则与交易员张数相乘。但必须小于最大持仓张数 |
| | | int symbolCnt = 0; |
| | | if (followerSetting.getFollowType().equals(FollowFollowerSettingEntity.FOLLOW_TYPE_PIECE)) { |
| | | symbolCnt = followerSetting.getFollowCnt(); |
| | | } else { |
| | | symbolCnt = followerSetting.getFollowCnt() * holdOrderEntity.getSymbolCnt(); |
| | | } |
| | | |
| | | // 若张数+当前持仓张数大于最大持仓张数,则取最大持仓减去当前持仓,若差值小于等于0,则不下单 |
| | | if (symbolCnt + holdingCnt> followerSetting.getMaxFollowCnt()) { |
| | | symbolCnt = followerSetting.getMaxFollowCnt() - holdingCnt; |
| | | } |
| | | |
| | | if (symbolCnt <= 0) { |
| | | continue; |
| | | } |
| | | |
| | | MemberWalletContractEntity walletContract = memberWalletContractDao.findWalletContractByMemberIdAndSymbol(followerSetting.getMemberId(), CoinTypeEnum.USDT.name()); |
| | | if (walletContract == null) { |
| | | log.info("钱包地址不存在:{}", followerSetting.getMemberId()); |
| | | continue; |
| | | } |
| | | |
| | | // 开仓手续费 建仓价*规格*手数*手续费率 |
| | | BigDecimal openFeePrice = openPrice.multiply(lotNumber) |
| | | .multiply(new BigDecimal(symbolCnt)) |
| | | .multiply(tradeSettingEntity.getFeeRatio().divide(new BigDecimal(100))) |
| | | .setScale(8, BigDecimal.ROUND_DOWN); |
| | | |
| | | // 保证金 |
| | | BigDecimal bondAmount = openPrice.multiply(lotNumber).multiply(new BigDecimal(symbolCnt)) |
| | | .multiply(BigDecimal.ONE.divide(new BigDecimal(holdOrderEntity.getLeverRatio()))) |
| | | .setScale(8, BigDecimal.ROUND_DOWN); |
| | | |
| | | // 预付款 |
| | | BigDecimal prePaymentAmount = bondAmount.add(openFeePrice).add(openFeePrice); |
| | | if (prePaymentAmount.compareTo(walletContract.getAvailableBalance()) > -1) { |
| | | log.info("可用金额不足"); |
| | | continue; |
| | | } |
| | | |
| | | MemberEntity memberEntity = memberDao.selectById(followerSetting.getMemberId()); |
| | | // 强平价 |
| | | BigDecimal forceClosingPrice = CalculateUtil.getForceSetPrice(bondAmount, openPrice, symbolCnt, lotNumber, holdOrderEntity.getOpeningType(), memberEntity); |
| | | |
| | | ContractHoldOrderEntity followHoldOrder = new ContractHoldOrderEntity(); |
| | | followHoldOrder.setMemberId(memberEntity.getId()); |
| | | followHoldOrder.setOrderNo(commonService.generateOrderNo(memberEntity.getId())); |
| | | followHoldOrder.setPositionType(ContractEntrustOrderEntity.POSITION_TYPE_ADD); |
| | | followHoldOrder.setTradeType(ContractHoldOrderEntity.TRADE_TYPE_MARK); |
| | | followHoldOrder.setSymbol(holdOrderEntity.getSymbol()); |
| | | followHoldOrder.setSymbolCnt(symbolCnt); |
| | | followHoldOrder.setSymbolSku(lotNumber); |
| | | followHoldOrder.setLeverRatio(holdOrderEntity.getLeverRatio()); |
| | | followHoldOrder.setForceClosingPrice(forceClosingPrice); |
| | | followHoldOrder.setOpeningFeeAmount(openFeePrice); |
| | | followHoldOrder.setOpeningPrice(openPrice); |
| | | followHoldOrder.setOpeningType(holdOrderEntity.getOpeningType()); |
| | | followHoldOrder.setMarkPrice(openPrice); |
| | | followHoldOrder.setIsCanClosing(ContractHoldOrderEntity.ORDER_CAN_CLOSING_Y); |
| | | followHoldOrder.setPrePaymentAmount(prePaymentAmount); |
| | | followHoldOrder.setBondAmount(bondAmount.add(openFeePrice)); |
| | | followHoldOrder.setOperateNo(1); |
| | | // 设置合约类型 |
| | | holdOrderEntity.setContractType(ContractOrderEntity.CONTRACTTYPE_DOCUMENTARY); |
| | | |
| | | ContractOrderEntity contractOrderEntity = ContractHoldOrderEntityMapper.INSTANCE.holdOrderToOrder(holdOrderEntity); |
| | | contractOrderEntity.setOpeningTime(new Date()); |
| | | contractHoldOrderDao.insert(holdOrderEntity); |
| | | int i = contractOrderDao.insert(contractOrderEntity); |
| | | |
| | | if (i > 0) { |
| | | memberWalletContractDao.increaseWalletContractBalanceById(prePaymentAmount.negate(), openFeePrice.negate(), null, walletContract.getId()); |
| | | |
| | | // 发送爆仓消息 |
| | | sendOrderBombMsg(holdOrderEntity.getId(), holdOrderEntity.getOpeningType(), forceClosingPrice, holdOrderEntity.getSymbol(), holdOrderEntity.getOperateNo()); |
| | | |
| | | // 计算佣金 |
| | | ThreadPoolUtils.calReturnMoney(memberEntity.getId(), contractOrderEntity.getOpeningFeeAmount(), contractOrderEntity, AgentReturnEntity.ORDER_TYPE_OPEN); |
| | | |
| | | // 插入财务流水 |
| | | if (holdOrderEntity.getOpeningType() == ContractHoldOrderEntity.OPENING_TYPE_MORE) { |
| | | LogRecordUtils.insertMemberAccountFlow(memberEntity.getId(), prePaymentAmount, walletContract.getAvailableBalance().subtract(prePaymentAmount), holdOrderEntity.getSymbol(), "买涨持仓", "买涨:" + holdOrderEntity.getSymbol()); |
| | | LogRecordUtils.insertFollowerNotice(memberEntity.getId(), NoticeConstant.OPEN_ORDER_TITLE, StrUtil.format(NoticeConstant.OPEN_ORDER_CONTENT, holdOrderEntity.getSymbol() + "开多", openPrice, followTraderInfoEntity.getNickname())); |
| | | } else { |
| | | LogRecordUtils.insertMemberAccountFlow(memberEntity.getId(), prePaymentAmount, walletContract.getAvailableBalance().subtract(prePaymentAmount), holdOrderEntity.getSymbol(), "买跌持仓", "买跌:" + holdOrderEntity.getSymbol()); |
| | | LogRecordUtils.insertFollowerNotice(memberEntity.getId(), NoticeConstant.OPEN_ORDER_TITLE, StrUtil.format(NoticeConstant.OPEN_ORDER_CONTENT, holdOrderEntity.getSymbol() + "开空", openPrice, followTraderInfoEntity.getNickname())); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | public void sendOrderBombMsg(Long id, int type, BigDecimal forceClosingPrice, String symbol, int operateNo) { |
| | | OrderModel model = null; |
| | | // 开多 |
| | | if (ContractHoldOrderEntity.OPENING_TYPE_MORE == type) { |
| | | model = new OrderModel(id, RabbitPriceTypeEnum.CLOSE_MORE_BOMB.getValue(), forceClosingPrice.setScale(8, RoundingMode.HALF_UP).toPlainString(), symbol, operateNo); |
| | | // 开空 |
| | | } else { |
| | | model = new OrderModel(id, RabbitPriceTypeEnum.CLOSE_LESS_BOMB.getValue(), forceClosingPrice.setScale(8, RoundingMode.HALF_UP).toPlainString(), symbol, operateNo); |
| | | } |
| | | producer.sendPriceOperate(JSONObject.toJSONString(model)); |
| | | } |
| | | } |