package com.xcong.excoin.modules.contract.service.impl;
|
|
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.util.StrUtil;
|
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.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.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.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.Date;
|
import java.util.List;
|
|
/**
|
* @author wzy
|
* @date 2020-06-01
|
**/
|
@Slf4j
|
@Service
|
public class RabbitOrderServiceImpl implements RabbitOrderService {
|
|
@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 FollowFollowerOrderRelationDao followFollowerOrderRelationDao;
|
@Resource
|
private FollowOrderOperationService followOrderOperationService;
|
@Resource
|
private FollowTraderInfoDao followTraderInfoDao;
|
@Resource
|
private FollowTraderProfitDetailDao followTraderProfitDetailDao;
|
@Resource
|
private FollowFollowerProfitDao followFollowerProfitDao;
|
|
@Transactional(rollbackFor = Exception.class)
|
@Override
|
public void cancelHoldOrder(List<Long> ids) {
|
if (CollUtil.isNotEmpty(ids)) {
|
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();
|
// 获取最新价
|
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) {
|
// 删除持仓表订单
|
contractHoldOrderDao.deleteById(holdOrderEntity.getId());
|
|
BigDecimal lotNumber = cacheSettingUtils.getSymbolSku(symbol);
|
// 盈亏
|
BigDecimal profitOrLoss = BigDecimal.ZERO;
|
Integer orderType = null;
|
Integer closingType = null;
|
// 开多
|
if (ContractHoldOrderEntity.OPENING_TYPE_MORE == holdOrderEntity.getOpeningType()) {
|
newPrice = newPrice.multiply(BigDecimal.ONE.subtract(memberEntity.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(memberEntity.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;
|
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()));
|
}
|
}
|
|
// 盈亏比例(回报率)
|
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);
|
contractOrderEntity.setClosingPrice(newPrice);
|
contractOrderEntity.setClosingFeeAmount(holdOrderEntity.getOpeningFeeAmount());
|
contractOrderEntity.setClosingTime(new Date());
|
contractOrderEntity.setClosingType(closingType);
|
contractOrderEntity.setRewardAmount(profitOrLoss);
|
contractOrderEntity.setRewardRatio(rewardRatio);
|
contractOrderDao.insert(contractOrderEntity);
|
|
// 计算盈利或亏损后可用金额和总金额应该增加或减少的
|
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 contractHoldOrderEntity) {
|
|
}
|
}
|