| | |
| | | package com.yami.trading.service.trader.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.yami.trading.bean.trader.domain.Trader; |
| | | import com.yami.trading.bean.trader.domain.TraderFollowUser; |
| | | import com.yami.trading.bean.trader.domain.TraderFollowUserOrder; |
| | | import com.yami.trading.common.constants.Constants; |
| | | import com.yami.trading.common.exception.BusinessException; |
| | | import com.yami.trading.common.util.Arith; |
| | | import com.yami.trading.common.util.StringUtils; |
| | | import com.yami.trading.dao.trader.TraderFollowUserMapper; |
| | | import com.yami.trading.dao.trader.TraderFollowUserOrderMapper; |
| | | import com.yami.trading.service.FollowWalletService; |
| | | import com.yami.trading.service.WalletService; |
| | | import com.yami.trading.service.trader.FollowCommissionService; |
| | | import com.yami.trading.service.trader.TraderFollowUserOrderService; |
| | | import com.yami.trading.service.trader.TraderFollowUserService; |
| | | import com.yami.trading.service.trader.TraderService; |
| | | import com.yami.trading.service.trader.TraderUserService; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.math.BigDecimal; |
| | | import java.time.Instant; |
| | | import java.math.RoundingMode; |
| | | import java.text.DecimalFormat; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.*; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.util.concurrent.ExecutorService; |
| | | import java.util.concurrent.Executors; |
| | | |
| | | @Service |
| | | public class TraderFollowUserServiceImpl implements TraderFollowUserService { |
| | | private static final ExecutorService STOP_FOLLOW_EXECUTOR = Executors.newFixedThreadPool(4); |
| | | |
| | | private final Set<String> stoppingTasks = ConcurrentHashMap.newKeySet(); |
| | | |
| | | @Resource |
| | | private TraderService traderService; |
| | | @Resource |
| | |
| | | @Resource |
| | | private TraderFollowUserMapper traderFollowUserMapper; |
| | | |
| | | @Resource |
| | | private TraderFollowUserOrderMapper traderFollowUserOrderMapper; |
| | | @Resource |
| | | private FollowWalletService followWalletService; |
| | | @Resource |
| | | private WalletService walletService; |
| | | |
| | | @Resource |
| | | private FollowCommissionService followCommissionService; |
| | | |
| | | @Lazy |
| | | @Resource |
| | | private TraderFollowUserOrderService traderFollowUserOrderService; |
| | | |
| | | public List<Map<String, Object>> getPaged(Page pageparam, String partyId, String profit) { |
| | | |
| | | // StringBuffer queryString = new StringBuffer(""); |
| | | // queryString.append(" SELECT * FROM "); |
| | | // queryString.append(" T_TRADER_FOLLOW_USER "); |
| | | // queryString.append(" where 1=1 "); |
| | | // |
| | | // Map<String, Object> parameters = new HashMap(); |
| | | // |
| | | // queryString.append(" and TRADER_PARTY_ID = :partyId"); |
| | | // parameters.put("partyId", partyId); |
| | | |
| | | // if (!StringUtils.isNullOrEmpty(profit)) { |
| | | // queryString.append(" and PROFIT >= 0 "); |
| | | // } |
| | | // |
| | | // queryString.append(" order by PROFIT desc "); |
| | | Page page = traderFollowUserMapper.selectPage(pageparam, Wrappers.<TraderFollowUser>lambdaQuery().eq(TraderFollowUser::getTraderPartyId, partyId).ge(TraderFollowUser::getProfit, 0).orderByDesc(TraderFollowUser::getProfit)); |
| | | // Page page = this.pagedQueryDao.pagedQuerySQL(pageNo, pageSize, queryString.toString(), parameters); |
| | | Page<TraderFollowUser> page = traderFollowUserMapper.selectPage(pageparam, |
| | | Wrappers.<TraderFollowUser>lambdaQuery() |
| | | .eq(TraderFollowUser::getTraderPartyId, partyId) |
| | | .orderByDesc(TraderFollowUser::getCreateTime) |
| | | .orderByDesc(TraderFollowUser::getUuid)); |
| | | List<Map<String, Object>> data = this.bulidData(page.getRecords()); |
| | | return data; |
| | | } |
| | |
| | | List<Map<String, Object>> result_traders = new ArrayList(); |
| | | DecimalFormat df2 = new DecimalFormat("#.##"); |
| | | df2.setRoundingMode(RoundingMode.FLOOR);// 向下取整 |
| | | SimpleDateFormat tsFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | if (traderFollowUsers == null) { |
| | | return result_traders; |
| | | } |
| | | for (int i = 0; i < traderFollowUsers.size(); i++) { |
| | | Map<String, Object> map = new HashMap<String, Object>(); |
| | | TraderFollowUser entity = traderFollowUsers.get(i); |
| | | map.put("id", entity.getUuid()); |
| | | map.put("name", entity.getUsername()); |
| | | map.put("profit", df2.format(entity.getProfit())); |
| | | map.put("amount_sum", df2.format(entity.getAmountSum())); |
| | | map.put("followState", entity.getState()); |
| | | map.put("symbol", entity.getSymbol()); |
| | | map.put("volume", df2.format(entity.getVolume())); |
| | | map.put("volumeMax", df2.format(entity.getVolumeMax())); |
| | | map.put("lever_rate", entity.getLeverRate() > 0 ? df2.format(entity.getLeverRate()) : ""); |
| | | map.put("followFailReason", entity.getFailReason() != null ? entity.getFailReason() : ""); |
| | | if (entity.getCreateTime() != null) { |
| | | map.put("follow_start_time", tsFmt.format(entity.getCreateTime())); |
| | | } else { |
| | | map.put("follow_start_time", ""); |
| | | } |
| | | map.put("follow_stop_time", formatEpochSecond(entity.getStopFinishTime(), tsFmt)); |
| | | map.put("follow_fail_time", formatEpochSecond(entity.getLastFailTime(), tsFmt)); |
| | | |
| | | result_traders.add(map); |
| | | } |
| | |
| | | |
| | | } |
| | | |
| | | private static String formatEpochSecond(Long sec, SimpleDateFormat tsFmt) { |
| | | if (sec == null || sec <= 0L) { |
| | | return ""; |
| | | } |
| | | return tsFmt.format(new Date(sec * 1000L)); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void save(TraderFollowUser entity, String trader_id) { |
| | | if (entity.getVolume() % 1 != 0 || entity.getVolume() <= 0 || entity.getVolumeMax() % 1 != 0) { |
| | | throw new BusinessException(1, "跟单参数输入错误"); |
| | | } |
| | | if (entity.getFollowType() == "1" && (entity.getVolume() > 3000 || entity.getVolume() < 1)) { |
| | | throw new BusinessException(1, "跟单参数输入错误"); |
| | | } |
| | | if (entity.getFollowType() == "2" && (entity.getVolume() > 5 || entity.getVolume() < 1)) { |
| | | throw new BusinessException(1, "跟单倍数输入错误"); |
| | | } |
| | | validateFollowConfig(entity); |
| | | Trader trader = this.traderService.findById(trader_id); |
| | | if (trader == null) { |
| | | throw new BusinessException(1, "交易员不存在"); |
| | |
| | | if ("0".equals(trader.getState())) { |
| | | throw new BusinessException(1, "交易员未开启带单"); |
| | | } |
| | | if (findByStateAndPartyId(entity.getPartyId(), trader.getPartyId(), "1") != null) { |
| | | throw new BusinessException(1, "用户已跟随交易员"); |
| | | } |
| | | if (Arith.sub(trader.getFollowerMax(), trader.getFollowerNow()) < 1) { |
| | | throw new BusinessException(1, "交易员跟随人数已满"); |
| | | if (trader.getChecked() != 1) { |
| | | throw new BusinessException(1, "交易员审核未通过"); |
| | | } |
| | | if (entity.getPartyId().equals(trader.getPartyId())) { |
| | | throw new BusinessException(1, "交易员不能跟随自己"); |
| | | } |
| | | validateFollowSymbol(entity.getSymbol(), trader.getSymbols()); |
| | | Trader trader_user = this.traderService.findByPartyId(entity.getPartyId()); |
| | | if (trader_user != null) { |
| | | if (trader_user != null && trader_user.getChecked() == 1) { |
| | | throw new BusinessException(1, "交易员无法跟随另一个交易员"); |
| | | } |
| | | // 跟单固定张数/固定比例---选择 1,固定张数,2,固定比例 |
| | | if (trader.getFollowVolumnMin() > 0) { |
| | | switch (entity.getFollowType()) { |
| | | case "1": |
| | | if (entity.getVolume() < trader.getFollowVolumnMin()) { |
| | | throw new BusinessException(1, "跟单参数输入错误"); |
| | | BigDecimal followMin = trader.getFollowVolumnMin(); |
| | | if (followMin != null && followMin.compareTo(BigDecimal.ZERO) > 0) { |
| | | double minVol = followMin.doubleValue(); |
| | | if (entity.getVolume() < minVol || entity.getVolumeMax() < minVol) { |
| | | throw new BusinessException(1, "跟单币数量不能低于交易员设置的最小值"); |
| | | } |
| | | if (entity.getVolumeMax() < trader.getFollowVolumnMin()) { |
| | | throw new BusinessException(1, "跟单参数输入错误"); |
| | | } |
| | | break; |
| | | case "2": |
| | | throw new BusinessException(1, "交易员已设置最小下单数,无法通过固定比例跟单"); |
| | | default: |
| | | break; |
| | | |
| | | TraderFollowUser latest = findByPartyIdAndTrader_partyId(entity.getPartyId(), trader.getPartyId()); |
| | | if (latest != null |
| | | && (TraderFollowUser.STATE_FOLLOWING.equals(latest.getState()) |
| | | || TraderFollowUser.STATE_STOPPING.equals(latest.getState()))) { |
| | | throw new BusinessException(1, "用户已跟随交易员"); |
| | | } |
| | | try { |
| | | followCommissionService.applyMonthlyFeeIfNeeded(trader, latest, entity); |
| | | } catch (BusinessException e) { |
| | | if (isInsufficientBalanceError(e)) { |
| | | recordFollowFailed(entity, trader, e.getMessage(), latest); |
| | | } |
| | | throw e; |
| | | } |
| | | |
| | | entity.setTraderPartyId(trader.getPartyId()); |
| | | entity.setCreateTime(new Date()); |
| | | entity.setFollowType(TraderFollowUser.FOLLOW_TYPE_FIXED); |
| | | entity.setState(TraderFollowUser.STATE_FOLLOWING); |
| | | entity.setInvestAmount(BigDecimal.valueOf(entity.getVolume())); |
| | | entity.setStopRequestTime(null); |
| | | entity.setStopFinishTime(null); |
| | | entity.setFailReason(null); |
| | | entity.setLastFailTime(null); |
| | | |
| | | trader.setFollowerNow((int) Arith.add(trader.getFollowerNow(), 1)); |
| | | long priorSessions = traderFollowUserMapper.selectCount(Wrappers.<TraderFollowUser>lambdaQuery() |
| | | .eq(TraderFollowUser::getTraderPartyId, trader.getPartyId()) |
| | | .eq(TraderFollowUser::getPartyId, entity.getPartyId()) |
| | | .in(TraderFollowUser::getState, TraderFollowUser.STATE_FOLLOWING, TraderFollowUser.STATE_STOPPING, |
| | | TraderFollowUser.STATE_STOPPED)); |
| | | if (priorSessions == 0L) { |
| | | trader.setFollowerSum((int) Arith.add(trader.getFollowerSum(), 1)); |
| | | } |
| | | trader.setFollowerNow((int) Arith.add(trader.getFollowerNow(), 1)); |
| | | traderService.update(trader); |
| | | /** |
| | | * 创建累计用户跟随累计表 |
| | | */ |
| | | traderUserService.saveTraderUserByPartyId(entity.getPartyId()); |
| | | |
| | | // ApplicationUtil.executeSaveOrUpdate(entity); |
| | | if (latest != null) { |
| | | entity.setProfit(latest.getProfit()); |
| | | entity.setAmountSum(latest.getAmountSum()); |
| | | if (entity.getMonthlyFeePaidPeriod() == null) { |
| | | entity.setMonthlyFeePaidPeriod(latest.getMonthlyFeePaidPeriod()); |
| | | } |
| | | } |
| | | entity.setUuid(null); |
| | | traderFollowUserMapper.insert(entity); |
| | | /** |
| | | * 纠正历史脏数据:手动停止跟单时跟单方 saveClose 未同步 T_TRADER_FOLLOW_USER_ORDER 状态, |
| | | * 再次跟单前应把「合约已平仓仍为 submitted」的映射置为 created,否则会占满 volumeMax。 |
| | | */ |
| | | traderFollowUserOrderService.reconcileStaleSubmittedMappings(entity.getPartyId(), entity.getTraderPartyId()); |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public void save(TraderFollowUser entity) { |
| | | if (entity.getFollowType() == null) { |
| | | entity.setFollowType(TraderFollowUser.FOLLOW_TYPE_FIXED); |
| | | } |
| | | if (entity.getState() == null) { |
| | | entity.setState(TraderFollowUser.STATE_FOLLOWING); |
| | | } |
| | | traderFollowUserMapper.insert(entity); |
| | | } |
| | | |
| | | @Override |
| | | public void update(TraderFollowUser entity) { |
| | | if (entity.getVolume() % 1 != 0 || entity.getVolume() <= 0 || entity.getVolumeMax() % 1 != 0) { |
| | | throw new BusinessException(1, "跟单参数输入错误"); |
| | | validateFollowConfig(entity); |
| | | entity.setFollowType(TraderFollowUser.FOLLOW_TYPE_FIXED); |
| | | entity.setInvestAmount(BigDecimal.valueOf(entity.getVolume())); |
| | | TraderFollowUser old = traderFollowUserMapper.selectById(entity.getUuid()); |
| | | if (old != null) { |
| | | Trader trader = this.traderService.findByPartyId(old.getTraderPartyId()); |
| | | if (trader != null) { |
| | | validateFollowSymbol(entity.getSymbol(), trader.getSymbols()); |
| | | } |
| | | if (entity.getFollowType() == "1" && (entity.getVolume() > 3000 || entity.getVolume() < 1)) { |
| | | throw new BusinessException(1, "跟单参数输入错误"); |
| | | } |
| | | if (entity.getFollowType() == "2" && (entity.getVolume() > 5 || entity.getVolume() < 1)) { |
| | | throw new BusinessException(1, "跟单倍数输入错误"); |
| | | } |
| | | |
| | | // ApplicationUtil.executeUpdate(entity); |
| | |
| | | @Override |
| | | public void deleteCancel(String id) { |
| | | TraderFollowUser entity = findById(id); |
| | | if (entity == null) { |
| | | return; |
| | | } |
| | | /** |
| | | * 将旧的交易员跟随用户-1 |
| | | */ |
| | |
| | | |
| | | if (entity != null) { |
| | | // ApplicationUtil.executeDelete(entity); |
| | | traderFollowUserMapper.deleteById(entity); |
| | | traderFollowUserMapper.deleteById(entity.getUuid()); |
| | | } |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public void cancelFollowAsync(String id, com.yami.trading.service.contract.ContractOrderService contractOrderService) { |
| | | TraderFollowUser entity = findById(id); |
| | | if (entity == null || TraderFollowUser.STATE_STOPPED.equals(entity.getState())) { |
| | | return; |
| | | } |
| | | if (TraderFollowUser.STATE_STOPPING.equals(entity.getState()) || !stoppingTasks.add(entity.getUuid())) { |
| | | return; |
| | | } |
| | | entity.setState(TraderFollowUser.STATE_STOPPING); |
| | | entity.setStopRequestTime(Instant.now().getEpochSecond()); |
| | | traderFollowUserMapper.updateById(entity); |
| | | STOP_FOLLOW_EXECUTOR.submit(() -> { |
| | | try { |
| | | List<TraderFollowUserOrder> openOrders = traderFollowUserOrderMapper.selectList( |
| | | Wrappers.<TraderFollowUserOrder>lambdaQuery() |
| | | .eq(TraderFollowUserOrder::getPartyId, entity.getPartyId()) |
| | | .eq(TraderFollowUserOrder::getTraderPartyId, entity.getTraderPartyId()) |
| | | .eq(TraderFollowUserOrder::getState, TraderFollowUserOrder.STATE_SUBMITTED)); |
| | | if (openOrders != null) { |
| | | for (TraderFollowUserOrder openOrder : openOrders) { |
| | | contractOrderService.saveClose(entity.getPartyId(), openOrder.getUserOrderNo()); |
| | | } |
| | | } |
| | | TraderFollowUser latest = findById(id); |
| | | if (latest != null) { |
| | | latest.setState(TraderFollowUser.STATE_STOPPED); |
| | | latest.setStopFinishTime(Instant.now().getEpochSecond()); |
| | | traderFollowUserMapper.updateById(latest); |
| | | refundFollowWalletToMainWallet(latest.getPartyId()); |
| | | Trader trader = this.traderService.findByPartyId(latest.getTraderPartyId()); |
| | | if (trader != null && trader.getFollowerNow() > 0) { |
| | | trader.setFollowerNow((int) Arith.sub(trader.getFollowerNow(), 1)); |
| | | this.traderService.update(trader); |
| | | } |
| | | } |
| | | } finally { |
| | | stoppingTasks.remove(entity.getUuid()); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | public List<TraderFollowUser> findByStateAndPartyId(String partyId, String trader_partyId, String state) { |
| | |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public List<TraderFollowUser> findActiveByTraderPartyId(String trader_partyId) { |
| | | List<TraderFollowUser> list = traderFollowUserMapper.selectList(Wrappers.<TraderFollowUser>lambdaQuery() |
| | | .eq(TraderFollowUser::getTraderPartyId, trader_partyId) |
| | | .eq(TraderFollowUser::getState, TraderFollowUser.STATE_FOLLOWING)); |
| | | if (list.size() > 0) { |
| | | return list; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | public List<TraderFollowUser> findByPartyId(String partyId) { |
| | | List<TraderFollowUser> list = traderFollowUserMapper.selectList(Wrappers.<TraderFollowUser>lambdaQuery().eq(TraderFollowUser::getPartyId, partyId)); |
| | | // List<TraderFollowUser> list = ApplicationUtil.executeSelect(TraderFollowUser.class, " WHERE PARTY_ID = ? ", |
| | |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public long countByPartyId(String partyId) { |
| | | if (StringUtils.isNullOrEmpty(partyId)) { |
| | | return 0L; |
| | | } |
| | | Long c = traderFollowUserMapper.selectCount(Wrappers.<TraderFollowUser>lambdaQuery() |
| | | .eq(TraderFollowUser::getPartyId, partyId)); |
| | | return c == null ? 0L : c.longValue(); |
| | | } |
| | | |
| | | @Override |
| | | public IPage<TraderFollowUser> pageByPartyId(Page<TraderFollowUser> page, String partyId) { |
| | | if (page == null || StringUtils.isNullOrEmpty(partyId)) { |
| | | return page; |
| | | } |
| | | return traderFollowUserMapper.selectPage(page, Wrappers.<TraderFollowUser>lambdaQuery() |
| | | .eq(TraderFollowUser::getPartyId, partyId) |
| | | .orderByDesc(TraderFollowUser::getUpdateTime) |
| | | .orderByDesc(TraderFollowUser::getCreateTime)); |
| | | } |
| | | |
| | | public TraderFollowUser findByPartyIdAndTrader_partyId(String partyId, String trader_partyId) { |
| | | List<TraderFollowUser> list = traderFollowUserMapper.selectList(Wrappers.<TraderFollowUser>lambdaQuery().eq(TraderFollowUser::getPartyId, partyId).eq(TraderFollowUser::getTraderPartyId, trader_partyId)); |
| | | List<TraderFollowUser> list = traderFollowUserMapper.selectList(Wrappers.<TraderFollowUser>lambdaQuery() |
| | | .eq(TraderFollowUser::getPartyId, partyId) |
| | | .eq(TraderFollowUser::getTraderPartyId, trader_partyId) |
| | | .orderByDesc(TraderFollowUser::getCreateTime) |
| | | .orderByDesc(TraderFollowUser::getUuid)); |
| | | // List<TraderFollowUser> list = ApplicationUtil.executeSelect(TraderFollowUser.class, |
| | | // " WHERE PARTY_ID= ? and TRADER_PARTY_ID = ? ", |
| | | // new Object[] { partyId, trader_partyId }); |
| | |
| | | return null; |
| | | } |
| | | |
| | | private boolean isInsufficientBalanceError(BusinessException e) { |
| | | if (e == null || e.getMessage() == null) { |
| | | return false; |
| | | } |
| | | return e.getMessage().contains("余额不足"); |
| | | } |
| | | |
| | | private void recordFollowFailed(TraderFollowUser entity, Trader trader, String reason, TraderFollowUser latest) { |
| | | TraderFollowUser failed = new TraderFollowUser(); |
| | | failed.setPartyId(entity.getPartyId()); |
| | | failed.setUsername(entity.getUsername()); |
| | | failed.setTraderPartyId(trader.getPartyId()); |
| | | failed.setSymbol(entity.getSymbol()); |
| | | failed.setFollowType(TraderFollowUser.FOLLOW_TYPE_FIXED); |
| | | failed.setVolume(entity.getVolume()); |
| | | failed.setVolumeMax(entity.getVolumeMax()); |
| | | failed.setInvestAmount(BigDecimal.valueOf(entity.getVolume())); |
| | | failed.setStopLoss(0D); |
| | | failed.setStopProfit(0D); |
| | | failed.setState(TraderFollowUser.STATE_FAILED); |
| | | failed.setFailReason(reason); |
| | | failed.setLastFailTime(Instant.now().getEpochSecond()); |
| | | failed.setCreateTime(new Date()); |
| | | if (latest != null && TraderFollowUser.STATE_FAILED.equals(latest.getState())) { |
| | | failed.setUuid(latest.getUuid()); |
| | | failed.setProfit(latest.getProfit()); |
| | | failed.setAmountSum(latest.getAmountSum()); |
| | | failed.setMonthlyFeePaidPeriod(latest.getMonthlyFeePaidPeriod()); |
| | | traderFollowUserMapper.updateById(failed); |
| | | return; |
| | | } |
| | | traderFollowUserMapper.insert(failed); |
| | | } |
| | | |
| | | public TraderFollowUser findById(String id) { |
| | | // return ApplicationUtil.executeGet(id, TraderFollowUser.class); |
| | | TraderFollowUser traderFollowUser = traderFollowUserMapper.selectById(id); |
| | | return traderFollowUser; |
| | | } |
| | | |
| | | private void validateFollowConfig(TraderFollowUser entity) { |
| | | entity.setFollowType(TraderFollowUser.FOLLOW_TYPE_FIXED); |
| | | if (entity.getVolume() <= 0 || entity.getVolumeMax() <= 0) { |
| | | throw new BusinessException(1, "跟单参数输入错误"); |
| | | } |
| | | if (entity.getVolumeMax() < entity.getVolume()) { |
| | | throw new BusinessException(1, "最大跟单币数量不能小于最小跟单币数量"); |
| | | } |
| | | if (entity.getStopLoss() < 0 || entity.getStopProfit() < 0) { |
| | | throw new BusinessException(1, "止盈止损参数输入错误"); |
| | | } |
| | | if (entity.getLeverRate() <= 0) { |
| | | throw new BusinessException(1, "杠杆倍数必须大于0"); |
| | | } |
| | | } |
| | | |
| | | private void validateFollowSymbol(String followSymbol, String traderSymbolsRaw) { |
| | | if (followSymbol == null || followSymbol.trim().isEmpty()) { |
| | | throw new BusinessException(1, "请选择跟单币种"); |
| | | } |
| | | String follow = followSymbol.trim(); |
| | | String raw = traderSymbolsRaw == null ? "" : traderSymbolsRaw.trim(); |
| | | if (raw.isEmpty()) { |
| | | throw new BusinessException(1, "交易员未配置带单币种"); |
| | | } |
| | | String[] arr = raw.split("[;;,,]+"); |
| | | for (String one : arr) { |
| | | if (follow.equalsIgnoreCase(one == null ? "" : one.trim())) { |
| | | return; |
| | | } |
| | | } |
| | | throw new BusinessException(1, "只能选择交易员带单币种中的一种进行跟单"); |
| | | } |
| | | |
| | | private void refundFollowWalletToMainWallet(String partyId) { |
| | | if (partyId == null || partyId.trim().isEmpty()) { |
| | | return; |
| | | } |
| | | com.yami.trading.bean.model.FollowWallet followWallet = followWalletService.saveWalletByPartyId(partyId); |
| | | if (followWallet == null || followWallet.getMoney() == null || followWallet.getMoney().compareTo(BigDecimal.ZERO) <= 0) { |
| | | return; |
| | | } |
| | | BigDecimal refund = followWallet.getMoney(); |
| | | walletService.updateMoney("USDT", partyId, refund, BigDecimal.ZERO, |
| | | Constants.MONEYLOG_CATEGORY_CONTRACT, Constants.WALLET_USDT, Constants.MONEYLOG_CONTENT_CONTRACT_CLOSE, |
| | | "停止跟单返还独立跟单账户资金"); |
| | | followWalletService.updateMoney("USDT", partyId, refund.negate(), BigDecimal.ZERO, |
| | | Constants.MONEYLOG_CATEGORY_CONTRACT, Constants.WALLET_USDT, Constants.MONEYLOG_CONTENT_CONTRACT_CLOSE, |
| | | "停止跟单划转资金到主钱包"); |
| | | } |
| | | |
| | | @Override |
| | | public void markFollowOpenFailed(String partyId, String traderPartyId, String reason) { |
| | | if (partyId == null || partyId.trim().isEmpty() || traderPartyId == null || traderPartyId.trim().isEmpty()) { |
| | | return; |
| | | } |
| | | List<TraderFollowUser> list = traderFollowUserMapper.selectList(Wrappers.<TraderFollowUser>lambdaQuery() |
| | | .eq(TraderFollowUser::getPartyId, partyId) |
| | | .eq(TraderFollowUser::getTraderPartyId, traderPartyId) |
| | | .eq(TraderFollowUser::getState, TraderFollowUser.STATE_FOLLOWING) |
| | | .orderByDesc(TraderFollowUser::getCreateTime) |
| | | .last("LIMIT 1")); |
| | | if (list == null || list.isEmpty()) { |
| | | return; |
| | | } |
| | | TraderFollowUser u = list.get(0); |
| | | String msg = reason == null ? "" : reason.trim(); |
| | | if (msg.length() > 900) { |
| | | msg = msg.substring(0, 900) + "…"; |
| | | } |
| | | long nowSec = Instant.now().getEpochSecond(); |
| | | u.setState(TraderFollowUser.STATE_FAILED); |
| | | u.setFailReason(msg); |
| | | u.setLastFailTime(nowSec); |
| | | u.setStopFinishTime(nowSec); |
| | | traderFollowUserMapper.updateById(u); |
| | | Trader trader = this.traderService.findByPartyId(traderPartyId); |
| | | if (trader != null && trader.getFollowerNow() > 0) { |
| | | trader.setFollowerNow((int) Arith.sub(trader.getFollowerNow(), 1)); |
| | | this.traderService.update(trader); |
| | | } |
| | | } |
| | | |
| | | } |