From 79e81397b1bf90e6833db97e4944f8fe7801a669 Mon Sep 17 00:00:00 2001 From: Helius <wangdoubleone@gmail.com> Date: Fri, 31 Jul 2020 17:04:24 +0800 Subject: [PATCH] add submit follower order --- src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerOrderRelationDao.java | 3 src/main/java/com/xcong/excoin/modules/documentary/dao/FollowTraderInfoDao.java | 2 src/main/java/com/xcong/excoin/modules/documentary/service/FollowOrderOperationService.java | 13 ++ src/main/java/com/xcong/excoin/modules/documentary/service/impl/FollowOrderOperationServiceImpl.java | 199 +++++++++++++++++++++++++++++++++++++++ src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerSettingDao.java | 4 src/main/java/com/xcong/excoin/modules/documentary/common/NoticeConstant.java | 13 ++ src/main/resources/mapper/documentary/FollowFollowerSettingDao.xml | 7 + src/main/resources/mapper/documentary/FollowTraderInfoDao.xml | 6 + src/main/java/com/xcong/excoin/utils/LogRecordUtils.java | 20 +++ src/main/resources/mapper/documentary/FollowFollowerOrderRelationDao.xml | 8 + 10 files changed, 273 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/xcong/excoin/modules/documentary/common/NoticeConstant.java b/src/main/java/com/xcong/excoin/modules/documentary/common/NoticeConstant.java new file mode 100644 index 0000000..aae8da4 --- /dev/null +++ b/src/main/java/com/xcong/excoin/modules/documentary/common/NoticeConstant.java @@ -0,0 +1,13 @@ +package com.xcong.excoin.modules.documentary.common; + +/** + * @author wzy + * @date 2020-07-31 + **/ +public class NoticeConstant { + + public static final String OPEN_ORDER_TITLE = "跟单开仓成功"; + + public static final String OPEN_ORDER_CONTENT = "{}开仓成功,开仓价{},交易员{}"; + +} diff --git a/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerOrderRelationDao.java b/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerOrderRelationDao.java index dff3af5..a6c1a0e 100644 --- a/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerOrderRelationDao.java +++ b/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerOrderRelationDao.java @@ -2,9 +2,12 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xcong.excoin.modules.documentary.entity.FollowFollowerOrderRelationEntity; +import io.lettuce.core.dynamic.annotation.Param; /** * @author helius */ public interface FollowFollowerOrderRelationDao extends BaseMapper<FollowFollowerOrderRelationEntity> { + + Integer selectFollowerHoldingSymbolCnt(@Param("tradeMemberId") Long tradeMemberId, @Param("memberId") Long memberId); } diff --git a/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerSettingDao.java b/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerSettingDao.java index aa057fc..f1c028a 100644 --- a/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerSettingDao.java +++ b/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerSettingDao.java @@ -5,6 +5,8 @@ import io.lettuce.core.dynamic.annotation.Param; +import java.util.List; + /** * @author helius */ @@ -13,4 +15,6 @@ FollowFollowerSettingEntity selectDocumentaryOrderSetInfoBymemberId(@Param("memberId")Long memberId); FollowFollowerSettingEntity selectOneBymemberIdAndTradeId(@Param("memberId")Long memberId, @Param("traderId")Long traderId); + + List<FollowFollowerSettingEntity> selectAllFollowerSettingByTradeMemberId(@Param("memberId") Long memberId); } diff --git a/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowTraderInfoDao.java b/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowTraderInfoDao.java index 2e452cd..6daeec0 100644 --- a/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowTraderInfoDao.java +++ b/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowTraderInfoDao.java @@ -9,4 +9,6 @@ FollowTraderInfoEntity selectFollowTraderInfoEntityBytreaderId(@Param("traderId")Long traderId); + FollowTraderInfoEntity selectTraderInfoByMemberId(@Param("memberId") Long memberId); + } diff --git a/src/main/java/com/xcong/excoin/modules/documentary/service/FollowOrderOperationService.java b/src/main/java/com/xcong/excoin/modules/documentary/service/FollowOrderOperationService.java new file mode 100644 index 0000000..2686947 --- /dev/null +++ b/src/main/java/com/xcong/excoin/modules/documentary/service/FollowOrderOperationService.java @@ -0,0 +1,13 @@ +package com.xcong.excoin.modules.documentary.service; + + +import com.xcong.excoin.modules.contract.entity.ContractHoldOrderEntity; + +/** + * @author helius + */ +public interface FollowOrderOperationService { + + + public void addFollowerOrder(Long id); +} diff --git a/src/main/java/com/xcong/excoin/modules/documentary/service/impl/FollowOrderOperationServiceImpl.java b/src/main/java/com/xcong/excoin/modules/documentary/service/impl/FollowOrderOperationServiceImpl.java new file mode 100644 index 0000000..93c91f9 --- /dev/null +++ b/src/main/java/com/xcong/excoin/modules/documentary/service/impl/FollowOrderOperationServiceImpl.java @@ -0,0 +1,199 @@ +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)); + } +} diff --git a/src/main/java/com/xcong/excoin/utils/LogRecordUtils.java b/src/main/java/com/xcong/excoin/utils/LogRecordUtils.java index 6bf4189..1722f78 100644 --- a/src/main/java/com/xcong/excoin/utils/LogRecordUtils.java +++ b/src/main/java/com/xcong/excoin/utils/LogRecordUtils.java @@ -4,6 +4,8 @@ import com.xcong.excoin.modules.coin.dao.MemberAccountMoneyChangeDao; import com.xcong.excoin.modules.coin.entity.MemberAccountFlowEntity; import com.xcong.excoin.modules.coin.entity.MemberAccountMoneyChange; +import com.xcong.excoin.modules.documentary.dao.FollowFollowerNoticeDao; +import com.xcong.excoin.modules.documentary.entity.FollowFollowerNoticeEntity; import java.math.BigDecimal; @@ -15,7 +17,7 @@ **/ public class LogRecordUtils { - public static void insertMemberAccountMoneyChange(Long memberId,String content, BigDecimal amount, String symbol, Integer status, Integer type) { + public static void insertMemberAccountMoneyChange(Long memberId, String content, BigDecimal amount, String symbol, Integer status, Integer type) { MemberAccountMoneyChange accountRecord = new MemberAccountMoneyChange(); accountRecord.setContent(content); accountRecord.setMemberId(memberId); @@ -36,4 +38,20 @@ memberAccountFlowEntity.setRemark(remark); SpringContextHolder.getBean(MemberAccountFlowEntityDao.class).insert(memberAccountFlowEntity); } + + /** + * 插入跟随者消息 + * + * @param memberId 跟随者用户ID + * @param title 消息标题 + * @param content 消息内容 + */ + public static void insertFollowerNotice(Long memberId, String title, String content) { + FollowFollowerNoticeEntity noticeEntity = new FollowFollowerNoticeEntity(); + noticeEntity.setMemberId(memberId); + noticeEntity.setTitle(title); + noticeEntity.setContent(content); + SpringContextHolder.getBean(FollowFollowerNoticeDao.class).insert(noticeEntity); + } + } diff --git a/src/main/resources/mapper/documentary/FollowFollowerOrderRelationDao.xml b/src/main/resources/mapper/documentary/FollowFollowerOrderRelationDao.xml index c546474..f24dcfb 100644 --- a/src/main/resources/mapper/documentary/FollowFollowerOrderRelationDao.xml +++ b/src/main/resources/mapper/documentary/FollowFollowerOrderRelationDao.xml @@ -2,4 +2,12 @@ <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.xcong.excoin.modules.documentary.dao.FollowFollowerOrderRelationDao"> + + <select id="selectFollowerHoldingSymbolCnt" resultType="java.lang.Integer"> + select + IFNULL(sum(b.symbol_cnt),0) + from follow_follower_order_relation a, contract_hold_order b + where a.order_id=b.id and a.order_type=1 and a.trade_member_id=#{tradeMemberId} + and a.member_id=#{memberId} + </select> </mapper> \ No newline at end of file diff --git a/src/main/resources/mapper/documentary/FollowFollowerSettingDao.xml b/src/main/resources/mapper/documentary/FollowFollowerSettingDao.xml index d7a9724..eafdf2e 100644 --- a/src/main/resources/mapper/documentary/FollowFollowerSettingDao.xml +++ b/src/main/resources/mapper/documentary/FollowFollowerSettingDao.xml @@ -18,4 +18,11 @@ member_id = #{memberId} and trader_id = #{traderId} </select> + + + <select id="selectAllFollowerSettingByTradeMemberId" resultType="com.xcong.excoin.modules.documentary.entity.FollowFollowerSettingEntity"> + select * from follow_follower_setting + where trader_member_id=#{memberId} + </select> + </mapper> \ No newline at end of file diff --git a/src/main/resources/mapper/documentary/FollowTraderInfoDao.xml b/src/main/resources/mapper/documentary/FollowTraderInfoDao.xml index 268e65b..aee0491 100644 --- a/src/main/resources/mapper/documentary/FollowTraderInfoDao.xml +++ b/src/main/resources/mapper/documentary/FollowTraderInfoDao.xml @@ -5,5 +5,9 @@ <select id="selectFollowTraderInfoEntityBytreaderId" resultType="com.xcong.excoin.modules.documentary.entity.FollowTraderInfoEntity"> select * from follow_trader_info where id = #{traderId} </select> - + + + <select id="selectTraderInfoByMemberId" resultType="com.xcong.excoin.modules.documentary.entity.FollowTraderInfoEntity"> + select * from follow_trader_info where member_id=#{memberId} + </select> </mapper> \ No newline at end of file -- Gitblit v1.9.1