package com.xcong.excoin.modules.documentary.service.impl;
|
|
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.StrUtil;
|
import com.alibaba.fastjson.JSONObject;
|
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
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.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.FollowFollowerSettingDao;
|
import com.xcong.excoin.modules.documentary.dao.FollowTraderInfoDao;
|
import com.xcong.excoin.modules.documentary.entity.FollowFollowerOrderRelationEntity;
|
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.MemberLevelRateDao;
|
import com.xcong.excoin.modules.member.dao.MemberSettingDao;
|
import com.xcong.excoin.modules.member.dao.MemberWalletContractDao;
|
import com.xcong.excoin.modules.member.entity.*;
|
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 org.springframework.transaction.annotation.Transactional;
|
|
import javax.annotation.Resource;
|
import java.math.BigDecimal;
|
import java.math.RoundingMode;
|
import java.util.ArrayList;
|
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;
|
@Resource
|
private RabbitOrderService rabbitOrderService;
|
@Resource
|
private MemberLevelRateDao memberLevelRateDao;
|
@Resource
|
private MemberSettingDao memberSettingDao;
|
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void addFollowerOrder(Long id) {
|
log.info("进入跟单处理逻辑");
|
// 查询交易员订单
|
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) {
|
|
if (!followerSetting.getSymbols().contains(holdOrderEntity.getSymbol().replace("/USDT", ""))) {
|
log.info("不在跟单币种内,不跟单:{},{}", followerSetting.getSymbols(), holdOrderEntity.getSymbol());
|
continue;
|
}
|
|
// 当前持仓张数
|
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();
|
}
|
|
if (followerSetting.getMaxFollowCnt() != null && followerSetting.getMaxFollowCnt() !=0) {
|
// 若张数+当前持仓张数大于最大持仓张数,则取最大持仓减去当前持仓,若差值小于等于0,则不下单
|
if (symbolCnt + holdingCnt > followerSetting.getMaxFollowCnt()) {
|
symbolCnt = followerSetting.getMaxFollowCnt() - holdingCnt;
|
}
|
|
if (symbolCnt <= 0) {
|
LogRecordUtils.insertFollowerNotice(followerSetting.getMemberId(), NoticeConstant.OPEN_ORDER_FOLLOW_FAIL_TITLE, StrUtil.format(NoticeConstant.OPEN_ORDER_FOLLOW_FAIL_CONTENT, followTraderInfoEntity.getNickname()));
|
continue;
|
}
|
}
|
|
MemberWalletContractEntity walletContract = memberWalletContractDao.findWalletContractByMemberIdAndSymbol(followerSetting.getMemberId(), CoinTypeEnum.USDT.name());
|
if (walletContract == null) {
|
log.info("钱包地址不存在:{}", followerSetting.getMemberId());
|
continue;
|
}
|
MemberLevelRateEntity levelRateEntity = memberLevelRateDao.selectLeverRateByMemberIdAndSymbol(followerSetting.getMemberId(), holdOrderEntity.getSymbol());
|
|
// 开仓手续费 建仓价*规格*手数*手续费率
|
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(levelRateEntity.getLevelRateUp())))
|
.setScale(8, BigDecimal.ROUND_DOWN);
|
|
// 预付款
|
BigDecimal prePaymentAmount = bondAmount.add(openFeePrice).add(openFeePrice);
|
if (prePaymentAmount.compareTo(walletContract.getAvailableBalance()) > -1) {
|
log.info("可用金额不足");
|
LogRecordUtils.insertFollowerNotice(followerSetting.getMemberId(), NoticeConstant.MONEY_NOT_ENOUGH_TITLE, StrUtil.format(NoticeConstant.MONEY_NOT_ENOUGH_CONTENT, followTraderInfoEntity.getNickname()));
|
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.setSymbolCntSale(symbolCnt);
|
followHoldOrder.setSymbolSku(lotNumber);
|
followHoldOrder.setLeverRatio(levelRateEntity.getLevelRateUp());
|
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);
|
// 设置合约类型
|
followHoldOrder.setContractType(ContractOrderEntity.CONTRACTTYPE_DOCUMENTARY);
|
|
ContractOrderEntity contractOrderEntity = ContractHoldOrderEntityMapper.INSTANCE.holdOrderToOrder(followHoldOrder);
|
contractOrderEntity.setOpeningTime(new Date());
|
contractHoldOrderDao.insert(followHoldOrder);
|
int i = contractOrderDao.insert(contractOrderEntity);
|
if (i > 0) {
|
memberWalletContractDao.increaseWalletContractBalanceById(prePaymentAmount.negate(), openFeePrice.negate(), null, walletContract.getId());
|
|
FollowFollowerOrderRelationEntity relationEntity = new FollowFollowerOrderRelationEntity();
|
relationEntity.setIsShow(FollowFollowerOrderRelationEntity.IS_SHOW_Y);
|
relationEntity.setMemberId(followHoldOrder.getMemberId());
|
relationEntity.setOrderId(followHoldOrder.getId());
|
relationEntity.setOrderType(FollowFollowerOrderRelationEntity.ORDER_TYPE_HOLD);
|
relationEntity.setTradeId(followTraderInfoEntity.getId());
|
relationEntity.setTradeMemberId(followTraderInfoEntity.getMemberId());
|
relationEntity.setTradeOrderNo(holdOrderEntity.getOrderNo());
|
followFollowerOrderRelationDao.insert(relationEntity);
|
|
// 发送爆仓消息
|
sendOrderBombMsg(followHoldOrder.getId(), followHoldOrder.getOpeningType(), forceClosingPrice, followHoldOrder.getSymbol(), followHoldOrder.getOperateNo(), followHoldOrder.getMemberId());
|
|
// 计算佣金
|
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()));
|
}
|
//更新更新消息提醒的状态
|
MemberSettingEntity memberSettingEntity = memberSettingDao.selectMemberSettingByMemberId(memberEntity.getId());
|
if(ObjectUtil.isNotEmpty(memberSettingEntity)){
|
memberSettingEntity.setMessageReminder(1);
|
memberSettingDao.updateById(memberSettingEntity);
|
}
|
}
|
}
|
}
|
}
|
|
public void sendOrderBombMsg(Long id, int type, BigDecimal forceClosingPrice, String symbol, int operateNo, Long memberId) {
|
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, memberId);
|
// 开空
|
} else {
|
model = new OrderModel(id, RabbitPriceTypeEnum.CLOSE_LESS_BOMB.getValue(), forceClosingPrice.setScale(8, RoundingMode.HALF_UP).toPlainString(), symbol, operateNo, memberId);
|
}
|
producer.sendPriceOperate(JSONObject.toJSONString(model));
|
}
|
|
|
@Override
|
public void closingFollowOrders(String orderNo) {
|
List<FollowFollowerOrderRelationEntity> orderRelations = followFollowerOrderRelationDao.selectFollowHoldOrderByTradeOrderNo(orderNo);
|
if (CollUtil.isNotEmpty(orderRelations)) {
|
for (FollowFollowerOrderRelationEntity orderRelation : orderRelations) {
|
List<Long> ids= new ArrayList<>();
|
ids.add(orderRelation.getOrderId());
|
rabbitOrderService.cancelHoldOrder(ids);
|
}
|
}
|
}
|
}
|