package com.nq.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.google.gson.Gson; import com.nq.dao.*; 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.RedisShardedPoolUtils; import com.nq.utils.stock.BuyAndSellUtils; import com.nq.utils.stock.GeneratePosition; import com.nq.utils.stock.GetStayDays; import com.nq.utils.stock.lide.LiDeDataUtils; import com.nq.utils.stock.pinyin.GetPyByChinese; import com.nq.utils.stock.sina.SinaStockApi; import com.nq.vo.agent.AgentIncomeVO; import com.nq.vo.foreigncurrency.ExchangeVO; 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 net.sf.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; import java.sql.Timestamp; import java.util.*; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ObjectUtils; import static com.nq.utils.DateTimeUtil.getCurrentTimeMiao; import static com.nq.utils.DateTimeUtil.getCurrentTimeMiaoZero; @Service("iUserPositionService") public class UserPositionServiceImpl implements IUserPositionService { private static final Logger log = LoggerFactory.getLogger(UserPositionServiceImpl.class); @Autowired UserPositionMapper userPositionMapper; @Autowired IUserService iUserService; @Autowired ISiteSettingService iSiteSettingService; @Autowired ISiteSpreadService iSiteSpreadService; @Autowired IStockService iStockService; @Autowired UserMapper userMapper; @Autowired UserCashDetailMapper userCashDetailMapper; @Autowired IAgentUserService iAgentUserService; @Autowired AgentUserMapper agentUserMapper; @Autowired SiteTaskLogMapper siteTaskLogMapper; @Autowired StockMapper stockMapper; @Autowired AgentAgencyFeeMapper agentAgencyFeeMapper; @Autowired IAgentAgencyFeeService iAgentAgencyFeeService; @Autowired ISiteProductService iSiteProductService; @Autowired FundsApplyMapper fundsApplyMapper; @Autowired UserStockSubscribeMapper userStockSubscribeMapper; @Autowired StockSubscribeMapper stockSubscribeMapper; @Autowired UserIndexPositionMapper userIndexPositionMapper; @Autowired IStockFuturesService iStockFuturesService; @Autowired IStockCoinService iStockCoinService; @Autowired CurrencyUtils currencyUtils; @Autowired StockDzMapper stockDzMapper; @Transactional public ServerResponse buy(Integer stockId, Integer buyNum, Integer buyType, Integer lever, BigDecimal profitTarget, BigDecimal stopTarget, HttpServletRequest request) throws Exception { // 判断周末不能买 Date today = new Date(); Calendar c = Calendar.getInstance(); c.setTime(today); /*int weekday = c.get(Calendar.DAY_OF_WEEK); if (weekday == 1) { return ServerResponse.createByErrorMsg("周末不能购买!"); } if (weekday == 7) { return ServerResponse.createByErrorMsg("周末不能购买!"); }*/ /*实名认证开关开启*/ SiteProduct siteProduct = iSiteProductService.getProductSetting(); User user = this.iUserService.getCurrentRefreshUser(request); if (siteProduct.getRealNameDisplay() && (StringUtils.isBlank(user.getRealName()) || StringUtils.isBlank(user.getIdCard()))) { return ServerResponse.createByErrorMsg("下单失败,请先实名认证"); } BigDecimal user_enable_amt = user.getEnableAmt(); BigDecimal user_enable_withdraw_amt = user.getEnaleWithdrawAmt(); log.info("用户 {} 下单,股票id = {} ,数量 = {} , 方向 = {} , 杠杆 = {}", new Object[]{user .getId(), stockId, 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("下单失败,系统设置错误"); } Stock stock = null; ServerResponse stock_res = this.iStockService.findStockById(stockId); if (!stock_res.isSuccess()) { return ServerResponse.createByErrorMsg("下单失败,股票代码错误"); } stock = (Stock) stock_res.getData(); log.info("--------------购买逻辑股票数据 buy stock------" + new Gson().toJson(stock)); if (Objects.equals(stock.getStockType(), "us")) { String am_begin = siteSetting.getTransAmBeginUs(); String am_end = siteSetting.getTransAmEndUs(); String pm_begin = siteSetting.getTransPmBeginUs(); String pm_end = siteSetting.getTransPmEndUs(); 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("下单失败,不在美股交易时段内"); } } else if (Objects.equals(stock.getStockType(), "hk")) { String am_begin = siteSetting.getTransAmBeginhk(); String am_end = siteSetting.getTransAmEndhk(); String pm_begin = siteSetting.getTransPmBeginhk(); String pm_end = siteSetting.getTransPmEndhk(); 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("周末或节假日不能交易!"); } } else { 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 = SinaStockApi.assembleLideStockListVO(LiDeDataUtils.getStock(stock.getStockCode())); if (ObjectUtils.isEmpty(stockListVO)) { stockListVO = SinaStockApi.assembleStockListVO(SinaStockApi.getSinaStock(stock.getStockGid())); } now_price = new BigDecimal(stockListVO.getNowPrice()); // if (stock.getDataBase()!=0){ // String date = getCurrentTimeMiaoZero(); // String result = HttpClientRequest.doGet(PropertiesUtil.getProperty("changePrice.url")+"?cat_time="+date+"&stock_gid="+stock.getStockGid()+"&price="+stockListVO.getNowPrice()); // JSONObject jsonObject = JSONObject.fromObject(result); // String nowPrice = jsonObject.getJSONObject("data").getString("new_price"); // if (nowPrice!=null){ // if ("us".equals(stock.getStockType())){ // ExchangeVO exchangeVO = this.iStockFuturesService.queryExchangeVO("USD").getData(); // now_price =new BigDecimal(nowPrice).multiply(new BigDecimal(exchangeVO.getNowPrice())); // } else if ("hk".equals(stock.getStockType())){ // ExchangeVO exchangeVO = this.iStockFuturesService.queryExchangeVO("HKD").getData(); // now_price =new BigDecimal(nowPrice).multiply(new BigDecimal(exchangeVO.getNowPrice())); // } else { // now_price = new BigDecimal(nowPrice); // } // // }else { // stockListVO.setNowPrice(stockListVO.getNowPrice()); // if ("us".equals(stock.getStockType())){ // ExchangeVO exchangeVO = this.iStockFuturesService.queryExchangeVO("USD").getData(); // now_price =new BigDecimal(nowPrice).multiply(new BigDecimal(exchangeVO.getNowPrice())); // } else if ("hk".equals(stock.getStockType())){ // ExchangeVO exchangeVO = this.iStockFuturesService.queryExchangeVO("HKD").getData(); // now_price =new BigDecimal(nowPrice).multiply(new BigDecimal(exchangeVO.getNowPrice())); // } else { // now_price = new BigDecimal(nowPrice); // } // } // } // String stockOther = RedisShardedPoolUtils.get(stock.getStockName(), 8); 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); log.info("当前涨跌幅 = {} % , 涨停幅度 = {} %", Double.valueOf(stock_crease), ztRate); if ((new BigDecimal(String.valueOf(stock_crease))).compareTo(ztRate) == 0 && buyType .intValue() == 0) { return ServerResponse.createByErrorMsg("当前股票已涨停不能买涨"); } if (stock.getStockPlate() == null || StringUtils.isEmpty(stock.getStockPlate())) { int maxcrease = siteSetting.getCreaseMaxPercent().intValue(); if (stock_crease > 0.0D && stock_crease >= maxcrease) { return ServerResponse.createByErrorMsg("下单失败,股票当前涨幅:" + stock_crease + ",大于最大涨幅:" + maxcrease); } if (stock_crease < 0.0D && -stock_crease > maxcrease) { return ServerResponse.createByErrorMsg("下单失败,股票当前跌幅:" + stock_crease + ",大于最大跌幅:" + maxcrease); } } else if ("创业".equals(stock.getStockPlate())) { int maxcrease = siteSetting.getCyCreaseMaxPercent().intValue(); if (stock_crease > 0.0D && stock_crease >= maxcrease) { return ServerResponse.createByErrorMsg("下单失败,创业股当前涨幅:" + stock_crease + ",大于最大涨幅:" + maxcrease); } if (stock_crease < 0.0D && -stock_crease > maxcrease) { return ServerResponse.createByErrorMsg("下单失败,创业股当前跌幅:" + stock_crease + ",大于最大跌幅:" + maxcrease); } } else { int maxcrease = siteSetting.getKcCreaseMaxPercent().intValue(); if (stock_crease > 0.0D && stock_crease >= maxcrease) { return ServerResponse.createByErrorMsg("下单失败,科创股当前涨幅:" + stock_crease + ",大于最大涨幅:" + maxcrease); } if (stock_crease < 0.0D && -stock_crease > maxcrease) { return ServerResponse.createByErrorMsg("下单失败,科创股当前跌幅:" + stock_crease + ",大于最大跌幅:" + maxcrease); } } 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())).divide(new BigDecimal(lever.intValue())).setScale(2, 4); BigDecimal buy_amt = now_price.multiply(new BigDecimal(buyNum.intValue())); //BigDecimal buy_amt_autual = now_price.multiply(new BigDecimal(buyNum.intValue())).divide(new BigDecimal(lever.intValue()), 2, 4); 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() + "元"); } BigDecimal max_buy_amt = user_enable_amt.multiply(siteSetting.getBuyMaxAmtPercent()); int compareCwInt = buy_amt_autual.compareTo(max_buy_amt); if (compareCwInt == 1) { return ServerResponse.createByErrorMsg("下单失败,不能超过可用资金的" + siteSetting .getBuyMaxAmtPercent().multiply(new BigDecimal("100")) + "%"); } int compareUserAmtInt = user_enable_amt.compareTo(buy_amt_autual); log.info("用户可用金额 = {} 实际购买金额 = {}", user_enable_amt, buy_amt_autual); log.info("比较 用户金额 和 实际 购买金额 = {}", Integer.valueOf(compareUserAmtInt)); if (compareUserAmtInt == -1) { return ServerResponse.createByErrorMsg("下单失败,融资可用金额小于" + buy_amt_autual + "元"); } if (user.getUserIndexAmt().compareTo(new BigDecimal("0")) == -1) { return ServerResponse.createByErrorMsg("失败,指数总资金小于0"); } // if (user.getUserFutAmt().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); //修改用户可用余额= 当前余额-下单总金额 BigDecimal reckon_enable = user_enable_amt.subtract(buy_amt_autual); //修改用户可取余额=当前可取余额-下单总金额 int compareUserWithdrawAmtInt = user_enable_withdraw_amt.compareTo(buy_amt_autual); if (compareUserWithdrawAmtInt == -1) { //若可取余额小于下单总额,但是可用余额充足,令可取余额为0 user.setEnaleWithdrawAmt(BigDecimal.ZERO); } else { user_enable_withdraw_amt = user_enable_withdraw_amt.subtract(buy_amt_autual); user.setEnaleWithdrawAmt(user_enable_withdraw_amt); } user.setEnableAmt(reckon_enable); int updateUserCount = this.userMapper.updateByPrimaryKeySelective(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("下单成功"); } /** * 用户修改止盈止损 */ @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("指数持仓单不存在"); } if (profitTarget != null && profitTarget > 0) { userIndexPosition.setProfitTargetPrice(BigDecimal.valueOf(profitTarget)); } if (stopTarget != null && stopTarget > 0) { userIndexPosition.setStopTargetPrice(BigDecimal.valueOf(stopTarget)); } log.info("指数止盈线" + profitTarget + "-------指数止损线" + stopTarget); update = this.userIndexPositionMapper.updateByPrimaryKeySelective(userIndexPosition); } else { UserPosition userPosition = this.userPositionMapper.findPositionBySn(positionSn); if (userPosition == null) { return ServerResponse.createByErrorMsg("持仓记录不存在"); } 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("修改成功"); } else { return ServerResponse.createByErrorMsg("修改失败"); } } public ServerResponse sell(String positionSn, int doType) throws Exception { log.info("【用戶交易平倉】 positionSn = {} , dotype = {}", positionSn, Integer.valueOf(doType)); SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting(); if (siteSetting == null) { log.error("平倉出錯,網站設置表不存在"); return ServerResponse.createByErrorMsg("下單失敗,系統設置錯誤"); } SiteProduct siteProduct = iSiteProductService.getProductSetting(); UserPosition userPosition = this.userPositionMapper.findPositionBySn(positionSn); if (doType != 0) { if (userPosition.getStockGid().contains("us")) { String am_begin = siteSetting.getTransAmBeginUs(); String am_end = siteSetting.getTransAmEndUs(); String pm_begin = siteSetting.getTransPmBeginUs(); String pm_end = siteSetting.getTransPmEndUs(); 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("平倉失敗,不在交易時段內"); } } else if (userPosition.getStockGid().contains("hk")) { String am_begin = siteSetting.getTransAmBeginhk(); String am_end = siteSetting.getTransAmEndhk(); String pm_begin = siteSetting.getTransPmBeginhk(); String pm_end = siteSetting.getTransPmEndhk(); 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("下單失敗,不在港股股交易時段內"); } } else { 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 (userPosition == null) { return ServerResponse.createByErrorMsg("平倉失敗,訂單不存在"); } User user = this.userMapper.selectByPrimaryKey(userPosition.getUserId()); if (user == null) { return ServerResponse.createByErrorMsg("平倉失敗,用戶不存在"); } /*實名認證開關開啟*/ if (siteProduct.getRealNameDisplay() && user.getIsLock().intValue() == 1) { return ServerResponse.createByErrorMsg("平倉失敗,用戶已被鎖定"); } if (userPosition.getSellOrderId() != null) { return ServerResponse.createByErrorMsg("平倉失敗,此訂單已平倉"); } if (1 == userPosition.getIsLock().intValue()) { return ServerResponse.createByErrorMsg("平倉失敗 " + userPosition.getLockMsg()); } if (!DateTimeUtil.isCanSell(userPosition.getBuyOrderTime(), siteSetting.getCantSellTimes().intValue())) { // return ServerResponse.createByErrorMsg(siteSetting.getCantSellTimes() + "分鐘內不能平倉"); return ServerResponse.createByErrorMsg("當日成交不可平倉"); } // if (DateTimeUtil.sameDate(DateTimeUtil.getCurrentDate(),userPosition.getBuyOrderTime())) { // return ServerResponse.createByErrorMsg("當天入倉的股票需要隔天才能出倉"); // } BigDecimal now_price; StockListVO stockListVO = new StockListVO(); StockCoin stockCoin = new StockCoin(); Stock stock = stockMapper.selectOne(new QueryWrapper().eq("stock_gid", userPosition.getStockGid())); //股票賣出的 價格 數據源 stockListVO = SinaStockApi.assembleLideStockListVO(LiDeDataUtils.getStock(userPosition.getStockCode())); if (ObjectUtils.isEmpty(stockListVO)) { stockListVO = SinaStockApi.assembleStockListVO(SinaStockApi.getSinaStock(userPosition.getStockGid())); } //stockListVO = SinaStockApi.assembleStockListVO(SinaStockApi.getSinaStock(userPosition.getStockGid())); // if (stock.getDataBase() != 0) { // String date = getCurrentTimeMiaoZero(); // String result = HttpClientRequest.doGet(PropertiesUtil.getProperty("changePrice.url")+"?cat_time="+date+"&stock_gid="+stock.getStockGid()+"&price="+stockListVO.getNowPrice()); // JSONObject jsonObject = JSONObject.fromObject(result); // String nowPrice1 = jsonObject.getJSONObject("data").getString("new_price"); // if (nowPrice1!=null){ // if ("us".equals(stock.getStockType())){ // ExchangeVO exchangeVO = this.iStockFuturesService.queryExchangeVO("USD").getData(); // now_price = new BigDecimal(nowPrice1).multiply(new BigDecimal(exchangeVO.getNowPrice())); // } else if ("hk".equals(stock.getStockType())){ // ExchangeVO exchangeVO = this.iStockFuturesService.queryExchangeVO("HKD").getData(); // now_price = new BigDecimal(nowPrice1).multiply(new BigDecimal(exchangeVO.getNowPrice())); // } else { // now_price = new BigDecimal(nowPrice1); // } // // }else { // stockListVO.setNowPrice(stockListVO.getNowPrice()); // if ("us".equals(stock.getStockType())){ // ExchangeVO exchangeVO = this.iStockFuturesService.queryExchangeVO("USD").getData(); // now_price = new BigDecimal(stockListVO.getNowPrice()).multiply(new BigDecimal(exchangeVO.getNowPrice())); // } else if ("hk".equals(stock.getStockType())){ // ExchangeVO exchangeVO = this.iStockFuturesService.queryExchangeVO("HKD").getData(); // now_price = new BigDecimal(stockListVO.getNowPrice()).multiply(new BigDecimal(exchangeVO.getNowPrice())); // } else { // now_price = new BigDecimal(stockListVO.getNowPrice()); // } // } // // } if (stockListVO.getNowPrice() == null) { return ServerResponse.createByErrorMsg("平倉失敗,獲取股票信息失敗"); } now_price = new BigDecimal(stockListVO.getNowPrice()); // BigDecimal now_price = new BigDecimal(stockListVO.getNowPrice()); if (now_price.compareTo(new BigDecimal("0")) != 1) { log.error("股票 = {} 收到報價 = {}", userPosition.getStockName(), now_price); return ServerResponse.createByErrorMsg("報價0,平倉失敗,請稍後再試"); } double stock_crease = stockListVO.getHcrate().doubleValue(); BigDecimal zsPrice = new BigDecimal(stockListVO.getPreclose_px()); BigDecimal ztPrice = zsPrice.multiply(new BigDecimal("0.1")).add(zsPrice); ztPrice = ztPrice.setScale(2, 4); BigDecimal chaPrice = ztPrice.subtract(zsPrice); BigDecimal ztRate = chaPrice.multiply(new BigDecimal("100")).divide(zsPrice, 2, 4); ztRate = ztRate.negate(); log.info("股票當前漲跌幅 = {} 跌停幅度 = {}", Double.valueOf(stock_crease), ztRate); if ((new BigDecimal(String.valueOf(stock_crease))).compareTo(ztRate) == 0 && "買漲" .equals(userPosition.getOrderDirection())) { return ServerResponse.createByErrorMsg("當前股票已跌停不能賣出"); } Integer buy_num = userPosition.getOrderNum(); BigDecimal all_buy_amt = userPosition.getOrderTotalPrice(); //BigDecimal all_sell_amt = now_price.multiply(new BigDecimal(buy_num.intValue())).divide(new BigDecimal(userPosition.getOrderLever())).setScale(2,4); BigDecimal all_sell_amt = now_price.multiply(new BigDecimal(buy_num.intValue())); BigDecimal profitLoss = new BigDecimal("0"); if ("买涨".equals(userPosition.getOrderDirection())) { log.info("買賣方向:{}", "漲"); // profitLoss = all_sell_amt.subtract(all_buy_amt).multiply(new BigDecimal(userPosition.getOrderLever())).setScale(2,4); profitLoss = all_sell_amt.subtract(all_buy_amt).setScale(2,4); } else { log.info("買賣方向:{}", "跌"); // profitLoss = all_buy_amt.subtract(all_sell_amt).multiply(new BigDecimal(userPosition.getOrderLever())).setScale(2,4); profitLoss = all_buy_amt.subtract(all_sell_amt).setScale(2,4); } log.info("買入總金額 = {} , 賣出總金額 = {} , 盈虧 = {}", new Object[]{all_buy_amt, all_sell_amt, profitLoss}); BigDecimal user_all_amt = user.getUserAmt(); BigDecimal user_enable_amt = user.getEnableAmt(); log.info("用戶原本總資金 = {} , 可用 = {}", user_all_amt, user_enable_amt); BigDecimal buy_fee_amt = userPosition.getOrderFee(); log.info("買入手續費 = {}", buy_fee_amt); BigDecimal orderSpread = userPosition.getOrderSpread(); log.info("印花稅 = {}", orderSpread); BigDecimal orderStayFee = userPosition.getOrderStayFee(); log.info("遞延費 = {}", orderStayFee); BigDecimal spreadRatePrice = userPosition.getSpreadRatePrice(); log.info("點差費 = {}", spreadRatePrice); BigDecimal sell_fee_amt = all_sell_amt.multiply(siteSetting.getSellFee()).setScale(2, 4); log.info("賣出手續費 = {}", sell_fee_amt); //總手續費= 買入手續費+賣出手續費+印花稅+遞延費+點差費 BigDecimal all_fee_amt = buy_fee_amt.add(sell_fee_amt).add(orderSpread).add(orderStayFee).add(spreadRatePrice); log.info("總的手續費費用 = {}", all_fee_amt); userPosition.setSellOrderId(GeneratePosition.getPositionId()); userPosition.setSellOrderPrice(now_price); userPosition.setSellOrderTime(new Date()); BigDecimal order_fee_all = buy_fee_amt.add(sell_fee_amt); userPosition.setOrderFee(order_fee_all); userPosition.setProfitAndLose(profitLoss); BigDecimal all_profit = profitLoss.subtract(all_fee_amt); userPosition.setAllProfitAndLose(all_profit); int updatePositionCount = this.userPositionMapper.updateByPrimaryKeySelective(userPosition); if (updatePositionCount > 0) { log.info("【用戶平倉】修改浮動盈虧記錄成功"); } else { log.error("用戶平倉】修改浮動盈虧記錄出錯"); throw new Exception("用戶平倉】修改浮動盈虧記錄出錯"); } BigDecimal freez_amt = all_buy_amt.divide(new BigDecimal(userPosition.getOrderLever().intValue()), 2, 4); //BigDecimal freez_amt = all_buy_amt; BigDecimal reckon_all = user_all_amt.add(all_profit); //修改用戶可用余額=當前可用余額+總盈虧+買入總金額+追加保證金 BigDecimal reckon_enable = user_enable_amt.add(all_profit).add(freez_amt).add(userPosition.getMarginAdd()); log.info("用戶平倉後的總資金 = {} , 可用資金 = {}", reckon_all, reckon_enable); user.setUserAmt(reckon_all); user.setEnableAmt(reckon_enable); int updateUserCount = this.userMapper.updateByPrimaryKeySelective(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(all_profit); ucd.setDeSummary("賣出股票," + userPosition.getStockCode() + "/" + userPosition.getStockName() + ",占用本金:" + freez_amt + ",總手續費:" + all_fee_amt + ",遞延費:" + orderStayFee + ",印花稅:" + orderSpread + ",盈虧:" + profitLoss + ",總盈虧:" + all_profit); ucd.setAddTime(new Date()); ucd.setIsRead(Integer.valueOf(0)); int insertSxfCount = this.userCashDetailMapper.insert(ucd); if (insertSxfCount > 0) { //核算代理收入-平倉手續費 iAgentAgencyFeeService.AgencyFeeIncome(2, userPosition.getPositionSn()); //核算代理收入-分紅 iAgentAgencyFeeService.AgencyFeeIncome(4, userPosition.getPositionSn()); log.info("【用戶平倉】保存明細記錄成功"); } else { log.error("用戶平倉】保存明細記錄出錯"); throw new Exception("用戶平倉】保存明細記錄出錯"); } return ServerResponse.createBySuccessMsg("平倉成功!"); } public ServerResponse sellbf(String positionSn, Integer quantity) throws Exception { log.info("【用戶交易部分平倉】 positionSn = {} , dotype = {}", positionSn, Integer.valueOf(quantity)); SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting(); if (siteSetting == null) { log.error("平倉出錯,網站設置表不存在"); return ServerResponse.createByErrorMsg("下單失敗,系統設置錯誤"); } SiteProduct siteProduct = iSiteProductService.getProductSetting(); UserPosition userPosition = this.userPositionMapper.findPositionBySn(positionSn); //部分平仓数量等于订单总数量,则调用全平接口 if(quantity.equals(userPosition.getOrderNum())){ return sell(positionSn,1); } //校验时间 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 (userPosition == null) { return ServerResponse.createByErrorMsg("平倉失敗,訂單不存在"); } User user = this.userMapper.selectByPrimaryKey(userPosition.getUserId()); if (user == null) { return ServerResponse.createByErrorMsg("平倉失敗,用戶不存在"); } /*實名認證開關開啟*/ if (siteProduct.getRealNameDisplay() && user.getIsLock().intValue() == 1) { return ServerResponse.createByErrorMsg("平倉失敗,用戶已被鎖定"); } if (userPosition.getSellOrderId() != null) { return ServerResponse.createByErrorMsg("平倉失敗,此訂單已平倉"); } if (1 == userPosition.getIsLock().intValue()) { return ServerResponse.createByErrorMsg("平倉失敗 " + userPosition.getLockMsg()); } if (!DateTimeUtil.isCanSell(userPosition.getBuyOrderTime(), siteSetting.getCantSellTimes().intValue())) { return ServerResponse.createByErrorMsg("當日成交不可平倉"); } BigDecimal now_price; StockListVO stockListVO = new StockListVO(); //股票賣出的 價格 數據源 stockListVO = SinaStockApi.assembleLideStockListVO(LiDeDataUtils.getStock(userPosition.getStockCode())); if (ObjectUtils.isEmpty(stockListVO)) { stockListVO = SinaStockApi.assembleStockListVO(SinaStockApi.getSinaStock(userPosition.getStockGid())); } if (stockListVO.getNowPrice() == null) { return ServerResponse.createByErrorMsg("平倉失敗,獲取股票信息失敗"); } now_price = new BigDecimal(stockListVO.getNowPrice()); if (now_price.compareTo(new BigDecimal("0")) != 1) { log.error("股票 = {} 收到報價 = {}", userPosition.getStockName(), now_price); return ServerResponse.createByErrorMsg("報價0,平倉失敗,請稍後再試"); } double stock_crease = stockListVO.getHcrate().doubleValue(); BigDecimal zsPrice = new BigDecimal(stockListVO.getPreclose_px()); BigDecimal ztPrice = zsPrice.multiply(new BigDecimal("0.1")).add(zsPrice); ztPrice = ztPrice.setScale(2, 4); BigDecimal chaPrice = ztPrice.subtract(zsPrice); BigDecimal ztRate = chaPrice.multiply(new BigDecimal("100")).divide(zsPrice, 2, 4); ztRate = ztRate.negate(); log.info("股票當前漲跌幅 = {} 跌停幅度 = {}", Double.valueOf(stock_crease), ztRate); if ((new BigDecimal(String.valueOf(stock_crease))).compareTo(ztRate) == 0 && "買漲" .equals(userPosition.getOrderDirection())) { return ServerResponse.createByErrorMsg("當前股票已跌停不能賣出"); } if (quantity <= 0) { return ServerResponse.createByErrorMsg("平倉失敗, 平仓数量不可小于0"); } if (quantity > userPosition.getOrderNum()) { return ServerResponse.createByErrorMsg("平倉失敗,平仓数量不可小于"+userPosition.getOrderNum()); } // Integer buy_num = userPosition.getOrderNum(); Integer buy_num = quantity; // BigDecimal all_buy_amt = userPosition.getOrderTotalPrice(); BigDecimal all_buy_amt = userPosition.getBuyOrderPrice().multiply(new BigDecimal(buy_num)).setScale(2,4); BigDecimal all_sell_amt = now_price.multiply(new BigDecimal(buy_num.intValue())); BigDecimal profitLoss = new BigDecimal("0"); if ("买涨".equals(userPosition.getOrderDirection())) { log.info("買賣方向:{}", "漲"); profitLoss = all_sell_amt.subtract(all_buy_amt).setScale(2,4); } else { log.info("買賣方向:{}", "跌"); profitLoss = all_buy_amt.subtract(all_sell_amt).setScale(2,4); } log.info("買入總金額 = {} , 賣出總金額 = {} , 盈虧 = {}", new Object[]{all_buy_amt, all_sell_amt, profitLoss}); BigDecimal user_all_amt = user.getUserAmt(); BigDecimal user_enable_amt = user.getEnableAmt(); log.info("用戶原本總資金 = {} , 可用 = {}", user_all_amt, user_enable_amt); BigDecimal buy_fee_amt = all_buy_amt.multiply(siteSetting.getBuyFee()).setScale(2,4); log.info("買入手續費 = {}", buy_fee_amt); BigDecimal orderSpread = all_buy_amt.multiply(siteSetting.getDutyFee()).setScale(2, 4); log.info("印花稅 = {}", orderSpread); // BigDecimal orderStayFee = all_buy_amt.multiply(siteSetting.getStayFee()).setScale(2, 4); // log.info("遞延費 = {}", orderStayFee); // // BigDecimal spreadRatePrice = userPosition.getSpreadRatePrice(); // log.info("點差費 = {}", spreadRatePrice); BigDecimal sell_fee_amt = all_sell_amt.multiply(siteSetting.getSellFee()).setScale(2, 4); log.info("賣出手續費 = {}", sell_fee_amt); //總手續費= 買入手續費+賣出手續費+印花稅+遞延費+點差費 // BigDecimal all_fee_amt = buy_fee_amt.add(sell_fee_amt).add(orderSpread).add(orderStayFee).add(spreadRatePrice); BigDecimal all_fee_amt = buy_fee_amt.add(sell_fee_amt).add(orderSpread); log.info("總的手續費費用 = {}", all_fee_amt); //复制一条新订单 UserPosition userPositionNew = new UserPosition(); BeanUtils.copyProperties(userPosition, userPositionNew); userPositionNew.setId(null); userPositionNew.setBuyOrderId(GeneratePosition.getPositionId()); userPositionNew.setPositionSn(KeyUtils.getUniqueKey()); userPositionNew.setOrderNum(buy_num); userPositionNew.setOrderTotalPrice(all_buy_amt); userPositionNew.setSellOrderId(GeneratePosition.getPositionId()); userPositionNew.setSellOrderPrice(now_price); userPositionNew.setSellOrderTime(new Date()); BigDecimal order_fee_all = buy_fee_amt.add(sell_fee_amt); userPositionNew.setOrderFee(order_fee_all); userPositionNew.setOrderSpread(orderSpread); userPositionNew.setProfitAndLose(profitLoss); BigDecimal all_profit = profitLoss.subtract(all_fee_amt); userPositionNew.setAllProfitAndLose(all_profit); userPositionMapper.insert(userPositionNew); //修改原订单 userPosition.setOrderNum(userPosition.getOrderNum() - userPositionNew.getOrderNum()); userPosition.setOrderTotalPrice(userPosition.getOrderTotalPrice().subtract(userPositionNew.getOrderTotalPrice())); userPosition.setOrderFee(userPosition.getOrderFee().subtract(buy_fee_amt)); userPosition.setOrderSpread(userPosition.getOrderSpread().subtract(orderSpread)); int updatePositionCount = this.userPositionMapper.updateByPrimaryKeySelective(userPosition); if (updatePositionCount > 0) { log.info("【用戶平倉】修改浮動盈虧記錄成功"); } else { log.error("用戶平倉】修改浮動盈虧記錄出錯"); throw new Exception("用戶平倉】修改浮動盈虧記錄出錯"); } BigDecimal freez_amt = all_buy_amt.divide(new BigDecimal(userPositionNew.getOrderLever().intValue()), 2, 4); BigDecimal reckon_all = user_all_amt.add(all_profit); //修改用戶可用余額=當前可用余額+總盈虧+買入總金額+追加保證金 BigDecimal reckon_enable = user_enable_amt.add(all_profit).add(freez_amt).add(userPositionNew.getMarginAdd()); log.info("用戶平倉後的總資金 = {} , 可用資金 = {}", reckon_all, reckon_enable); user.setUserAmt(reckon_all); user.setEnableAmt(reckon_enable); int updateUserCount = this.userMapper.updateByPrimaryKeySelective(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(all_profit); ucd.setDeSummary("賣出股票," + userPositionNew.getStockCode() + "/" + userPositionNew.getStockName() + ",占用本金:" + freez_amt + ",總手續費:" + all_fee_amt + ",遞延費:" + 0 + ",印花稅:" + orderSpread + ",盈虧:" + profitLoss + ",總盈虧:" + all_profit); ucd.setAddTime(new Date()); ucd.setIsRead(Integer.valueOf(0)); int insertSxfCount = this.userCashDetailMapper.insert(ucd); if (insertSxfCount > 0) { //核算代理收入-平倉手續費 iAgentAgencyFeeService.AgencyFeeIncome(2, userPositionNew.getPositionSn()); //核算代理收入-分紅 iAgentAgencyFeeService.AgencyFeeIncome(4, userPositionNew.getPositionSn()); log.info("【用戶平倉】保存明細記錄成功"); } else { log.error("用戶平倉】保存明細記錄出錯"); throw new Exception("用戶平倉】保存明細記錄出錯"); } 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) { /*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("追加失败,不在交易时段内"); }*/ } UserPosition userPosition = this.userPositionMapper.findPositionBySn(positionSn); if (userPosition == null) { return ServerResponse.createByErrorMsg("追加失败,订单不存在"); } User user = this.userMapper.selectByPrimaryKey(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 = user.getUserAmt(); BigDecimal user_enable_amt = user.getEnableAmt(); 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); user.setEnableAmt(reckon_enable); int updateUserCount = this.userMapper.updateByPrimaryKeySelective(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("该持仓不存在"); } /*if (position.getSellOrderId() == null) { return ServerResponse.createByErrorMsg("持仓单不能删除!"); }*/ int updateCount = this.userPositionMapper.deleteByPrimaryKey(positionId); if (updateCount > 0) { return ServerResponse.createBySuccessMsg("删除成功"); } return ServerResponse.createByErrorMsg("删除失败"); } public ServerResponse findMyPositionByCodeAndSpell(String stockCode, String stockSpell, Integer state, HttpServletRequest request, int pageNum, int pageSize) { User user = this.iUserService.getCurrentUser(request); PageHelper.startPage(pageNum, pageSize); List userPositions = this.userPositionMapper.findMyPositionByCodeAndSpell(user.getId(), stockCode, stockSpell, state); List userPositionVOS = Lists.newArrayList(); if (userPositions.size() > 0) { for (UserPosition position : userPositions) { UserPositionVO userPositionVO = assembleUserPositionVO(position); userPositionVO.setBuyAmtAutual( position.getBuyOrderPrice() .multiply(new BigDecimal(position.getOrderNum())) .divide(new BigDecimal(position.getOrderLever()), 2, RoundingMode.HALF_UP) ); 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) { StockListVO stockListVO = SinaStockApi.assembleLideStockListVO(LiDeDataUtils.getStock(position.getStockCode())); if (ObjectUtils.isEmpty(stockListVO)) { stockListVO = SinaStockApi.assembleStockListVO(SinaStockApi.getSinaStock(position.getStockGid())); } if (stockListVO.getNowPrice() == null || new BigDecimal(stockListVO.getNowPrice()).compareTo(BigDecimal.ZERO) <= 0) { // stockListVO.setNowPrice("0"); stockListVO.setNowPrice(String.valueOf(position.getBuyOrderIdIndex())); } BigDecimal nowPrice = new BigDecimal(stockListVO.getNowPrice()); if (nowPrice.compareTo(new BigDecimal("0")) != 0) { BigDecimal buyPrice = position.getBuyOrderPrice(); BigDecimal subPrice = nowPrice.subtract(buyPrice); BigDecimal profit_and_lose = subPrice.multiply(new BigDecimal(position.getOrderNum().intValue())); //BigDecimal profit_and_lose = subPrice.multiply(new BigDecimal(position.getOrderNum().intValue())).divide(new BigDecimal(position.getOrderLever())).setScale(2,4); if ("买跌".equals(position.getOrderDirection())) { profit_and_lose = profit_and_lose.negate(); } BigDecimal total_fee = position.getOrderFee().add(position.getOrderSpread()).add(position.getOrderStayFee()); BigDecimal position_profit = profit_and_lose.subtract(total_fee); allProfitAndLose = allProfitAndLose.add(position_profit); BigDecimal position_freez = position.getOrderTotalPrice().divide(new BigDecimal(position.getOrderLever().intValue()), 2, 4); //BigDecimal position_freez = position.getOrderTotalPrice(); allFreezAmt = allFreezAmt.add(position_freez).add(position.getMarginAdd()); continue; } log.info("查询所有持仓单的总盈亏,现价返回0,当前为集合竞价"); } //加上分仓交易保证金 List fundsApplyList = fundsApplyMapper.getUserMarginList(userId); for (FundsApply fundsApply : fundsApplyList) { allFreezAmt = allFreezAmt.add(fundsApply.getMargin()); } 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); } PageHelper.startPage(pageNum, pageSize); List userPositions = this.userPositionMapper.listByAgent(positionType, state, userId, searchId, positionSn, begin_time, end_time); 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 userPositions = this.userPositionMapper.listByAgent(positionType, Integer.valueOf(1), null, agentId, null, begin_time, end_time); 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) { 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 userPositions = this.userPositionMapper.listByAgent(positionType, state, userId, agentId, positionSn, begin_time, end_time); List adminPositionVOS = Lists.newArrayList(); for (UserPosition position : userPositions) { AdminPositionVO adminPositionVO = assembleAdminPositionVO(position); adminPositionVOS.add(adminPositionVO); } PageInfo pageInfo = new PageInfo(userPositions); pageInfo.setList(adminPositionVOS); return ServerResponse.createBySuccess(pageInfo); } 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.selectByPrimaryKey(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("股票不存在"); } log.info("--------------购买逻辑股票数据 create stock------" + new Gson().toJson(stock)); SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting(); if (siteSetting == null) { log.error("下单出错,网站设置表不存在"); return ServerResponse.createByErrorMsg("下单失败,系统设置错误"); } BigDecimal user_enable_amt = user.getEnableAmt(); BigDecimal buy_amt = (new BigDecimal(buyPrice)).multiply(new BigDecimal(buyNum.intValue())); BigDecimal buy_amt_autual = buy_amt.divide(new BigDecimal(lever.intValue()), 2, 4); int compareUserAmtInt = user_enable_amt.compareTo(buy_amt_autual); log.info("用户可用金额 = {} 实际购买金额 = {}", user_enable_amt, buy_amt_autual); log.info("比较 用户金额 和 实际 购买金额 = {}", Integer.valueOf(compareUserAmtInt)); if (compareUserAmtInt == -1) { log.info("下单失败,用户可用金额小于" + buy_amt_autual + "元"); return ServerResponse.createByErrorMsg("下单失败,用户可用金额小于" + buy_amt_autual + "元"); } if (user.getUserIndexAmt().compareTo(new BigDecimal("0")) == -1) { log.info("失败,指数总资金小于0"); 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(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 = SinaStockApi.assembleLideStockListVO(LiDeDataUtils.getStock(stock.getStockCode())); if (ObjectUtils.isEmpty(stockListVO)) { stockListVO = SinaStockApi.assembleStockListVO(SinaStockApi.getSinaStock(stock.getStockGid())); } 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("【创建持仓】保存记录出错"); } BigDecimal reckon_enable = user_enable_amt.subtract(buy_amt_autual); user.setEnableAmt(reckon_enable); int updateUserCount = this.userMapper.updateByPrimaryKeySelective(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 = getPositionProfitVO(position); adminPositionVO.setProfitAndLose(positionProfitVO.getProfitAndLose()); adminPositionVO.setAllProfitAndLose(positionProfitVO.getAllProfitAndLose()); adminPositionVO.setNow_price(positionProfitVO.getNowPrice()); return adminPositionVO; } private AgentPositionVO assembleAgentPositionVO(UserPosition position) { AgentPositionVO agentPositionVO = new AgentPositionVO(); 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 = getPositionProfitVO(position); agentPositionVO.setProfitAndLose(positionProfitVO.getProfitAndLose()); agentPositionVO.setAllProfitAndLose(positionProfitVO.getAllProfitAndLose()); agentPositionVO.setNow_price(positionProfitVO.getNowPrice()); return agentPositionVO; } private UserPositionVO assembleUserPositionVO(UserPosition position) { UserPositionVO userPositionVO = new UserPositionVO(); userPositionVO.setId(position.getId()); userPositionVO.setPositionType(position.getPositionType()); userPositionVO.setPositionSn(position.getPositionSn()); userPositionVO.setUserId(position.getUserId()); userPositionVO.setNickName(position.getNickName()); userPositionVO.setAgentId(position.getAgentId()); userPositionVO.setStockName(position.getStockName()); userPositionVO.setStockCode(position.getStockCode()); userPositionVO.setStockGid(position.getStockGid()); userPositionVO.setStockSpell(position.getStockSpell()); userPositionVO.setBuyOrderId(position.getBuyOrderId()); userPositionVO.setBuyOrderTime(position.getBuyOrderTime()); userPositionVO.setBuyOrderPrice(position.getBuyOrderPrice()); userPositionVO.setSellOrderId(position.getSellOrderId()); userPositionVO.setSellOrderTime(position.getSellOrderTime()); userPositionVO.setSellOrderPrice(position.getSellOrderPrice()); userPositionVO.setProfitTargetPrice(position.getProfitTargetPrice()); userPositionVO.setStopTargetPrice(position.getStopTargetPrice()); userPositionVO.setOrderDirection(position.getOrderDirection()); userPositionVO.setOrderNum(position.getOrderNum()); userPositionVO.setOrderLever(position.getOrderLever()); userPositionVO.setOrderTotalPrice(position.getOrderTotalPrice()); userPositionVO.setOrderFee(position.getOrderFee()); userPositionVO.setOrderSpread(position.getOrderSpread()); userPositionVO.setOrderStayFee(position.getOrderStayFee()); userPositionVO.setOrderStayDays(position.getOrderStayDays()); userPositionVO.setMarginAdd(position.getMarginAdd()); userPositionVO.setStockPlate(position.getStockPlate()); userPositionVO.setSpreadRatePrice(position.getSpreadRatePrice()); PositionProfitVO positionProfitVO = getPositionProfitVO(position); userPositionVO.setProfitAndLose(positionProfitVO.getProfitAndLose()); userPositionVO.setAllProfitAndLose(positionProfitVO.getAllProfitAndLose()); userPositionVO.setNow_price(positionProfitVO.getNowPrice()); userPositionVO.setAllProfitAndLoseStr(positionProfitVO.getAllProfitAndLoseStr()); return userPositionVO; } public PositionProfitVO getPositionProfitVO(UserPosition position) { BigDecimal profitAndLose = new BigDecimal("0"); BigDecimal allProfitAndLose = new BigDecimal("0"); String allProfitAndLoseStr = ""; String nowPrice = ""; if (position.getSellOrderId() != null) { BigDecimal subPrice = position.getSellOrderPrice().subtract(position.getBuyOrderPrice()); // profitAndLose = subPrice.multiply(new BigDecimal(position.getOrderNum().intValue())).multiply(new BigDecimal(position.getOrderLever())).setScale(2,4); profitAndLose = subPrice.multiply(new BigDecimal(position.getOrderNum().intValue())).setScale(2,4); if ("买跌".equals(position.getOrderDirection())) { profitAndLose = profitAndLose.negate(); } allProfitAndLose = profitAndLose.subtract(position.getOrderFee()).subtract(position.getOrderSpread()).subtract(position.getOrderStayFee()).subtract(position.getSpreadRatePrice()); } else { StockListVO stockListVO = new StockListVO(); StockCoin stockCoin = new StockCoin(); stockListVO = SinaStockApi.assembleLideStockListVO(LiDeDataUtils.getStock(position.getStockCode())); if (ObjectUtils.isEmpty(stockListVO)) { stockListVO = SinaStockApi.assembleStockListVO(SinaStockApi.getSinaStock(position.getStockGid())); } // stockListVO = SinaStockApi.assembleStockListVO(SinaStockApi.getSinaStock(position.getStockGid())); nowPrice = stockListVO.getNowPrice(); if (nowPrice == null || new BigDecimal(stockListVO.getNowPrice()).compareTo(BigDecimal.ZERO) <= 0) { if(null != position.getBuyOrderIdIndex() && position.getBuyOrderIdIndex().compareTo(BigDecimal.ZERO) > 0){ nowPrice = String.valueOf(position.getBuyOrderIdIndex()); }else { nowPrice = String.valueOf(position.getBuyOrderPrice()); } } BigDecimal subPrice = (new BigDecimal(nowPrice)).subtract(position.getBuyOrderPrice()); // profitAndLose = subPrice.multiply(new BigDecimal(position.getOrderNum().intValue())).multiply(new BigDecimal(position.getOrderLever())).setScale(2,4); profitAndLose = subPrice.multiply(new BigDecimal(position.getOrderNum().intValue())).setScale(2,4); if ("买跌".equals(position.getOrderDirection())) { profitAndLose = profitAndLose.negate(); } //总盈亏= 浮动盈亏 – 手续费 – 印花税 – 留仓费 – 点差费 allProfitAndLose = profitAndLose.subtract(position.getOrderFee()).subtract(position.getOrderSpread()).subtract(position.getOrderStayFee()).subtract(position.getSpreadRatePrice()); //改成盈亏百分比 BigDecimal allProfitAndLoseStrTemp = new BigDecimal(nowPrice).subtract(position.getBuyOrderPrice()).divide(position.getBuyOrderPrice(), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).setScale(2,4); allProfitAndLoseStr = allProfitAndLoseStrTemp.toString() + "%"; } PositionProfitVO positionProfitVO = new PositionProfitVO(); positionProfitVO.setProfitAndLose(profitAndLose); positionProfitVO.setAllProfitAndLose(allProfitAndLose); positionProfitVO.setAllProfitAndLoseStr(allProfitAndLoseStr); positionProfitVO.setNowPrice(nowPrice); return positionProfitVO; } /*股票入仓最新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 = assembleUserPositionVO(position); 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 = assembleUserPositionVO(position); } 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) { UserStockSubscribe userStockSubscribe = userStockSubscribeMapper.load(id); if (userStockSubscribe == null) { return ServerResponse.createByErrorMsg("无该申购记录"); } StockSubscribe stockSubscribe = stockSubscribeMapper.selectOne(new QueryWrapper().eq("code", userStockSubscribe.getNewCode())); if (userStockSubscribe == null) { return ServerResponse.createByErrorMsg("该新股不存在"); } if ((userStockSubscribe.getStatus() == 4 || userStockSubscribe.getStatus() == 3) && (userStockSubscribe.getType() == 2 || userStockSubscribe.getType() == 1)) { // String sinaStock = SinaStockApi.getSinaStock(stockSubscribe.getStockType()+userStockSubscribe.getNewCode()); // String[] arrayOfString = sinaStock.split(","); // if (arrayOfString.length < 10){ // return ServerResponse.createByErrorMsg("數據源無該新股數據,轉持倉失敗"); // } UserPosition userPosition = new UserPosition(); userPosition.setPositionType(1); userPosition.setPositionSn(KeyUtils.getUniqueKey()); userPosition.setUserId(userStockSubscribe.getUserId()); userPosition.setNickName(userStockSubscribe.getRealName()); userPosition.setAgentId(userStockSubscribe.getAgentId()); userPosition.setStockCode(userStockSubscribe.getNewCode()); userPosition.setStockName(userStockSubscribe.getNewName()); userPosition.setStockGid(stockSubscribe.getStockType() + userStockSubscribe.getNewCode()); 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 buy_fee_amt = new BigDecimal(0); 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); // 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); // } 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")); log.info("--------------购买逻辑股票数据 newStockToPosition stock------" + new Gson().toJson(userPosition)); int ret = 0; ret = this.userPositionMapper.insert(userPosition); if (ret > 0) { userStockSubscribe.setStatus(5); userStockSubscribeMapper.update1(userStockSubscribe); if (userStockSubscribe.getType() == 1 || userStockSubscribe.getType() == 2) { User user = userMapper.selectByPrimaryKey(userStockSubscribe.getUserId()); user.setDjzj(user.getDjzj().subtract(userStockSubscribe.getBond())); ret = userMapper.updateByPrimaryKey(user); } if (ret > 0) { return ServerResponse.createBySuccessMsg("新股轉持倉成功"); } else { return ServerResponse.createByErrorMsg("新股轉持倉失敗"); } } else { return ServerResponse.createByErrorMsg("新股轉持倉失敗"); } } return ServerResponse.createByErrorMsg("新股轉持倉失敗"); } @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); } /** * 大宗下單 * * @param stockCode * @param password * @param num * @param request * @return */ @Transactional public ServerResponse buyDz(String stockCode, String password, Integer num, 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("下單失敗,請先實名認證"); } BigDecimal user_enable_amt = user.getEnableAmt(); BigDecimal user_enable_withdraw_amt = user.getEnaleWithdrawAmt(); log.info("用戶 {} 下單,股票code = {} ,數量 = {}", new Object[]{user .getId(), stockCode, num}); if (siteProduct.getRealNameDisplay() && user.getIsLock().intValue() == 1) { return ServerResponse.createByErrorMsg("下單失敗,賬戶已被鎖定"); } SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting(); if (siteSetting == null) { log.error("下單出錯,網站設置表不存在"); return ServerResponse.createByErrorMsg("下單失敗,系統設置錯誤"); } StockDz stockDz = null; stockDz = this.stockDzMapper.selectOne(new QueryWrapper().eq("stock_code", stockCode)); String am_begin = siteSetting.getTransAmBeginhk(); String am_end = siteSetting.getTransAmEndhk(); String pm_begin = siteSetting.getTransPmBeginhk(); String pm_end = siteSetting.getTransPmEndhk(); boolean am_flag = BuyAndSellUtils.isTransTime(am_begin, am_end); boolean pm_flag = BuyAndSellUtils.isTransTime(pm_begin, pm_end); log.info("是否在大宗交易時間 = {}", Boolean.valueOf(pm_flag)); //15-15:30 // if (!pm_flag) { // return ServerResponse.createByErrorMsg("下單失敗,不在交易時段內"); // } if (siteProduct.getHolidayDisplay()) { return ServerResponse.createByErrorMsg("周末或節假日不能交易!"); } if (!Objects.equals(stockDz.getPassword(), password)) { return ServerResponse.createByErrorMsg("下單失敗,密鑰錯誤"); } if (stockDz.getIsLock().intValue() != 0) { return ServerResponse.createByErrorMsg("下單失敗,當前股票不能交易"); } List dbPosition = findPositionByStockCodeAndTimes(siteSetting.getBuySameTimes().intValue(), stockDz.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 (num < stockDz.getStockNum().intValue()) { return ServerResponse.createByErrorMsg("下單失敗,購買數量最小為" + stockDz.getStockNum() + "股"); } if (num > siteSetting.getBuyMaxNum()) { return ServerResponse.createByErrorMsg("下單失敗,購買數量大於" + siteSetting.getBuyMaxNum() + "股"); } BigDecimal now_price; StockListVO stockListVO = new StockListVO(); //價格處理 stockListVO = SinaStockApi.assembleLideStockListVO(LiDeDataUtils.getStock(stockDz.getStockCode())); if (ObjectUtils.isEmpty(stockListVO)) { stockListVO = SinaStockApi.assembleStockListVO(SinaStockApi.getSinaStock(stockDz.getStockGid())); } now_price = new BigDecimal(stockListVO.getNowPrice()).multiply(stockDz.getDiscount()); if (now_price.compareTo(new BigDecimal("0")) == 0) { return ServerResponse.createByErrorMsg("報價0,請稍後再試"); } double stock_crease = stockListVO.getHcrate().doubleValue(); BigDecimal maxRisePercent = new BigDecimal("0"); if (stockDz.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); log.info("當前漲跌幅 = {} % , 漲停幅度 = {} %", Double.valueOf(stock_crease), ztRate); if (stockDz.getStockPlate() == null || StringUtils.isEmpty(stockDz.getStockPlate())) { int maxcrease = siteSetting.getCreaseMaxPercent().intValue(); if (stock_crease > 0.0D && stock_crease >= maxcrease) { return ServerResponse.createByErrorMsg("下單失敗,股票當前漲幅:" + stock_crease + ",大於最大漲幅:" + maxcrease); } if (stock_crease < 0.0D && -stock_crease > maxcrease) { return ServerResponse.createByErrorMsg("下單失敗,股票當前跌幅:" + stock_crease + ",大於最大跌幅:" + maxcrease); } } else if ("創業".equals(stockDz.getStockPlate())) { int maxcrease = siteSetting.getCyCreaseMaxPercent().intValue(); if (stock_crease > 0.0D && stock_crease >= maxcrease) { return ServerResponse.createByErrorMsg("下單失敗,創業股當前漲幅:" + stock_crease + ",大於最大漲幅:" + maxcrease); } if (stock_crease < 0.0D && -stock_crease > maxcrease) { return ServerResponse.createByErrorMsg("下單失敗,創業股當前跌幅:" + stock_crease + ",大於最大跌幅:" + maxcrease); } } else { int maxcrease = siteSetting.getKcCreaseMaxPercent().intValue(); if (stock_crease > 0.0D && stock_crease >= maxcrease) { return ServerResponse.createByErrorMsg("下單失敗,科創股當前漲幅:" + stock_crease + ",大於最大漲幅:" + maxcrease); } if (stock_crease < 0.0D && -stock_crease > maxcrease) { return ServerResponse.createByErrorMsg("下單失敗,科創股當前跌幅:" + stock_crease + ",大於最大跌幅:" + maxcrease); } } ServerResponse serverResponse = this.iStockService.selectRateByDaysAndStockCode(stockDz.getStockCode(), siteSetting.getStockDays().intValue()); if (!serverResponse.isSuccess()) { return serverResponse; } BigDecimal daysRate = (BigDecimal) serverResponse.getData(); log.info("股票 {} , {} 天內 漲幅 {} , 設置的漲幅 = {}", new Object[]{stockDz.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())).divide(new BigDecimal(lever.intValue())).setScale(2, 4); BigDecimal buy_amt = now_price.multiply(new BigDecimal(num.intValue())); //BigDecimal buy_amt_autual = now_price.multiply(new BigDecimal(buyNum.intValue())).divide(new BigDecimal(lever.intValue()), 2, 4); BigDecimal buy_amt_autual = buy_amt.divide(new BigDecimal(1), 2, 4); int compareInt = buy_amt_autual.compareTo(new BigDecimal(siteSetting.getBuyMinAmt().intValue())); if (compareInt == -1) { return ServerResponse.createByErrorMsg("下單失敗,購買金額小於" + siteSetting .getBuyMinAmt() + "元"); } BigDecimal max_buy_amt = user_enable_amt.multiply(siteSetting.getBuyMaxAmtPercent()); int compareCwInt = buy_amt_autual.compareTo(max_buy_amt); if (compareCwInt == 1) { return ServerResponse.createByErrorMsg("下單失敗,不能超過可用資金的" + siteSetting .getBuyMaxAmtPercent().multiply(new BigDecimal("100")) + "%"); } int compareUserAmtInt = user_enable_amt.compareTo(buy_amt_autual); log.info("用戶可用金額 = {} 實際購買金額 = {}", user_enable_amt, buy_amt_autual); log.info("比較 用戶金額 和 實際 購買金額 = {}", Integer.valueOf(compareUserAmtInt)); if (compareUserAmtInt == -1) { return ServerResponse.createByErrorMsg("下單失敗,融資可用金額小於" + buy_amt_autual + "元"); } // if (user.getUserIndexAmt().compareTo(new BigDecimal("0")) == -1) { // return ServerResponse.createByErrorMsg("失敗,指數總資金小於0"); // } // 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.getStockGid()); userPosition.setStockSpell(GetPyByChinese.converterToFirstSpell(stockDz.getStockName())); userPosition.setBuyOrderId(GeneratePosition.getPositionId()); userPosition.setBuyOrderTime(new Date()); userPosition.setBuyOrderPrice(now_price); userPosition.setOrderDirection("買漲"); userPosition.setOrderNum(num); if (stockDz.getStockPlate() != null) { userPosition.setStockPlate(stockDz.getStockPlate()); } userPosition.setIsLock(Integer.valueOf(0)); userPosition.setOrderLever(1); 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, stockDz.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")); log.info("--------------购买逻辑股票数据 buyDz stock------" + new Gson().toJson(userPosition)); 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); //修改用戶可用余額= 當前余額-下單總金額 BigDecimal reckon_enable = user_enable_amt.subtract(buy_amt_autual); //修改用戶可取余額=當前可取余額-下單總金額 int compareUserWithdrawAmtInt = user_enable_withdraw_amt.compareTo(buy_amt_autual); if (compareUserWithdrawAmtInt == -1) { //若可取余額小於下單總額,但是可用余額充足,令可取余額為0 user.setEnaleWithdrawAmt(BigDecimal.ZERO); } else { user_enable_withdraw_amt = user_enable_withdraw_amt.subtract(buy_amt_autual); user.setEnaleWithdrawAmt(user_enable_withdraw_amt); } user.setEnableAmt(reckon_enable); int updateUserCount = this.userMapper.updateByPrimaryKeySelective(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抢筹 * * @param stockId * @param buyNum * @param buyType * @param lever * @param profitTarget * @param stopTarget * @param request * @return */ @Transactional(isolation = Isolation.SERIALIZABLE) @Override 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("下單失敗,請先實名認證"); } BigDecimal user_enable_amt = user.getEnableAmt(); BigDecimal user_enable_withdraw_amt = user.getEnaleWithdrawAmt(); 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("下單失敗,系統設置錯誤"); } if (siteSetting.getVipQcMaxAmt().compareTo(user_enable_amt) > 0) { return ServerResponse.createByErrorMsg("下單失敗,可用余額小於" + siteSetting.getVipQcMaxAmt()); } Stock stock = null; ServerResponse stock_res = this.iStockService.findStockByCode(stockCode); if (!stock_res.isSuccess()) { return ServerResponse.createByErrorMsg("下單失敗,股票代碼錯誤"); } 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 = SinaStockApi.assembleLideStockListVO(LiDeDataUtils.getStock(stock.getStockCode())); if (ObjectUtils.isEmpty(stockListVO)) { stockListVO = SinaStockApi.assembleStockListVO(SinaStockApi.getSinaStock(stock.getStockGid())); } 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); log.info("當前漲跌幅 = {} % , 漲停幅度 = {} %", Double.valueOf(stock_crease), ztRate); // if ((new BigDecimal(String.valueOf(stock_crease))).compareTo(ztRate) == 0 && buyType // .intValue() == 0) { // return ServerResponse.createByErrorMsg("當前股票已漲停不能買漲"); // } if (stock.getStockPlate() == null || StringUtils.isEmpty(stock.getStockPlate())) { int maxcrease = siteSetting.getCreaseMaxPercent().intValue(); if (stock_crease > 0.0D && stock_crease >= maxcrease) { return ServerResponse.createByErrorMsg("下單失敗,股票當前漲幅:" + stock_crease + ",大於最大漲幅:" + maxcrease); } if (stock_crease < 0.0D && -stock_crease > maxcrease) { return ServerResponse.createByErrorMsg("下單失敗,股票當前跌幅:" + stock_crease + ",大於最大跌幅:" + maxcrease); } } else if ("創業".equals(stock.getStockPlate())) { int maxcrease = siteSetting.getCyCreaseMaxPercent().intValue(); if (stock_crease > 0.0D && stock_crease >= maxcrease) { return ServerResponse.createByErrorMsg("下單失敗,創業股當前漲幅:" + stock_crease + ",大於最大漲幅:" + maxcrease); } if (stock_crease < 0.0D && -stock_crease > maxcrease) { return ServerResponse.createByErrorMsg("下單失敗,創業股當前跌幅:" + stock_crease + ",大於最大跌幅:" + maxcrease); } } else { int maxcrease = siteSetting.getKcCreaseMaxPercent().intValue(); if (stock_crease > 0.0D && stock_crease >= maxcrease) { return ServerResponse.createByErrorMsg("下單失敗,科創股當前漲幅:" + stock_crease + ",大於最大漲幅:" + maxcrease); } if (stock_crease < 0.0D && -stock_crease > maxcrease) { return ServerResponse.createByErrorMsg("下單失敗,科創股當前跌幅:" + stock_crease + ",大於最大跌幅:" + maxcrease); } } 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())).divide(new BigDecimal(lever.intValue())).setScale(2, 4); BigDecimal buy_amt = now_price.multiply(new BigDecimal(buyNum.intValue())); //BigDecimal buy_amt_autual = now_price.multiply(new BigDecimal(buyNum.intValue())).divide(new BigDecimal(lever.intValue()), 2, 4); 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() + "元"); } BigDecimal max_buy_amt = user_enable_amt.multiply(siteSetting.getBuyMaxAmtPercent()); int compareCwInt = buy_amt_autual.compareTo(max_buy_amt); if (compareCwInt == 1) { return ServerResponse.createByErrorMsg("下單失敗,不能超過可用資金的" + siteSetting .getBuyMaxAmtPercent().multiply(new BigDecimal("100")) + "%"); } int compareUserAmtInt = user_enable_amt.compareTo(buy_amt_autual); log.info("用戶可用金額 = {} 實際購買金額 = {}", user_enable_amt, buy_amt_autual); log.info("比較 用戶金額 和 實際 購買金額 = {}", Integer.valueOf(compareUserAmtInt)); if (compareUserAmtInt == -1) { return ServerResponse.createByErrorMsg("下單失敗,可用金額小於" + buy_amt_autual + "元"); } // 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")); log.info("--------------购买逻辑股票数据 buyVipQc stock------" + new Gson().toJson(userPosition)); 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); //修改用戶可用余額= 當前余額-下單總金額 BigDecimal reckon_enable = user_enable_amt.subtract(buy_amt_autual); //修改用戶可取余額=當前可取余額-下單總金額 int compareUserWithdrawAmtInt = user_enable_withdraw_amt.compareTo(buy_amt_autual); if (compareUserWithdrawAmtInt < 0) { //若可取余額小於下單總額,但是可用余額充足,令可取余額為0 user.setEnaleWithdrawAmt(BigDecimal.ZERO); } else { user_enable_withdraw_amt = user_enable_withdraw_amt.subtract(buy_amt_autual); user.setEnaleWithdrawAmt(user_enable_withdraw_amt); } user.setEnableAmt(reckon_enable); int updateUserCount = this.userMapper.updateByPrimaryKeySelective(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("下單成功"); } @Override public void synchronizePrice(){ Map priceMap = new HashMap<>(); List userPositions = this.userPositionMapper.synchronizePrice(); log.info("-------------------同步收盘价,查询数据总量 {}个--------------",userPositions.size()); int count = 0; for (UserPosition position : userPositions) { if(priceMap.containsKey(position.getStockGid())){ BigDecimal newPrice = priceMap.get(position.getStockGid()); position.setBuyOrderIdIndex(newPrice); userPositionMapper.updateByPrimaryKey(position); }else { StockListVO stockListVO = new StockListVO(); stockListVO = SinaStockApi.assembleLideStockListVO(LiDeDataUtils.getStock(position.getStockCode())); if (ObjectUtils.isEmpty(stockListVO)) { stockListVO = SinaStockApi.assembleStockListVO(SinaStockApi.getSinaStock(position.getStockGid())); } if(stockListVO.getNowPrice() != null && new BigDecimal(stockListVO.getNowPrice()).compareTo(BigDecimal.ZERO) > 0){ position.setBuyOrderIdIndex(new BigDecimal(stockListVO.getNowPrice())); priceMap.put(position.getStockGid(),new BigDecimal(stockListVO.getNowPrice())); userPositionMapper.updateByPrimaryKey(position); } } count++; } log.info("-------------------同步收盘价 {}个--------------",count); } }