package com.nq.service.impl; import cn.hutool.core.convert.Convert; import cn.hutool.core.date.DateUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.nq.dao.*; import com.nq.enums.EConfigKey; import com.nq.enums.EStockType; import com.nq.enums.EUserAssets; import com.nq.pojo.*; import com.nq.service.*; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.google.common.collect.Lists; import com.nq.common.ServerResponse; import com.nq.utils.*; import com.nq.utils.redis.RedisKeyUtil; import com.nq.utils.stock.BuyAndSellUtils; import com.nq.utils.stock.GeneratePosition; import com.nq.utils.stock.GetStayDays; import com.nq.utils.stock.pinyin.GetPyByChinese; import com.nq.utils.stock.sina.StockApi; import com.nq.utils.timeutil.DateTimeUtil; import com.nq.vo.agent.AgentIncomeVO; import com.nq.vo.position.AdminPositionVO; import com.nq.vo.position.AgentPositionVO; import com.nq.vo.position.PositionProfitVO; import com.nq.vo.position.PositionVO; import com.nq.vo.position.UserPositionVO; import com.nq.vo.stock.StockListVO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.sql.Timestamp; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; @Service("iUserPositionService") public class UserPositionServiceImpl implements IUserPositionService { private static final Logger log = LoggerFactory.getLogger(UserPositionServiceImpl.class); @Resource UserPositionMapper userPositionMapper; @Autowired IUserService iUserService; @Autowired IUserAssetsServices userAssetsServices; @Autowired UserAssetsMapper userAssetsMapper; @Autowired ISiteSettingService iSiteSettingService; @Autowired ISiteSpreadService iSiteSpreadService; @Autowired IStockService iStockService; @Resource UserMapper userMapper; @Resource UserCashDetailMapper userCashDetailMapper; @Autowired IAgentUserService iAgentUserService; @Resource AgentUserMapper agentUserMapper; @Resource SiteTaskLogMapper siteTaskLogMapper; @Autowired StockMapper stockMapper; @Autowired AgentAgencyFeeMapper agentAgencyFeeMapper; @Autowired IAgentAgencyFeeService iAgentAgencyFeeService; @Autowired ISiteProductService iSiteProductService; @Autowired FundsApplyMapper fundsApplyMapper; @Autowired UserStockSubscribeMapper userStockSubscribeMapper; @Resource StockSubscribeMapper stockSubscribeMapper; @Resource UserIndexPositionMapper userIndexPositionMapper; @Autowired IStockFuturesService iStockFuturesService; @Autowired IStockCoinService iStockCoinService; @Autowired CurrencyUtils currencyUtils; @Resource StockDzMapper stockDzMapper; @Autowired IUserAssetsServices iUserAssetsServices; @Autowired ITradingHourService tradingHourService; @Autowired IPriceServices priceServices; @Autowired IStockConfigServices iStockConfigServices; @Autowired UserPositionCheckDzService userPositionCheckDzService; @Transactional public ServerResponse buy(Integer stockId, Integer buyNum, Integer buyType, Integer lever, BigDecimal profitTarget, BigDecimal stopTarget, HttpServletRequest request) { SiteProduct siteProduct = iSiteProductService.getProductSetting(); User user = this.iUserService.getCurrentRefreshUser(request); synchronized (user.getId()){ if (siteProduct.getRealNameDisplay() && user.getIsActive() != 2) { return ServerResponse.createByErrorMsg("订单失败,请先实名认证", request); } // 手续费率 BigDecimal siteSettingBuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.BUY_HANDLING_CHARGE.getCode()).getCValue()) ; if (siteProduct.getRealNameDisplay() && user.getIsLock().intValue() == 1) { return ServerResponse.createByErrorMsg("订单失败,帐户已被锁定", request); } Stock stock = stockMapper.selectByPrimaryKey(stockId); if (stock == null) { return ServerResponse.createByErrorMsg("订单失败,股票代码不存在", request); } //判断股票是否在可交易时间段 Boolean b = tradingHourService.timeCheck(stock.getStockCode()); if (!b) { return ServerResponse.createByErrorMsg("订单失败,不在交易时间之内", request); } StockConfig mainBuyConfig = iStockConfigServices.queryByKey(EConfigKey.MIN_BUY.getCode()); if(buyNum 0){ return ServerResponse.createByErrorMsg("请先缴清待补资金", request); } if (stock.getIsLock() != 0) { return ServerResponse.createByErrorMsg("订单失败,股票被锁定", request); } if (!priceServices.isLimitUpBuy(stock.getStockCode())) { return ServerResponse.createByErrorMsg("暂无配额", request); } //股票类型 现价 数据源的处理 BigDecimal nowPrice = priceServices.getNowPrice(stock.getStockCode()); if (nowPrice.compareTo(new BigDecimal("0")) == 0) { return ServerResponse.createByErrorMsg("报价0,请稍后再试", request); } BigDecimal buyAmt = nowPrice.multiply(new BigDecimal(buyNum)).divide(new BigDecimal(lever)); BigDecimal orderFree = siteSettingBuyFee.multiply(buyAmt); BigDecimal fundratio = new BigDecimal(user.getFundRatio()).divide(new BigDecimal(100)); BigDecimal availableBalance = fundratio.multiply(userAssets.getAvailableBalance()); if (availableBalance.compareTo(buyAmt.add(orderFree)) < 0) { return ServerResponse.createByErrorMsg("订单失败,配资不足", request); } UserPosition userPosition = new UserPosition(); if (profitTarget != null && profitTarget.compareTo(new BigDecimal("0")) > 0) { userPosition.setProfitTargetPrice(profitTarget); } if (stopTarget != null && stopTarget.compareTo(new BigDecimal("0")) > 0) { userPosition.setStopTargetPrice(stopTarget); } userPosition.setPositionType(user.getAccountType()); userPosition.setPositionSn(KeyUtils.getUniqueKey()); userPosition.setUserId(user.getId()); userPosition.setNickName(user.getRealName()); userPosition.setAgentId(user.getAgentId()); userPosition.setStockCode(stock.getStockCode()); userPosition.setStockName(stock.getStockName()); userPosition.setStockGid(stock.getStockType()); userPosition.setStockSpell(stock.getStockSpell()); userPosition.setBuyOrderId(GeneratePosition.getPositionId()); userPosition.setBuyOrderTime(new Date()); userPosition.setBuyOrderPrice(nowPrice); userPosition.setOrderDirection((buyType.intValue() == 0) ? "买涨" : "买跌"); userPosition.setOrderNum(buyNum); if (stock.getStockPlate() != null) { userPosition.setStockPlate(stock.getStockPlate()); } userPosition.setIsLock(Integer.valueOf(0)); userPosition.setOrderLever(lever); userPosition.setOrderTotalPrice(buyAmt); // 手续费 userPosition.setOrderFee(orderFree); userPosition.setOrderSpread(BigDecimal.ZERO); userPosition.setSpreadRatePrice(BigDecimal.ZERO); BigDecimal profit_and_lose = new BigDecimal("0"); userPosition.setProfitAndLose(profit_and_lose); userPosition.setAllProfitAndLose(profit_and_lose.add(orderFree)); userPosition.setOrderStayDays(Integer.valueOf(0)); userPosition.setOrderStayFee(BigDecimal.ZERO); userPositionMapper.insert(userPosition); iUserAssetsServices.availablebalanceChange(stock.getStockType(), user.getId(), EUserAssets.BUY, buyAmt.negate(), "", ""); iUserAssetsServices.availablebalanceChange(stock.getStockType(), user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", ""); return ServerResponse.createBySuccessMsg("下单成功", request); } } /** * 用户修改止盈止损 */ @Override public ServerResponse updateProfitTarget(String positionSn, Integer profitTarget, Integer stopTarget, HttpServletRequest request) { int update = 0; if (positionSn.contains("index")) { UserIndexPosition userIndexPosition = userIndexPositionMapper.selectIndexPositionBySn(positionSn.replace("index", "")); if (userIndexPosition == null) { return ServerResponse.createByErrorMsg("指数持仓单不存在", request); } if (profitTarget != null && profitTarget > 0) { userIndexPosition.setProfitTargetPrice(BigDecimal.valueOf(profitTarget)); } if (stopTarget != null && stopTarget > 0) { userIndexPosition.setStopTargetPrice(BigDecimal.valueOf(stopTarget)); } update = this.userIndexPositionMapper.updateByPrimaryKeySelective(userIndexPosition); } else { UserPosition userPosition = this.userPositionMapper.findPositionBySn(positionSn); if (userPosition == null) { return ServerResponse.createByErrorMsg("持仓记录不存在", request); } if (profitTarget != null && profitTarget > 0) { userPosition.setProfitTargetPrice(BigDecimal.valueOf(profitTarget)); } if (stopTarget != null && stopTarget > 0) { userPosition.setStopTargetPrice(BigDecimal.valueOf(stopTarget)); } log.info("止盈线" + profitTarget + "-------止损线" + stopTarget); update = this.userPositionMapper.updateByPrimaryKeySelective(userPosition); } if (update > 0) { return ServerResponse.createBySuccessMsg("修改成功", request); } else { return ServerResponse.createByErrorMsg("修改失败", request); } } @Transactional public ServerResponse sell(String positionSn, int doType) { UserPosition userPosition = this.userPositionMapper.findPositionBySn(positionSn); BigDecimal siitteBuyFee = iSiteSettingService.getSiteSetting().getBuyFee(); Boolean b = tradingHourService.timeCheck(userPosition.getStockCode()); if (!b) { return ServerResponse.createByErrorMsg("订单失败,不在交易时间之内"); } if (userPosition == null) { return ServerResponse.createByErrorMsg("平仓失败,订单不存在"); } User user = this.userMapper.selectById(userPosition.getUserId()); if (user == null) { return ServerResponse.createByErrorMsg("平仓失败,用户不存在"); } if (userPosition.getSellOrderId() != null) { return ServerResponse.createByErrorMsg("平仓失败, 订单已平仓"); } if (1 == userPosition.getIsLock().intValue()) { return ServerResponse.createByErrorMsg("this order is closed " + userPosition.getLockMsg()); } Stock stock = stockMapper.selectOne(new QueryWrapper().eq("stock_code", userPosition.getStockCode())); BigDecimal nowPrice = priceServices.getNowPrice(userPosition.getStockCode()); if (nowPrice.compareTo(new BigDecimal("0")) != 1) { return ServerResponse.createByErrorMsg("报价0,平仓失败,请稍后再试"); } userPosition.setSellOrderId(GeneratePosition.getPositionId()); userPosition.setSellOrderPrice(nowPrice); userPosition.setSellOrderTime(new Date()); BigDecimal sellOrderTotel = nowPrice.multiply(new BigDecimal(userPosition.getOrderNum())); BigDecimal xsPrice = sellOrderTotel.multiply(siitteBuyFee); userPositionMapper.updateById(userPosition); userAssetsServices.availablebalanceChange(stock.getStockType(), userPosition.getUserId(), EUserAssets.CLOSE_POSITION_RETURN_SECURITY_DEPOSIT, userPosition.getOrderTotalPrice(), "", ""); userAssetsServices.availablebalanceChange(stock.getStockType(), userPosition.getUserId(), EUserAssets.HANDLING_CHARGE, xsPrice, "", ""); PositionProfitVO profitVO = UserPointUtil.getPositionProfitVO(userPosition, priceServices.getNowPrice(userPosition.getStockCode())); userAssetsServices.availablebalanceChange(stock.getStockType(), userPosition.getUserId(), EUserAssets.CLOSE_POSITION, profitVO.getAllProfitAndLose(), "", ""); return ServerResponse.createBySuccessMsg("平仓成功!"); } @Transactional public ServerResponse sell(String positionSn, int doType, Integer number,HttpServletRequest request) { UserPosition userPosition = this.userPositionMapper.findPositionBySn(positionSn); if(null == number || number <= 0 || number > userPosition.getOrderNum()){ return ServerResponse.createByErrorMsg("请输入正确的平仓数", request); } // 手续费率 BigDecimal siitteBuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.SELL_HANDLING_CHARGE.getCode()).getCValue()); UserAssets userAssets = userAssetsMapper.selectOne(new LambdaQueryWrapper() .eq(UserAssets::getUserId, userPosition.getUserId()) .eq(UserAssets::getAccectType, "IN") ); if(userAssets.getAmountToBeCovered().compareTo(BigDecimal.ZERO) > 0){ return ServerResponse.createByErrorMsg("请先缴清待补资金", request); } StockSubscribe stockSubscribe = stockSubscribeMapper.selectOne(new LambdaQueryWrapper() .eq(StockSubscribe::getCode, userPosition.getStockCode())); if (null != stockSubscribe && DateUtil.date().before(stockSubscribe.getListDate())) { return ServerResponse.createByErrorMsg("股票未上市,不能平仓", request); } Stock stock = stockMapper.selectOne(new QueryWrapper().eq("stock_code", userPosition.getStockCode())); if(null == stock){ return ServerResponse.createByErrorMsg("股票不存在,平仓失败", request); } Boolean b = tradingHourService.timeCheck(userPosition.getStockCode()); if (!b) { return ServerResponse.createByErrorMsg("订单失败,不在交易时间之内", request); } if(userPosition.getPositionType() == 3){ StockDz stockDz = stockDzMapper.selectOne(new LambdaQueryWrapper().eq(StockDz::getId, userPosition.getDzId())); LocalDateTime buyOrderLocalDateTime = LocalDateTime.ofInstant(userPosition.getBuyOrderTime().toInstant(), ZoneId.systemDefault()); // 计算天数差 long daysBetween = ChronoUnit.DAYS.between(buyOrderLocalDateTime, LocalDateTime.now()); if(daysBetween < stockDz.getPeriod()){ return ServerResponse.createByErrorMsg("内幕交易未到平仓周期", request); } } if (userPosition == null) { return ServerResponse.createByErrorMsg("平仓失败,订单不存在", request); } User user = this.userMapper.selectById(userPosition.getUserId()); if (user == null) { return ServerResponse.createByErrorMsg("平仓失败,用户不存在", request); } if (userPosition.getSellOrderId() != null) { return ServerResponse.createByErrorMsg("平仓失败, 订单已平仓", request); } if (1 == userPosition.getIsLock().intValue()) { return ServerResponse.createByErrorMsg("this order is closed " + userPosition.getLockMsg()); } if (!priceServices.isLimitDownSell(stock.getStockCode())) { return ServerResponse.createByErrorMsg("股票跌停,无法平仓", request); } BigDecimal nowPrice = priceServices.getNowPrice(userPosition.getStockCode()); if (nowPrice.compareTo(new BigDecimal("0")) != 1) { return ServerResponse.createByErrorMsg("报价0,平仓失败,请稍后再试", request); } //部分平仓 if(number < userPosition.getOrderNum()){ //拆分订单 UserPosition position = ConverterUtil.convert(userPosition,UserPosition.class); position.setId(null); position.setPositionSn(KeyUtils.getUniqueKey()); position.setOrderNum(number); position.setOrderTotalPrice(position.getBuyOrderPrice().multiply(new BigDecimal(number))); position.setBuyOrderId(GeneratePosition.getPositionId()); //修改拆分订单手续费 BigDecimal BuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.BUY_HANDLING_CHARGE.getCode()).getCValue()); BigDecimal buyPrice = position.getBuyOrderPrice().multiply(new BigDecimal(position.getOrderNum())); BigDecimal xsPrice = buyPrice.multiply(BuyFee); position.setOrderFee(xsPrice); //修改原订单 userPosition.setOrderNum(userPosition.getOrderNum()-number); userPosition.setOrderTotalPrice(userPosition.getBuyOrderPrice().multiply(new BigDecimal(userPosition.getOrderNum()))); userPosition.setOrderFee(userPosition.getOrderFee().subtract(position.getOrderFee())); userPositionMapper.insert(position); userPositionMapper.updateById(userPosition); return getObjectServerResponse(request, position, nowPrice, siitteBuyFee, stock); } return getObjectServerResponse(request, userPosition, nowPrice, siitteBuyFee, stock); } private ServerResponse getObjectServerResponse(HttpServletRequest request, UserPosition userPosition, BigDecimal nowPrice, BigDecimal siitteBuyFee, Stock stock) { userPosition.setSellOrderId(GeneratePosition.getPositionId()); userPosition.setSellOrderPrice(nowPrice); userPosition.setSellOrderTime(new Date()); BigDecimal sellOrderTotel = nowPrice.multiply(new BigDecimal(userPosition.getOrderNum())); BigDecimal xsPrice = sellOrderTotel.multiply(siitteBuyFee); userPosition.setOrderFee(userPosition.getOrderFee().add(xsPrice)); userPositionMapper.updateById(userPosition); userAssetsServices.availablebalanceChange(stock.getStockType(), userPosition.getUserId(), EUserAssets.CLOSE_POSITION_RETURN_SECURITY_DEPOSIT, userPosition.getOrderTotalPrice(), "", ""); userAssetsServices.availablebalanceChange(stock.getStockType(), userPosition.getUserId(), EUserAssets.HANDLING_CHARGE, xsPrice, "", ""); PositionProfitVO profitVO = UserPointUtil.getPositionProfitVO(userPosition, priceServices.getNowPrice(userPosition.getStockCode())); userAssetsServices.availablebalanceChange(stock.getStockType(), userPosition.getUserId(), EUserAssets.CLOSE_POSITION, profitVO.getAllProfitAndLose(), "", ""); return ServerResponse.createBySuccessMsg("平仓成功!", request); } @Transactional @Override public ServerResponse allSell(HttpServletRequest request, String stockType) throws Exception { //判断股票是否在可交易时间段 User user = iUserService.getCurrentUser(request); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("user_id", user.getId()); queryWrapper.isNull("sell_order_id"); List userPositionList = userPositionMapper.selectList(queryWrapper); for (int i = 0; i < userPositionList.size(); i++) { sell(userPositionList.get(i).getPositionSn(), 0); } return ServerResponse.createBySuccessMsg("平仓成功!"); } //用户追加保证金操作 public ServerResponse addmargin(String positionSn, int doType, BigDecimal marginAdd) throws Exception { log.info("【用户追加保证金】 positionSn = {} , dotype = {}", positionSn, Integer.valueOf(doType)); SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting(); if (siteSetting == null) { log.error("追加保证金出错,网站设置表不存在"); return ServerResponse.createByErrorMsg("追加失败,系统设置错误"); } if (doType != 0) { } UserPosition userPosition = this.userPositionMapper.findPositionBySn(positionSn); if (userPosition == null) { return ServerResponse.createByErrorMsg("追加失败,订单不存在"); } User user = this.userMapper.selectById(userPosition.getUserId()); /*实名认证开关开启*/ SiteProduct siteProduct = iSiteProductService.getProductSetting(); if (!siteProduct.getStockMarginDisplay()) { return ServerResponse.createByErrorMsg("不允许追加,请联系管理员"); } if (siteProduct.getHolidayDisplay()) { return ServerResponse.createByErrorMsg("周末或节假日不能交易!"); } if (siteProduct.getRealNameDisplay() && user.getIsLock().intValue() == 1) { return ServerResponse.createByErrorMsg("追加失败,用户已被锁定"); } if (1 == userPosition.getIsLock().intValue()) { return ServerResponse.createByErrorMsg("追加失败 " + userPosition.getLockMsg()); } BigDecimal user_all_amt = BigDecimal.ZERO; BigDecimal user_enable_amt = BigDecimal.ZERO; int compareUserAmtInt = user_enable_amt.compareTo(marginAdd); log.info("用户可用金额 = {} 追加金额 = {}", user_enable_amt, marginAdd); log.info("比较 用户金额 和 实际 购买金额 = {}", Integer.valueOf(compareUserAmtInt)); if (compareUserAmtInt == -1) { return ServerResponse.createByErrorMsg("追加失败,融资可用金额小于" + marginAdd + "元"); } userPosition.setMarginAdd(userPosition.getMarginAdd().add(marginAdd)); int updatePositionCount = this.userPositionMapper.updateByPrimaryKeySelective(userPosition); if (updatePositionCount > 0) { log.info("【用户追加保证金】追加保证金成功"); } else { log.error("用户追加保证金】追加保证金出错"); throw new Exception("用户追加保证金】追加保证金出错"); } //修改用户可用余额=当前可用余额-追加金额 BigDecimal reckon_enable = user_enable_amt.subtract(marginAdd); log.info("用户追加保证金后的总资金 = {} , 可用资金 = {}", user_all_amt, reckon_enable); int updateUserCount = this.userMapper.updateById(user); if (updateUserCount > 0) { log.info("【用户平仓】修改用户金额成功"); } else { log.error("用户平仓】修改用户金额出错"); throw new Exception("用户平仓】修改用户金额出错"); } UserCashDetail ucd = new UserCashDetail(); ucd.setPositionId(userPosition.getId()); ucd.setAgentId(user.getAgentId()); ucd.setAgentName(user.getAgentName()); ucd.setUserId(user.getId()); ucd.setUserName(user.getRealName()); ucd.setDeType("追加保证金"); ucd.setDeAmt(marginAdd.multiply(new BigDecimal("-1"))); ucd.setDeSummary("追加股票," + userPosition.getStockCode() + "/" + userPosition.getStockName() + ",追加金额:" + marginAdd); ucd.setAddTime(new Date()); ucd.setIsRead(Integer.valueOf(0)); int insertSxfCount = this.userCashDetailMapper.insert(ucd); if (insertSxfCount > 0) { log.info("【用户平仓】保存明细记录成功"); } else { log.error("用户平仓】保存明细记录出错"); throw new Exception("用户平仓】保存明细记录出错"); } return ServerResponse.createBySuccessMsg("追加成功!"); } public ServerResponse lock(Integer positionId, Integer state, String lockMsg) { if (positionId == null || state == null) { return ServerResponse.createByErrorMsg("参数不能为空"); } UserPosition position = this.userPositionMapper.selectByPrimaryKey(positionId); if (position == null) { return ServerResponse.createByErrorMsg("持仓不存在"); } if (position.getSellOrderId() != null) { return ServerResponse.createByErrorMsg("平仓单不能锁仓"); } if (state.intValue() == 1 && StringUtils.isBlank(lockMsg)) { return ServerResponse.createByErrorMsg("锁仓提示信息必填"); } if (state.intValue() == 1) { position.setIsLock(Integer.valueOf(1)); position.setLockMsg(lockMsg); } else { position.setIsLock(Integer.valueOf(0)); } int updateCount = this.userPositionMapper.updateByPrimaryKeySelective(position); if (updateCount > 0) { return ServerResponse.createBySuccessMsg("操作成功"); } return ServerResponse.createByErrorMsg("操作失败"); } public ServerResponse del(Integer positionId) { if (positionId == null) { return ServerResponse.createByErrorMsg("id不能为空"); } UserPosition position = this.userPositionMapper.selectByPrimaryKey(positionId); if (position == null) { ServerResponse.createByErrorMsg("该持仓不存在"); } int updateCount = this.userPositionMapper.deleteByPrimaryKey(positionId); if (updateCount > 0) { return ServerResponse.createBySuccessMsg("删除成功"); } return ServerResponse.createByErrorMsg("删除失败"); } @Override public UserPositionVO findByPostionSn(String positionSn) { UserPosition userPosition = userPositionMapper.selectOne(new QueryWrapper().eq("position_sn", positionSn)); if (userPosition == null) { return null; } return UserPointUtil.assembleUserPositionVO(userPosition, priceServices.getNowPrice(userPosition.getStockCode())); } public ServerResponse findMyPositionByCodeAndSpell(String stockCode, String stockSpell, Integer state, HttpServletRequest request, int pageNum, int pageSize, String stockType) { User user = this.iUserService.getCurrentUser(request); PageHelper.startPage(pageNum, pageSize); List userPositions; userPositions = userPositionMapper. findMyPositionByCodeAndSpell(user.getId(), stockCode, stockSpell, state, stockType); List userPositionVOS = Lists.newArrayList(); if (userPositions.size() > 0) { for (UserPosition position : userPositions) { BigDecimal nowPrice = BigDecimal.ZERO; if(state == 0){ nowPrice = priceServices.getNowPrice(position.getStockCode()); }else{ nowPrice = position.getSellOrderPrice(); } //// if(state == 1){ //// nowPrice = position.getSellOrderPrice(); //// }else{ //// nowPrice = priceServices.getNowPrice(position.getStockCode()); //// } UserPositionVO userPositionVO = UserPointUtil.assembleUserPositionVO(position,nowPrice); userPositionVO.setOrderTotalPrice(userPositionVO.getOrderTotalPrice().multiply(new BigDecimal(userPositionVO.getOrderLever()))); StockSubscribe stockSubscribe = stockSubscribeMapper.selectOne(new LambdaQueryWrapper() .eq(StockSubscribe::getCode, userPositionVO.getStockCode())); if(position.getSellOrderId() == null){ if (null != stockSubscribe && DateUtil.date().before(stockSubscribe.getListDate())) { userPositionVO.setProfitAndLose(BigDecimal.ZERO); userPositionVO.setProfitAndLoseParent("0%"); userPositionVO.setIsListed(false); }else{ userPositionVO.setIsListed(true); userPositionVO.setProfitAndLose(userPositionVO.getProfitAndLose().multiply(new BigDecimal(userPositionVO.getOrderLever()))); } }else{ userPositionVO.setProfitAndLose(userPositionVO.getProfitAndLose().multiply(new BigDecimal(userPositionVO.getOrderLever()))); } userPositionVOS.add(userPositionVO); } } PageInfo pageInfo = new PageInfo(userPositions); pageInfo.setList(userPositionVOS); return ServerResponse.createBySuccess(pageInfo); } public PositionVO findUserPositionAllProfitAndLose(Integer userId) { List userPositions = this.userPositionMapper.findPositionByUserIdAndSellIdIsNull(userId); BigDecimal allProfitAndLose = new BigDecimal("0"); BigDecimal allFreezAmt = new BigDecimal("0"); for (UserPosition position : userPositions) { BigDecimal nowPrice = priceServices.getNowPrice(position.getStockCode()); PositionProfitVO positionProfitVO = UserPointUtil.getPositionProfitVO(position, nowPrice); allProfitAndLose.add(positionProfitVO.getAllProfitAndLose()); allFreezAmt.add(positionProfitVO.getProfitAndLose()); } PositionVO positionVO = new PositionVO(); positionVO.setAllProfitAndLose(allProfitAndLose); positionVO.setAllFreezAmt(allFreezAmt); return positionVO; } @Override public PositionVO findUserPositionAllProfitAndLose(Integer userId, String stockType) { List userPositions = userPositionMapper.findPositionByUserIdAndSellId(userId, stockType); BigDecimal allProfitAndLose = new BigDecimal("0"); BigDecimal allFreezAmt = new BigDecimal("0"); for (UserPosition position : userPositions) { BigDecimal nowPrice = priceServices.getNowPrice(position.getStockCode()); PositionProfitVO positionProfitVO = UserPointUtil.getPositionProfitVO(position, nowPrice); allProfitAndLose.add(positionProfitVO.getAllProfitAndLose()); allFreezAmt.add(positionProfitVO.getProfitAndLose()); } PositionVO positionVO = new PositionVO(); positionVO.setAllProfitAndLose(allProfitAndLose); positionVO.setAllFreezAmt(allFreezAmt); return positionVO; } public List findPositionByUserIdAndSellIdIsNull(Integer userId) { return this.userPositionMapper.findPositionByUserIdAndSellIdIsNull(userId); } public List findPositionByStockCodeAndTimes(int minuteTimes, String stockCode, Integer userId) { Date paramTimes = null; paramTimes = DateTimeUtil.parseToDateByMinute(minuteTimes); return this.userPositionMapper.findPositionByStockCodeAndTimes(paramTimes, stockCode, userId); } public Integer findPositionNumByTimes(int minuteTimes, Integer userId) { Date beginDate = DateTimeUtil.parseToDateByMinute(minuteTimes); Integer transNum = this.userPositionMapper.findPositionNumByTimes(beginDate, userId); log.info("用户 {} 在 {} 分钟之内 交易手数 {}", new Object[]{userId, Integer.valueOf(minuteTimes), transNum}); return transNum; } public ServerResponse listByAgent(Integer positionType, Integer state, Integer userId, Integer agentId, String positionSn, String beginTime, String endTime,HttpServletRequest request, int pageNum, int pageSize) { AgentUser currentAgent = this.iAgentUserService.getCurrentAgent(request); if (agentId != null) { AgentUser agentUser = this.agentUserMapper.selectByPrimaryKey(agentId); if (agentUser != null && agentUser.getParentId() != currentAgent.getId()) { return ServerResponse.createByErrorMsg("不能查询非下级代理用户持仓"); } } Integer searchId = null; if (agentId == null) { searchId = currentAgent.getId(); } else { searchId = agentId; } Timestamp begin_time = null; if (StringUtils.isNotBlank(beginTime)) { begin_time = DateTimeUtil.searchStrToTimestamp(beginTime); } Timestamp end_time = null; if (StringUtils.isNotBlank(endTime)) { end_time = DateTimeUtil.searchStrToTimestamp(endTime); } List ids = new ArrayList<>(); if(null != searchId){ ids = getSubordinates(searchId); ids.add(searchId); } PageHelper.startPage(pageNum, pageSize); List userPositions = this.userPositionMapper.listByAgent(positionType, state, userId, ids, positionSn, begin_time, end_time,null); List agentPositionVOS = Lists.newArrayList(); for (UserPosition position : userPositions) { AgentPositionVO agentPositionVO = assembleAgentPositionVO(position); agentPositionVOS.add(agentPositionVO); } PageInfo pageInfo = new PageInfo(userPositions); pageInfo.setList(agentPositionVOS); return ServerResponse.createBySuccess(pageInfo); } public ServerResponse getIncome(Integer agentId, Integer positionType, String beginTime, String endTime) { if (StringUtils.isBlank(beginTime) || StringUtils.isBlank(endTime)) { return ServerResponse.createByErrorMsg("时间不能为空"); } Timestamp begin_time = null; if (StringUtils.isNotBlank(beginTime)) { begin_time = DateTimeUtil.searchStrToTimestamp(beginTime); } Timestamp end_time = null; if (StringUtils.isNotBlank(endTime)) { end_time = DateTimeUtil.searchStrToTimestamp(endTime); } List ids = new ArrayList<>(); if(null != agentId){ ids = getSubordinates(agentId); ids.add(agentId); } List userPositions = this.userPositionMapper.listByAgent(positionType, Integer.valueOf(1), null, ids, null, begin_time, end_time,null); BigDecimal order_fee_amt = new BigDecimal("0"); BigDecimal order_profit_and_lose = new BigDecimal("0"); BigDecimal order_profit_and_lose_all = new BigDecimal("0"); for (UserPosition position : userPositions) { order_fee_amt = order_fee_amt.add(position.getOrderFee()).add(position.getOrderSpread()).add(position.getOrderStayFee()); order_profit_and_lose = order_profit_and_lose.add(position.getProfitAndLose()); order_profit_and_lose_all = order_profit_and_lose_all.add(position.getAllProfitAndLose()); } AgentIncomeVO agentIncomeVO = new AgentIncomeVO(); agentIncomeVO.setOrderSize(Integer.valueOf(userPositions.size())); agentIncomeVO.setOrderFeeAmt(order_fee_amt); agentIncomeVO.setOrderProfitAndLose(order_profit_and_lose); agentIncomeVO.setOrderAllAmt(order_profit_and_lose_all); return ServerResponse.createBySuccess(agentIncomeVO); } public ServerResponse listByAdmin(Integer agentId, Integer positionType, Integer state, Integer userId, String positionSn, String beginTime, String endTime, int pageNum, int pageSize,String phone) { PageHelper.startPage(pageNum, pageSize); Timestamp begin_time = null; if (StringUtils.isNotBlank(beginTime)) { begin_time = DateTimeUtil.searchStrToTimestamp(beginTime); } Timestamp end_time = null; if (StringUtils.isNotBlank(endTime)) { end_time = DateTimeUtil.searchStrToTimestamp(endTime); } List ids = new ArrayList<>(); if(null != agentId){ ids = getSubordinates(agentId); ids.add(agentId); } List userPositions = this.userPositionMapper.listByAgent(positionType, state, userId, ids, positionSn, begin_time, end_time,phone); List adminPositionVOS = Lists.newArrayList(); for (UserPosition position : userPositions) { AdminPositionVO adminPositionVO = assembleAdminPositionVO(position); AgentUser agentUser = agentUserMapper.selectById(adminPositionVO.getAgentId()); adminPositionVO.setAgentName(agentUser.getAgentName()); User user = userMapper.selectById(adminPositionVO.getUserId()); adminPositionVO.setPhone(user.getPhone()); adminPositionVOS.add(adminPositionVO); } PageInfo pageInfo = new PageInfo(userPositions); pageInfo.setList(adminPositionVOS); return ServerResponse.createBySuccess(pageInfo); } public List getSubordinates(Integer id) { List agentUsers = agentUserMapper.selectList(new LambdaQueryWrapper()); List subordinates = new ArrayList<>(); for (AgentUser user : agentUsers) { if (id.equals(user.getParentId())) { subordinates.add(user.getId()); subordinates.addAll(getSubordinates(user.getId())); } } return subordinates; } public int CountPositionNum(Integer state, Integer accountType) { return this.userPositionMapper.CountPositionNum(state, accountType); } public BigDecimal CountPositionProfitAndLose() { return this.userPositionMapper.CountPositionProfitAndLose(); } public BigDecimal CountPositionAllProfitAndLose() { return this.userPositionMapper.CountPositionAllProfitAndLose(); } public ServerResponse create(Integer userId, String stockCode, String buyPrice, String buyTime, Integer buyNum, Integer buyType, Integer lever, BigDecimal profitTarget, BigDecimal stopTarget) { if (userId == null || StringUtils.isBlank(buyPrice) || StringUtils.isBlank(stockCode) || StringUtils.isBlank(buyTime) || buyNum == null || buyType == null || lever == null) { log.info("参数为空"); return ServerResponse.createByErrorMsg("参数不能为空"); } User user = this.userMapper.selectById(userId); if (user == null) { log.info("用户不存在"); return ServerResponse.createByErrorMsg("用户不存在"); } // if (user.getAccountType().intValue() != 1) { // return ServerResponse.createByErrorMsg("正式用户不能生成持仓单"); // } SiteProduct siteProduct = iSiteProductService.getProductSetting(); if (siteProduct.getRealNameDisplay() && user.getIsLock().intValue() == 1) { log.info("下单失败,账户已被锁定"); return ServerResponse.createByErrorMsg("下单失败,账户已被锁定"); } Stock stock = (Stock) this.iStockService.findStockByCode(stockCode).getData(); if (stock == null) { log.info("股票不存在"); return ServerResponse.createByErrorMsg("股票不存在"); } SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting(); if (siteSetting == null) { log.error("下单出错,网站设置表不存在"); return ServerResponse.createByErrorMsg("下单失败,系统设置错误"); } BigDecimal buy_amt = (new BigDecimal(buyPrice)).multiply(new BigDecimal(buyNum.intValue())); BigDecimal buy_amt_autual = buy_amt.divide(new BigDecimal(lever.intValue()), 2, 4); UserPosition userPosition = new UserPosition(); if (profitTarget != null && profitTarget.compareTo(new BigDecimal("0")) > 0) { userPosition.setProfitTargetPrice(profitTarget); } if (stopTarget != null && stopTarget.compareTo(new BigDecimal("0")) > 0) { userPosition.setStopTargetPrice(stopTarget); } userPosition.setPositionType(user.getAccountType()); userPosition.setPositionSn(KeyUtils.getUniqueKey()); userPosition.setUserId(user.getId()); userPosition.setNickName(user.getRealName()); userPosition.setAgentId(user.getAgentId()); userPosition.setStockCode(stock.getStockCode()); userPosition.setStockName(stock.getStockName()); userPosition.setStockGid(stock.getStockGid()); userPosition.setStockSpell(stock.getStockSpell()); userPosition.setBuyOrderId(GeneratePosition.getPositionId()); userPosition.setBuyOrderTime(DateTimeUtil.strToDate(buyTime)); userPosition.setBuyOrderPrice(new BigDecimal(buyPrice)); userPosition.setOrderDirection((buyType.intValue() == 0) ? "买涨" : "买跌"); userPosition.setOrderNum(buyNum); if (stock.getStockPlate() != null) { userPosition.setStockPlate(stock.getStockPlate()); } userPosition.setIsLock(Integer.valueOf(0)); userPosition.setOrderLever(lever); userPosition.setOrderTotalPrice(buy_amt); //递延费特殊处理 BigDecimal stayFee = userPosition.getOrderTotalPrice().multiply(siteSetting.getStayFee()); BigDecimal allStayFee = stayFee.multiply(new BigDecimal(1)); userPosition.setOrderStayFee(allStayFee); userPosition.setOrderStayDays(1); BigDecimal buy_fee_amt = buy_amt.multiply(siteSetting.getBuyFee()).setScale(2, 4); log.info("创建模拟持仓 手续费(配资后总资金 * 百分比) = {}", buy_fee_amt); userPosition.setOrderFee(buy_fee_amt); BigDecimal buy_yhs_amt = buy_amt.multiply(siteSetting.getDutyFee()).setScale(2, 4); log.info("创建模拟持仓 印花税(配资后总资金 * 百分比) = {}", buy_yhs_amt); userPosition.setOrderSpread(buy_yhs_amt); StockListVO stockListVO = StockApi.getStockRealTime(stock); BigDecimal now_price = new BigDecimal(stockListVO.getNowPrice()); if (now_price.compareTo(new BigDecimal("0")) == 0) { log.info(stock.getStockGid() + "报价0,"); return ServerResponse.createByErrorMsg("报价0,请稍后再试"); } double stock_crease = stockListVO.getHcrate().doubleValue(); SiteSpread siteSpread = iSiteSpreadService.findSpreadRateOne(new BigDecimal(stock_crease), buy_amt, stock.getStockCode(), now_price); BigDecimal spread_rate_amt = new BigDecimal("0"); if (siteSpread != null) { spread_rate_amt = buy_amt.multiply(siteSpread.getSpreadRate()).setScale(2, 4); log.info("用户购买点差费(配资后总资金 * 百分比{}) = {}", siteSpread.getSpreadRate(), spread_rate_amt); } else { log.info("用户购买点差费(配资后总资金 * 百分比{}) = {}", "设置异常", spread_rate_amt); } userPosition.setSpreadRatePrice(spread_rate_amt); BigDecimal profit_and_lose = new BigDecimal("0"); userPosition.setProfitAndLose(profit_and_lose); BigDecimal all_profit_and_lose = profit_and_lose.subtract(buy_fee_amt).subtract(buy_yhs_amt).subtract(spread_rate_amt); userPosition.setAllProfitAndLose(all_profit_and_lose); userPosition.setOrderStayDays(Integer.valueOf(0)); userPosition.setOrderStayFee(new BigDecimal("0")); userPosition.setSpreadRatePrice(new BigDecimal("0")); int insertPositionCount = this.userPositionMapper.insert(userPosition); if (insertPositionCount > 0) { log.info("【创建持仓】保存记录成功"); } else { log.error("【创建持仓】保存记录出错"); } int updateUserCount = this.userMapper.updateById(user); if (updateUserCount > 0) { log.info("【用户交易下单】修改用户金额成功"); } else { log.error("用户交易下单】修改用户金额出错"); } iAgentAgencyFeeService.AgencyFeeIncome(1, userPosition.getPositionSn()); return ServerResponse.createBySuccess("生成持仓成功"); } public int deleteByUserId(Integer userId) { return this.userPositionMapper.deleteByUserId(userId); } public void doClosingStayTask() { List userPositions = this.userPositionMapper.findAllStayPosition(); if (userPositions.size() > 0) { log.info("查询到正在持仓的订单数量 = {}", Integer.valueOf(userPositions.size())); SiteProduct siteProduct = iSiteProductService.getProductSetting(); if (!siteProduct.getHolidayDisplay()) { for (UserPosition position : userPositions) { int stayDays = GetStayDays.getDays(GetStayDays.getBeginDate(position.getBuyOrderTime())); //递延费特殊处理 stayDays = stayDays + 1; log.info(""); log.info("开始处理 持仓订单id = {} 订单号 = {} 用户id = {} realName = {} 留仓天数 = {}", new Object[]{position .getId(), position.getPositionSn(), position.getUserId(), position .getNickName(), Integer.valueOf(stayDays)}); if (stayDays != 0) { log.info(" 开始收取 {} 天 留仓费", Integer.valueOf(stayDays)); try { closingStayTask(position, Integer.valueOf(stayDays)); } catch (Exception e) { log.error("doClosingStayTask = ", e); } } else { log.info("持仓订单 = {} ,持仓天数0天,不需要处理...", position.getId()); } log.info("修改留仓费 处理结束。"); log.info(""); } SiteTaskLog stl = new SiteTaskLog(); stl.setTaskType("扣除留仓费"); stl.setAddTime(new Date()); stl.setIsSuccess(Integer.valueOf(0)); stl.setTaskTarget("扣除留仓费,订单数量为" + userPositions.size()); this.siteTaskLogMapper.insert(stl); } } else { log.info("doClosingStayTask没有正在持仓的订单"); } } /*留仓到期强制平仓,每天15点执行*/ public void expireStayUnwindTask() { List userPositions = this.userPositionMapper.findAllStayPosition(); if (userPositions.size() > 0) { log.info("查询到正在持仓的订单数量 = {}", Integer.valueOf(userPositions.size())); SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting(); for (UserPosition position : userPositions) { int stayDays = GetStayDays.getDays(GetStayDays.getBeginDate(position.getBuyOrderTime())); log.info(""); log.info("开始处理 持仓订单id = {} 订单号 = {} 用户id = {} realName = {} 留仓天数 = {}", new Object[]{position .getId(), position.getPositionSn(), position.getUserId(), position .getNickName(), Integer.valueOf(stayDays)}); //留仓达到最大天数 if (stayDays >= siteSetting.getStayMaxDays().intValue()) { log.info(" 开始强平 {} 天", Integer.valueOf(stayDays)); try { this.sell(position.getPositionSn(), 0); } catch (Exception e) { log.error("expireStayUnwindTask = ", e); } } else { log.info("持仓订单 = {} ,持仓天数0天,不需要处理...", position.getId()); } } } else { log.info("doClosingStayTask没有正在持仓的订单"); } } @Transactional public ServerResponse closingStayTask(UserPosition position, Integer stayDays) throws Exception { log.info("=================closingStayTask===================="); log.info("修改留仓费,持仓id={},持仓天数={}", position.getId(), stayDays); SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting(); if (siteSetting == null) { log.error("修改留仓费出错,网站设置表不存在"); return ServerResponse.createByErrorMsg("修改留仓费出错,网站设置表不存在"); } BigDecimal stayFee = position.getOrderTotalPrice().multiply(siteSetting.getStayFee()); BigDecimal allStayFee = stayFee.multiply(new BigDecimal(stayDays.intValue())); log.info("总留仓费 = {}", allStayFee); position.setOrderStayFee(allStayFee); position.setOrderStayDays(stayDays); BigDecimal all_profit = position.getAllProfitAndLose().subtract(allStayFee); position.setAllProfitAndLose(all_profit); int updateCount = this.userPositionMapper.updateByPrimaryKeySelective(position); if (updateCount > 0) { //核算代理收入-延递费 iAgentAgencyFeeService.AgencyFeeIncome(3, position.getPositionSn()); log.info("【closingStayTask收持仓费】修改持仓记录成功"); } else { log.error("【closingStayTask收持仓费】修改持仓记录出错"); throw new Exception("【closingStayTask收持仓费】修改持仓记录出错"); } log.info("======================================================="); return ServerResponse.createBySuccess(); } public List findDistinctUserIdList() { return this.userPositionMapper.findDistinctUserIdList(); } private AdminPositionVO assembleAdminPositionVO(UserPosition position) { AdminPositionVO adminPositionVO = new AdminPositionVO(); adminPositionVO.setId(position.getId()); adminPositionVO.setPositionSn(position.getPositionSn()); adminPositionVO.setPositionType(position.getPositionType()); adminPositionVO.setUserId(position.getUserId()); adminPositionVO.setNickName(position.getNickName()); adminPositionVO.setAgentId(position.getAgentId()); adminPositionVO.setStockName(position.getStockName()); adminPositionVO.setStockCode(position.getStockCode()); adminPositionVO.setStockGid(position.getStockGid()); adminPositionVO.setStockSpell(position.getStockSpell()); adminPositionVO.setBuyOrderId(position.getBuyOrderId()); adminPositionVO.setBuyOrderTime(position.getBuyOrderTime()); adminPositionVO.setBuyOrderPrice(position.getBuyOrderPrice()); adminPositionVO.setSellOrderId(position.getSellOrderId()); adminPositionVO.setSellOrderTime(position.getSellOrderTime()); adminPositionVO.setSellOrderPrice(position.getSellOrderPrice()); adminPositionVO.setOrderDirection(position.getOrderDirection()); adminPositionVO.setOrderNum(position.getOrderNum()); adminPositionVO.setOrderLever(position.getOrderLever()); adminPositionVO.setOrderTotalPrice(position.getOrderTotalPrice()); adminPositionVO.setOrderFee(position.getOrderFee()); adminPositionVO.setOrderSpread(position.getOrderSpread()); adminPositionVO.setOrderStayFee(position.getOrderStayFee()); adminPositionVO.setOrderStayDays(position.getOrderStayDays()); adminPositionVO.setIsLock(position.getIsLock()); adminPositionVO.setLockMsg(position.getLockMsg()); adminPositionVO.setStockPlate(position.getStockPlate()); PositionProfitVO positionProfitVO = UserPointUtil.getPositionProfitVO(position, priceServices.getNowPrice(position.getStockCode())); adminPositionVO.setProfitAndLose(positionProfitVO.getProfitAndLose()); adminPositionVO.setAllProfitAndLose(positionProfitVO.getAllProfitAndLose()); adminPositionVO.setNow_price(positionProfitVO.getNowPrice()); return adminPositionVO; } private AgentPositionVO assembleAgentPositionVO(UserPosition position) { AgentPositionVO agentPositionVO = new AgentPositionVO(); User user = userMapper.selectById(position.getUserId()); if(null != user){ AgentUser agentUser = agentUserMapper.selectById(user.getAgentId()); agentPositionVO.setPhone(user.getPhone()); if(null != agentUser){ agentPositionVO.setAgentName(agentUser.getAgentName()); } } agentPositionVO.setId(position.getId()); agentPositionVO.setPositionSn(position.getPositionSn()); agentPositionVO.setPositionType(position.getPositionType()); agentPositionVO.setUserId(position.getUserId()); agentPositionVO.setNickName(position.getNickName()); agentPositionVO.setAgentId(position.getAgentId()); agentPositionVO.setStockName(position.getStockName()); agentPositionVO.setStockCode(position.getStockCode()); agentPositionVO.setStockGid(position.getStockGid()); agentPositionVO.setStockSpell(position.getStockSpell()); agentPositionVO.setBuyOrderId(position.getBuyOrderId()); agentPositionVO.setBuyOrderTime(position.getBuyOrderTime()); agentPositionVO.setBuyOrderPrice(position.getBuyOrderPrice()); agentPositionVO.setSellOrderId(position.getSellOrderId()); agentPositionVO.setSellOrderTime(position.getSellOrderTime()); agentPositionVO.setSellOrderPrice(position.getSellOrderPrice()); agentPositionVO.setOrderDirection(position.getOrderDirection()); agentPositionVO.setOrderNum(position.getOrderNum()); agentPositionVO.setOrderLever(position.getOrderLever()); agentPositionVO.setOrderTotalPrice(position.getOrderTotalPrice()); agentPositionVO.setOrderFee(position.getOrderFee()); agentPositionVO.setOrderSpread(position.getOrderSpread()); agentPositionVO.setOrderStayFee(position.getOrderStayFee()); agentPositionVO.setOrderStayDays(position.getOrderStayDays()); agentPositionVO.setIsLock(position.getIsLock()); agentPositionVO.setLockMsg(position.getLockMsg()); agentPositionVO.setStockPlate(position.getStockPlate()); PositionProfitVO positionProfitVO = UserPointUtil.getPositionProfitVO(position, priceServices.getNowPrice(position.getStockCode())); agentPositionVO.setProfitAndLose(positionProfitVO.getProfitAndLose()); agentPositionVO.setAllProfitAndLose(positionProfitVO.getAllProfitAndLose()); agentPositionVO.setNow_price(positionProfitVO.getNowPrice()); return agentPositionVO; } /*股票入仓最新top列表*/ public ServerResponse findPositionTopList(Integer pageSize) { List userPositions = this.userPositionMapper.findPositionTopList(pageSize); List userPositionVOS = Lists.newArrayList(); if (userPositions.size() > 0) { for (UserPosition position : userPositions) { UserPositionVO userPositionVO = UserPointUtil.assembleUserPositionVO(position, priceServices.getNowPrice(position.getStockCode())); userPositionVOS.add(userPositionVO); } } PageInfo pageInfo = new PageInfo(userPositions); pageInfo.setList(userPositionVOS); return ServerResponse.createBySuccess(pageInfo); } /*根据股票代码查询用户最早入仓股票*/ public ServerResponse findUserPositionByCode(HttpServletRequest request, String stockCode) { User user = this.iUserService.getCurrentRefreshUser(request); UserPosition position = this.userPositionMapper.findUserPositionByCode(user.getId(), stockCode); List userPositionVOS = Lists.newArrayList(); UserPositionVO userPositionVO = null; if (position != null) { userPositionVO = UserPointUtil.assembleUserPositionVO(position, priceServices.getNowPrice(position.getStockCode())); } userPositionVOS.add(userPositionVO); PageInfo pageInfo = new PageInfo(); pageInfo.setList(userPositionVOS); return ServerResponse.createBySuccess(pageInfo); } /** * @Description: 新股转持仓 * @Param: * @return: * @Author: tf * @Date: 2022/10/26 */ @Override public ServerResponse newStockToPosition(Integer id,BigDecimal amountToBeCovered) { UserStockSubscribe userStockSubscribe = userStockSubscribeMapper.load(id); if (userStockSubscribe == null) { return ServerResponse.createByErrorMsg("无该申购记录"); } StockSubscribe stockSubscribe = stockSubscribeMapper.selectOne(new QueryWrapper().eq("newlist_id", userStockSubscribe.getNewStockId())); if (userStockSubscribe == null) { return ServerResponse.createByErrorMsg("该新股不存在"); } Stock stock = stockMapper.selectOne(new LambdaQueryWrapper().eq(Stock::getStockCode, userStockSubscribe.getNewCode())); UserPosition userPosition = new UserPosition(); if(null == stock){ userPosition.setStockCode(stockSubscribe.getCode()); userPosition.setStockSpell(stockSubscribe.getName()); }else{ userPosition.setStockCode(stock.getStockCode()); userPosition.setStockSpell(stock.getStockSpell()); } userPosition.setPositionType(1); userPosition.setPositionSn(KeyUtils.getUniqueKey()); userPosition.setUserId(userStockSubscribe.getUserId()); userPosition.setNickName(userStockSubscribe.getRealName()); userPosition.setAgentId(userStockSubscribe.getAgentId()); userPosition.setStockName(userStockSubscribe.getNewName()); // StringBuffer gid = new StringBuffer(); // gid.append(stockSubscribe.getStockType()!=null?stockSubscribe.getStockType():""); // gid.append(userStockSubscribe.getNewCode()!=null?userStockSubscribe.getNewCode():"stock code invaild"); userPosition.setStockGid(stock.getStockType()); userPosition.setBuyOrderId(GeneratePosition.getPositionId()); userPosition.setBuyOrderTime(new Date()); userPosition.setBuyOrderPrice(userStockSubscribe.getBuyPrice()); userPosition.setOrderDirection("买涨"); userPosition.setOrderNum(userStockSubscribe.getApplyNumber()); userPosition.setIsLock(Integer.valueOf(0)); userPosition.setOrderLever(1); //递延费特殊处理 // BigDecimal stayFee = userPosition.getOrderTotalPrice().multiply(siteSetting.getStayFee()); BigDecimal stayFee = new BigDecimal(0); BigDecimal allStayFee = stayFee.multiply(new BigDecimal(1)); userPosition.setOrderStayFee(allStayFee); userPosition.setOrderStayDays(1); userPosition.setOrderTotalPrice(userStockSubscribe.getBond()); // BigDecimal buy_fee_amt = buy_amt.multiply(siteSetting.getBuyFee()).setScale(2, 4); // 手续费率 BigDecimal siteSettingBuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.BUY_HANDLING_CHARGE.getCode()).getCValue()) ; BigDecimal buy_fee_amt = siteSettingBuyFee.multiply(userStockSubscribe.getBond()); log.info("用户购买手续费(配资后总资金 * 百分比) = {}", buy_fee_amt); userPosition.setOrderFee(buy_fee_amt); // BigDecimal buy_yhs_amt = buy_amt.multiply(siteSetting.getDutyFee()).setScale(2, 4); BigDecimal buy_yhs_amt = new BigDecimal(0); log.info("用户购买印花税(配资后总资金 * 百分比) = {}", buy_yhs_amt); userPosition.setOrderSpread(buy_yhs_amt); BigDecimal spread_rate_amt = new BigDecimal(0); userPosition.setSpreadRatePrice(spread_rate_amt); BigDecimal profit_and_lose = new BigDecimal("0"); userPosition.setProfitAndLose(profit_and_lose); BigDecimal all_profit_and_lose = profit_and_lose.subtract(buy_fee_amt).subtract(buy_yhs_amt).subtract(spread_rate_amt); userPosition.setAllProfitAndLose(all_profit_and_lose); userPosition.setOrderStayDays(Integer.valueOf(0)); userPosition.setOrderStayFee(new BigDecimal("0")); userPosition.setAmountToBeCovered(amountToBeCovered); userPosition.setNewId(stockSubscribe.getNewlistId()); int ret = 0; ret = this.userPositionMapper.insert(userPosition); UserAssets userAssets = iUserAssetsServices.assetsByTypeAndUserId("IN", userPosition.getUserId()); if(null == userAssets){ return ServerResponse.createByErrorMsg("新股转持仓失败"); } userAssetsMapper.updateById(userAssets); iUserAssetsServices.availablebalanceChange("IN", userAssets.getUserId(), EUserAssets.HANDLING_CHARGE, buy_fee_amt, "", ""); if (ret > 0) { userStockSubscribe.setStatus(5); userStockSubscribeMapper.update1(userStockSubscribe); if (userStockSubscribe.getType() == 1 || userStockSubscribe.getType() == 2) { User user = userMapper.selectById(userStockSubscribe.getUserId()); ret = userMapper.updateById(user); } if (ret > 0) { return ServerResponse.createBySuccessMsg("新股转持仓成功"); } else { return ServerResponse.createByErrorMsg("新股转持仓失败"); } } else { return ServerResponse.createByErrorMsg("新股转持仓失败"); } } /** * vip抢筹 * * @param buyNum * @param buyType * @param lever * @param profitTarget * @param stopTarget * @param request * @return */ @Transactional public ServerResponse buyVipQc(String stockCode, Integer buyNum, Integer buyType, Integer lever, BigDecimal profitTarget, BigDecimal stopTarget, HttpServletRequest request) throws Exception { /*实名认证开关开启*/ SiteProduct siteProduct = iSiteProductService.getProductSetting(); User user = this.iUserService.getCurrentRefreshUser(request); if (siteProduct.getRealNameDisplay() && (StringUtils.isBlank(user.getRealName()) || StringUtils.isBlank(user.getIdCard()))) { return ServerResponse.createByErrorMsg("下单失败,请先实名认证"); } log.info("用户 {} 下单,股票id = {} ,数量 = {} , 方向 = {} , 杠杆 = {}", new Object[]{user .getId(), stockCode, buyNum, buyType, lever}); if (siteProduct.getRealNameDisplay() && user.getIsLock().intValue() == 1) { return ServerResponse.createByErrorMsg("下单失败,账户已被锁定"); } SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting(); if (siteSetting == null) { log.error("下单出错,网站设置表不存在"); return ServerResponse.createByErrorMsg("下单失败,系统设置错误"); } ServerResponse stock_res = this.iStockService.findStockByCode(stockCode); if (!stock_res.isSuccess()) { return ServerResponse.createByErrorMsg("下单失败,股票代码错误"); } Stock stock = (Stock) stock_res.getData(); String am_begin = siteSetting.getTransAmBegin(); String am_end = siteSetting.getTransAmEnd(); String pm_begin = siteSetting.getTransPmBegin(); String pm_end = siteSetting.getTransPmEnd(); boolean am_flag = BuyAndSellUtils.isTransTime(am_begin, am_end); boolean pm_flag = BuyAndSellUtils.isTransTime(pm_begin, pm_end); log.info("是否在上午交易时间 = {} 是否在下午交易时间 = {}", Boolean.valueOf(am_flag), Boolean.valueOf(pm_flag)); if (!am_flag && !pm_flag) { return ServerResponse.createByErrorMsg("下单失败,不在交易时段内"); } if (siteProduct.getHolidayDisplay()) { return ServerResponse.createByErrorMsg("周末或节假日不能交易!"); } if (stock.getIsLock().intValue() != 0) { return ServerResponse.createByErrorMsg("下单失败,当前股票不能交易"); } List dbPosition = findPositionByStockCodeAndTimes(siteSetting.getBuySameTimes().intValue(), stock .getStockCode(), user.getId()); if (dbPosition.size() >= siteSetting.getBuySameNums().intValue()) { return ServerResponse.createByErrorMsg("频繁交易," + siteSetting.getBuySameTimes() + "分钟内同一股票持仓不得超过" + siteSetting .getBuySameNums() + "条"); } Integer transNum = findPositionNumByTimes(siteSetting.getBuyNumTimes().intValue(), user.getId()); if (transNum.intValue() / 100 >= siteSetting.getBuyNumLots().intValue()) { return ServerResponse.createByErrorMsg("频繁交易," + siteSetting .getBuyNumTimes() + "分钟内不能超过" + siteSetting.getBuyNumLots() + "手"); } if (buyNum.intValue() < siteSetting.getBuyMinNum().intValue()) { return ServerResponse.createByErrorMsg("下单失败,购买数量小于" + siteSetting .getBuyMinNum() + "股"); } if (buyNum.intValue() > siteSetting.getBuyMaxNum().intValue()) { return ServerResponse.createByErrorMsg("下单失败,购买数量大于" + siteSetting .getBuyMaxNum() + "股"); } BigDecimal now_price; StockListVO stockListVO = new StockListVO(); StockCoin stockCoin = new StockCoin(); //股票 stockListVO = StockApi.getStockRealTime(stock); now_price = new BigDecimal(stockListVO.getNowPrice()); if (now_price.compareTo(new BigDecimal("0")) == 0) { return ServerResponse.createByErrorMsg("报价0,请稍后再试"); } double stock_crease = stockListVO.getHcrate().doubleValue(); BigDecimal maxRisePercent = new BigDecimal("0"); if (stock.getStockPlate() != null) { maxRisePercent = new BigDecimal("0.2"); log.info("【科创股票】"); } else { maxRisePercent = new BigDecimal("0.1"); log.info("【普通A股】"); } if (stockListVO.getName().startsWith("ST") || stockListVO.getName().endsWith("退")) { return ServerResponse.createByErrorMsg("ST和已退市的股票不能入仓"); } BigDecimal zsPrice = new BigDecimal(stockListVO.getPreclose_px()); BigDecimal ztPrice = zsPrice.multiply(maxRisePercent).add(zsPrice); ztPrice = ztPrice.setScale(2, 4); BigDecimal chaPrice = ztPrice.subtract(zsPrice); BigDecimal ztRate = chaPrice.multiply(new BigDecimal("100")).divide(zsPrice, 2, 4); ServerResponse serverResponse = this.iStockService.selectRateByDaysAndStockCode(stock .getStockCode(), siteSetting.getStockDays().intValue()); if (!serverResponse.isSuccess()) { return serverResponse; } BigDecimal daysRate = (BigDecimal) serverResponse.getData(); log.info("股票 {} , {} 天内 涨幅 {} , 设置的涨幅 = {}", new Object[]{stock.getStockCode(), siteSetting .getStockDays(), daysRate, siteSetting.getStockRate()}); if (daysRate != null && siteSetting.getStockRate().compareTo(daysRate) == -1) { return serverResponse.createByErrorMsg(siteSetting.getStockDays() + "天内涨幅超过 " + siteSetting .getStockRate() + "不能交易"); } BigDecimal buy_amt = now_price.multiply(new BigDecimal(buyNum.intValue())); BigDecimal buy_amt_autual = buy_amt.divide(new BigDecimal(lever.intValue()), 2, 4); int compareInt = buy_amt_autual.compareTo(new BigDecimal(siteSetting.getBuyMinAmt().intValue())); if (compareInt == -1) { return ServerResponse.createByErrorMsg("下单失败,购买金额小于" + siteSetting .getBuyMinAmt() + "元"); } // if (user.getUserIndexAmt().compareTo(new BigDecimal("0")) == -1) { // return ServerResponse.createByErrorMsg("失败,指数总资金小于0"); // } UserPosition userPosition = new UserPosition(); if (profitTarget != null && profitTarget.compareTo(new BigDecimal("0")) > 0) { userPosition.setProfitTargetPrice(profitTarget); } if (stopTarget != null && stopTarget.compareTo(new BigDecimal("0")) > 0) { userPosition.setStopTargetPrice(stopTarget); } userPosition.setPositionType(user.getAccountType()); userPosition.setPositionSn(KeyUtils.getUniqueKey()); userPosition.setUserId(user.getId()); userPosition.setNickName(user.getRealName()); userPosition.setAgentId(user.getAgentId()); userPosition.setStockCode(stock.getStockCode()); userPosition.setStockName(stock.getStockName()); userPosition.setStockGid(stock.getStockGid()); userPosition.setStockSpell(stock.getStockSpell()); userPosition.setBuyOrderId(GeneratePosition.getPositionId()); userPosition.setBuyOrderTime(new Date()); userPosition.setBuyOrderPrice(now_price); userPosition.setOrderDirection((buyType.intValue() == 0) ? "买涨" : "买跌"); userPosition.setOrderNum(buyNum); if (stock.getStockPlate() != null) { userPosition.setStockPlate(stock.getStockPlate()); } userPosition.setIsLock(Integer.valueOf(0)); userPosition.setOrderLever(lever); userPosition.setOrderTotalPrice(buy_amt); //递延费特殊处理 BigDecimal stayFee = userPosition.getOrderTotalPrice().multiply(siteSetting.getStayFee()); BigDecimal allStayFee = stayFee.multiply(new BigDecimal(1)); userPosition.setOrderStayFee(allStayFee); userPosition.setOrderStayDays(1); BigDecimal buy_fee_amt = buy_amt.multiply(siteSetting.getBuyFee()).setScale(2, 4); log.info("用户购买手续费(配资后总资金 * 百分比) = {}", buy_fee_amt); userPosition.setOrderFee(buy_fee_amt); BigDecimal buy_yhs_amt = buy_amt.multiply(siteSetting.getDutyFee()).setScale(2, 4); log.info("用户购买印花税(配资后总资金 * 百分比) = {}", buy_yhs_amt); userPosition.setOrderSpread(buy_yhs_amt); SiteSpread siteSpread = iSiteSpreadService.findSpreadRateOne(new BigDecimal(stock_crease), buy_amt, stock.getStockCode(), now_price); BigDecimal spread_rate_amt = new BigDecimal("0"); if (siteSpread != null) { spread_rate_amt = buy_amt.multiply(siteSpread.getSpreadRate()).setScale(2, 4); log.info("用户购买点差费(配资后总资金 * 百分比{}) = {}", siteSpread.getSpreadRate(), spread_rate_amt); } else { log.info("用户购买点差费(配资后总资金 * 百分比{}) = {}", "设置异常", spread_rate_amt); } userPosition.setSpreadRatePrice(spread_rate_amt); BigDecimal profit_and_lose = new BigDecimal("0"); userPosition.setProfitAndLose(profit_and_lose); BigDecimal all_profit_and_lose = profit_and_lose.subtract(buy_fee_amt).subtract(buy_yhs_amt).subtract(spread_rate_amt); userPosition.setAllProfitAndLose(all_profit_and_lose); userPosition.setOrderStayDays(Integer.valueOf(0)); userPosition.setOrderStayFee(new BigDecimal("0")); int insertPositionCount = 0; this.userPositionMapper.insert(userPosition); insertPositionCount = userPosition.getId(); if (insertPositionCount > 0) { //修改用户可用余额= 当前余额-下单金额-买入手续费-印花税-点差费 //BigDecimal reckon_enable = user_enable_amt.subtract(buy_amt_autual).subtract(buy_fee_amt).subtract(buy_yhs_amt).subtract(spread_rate_amt); //修改用户可用余额= 当前余额-下单总金额 int updateUserCount = this.userMapper.updateById(user); if (updateUserCount > 0) { log.info("【用户交易下单】修改用户金额成功"); } else { log.error("用户交易下单】修改用户金额出错"); throw new Exception("用户交易下单】修改用户金额出错"); } //核算代理收入-入仓手续费 iAgentAgencyFeeService.AgencyFeeIncome(1, userPosition.getPositionSn()); log.info("【用户交易下单】保存持仓记录成功"); } else { log.error("用户交易下单】保存持仓记录出错"); throw new Exception("用户交易下单】保存持仓记录出错"); } return ServerResponse.createBySuccess("vip抢筹Order successful"); } /** * 大宗下单 * * @param stockCode * @param password * @param num * @param request * @return */ @Transactional public ServerResponse buyDz(Integer dzId, String password, Integer num, HttpServletRequest request) throws Exception { /*实名认证开关开启*/ SiteProduct siteProduct = iSiteProductService.getProductSetting(); User user = this.iUserService.getCurrentRefreshUser(request); if (siteProduct.getRealNameDisplay() && user.getIsActive() != 2) { return ServerResponse.createByErrorMsg("Order failed, please first real name authentication"); } if (siteProduct.getRealNameDisplay() && user.getIsLock().intValue() == 1) { return ServerResponse.createByErrorMsg("Order failed, account has been locked"); } UserAssets userAssets = userAssetsServices.assetsByTypeAndUserId("IN", user.getId()); if(userAssets.getAmountToBeCovered().compareTo(BigDecimal.ZERO) > 0){ return ServerResponse.createByErrorMsg("请先缴清待补资金", request); } StockDz stockDz = this.stockDzMapper.selectOne(new QueryWrapper().eq("id", dzId)); if (StringUtils.isNotEmpty(stockDz.getPassword()) && !Objects.equals(stockDz.getPassword(), password)) { return ServerResponse.createByErrorMsg("密码错误", request); } if (stockDz.getIsLock() != 0) { return ServerResponse.createByErrorMsg("股票被锁定,不能购买", request); } //价格处理 Stock stock = stockMapper.selectOne(new QueryWrapper().eq("stock_code", stockDz.getStockCode())); if(stockDz.getStartTime().getTime() > new Date().getTime() || stockDz.getEndTime().getTime() < new Date().getTime()){ return ServerResponse.createByErrorMsg("不在内幕交易时间之内", request); } // BigDecimal nowPrice = priceServices.getNowPrice(stockDz.getStockCode()).multiply(stockDz.getDiscount()); BigDecimal nowPrice = stockDz.getNowPrice(); if (nowPrice.compareTo(new BigDecimal("0")) == 0) { return ServerResponse.createByErrorMsg("股票价格0,请重试", request); } if (stockDz.getStockNum() > num) { return ServerResponse.createByErrorMsg("最小购买数据" + stockDz.getStockNum(), request); } BigDecimal siteSettingBuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.BUY_HANDLING_CHARGE.getCode()).getCValue()) ; BigDecimal buyAmt = nowPrice.multiply(new BigDecimal(num.intValue())); BigDecimal orderFree = siteSettingBuyFee.multiply(buyAmt); BigDecimal fundratio = new BigDecimal(user.getFundRatio()).divide(new BigDecimal(100)); BigDecimal availableBalance = fundratio.multiply(userAssets.getAvailableBalance()); if (availableBalance.compareTo(buyAmt.add(orderFree)) < 0) { return ServerResponse.createByErrorMsg("订单失败,配资不足", request); } //判断审核开关 if(stockDz.getSwitchType() == 1){ UserPosition userPosition = getUserPosition(dzId,num, user, stockDz, nowPrice, stock, buyAmt); UserPositionCheckDz userPositionCheckDz = Convert.convert(UserPositionCheckDz.class, userPosition); userPositionCheckDz.setDzId(dzId); userPositionCheckDzService.save(userPositionCheckDz); return ServerResponse.createBySuccess("购买成功,等待审核", request); } // 创建UserPosition对象 UserPosition userPosition = getUserPosition(dzId,num, user, stockDz, nowPrice, stock, buyAmt); userPositionMapper.insert(userPosition); BigDecimal buy_fee_amt = siteSettingBuyFee.multiply(buyAmt); userAssetsServices.availablebalanceChange(EStockType.IN.getCode(), user.getId(), EUserAssets.BUY, buyAmt.negate(),"",""); iUserAssetsServices.availablebalanceChange("IN", userAssets.getUserId(), EUserAssets.HANDLING_CHARGE, buy_fee_amt, "", ""); return ServerResponse.createBySuccess("购买成功", request); } private UserPosition getUserPosition(Integer dzId,Integer num, User user, StockDz stockDz, BigDecimal nowPrice, Stock stock, BigDecimal buyAmt) { UserPosition userPosition = new UserPosition(); userPosition.setPositionType(3); userPosition.setPositionSn(KeyUtils.getUniqueKey()); userPosition.setUserId(user.getId()); userPosition.setNickName(user.getRealName()); userPosition.setAgentId(user.getAgentId()); userPosition.setStockCode(stockDz.getStockCode()); userPosition.setStockName(stockDz.getStockName()); userPosition.setStockGid(stockDz.getStockType()); userPosition.setBuyOrderId(GeneratePosition.getPositionId()); userPosition.setBuyOrderTime(new Date()); userPosition.setBuyOrderPrice(nowPrice); userPosition.setOrderDirection("买涨"); userPosition.setOrderNum(num); userPosition.setStockSpell(stock.getStockSpell()); userPosition.setIsLock(Integer.valueOf(0)); userPosition.setOrderLever(1); userPosition.setOrderTotalPrice(buyAmt); userPosition.setSpreadRatePrice(BigDecimal.ZERO); BigDecimal profit_and_lose = new BigDecimal("0"); BigDecimal siteSettingBuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.BUY_HANDLING_CHARGE.getCode()).getCValue()) ; BigDecimal orderFree = siteSettingBuyFee.multiply(buyAmt); userPosition.setOrderFee(orderFree); userPosition.setProfitAndLose(profit_and_lose.add(orderFree)); BigDecimal all_profit_and_lose = profit_and_lose.subtract(BigDecimal.ZERO).subtract(BigDecimal.ZERO).subtract(BigDecimal.ZERO); userPosition.setAllProfitAndLose(all_profit_and_lose); userPosition.setOrderStayDays(Integer.valueOf(0)); userPosition.setOrderStayFee(new BigDecimal("0")); userPosition.setOrderSpread(BigDecimal.ZERO); userPosition.setDzId(dzId); return userPosition; } @Override public ServerResponse buyStockDzList(HttpServletRequest request) { User user = this.iUserService.getCurrentRefreshUser(request); if (user == null) { return null; } List dzList = userPositionMapper.selectList(new QueryWrapper().eq("user_id", user.getId()).eq("position_type", 3).orderByDesc("buy_order_time")); return ServerResponse.createBySuccess(dzList); } @Override @Transactional public void stockConstraint(List list) { try { SiteSetting siteSetting = iSiteSettingService.getSiteSetting(); for (UserPosition position : list) { UserAssets userAssets = userAssetsMapper.selectOne(new LambdaQueryWrapper() .eq(UserAssets::getUserId, position.getUserId()) .eq(UserAssets::getAccectType, "IN") ); if(userAssets.getAmountToBeCovered().compareTo(BigDecimal.ZERO) > 0){ continue; } //平仓检查 Result result = getResult(position); if (result == null) continue; Integer liquidation = 0; liquidation = isLiquidation(position, result.signum, result.profit, liquidation); if(liquidation != 0){ extracted(position, result.nowPrice, result.stock,liquidation); } } }catch (Exception e){ log.error("强制平仓--->错误",e); } } private Result getResult(UserPosition position) { // 检查订单是否存在 if (position == null) { log.info("订单不存在,订单id: {}", position.getId()); return null; } // 检查用户是否存在 User user = this.userMapper.selectById(position.getUserId()); if (user == null) { log.info("用户不存在,订单id: {}", position.getId()); return null; } // 检查是否在交易时间内 // if (!tradingHourService.timeCheck(position.getStockCode())) { // log.info("不在交易时间之内,订单id: {}", position.getId()); // return null; // } //判断订单 if (1 == position.getIsLock().intValue()) { log.info("订单已终止,订单id: {}", position.getId()); return null; } // 检查股票是否垫停 Stock stock = stockMapper.selectOne(new QueryWrapper().eq("stock_code", position.getStockCode())); // if (!priceServices.isLimitDownSell(stock.getStockCode())) { // log.info("股票跌停,无法平仓,订单id: {}", position.getId()); // return null; // } //最新报价 BigDecimal nowPrice = priceServices.getNowPrice(position.getStockCode()); // if (nowPrice.compareTo(BigDecimal.ZERO) <= 0) { // log.info("报价0,平仓失败,订单id: {}", position.getId()); // return null; // } //判断订单是否已到强制平仓价格 BigDecimal purchaseAmount = position.getBuyOrderPrice().multiply(new BigDecimal(position.getOrderNum()));// 买入价总额 BigDecimal nowPriceAmount = nowPrice.multiply(new BigDecimal(position.getOrderNum())); // 现价总额 BigDecimal profit = nowPriceAmount.subtract(purchaseAmount);//利润 int signum = profit.signum(); // -1, 0, 1,分别表示 负数、零、正数 Result result = new Result(stock, nowPrice, profit, signum); return result; } private static class Result { public final Stock stock;//股票 public final BigDecimal nowPrice;//现价 public final BigDecimal profit;//利润 public final int signum;// -1, 0, 1,分别表示 负数、零、正数 public Result(Stock stock, BigDecimal nowPrice, BigDecimal profit, int signum) { this.stock = stock; this.nowPrice = nowPrice; this.profit = profit; this.signum = signum; } } //判断平仓 private Integer isLiquidation(UserPosition position, int signum, BigDecimal profit, Integer liquidation) { //-1强平 0未触发 1止损强平 2止盈强平 //最新报价 BigDecimal nowPrice = priceServices.getNowPrice(position.getStockCode()); if(position.getOrderDirection().equals("买涨")){ //判断亏损金额是否达到保证金金额 BigDecimal negate = profit.negate(); //如果买涨 signum 为-1则表示亏损 if(signum == -1){ //止损 if(null != position.getStopTargetPrice() && nowPrice.compareTo(position.getStopTargetPrice()) <= 0){ //强制平仓 return liquidation = 1; } if (negate.compareTo(position.getOrderTotalPrice()) >= 0){//亏平强平 //强制平仓 return liquidation = -1; } }else{ //止盈 if(null != position.getProfitTargetPrice() && nowPrice.compareTo(position.getProfitTargetPrice()) >= 0){ //强制平仓 return liquidation = 2; } } }else{ //买跌 signum if(signum == 1){ //止损 if(null != position.getStopTargetPrice() && nowPrice.compareTo(position.getStopTargetPrice()) >= 0){ //强制平仓 return liquidation = 1; } //判断亏损金额是否达到保证金金额 if (profit.compareTo(position.getOrderTotalPrice()) >= 0){//亏平强平 //强制平仓 return liquidation = -1; } }else{ //止盈 if(null != position.getProfitTargetPrice() && nowPrice.compareTo(position.getProfitTargetPrice()) <= 0){ //强制平仓 return liquidation = 2; } } } return liquidation; } //平仓 private void extracted(UserPosition position, BigDecimal nowPrice, Stock stock,Integer liquidation) { //-1强平 0未触发 1止损强平 2止盈强平 BigDecimal siitteBuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.SELL_HANDLING_CHARGE.getCode()).getCValue()) ; BigDecimal sellOrderTotel = nowPrice.multiply(new BigDecimal(position.getOrderNum())); BigDecimal xsPrice = sellOrderTotel.multiply(siitteBuyFee);//手续费 // 更新订单信息 position.setSellOrderId(GeneratePosition.getPositionId()); position.setSellOrderPrice(nowPrice); position.setSellOrderTime(new Date()); userPositionMapper.updateById(position); if(liquidation == -1){ userAssetsServices.availablebalanceChange(stock.getStockType(), position.getUserId(), EUserAssets.CONSTRAINT_CLOSE_POSITION, position.getOrderTotalPrice(), "", ""); }else if(liquidation == 1 || liquidation == 2){ userAssetsServices.availablebalanceChange(stock.getStockType(), position.getUserId(), EUserAssets.HANDLING_CHARGE, xsPrice, "", ""); PositionProfitVO profitVO = UserPointUtil.getPositionProfitVO(position, priceServices.getNowPrice(position.getStockCode())); userAssetsServices.availablebalanceChange(stock.getStockType(), position.getUserId(), EUserAssets.CLOSE_POSITION, profitVO.getAllProfitAndLose(), "", ""); } log.info("强制平仓成功,订单id: {}", position.getId()); } }