| src/main/java/com/nq/controller/StockApiController.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/service/IStockService.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/service/impl/StockServiceImpl.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/service/impl/UserPendingorderServiceImpl.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/service/impl/UserStockSubscribeServiceImpl.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/utils/stock/sina/StockApi.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/utils/task/stock/CarryPositionTask.java | ●●●●● patch | view | raw | blame | history | |
| src/main/resources/application.properties | ●●●●● patch | view | raw | blame | history | |
| src/main/resources/mapper/StockMapper.xml | ●●●●● patch | view | raw | blame | history |
src/main/java/com/nq/controller/StockApiController.java
@@ -179,7 +179,7 @@ @RequestMapping("getPremarketStock.do") @ResponseBody public ServerResponse getPremarketStock() { return this.iStockService.getPremarketStock(); return ServerResponse.createBySuccess(this.iStockService.getPremarketStock()); } } src/main/java/com/nq/service/IStockService.java
@@ -3,6 +3,8 @@ import com.github.pagehelper.PageInfo; import com.nq.common.ServerResponse; import com.nq.pojo.Stock; import com.nq.vo.stock.PremarketStockVO; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -127,5 +129,5 @@ ServerResponse getStocksByKeyWords(int pageNum, int pageSize, String keyWords); ServerResponse getPremarketStock(); List<PremarketStockVO> getPremarketStock(); } src/main/java/com/nq/service/impl/StockServiceImpl.java
@@ -2,6 +2,7 @@ import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.http.HttpUtil; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; @@ -36,6 +37,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; import java.util.stream.Collectors; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -85,6 +87,9 @@ @Resource StockSettingMapper stockSettingMapper; @Autowired IStockService iStockService; public ServerResponse getMarket() { String market_url = PropertiesUtil.getProperty("sina.market.url"); @@ -167,6 +172,24 @@ if (stockList.size() > 0) { stockListVOS.addAll(Objects.requireNonNull(StockApi.getStockReailTimes(stockList))); } List<PremarketStockVO> premarketStock = iStockService.getPremarketStock(); Map<String, PremarketStockVO> stockMap = premarketStock.stream() .collect(Collectors.toMap( PremarketStockVO::getCode, stock -> stock )); stockListVOS.forEach(f->{ PremarketStockVO p = stockMap.get(f.getCode()); if (ObjectUtil.isNotEmpty(p)){ f.setNowPrice(p.getPrice().toString()); f.setHcrate(p.getHcrate()); f.setHcrateP(p.getHcrateP()); } }); RPageInfo resultPageInfo = new RPageInfo(); resultPageInfo.setList(stockListVOS); @@ -913,68 +936,63 @@ } @Override public ServerResponse getPremarketStock() { try { List<StockSetting> stockSettings = stockSettingMapper.selectList(new QueryWrapper<>()); List<PremarketStockVO> resultList = new ArrayList<>(); Date now = new Date(); for (StockSetting setting : stockSettings) { String startTime = setting.getStartTime(); String endTime = setting.getEndTime(); // 判断当前时间是否在交易时间内(startTime和endTime是完整的日期时间格式) if (isTimeInRange(now, startTime, endTime)) { Stock stock = stockMapper.selectOne(new QueryWrapper<Stock>().eq("stock_code", setting.getStockCode())); if (stock == null) { continue; // 股票不存在,跳过 } // 获取真实数据,用于获取前收盘价(pc) StockRealTimeBean realTimeStock = RedisKeyUtil.getCacheRealTimeStock(stock); if (realTimeStock == null || realTimeStock.getPc() == null) { continue; // 无法获取真实数据,跳过 } // 获取前收盘价(昨收) BigDecimal prevClose = new BigDecimal(realTimeStock.getPc()); // 计算盘前价格(根据StockSetting配置) BigDecimal premarketPrice; if ("0".equals(setting.getType())) { // type=0: 直接指定价格 premarketPrice = new BigDecimal(setting.getPrice()); } else { // type=1: 百分比调价格,基于昨收计算 premarketPrice = prevClose.multiply(new BigDecimal(setting.getPrice())); } // 根据盘前价格和昨收计算涨跌幅 = (盘前价格 - 昨收) / 昨收 BigDecimal hcrate = BigDecimal.ZERO; if (prevClose.compareTo(BigDecimal.ZERO) > 0) { hcrate = premarketPrice.subtract(prevClose) .divide(prevClose, 4, RoundingMode.HALF_UP); } // 格式化涨跌幅为带百分号的字符串 String hcrateP = hcrate.multiply(new BigDecimal("100")) .setScale(2, RoundingMode.HALF_UP) + "%"; PremarketStockVO vo = new PremarketStockVO(); vo.setCode(setting.getStockCode()); vo.setPrice(premarketPrice); // price返回盘前价格 vo.setHcrate(hcrate); vo.setHcrateP(hcrateP); resultList.add(vo); public List<PremarketStockVO> getPremarketStock() { List<StockSetting> stockSettings = stockSettingMapper.selectList(new QueryWrapper<>()); List<PremarketStockVO> resultList = new ArrayList<>(); Date now = new Date(); for (StockSetting setting : stockSettings) { String startTime = setting.getStartTime(); String endTime = setting.getEndTime(); // 判断当前时间是否在交易时间内(startTime和endTime是完整的日期时间格式) if (isTimeInRange(now, startTime, endTime)) { Stock stock = stockMapper.selectOne(new QueryWrapper<Stock>().eq("stock_code", setting.getStockCode())); if (stock == null) { continue; // 股票不存在,跳过 } // 获取真实数据,用于获取前收盘价(pc) StockRealTimeBean realTimeStock = RedisKeyUtil.getCacheRealTimeStock(stock); if (realTimeStock == null || realTimeStock.getPc() == null) { continue; // 无法获取真实数据,跳过 } // 获取前收盘价(昨收) BigDecimal prevClose = new BigDecimal(realTimeStock.getPc()); // 计算盘前价格(根据StockSetting配置) BigDecimal premarketPrice; if ("0".equals(setting.getType())) { // type=0: 直接指定价格 premarketPrice = new BigDecimal(setting.getPrice()); } else { // type=1: 百分比调价格,基于昨收计算 premarketPrice = prevClose.multiply(new BigDecimal(setting.getPrice())); } // 根据盘前价格和昨收计算涨跌幅 = (盘前价格 - 昨收) / 昨收 BigDecimal hcrate = BigDecimal.ZERO; if (prevClose.compareTo(BigDecimal.ZERO) > 0) { hcrate = premarketPrice.subtract(prevClose) .divide(prevClose, 4, RoundingMode.HALF_UP); } // 格式化涨跌幅为带百分号的字符串 String hcrateP = hcrate.multiply(new BigDecimal("100")) .setScale(2, RoundingMode.HALF_UP) + "%"; PremarketStockVO vo = new PremarketStockVO(); vo.setCode(setting.getStockCode()); vo.setPrice(premarketPrice); // price返回盘前价格 vo.setHcrate(hcrate); vo.setHcrateP(hcrateP); resultList.add(vo); } return ServerResponse.createBySuccess(resultList); } catch (Exception e) { log.error("getPremarketStock error", e); return ServerResponse.createByErrorMsg("查询盘前交易数据失败"); } return resultList; } /** src/main/java/com/nq/service/impl/UserPendingorderServiceImpl.java
@@ -5,7 +5,10 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -23,6 +26,7 @@ import com.nq.vo.foreigncurrency.ExchangeVO; import com.nq.vo.position.UserPendingorderVO; import com.nq.vo.stock.MarketVO; import com.nq.vo.stock.PremarketStockVO; import com.nq.vo.stock.StockListVO; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -83,6 +87,9 @@ @Autowired private UserPositionMapper userPositionMapper; @Autowired IStockService iStockService; @Override @org.springframework.transaction.annotation.Transactional(rollbackFor = Exception.class) @@ -253,7 +260,18 @@ // 查询所有待处理的挂单 List<UserPendingorder> userPendingorders = userPendingorderMapper.selectList(new QueryWrapper<UserPendingorder>().eq("status", 0)); log.info("当前有挂单数量:{}", userPendingorders.size()); List<PremarketStockVO> premarketStock = iStockService.getPremarketStock(); Map<String, PremarketStockVO> stockMap = premarketStock.stream() .collect(Collectors.toMap( PremarketStockVO::getCode, stock -> stock )); orderLoop: for (UserPendingorder userPendingorder : userPendingorders) { try { // 参数校验 @@ -271,25 +289,36 @@ this.userPendingorderMapper.updateById(userPendingorder); continue; } PremarketStockVO p = stockMap.get(stock.getStockCode()); // 获取当前价格 BigDecimal nowPrice = priceServices.getNowPrice(stock.getStockCode()); if (nowPrice.compareTo(BigDecimal.ZERO) == 0) { continue; if(ObjectUtil.isEmpty(p)){ if (nowPrice.compareTo(BigDecimal.ZERO) == 0) { continue; } // 判断价格是否达到目标价格:当前价格 <= 挂单价就买入 if (nowPrice.compareTo(userPendingorder.getTargetPrice()) > 0) { // 当前价格大于挂单价,继续等待 continue; } // 价格达到目标价格,先进行验证 // 判断股票是否在可交易时间段 Boolean b = tradingHourService.timeCheck(stock.getStockCode(), stock.getStockType()); if (!b) { continue; } }else{ // 判断价格是否达到目标价格:当前价格 <= 挂单价就买入 if (p.getPrice().compareTo(userPendingorder.getTargetPrice()) > 0) { // 当前价格大于挂单价,继续等待 continue; } nowPrice = p.getPrice(); } // 判断价格是否达到目标价格:当前价格 <= 挂单价就买入 if (nowPrice.compareTo(userPendingorder.getTargetPrice()) > 0) { // 当前价格大于挂单价,继续等待 continue; } // 价格达到目标价格,先进行验证 // 判断股票是否在可交易时间段 Boolean b = tradingHourService.timeCheck(stock.getStockCode(), stock.getStockType()); if (!b) { continue; } // 检查股票是否被锁定 if (stock.getIsLock() != 0) { src/main/java/com/nq/service/impl/UserStockSubscribeServiceImpl.java
@@ -321,8 +321,8 @@ } ret = userStockSubscribeMapper.update1(model); userAssetsMapper.updateById(userAssets); iUserPositionService.newStockToPosition(model.getId(),userAssets.getAmountToBeCovered());//转持仓 model.setStatus(5); // iUserPositionService.newStockToPosition(model.getId(),userAssets.getAmountToBeCovered());//转持仓 // model.setStatus(5); }else{ if(model.getApplyNumber()>model.getApplyNums()){ return ServerResponse.createByErrorMsg("配置中签数量不能超过申请数量",request); src/main/java/com/nq/utils/stock/sina/StockApi.java
@@ -34,7 +34,9 @@ } List<StockListVO> stockListVOs = new ArrayList<>(); try { for (int i = 0; i < stocks.size(); i++) { Stock stock = stocks.get(i); StockRealTimeBean realTimeStock = RedisKeyUtil.getCacheRealTimeStock(stock); StockListVO stockListVO = new StockListVO(); src/main/java/com/nq/utils/task/stock/CarryPositionTask.java
@@ -61,44 +61,44 @@ private final AtomicBoolean ballot = new AtomicBoolean(false); @Scheduled(cron = "0 0/1 * * * ?") public void ballot() { if (ballot.get()) { // 判断任务是否在处理中 return; } if (ballotLock.tryLock()) { try { ballot.set(true); // 设置处理中标识为true // log.info("新股上市转持仓定时任务--------->开始"); log.info("新股上市定时任务--------->开始"); List<StockSubscribe> stockSubscribes = stockSubscribeMapper.selectList(new LambdaQueryWrapper<StockSubscribe>() .lt(StockSubscribe::getListDate, DateUtil.date())); if (CollectionUtils.isNotEmpty(stockSubscribes)) { List<String> codeList = stockSubscribes.stream().map(StockSubscribe::getCode).collect(Collectors.toList()); List<UserStockSubscribe> userStockSubscribes = userStockSubscribeMapper.selectList(new LambdaQueryWrapper<UserStockSubscribe>() .eq(UserStockSubscribe::getStatus, 4).in(UserStockSubscribe::getNewCode, codeList)); //订单转持仓 userStockSubscribes.forEach(f -> { ServerResponse serverResponse = iUserPositionService.newStockToPosition(f.getId(),BigDecimal.ZERO);//转持仓 if(serverResponse.isSuccess()){ f.setStatus(5); userStockSubscribeMapper.updateById(f); }else{ log.info("新股上市定时任务失败申购订单id:"+f.getId()+",失败原因:"+serverResponse.getMsg()); } }); } log.info("新股上市定时任务--------->结束"); } catch (Exception e) { log.error("新股上市定时任务发生异常", e); } finally { ballotLock.unlock(); ballot.set(false); // 设置处理中标识为false } } else { log.info("新股上市定时任务--------->上次任务还未执行完成,本次任务忽略"); } } // @Scheduled(cron = "0 0/1 * * * ?") // public void ballot() { // if (ballot.get()) { // 判断任务是否在处理中 // return; // } // if (ballotLock.tryLock()) { // try { // ballot.set(true); // 设置处理中标识为true //// log.info("新股上市转持仓定时任务--------->开始"); // log.info("新股上市定时任务--------->开始"); // List<StockSubscribe> stockSubscribes = stockSubscribeMapper.selectList(new LambdaQueryWrapper<StockSubscribe>() // .lt(StockSubscribe::getListDate, DateUtil.date())); // if (CollectionUtils.isNotEmpty(stockSubscribes)) { // List<String> codeList = stockSubscribes.stream().map(StockSubscribe::getCode).collect(Collectors.toList()); // List<UserStockSubscribe> userStockSubscribes = userStockSubscribeMapper.selectList(new LambdaQueryWrapper<UserStockSubscribe>() // .eq(UserStockSubscribe::getStatus, 4).in(UserStockSubscribe::getNewCode, codeList)); // //订单转持仓 // userStockSubscribes.forEach(f -> { // ServerResponse serverResponse = iUserPositionService.newStockToPosition(f.getId(),BigDecimal.ZERO);//转持仓 // if(serverResponse.isSuccess()){ // f.setStatus(5); // userStockSubscribeMapper.updateById(f); // }else{ // log.info("新股上市定时任务失败申购订单id:"+f.getId()+",失败原因:"+serverResponse.getMsg()); // } // }); // } // log.info("新股上市定时任务--------->结束"); // } catch (Exception e) { // log.error("新股上市定时任务发生异常", e); // } finally { // ballotLock.unlock(); // ballot.set(false); // 设置处理中标识为false // } // } else { // log.info("新股上市定时任务--------->上次任务还未执行完成,本次任务忽略"); // } // } private final AtomicBoolean subscription = new AtomicBoolean(false); src/main/resources/application.properties
@@ -46,7 +46,7 @@ JP_HTTP_API = http://api-jp.js-stock.top/ JP_WS_URL = ws://api-jp-ws.js-stock.top JP_KEY = 43zGhZNUYT5lwsmEenUO JP_KEY = ZDX1s51GoJhoeuajaDpx #默认首页显示指数code #us_home_indices_code=15882,15881,16571 #hk_home_indices_code=535606773,535606776,535606785 src/main/resources/mapper/StockMapper.xml
@@ -319,7 +319,7 @@ <include refid="Base_Column_List"/> FROM stock where 1=1 where 1=1 and is_show = 0 <if test="stockType != null and stockType != '' "> and stock_type = #{stockType} </if>