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();
|
}
|
|
if (followerSetting.getMaxFollowCnt() != null && followerSetting.getMaxFollowCnt() !=0) {
|
// 若张数+当前持仓张数大于最大持仓张数,则取最大持仓减去当前持仓,若差值小于等于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));
|
}
|
}
|