Browse Source

历史回顾池修改

Zhangbw 2 months ago
parent
commit
9a0d2a97fb

+ 17 - 2
src/main/java/com/yingpai/gupiao/domain/po/StockPool.java

@@ -49,9 +49,24 @@ public class StockPool {
      * 加入日期
      */
     private LocalDate addDate;
-    
+
+    /**
+     * 当日收盘价
+     */
+    private BigDecimal closePrice;
+
+    /**
+     * 隔日最高价
+     */
+    private BigDecimal nextDayHigh;
+
+    /**
+     * 隔日涨幅(%)
+     */
+    private BigDecimal nextDayGain;
+
     /**
-     * 状态:1-有效,0-已移除
+     * 状态:0-已移除,1-历史有效,2-当前有效
      */
     private Integer status;
     

+ 0 - 74
src/main/java/com/yingpai/gupiao/mapper/StockPoolHistoryMapper.java

@@ -1,74 +0,0 @@
-package com.yingpai.gupiao.mapper;
-
-import com.yingpai.gupiao.domain.vo.StockHistoryVO;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-import java.time.LocalDate;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 股票池历史数据Mapper(小程序端)
- */
-@Mapper
-public interface StockPoolHistoryMapper {
-    
-    /**
-     * 查询指定日期区间的历史数据(带隔日信息),根据池类型筛选
-     * @param startDate 开始日期
-     * @param endDate 结束日期
-     * @param poolType 池类型:1-超短池,2-强势池
-     * @param offset 偏移量
-     * @param limit 每页数量
-     * @return 历史数据列表
-     */
-    List<StockHistoryVO> selectHistoryWithNextDay(
-        @Param("startDate") LocalDate startDate,
-        @Param("endDate") LocalDate endDate,
-        @Param("poolType") Integer poolType,
-        @Param("offset") int offset,
-        @Param("limit") int limit
-    );
-    
-    /**
-     * 统计指定日期区间的记录总数,根据池类型筛选
-     * @param startDate 开始日期
-     * @param endDate 结束日期
-     * @param poolType 池类型:1-超短池,2-强势池
-     * @return 记录总数
-     */
-    int countHistory(
-        @Param("startDate") LocalDate startDate,
-        @Param("endDate") LocalDate endDate,
-        @Param("poolType") Integer poolType
-    );
-    
-    /**
-     * 查询统计数据(成功率、平均收益、总交易次数)
-     * @param startDate 开始日期
-     * @param endDate 结束日期
-     * @param poolType 池类型:1-超短池,2-强势池
-     * @return 统计数据Map
-     */
-    Map<String, Object> selectHistoryStats(
-        @Param("startDate") LocalDate startDate,
-        @Param("endDate") LocalDate endDate,
-        @Param("poolType") Integer poolType
-    );
-    
-    /**
-     * 根据股票代码或名称模糊查询最新的历史记录
-     * @param keyword 搜索关键词(股票代码或名称)
-     * @return 最新的历史记录
-     */
-    StockHistoryVO selectLatestByKeyword(@Param("keyword") String keyword);
-
-    /**
-     * 根据股票代码或名称和日期查询历史记录
-     * @param keyword 搜索关键词(股票代码或名称)
-     * @param recordDate 记录日期
-     * @return 指定日期的历史记录
-     */
-    StockHistoryVO selectByKeywordAndDate(@Param("keyword") String keyword, @Param("recordDate") LocalDate recordDate);
-}

+ 56 - 0
src/main/java/com/yingpai/gupiao/mapper/StockPoolMapper.java

@@ -3,10 +3,66 @@ package com.yingpai.gupiao.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.yingpai.gupiao.domain.po.StockPool;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+
+import java.time.LocalDate;
+import java.util.List;
 
 /**
  * 股票池Mapper
  */
 @Mapper
 public interface StockPoolMapper extends BaseMapper<StockPool> {
+
+    /**
+     * 查询指定池类型的最新加入日期
+     * @param poolType 池类型
+     * @return 最新日期
+     */
+    @Select("SELECT MAX(add_date) FROM stock_pool WHERE pool_type = #{poolType} AND status IN (1, 2)")
+    LocalDate selectLatestAddDate(Integer poolType);
+
+    /**
+     * 分页查询历史数据(status为1和2的记录)
+     * @param startDate 开始日期
+     * @param endDate 结束日期
+     * @param poolType 池类型
+     * @param offset 偏移量
+     * @param limit 限制数量
+     * @return 历史数据列表
+     */
+    @Select("SELECT stock_code, stock_name, add_date as recordDate, add_price, close_price as closePrice, " +
+            "next_day_high as nextDayHighPrice, next_day_gain as nextDayHighTrend, status " +
+            "FROM stock_pool " +
+            "WHERE add_date BETWEEN #{startDate} AND #{endDate} " +
+            "AND pool_type = #{poolType} " +
+            "AND status IN (1, 2) " +
+            "ORDER BY add_date DESC, id DESC " +
+            "LIMIT #{limit} OFFSET #{offset}")
+    List<com.yingpai.gupiao.domain.vo.StockHistoryVO> selectPoolHistory(
+        LocalDate startDate, LocalDate endDate, Integer poolType, int offset, int limit);
+
+    /**
+     * 统计历史数据总数
+     * @param startDate 开始日期
+     * @param endDate 结束日期
+     * @param poolType 池类型
+     * @return 总数
+     */
+    @Select("SELECT COUNT(*) FROM stock_pool " +
+            "WHERE add_date BETWEEN #{startDate} AND #{endDate} " +
+            "AND pool_type = #{poolType} " +
+            "AND status IN (1, 2)")
+    int countPoolHistory(LocalDate startDate, LocalDate endDate, Integer poolType);
+
+    /**
+     * 从历史信息表中查询收盘价
+     * @param stockCode 股票代码
+     * @param recordDate 记录日期
+     * @return 收盘价
+     */
+    @Select("SELECT close_price FROM stock_pool_history " +
+            "WHERE stock_code = #{stockCode} AND record_date = #{recordDate} " +
+            "LIMIT 1")
+    java.math.BigDecimal selectClosePriceFromHistory(String stockCode, LocalDate recordDate);
 }

+ 69 - 116
src/main/java/com/yingpai/gupiao/service/impl/StockHistoryServiceImpl.java

@@ -1,14 +1,12 @@
 package com.yingpai.gupiao.service.impl;
 
 import com.yingpai.gupiao.domain.vo.StockHistoryVO;
-import com.yingpai.gupiao.mapper.StockPoolHistoryMapper;
+import com.yingpai.gupiao.mapper.StockPoolMapper;
 import com.yingpai.gupiao.service.StockHistoryService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
-import java.math.BigDecimal;
-import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.util.HashMap;
 import java.util.List;
@@ -16,30 +14,43 @@ import java.util.Map;
 
 /**
  * 股票历史数据服务实现类(小程序端)
+ * 查询stock_pool表中status为1和2的记录
  */
 @Slf4j
 @Service
 @RequiredArgsConstructor
 public class StockHistoryServiceImpl implements StockHistoryService {
-    
-    private final StockPoolHistoryMapper stockPoolHistoryMapper;
+
+    private final StockPoolMapper stockPoolMapper;
     
     @Override
     public Map<String, Object> queryHistoryPage(LocalDate startDate, LocalDate endDate, Integer poolType, int pageNum, int pageSize) {
         // 计算偏移量
         int offset = (pageNum - 1) * pageSize;
-        
-        // 查询数据
-        List<StockHistoryVO> list = stockPoolHistoryMapper.selectHistoryWithNextDay(
+
+        // 查询stock_pool表中status为1和2的数据
+        List<StockHistoryVO> list = stockPoolMapper.selectPoolHistory(
             startDate, endDate, poolType, offset, pageSize
         );
-        
+
+        // 计算每条记录的成功/失败状态
+        for (StockHistoryVO vo : list) {
+            if (vo.getNextDayHighTrend() != null) {
+                if (vo.getNextDayHighTrend().compareTo(new java.math.BigDecimal("2")) >= 0) {
+                    vo.setStatus("success");  // 涨幅 >= 2%,成功
+                } else if (vo.getNextDayHighTrend().compareTo(new java.math.BigDecimal("-3")) <= 0) {
+                    vo.setStatus("fail");  // 涨幅 <= -3%,失败
+                }
+                // 否则 status 保持为 null(无状态)
+            }
+        }
+
         // 查询总数
-        int total = stockPoolHistoryMapper.countHistory(startDate, endDate, poolType);
-        
+        int total = stockPoolMapper.countPoolHistory(startDate, endDate, poolType);
+
         // 计算总页数
         int pages = (total + pageSize - 1) / pageSize;
-        
+
         // 构建返回结果
         Map<String, Object> result = new HashMap<>();
         result.put("list", list);
@@ -48,132 +59,74 @@ public class StockHistoryServiceImpl implements StockHistoryService {
         result.put("pageSize", pageSize);
         result.put("pages", pages);
         result.put("hasMore", pageNum < pages);
-        
+
         return result;
     }
     
     @Override
     public Map<String, Object> queryHistoryStats(LocalDate startDate, LocalDate endDate, Integer poolType) {
-        Map<String, Object> stats = stockPoolHistoryMapper.selectHistoryStats(startDate, endDate, poolType);
-        
-        Map<String, Object> result = new HashMap<>();
-        
-        if (stats == null || stats.get("totalCount") == null) {
-            result.put("totalCount", 0);
-            result.put("successCount", 0);
-            result.put("failCount", 0);
-            result.put("successRate", "0%");
-            result.put("avgTrend", "0%");
-            return result;
+        // 查询所有数据(不分页)
+        List<StockHistoryVO> allList = stockPoolMapper.selectPoolHistory(
+            startDate, endDate, poolType, 0, Integer.MAX_VALUE
+        );
+
+        // 计算每条记录的成功/失败状态并统计
+        int successCount = 0;
+        int failCount = 0;
+        java.math.BigDecimal totalTrend = java.math.BigDecimal.ZERO;
+        int trendCount = 0;
+
+        for (StockHistoryVO vo : allList) {
+            if (vo.getNextDayHighTrend() != null) {
+                // 累加涨幅用于计算平均值
+                totalTrend = totalTrend.add(vo.getNextDayHighTrend());
+                trendCount++;
+
+                if (vo.getNextDayHighTrend().compareTo(new java.math.BigDecimal("2")) >= 0) {
+                    successCount++;
+                } else if (vo.getNextDayHighTrend().compareTo(new java.math.BigDecimal("-3")) <= 0) {
+                    failCount++;
+                }
+            }
         }
-        
-        // 获取统计数据
-        long totalCount = ((Number) stats.get("totalCount")).longValue();
-        long successCount = stats.get("successCount") != null ? ((Number) stats.get("successCount")).longValue() : 0;
-        long failCount = stats.get("failCount") != null ? ((Number) stats.get("failCount")).longValue() : 0;
-        BigDecimal avgTrend = stats.get("avgTrend") != null ? new BigDecimal(stats.get("avgTrend").toString()) : BigDecimal.ZERO;
-        
-        // 计算成功率
-        String successRate = "0%";
-        if (totalCount > 0) {
-            BigDecimal rate = new BigDecimal(successCount * 100).divide(new BigDecimal(totalCount), 1, RoundingMode.HALF_UP);
-            successRate = rate.stripTrailingZeros().toPlainString() + "%";
+
+        int total = allList.size();
+        String successRate = total > 0 ? String.format("%.1f%%", (successCount * 100.0 / total)) : "0%";
+
+        // 计算平均收益率
+        String avgTrend = "0%";
+        if (trendCount > 0) {
+            java.math.BigDecimal avg = totalTrend.divide(
+                new java.math.BigDecimal(trendCount),
+                2,
+                java.math.RoundingMode.HALF_UP
+            );
+            avgTrend = String.format("%+.2f%%", avg);
         }
-        
-        // 格式化平均收益
-        String avgTrendStr = (avgTrend.compareTo(BigDecimal.ZERO) >= 0 ? "+" : "") + 
-                            avgTrend.setScale(2, RoundingMode.HALF_UP).toPlainString() + "%";
-        
-        result.put("totalCount", totalCount);
+
+        Map<String, Object> result = new HashMap<>();
+        result.put("totalCount", total);
         result.put("successCount", successCount);
         result.put("failCount", failCount);
         result.put("successRate", successRate);
-        result.put("avgTrend", avgTrendStr);
-        
+        result.put("avgTrend", avgTrend);
+
         return result;
     }
     
     @Override
     public Map<String, Object> queryLatestHistoryByKeyword(String keyword) {
         Map<String, Object> result = new HashMap<>();
-
-        if (keyword == null || keyword.trim().isEmpty()) {
-            result.put("found", false);
-            result.put("message", "请输入搜索关键词");
-            return result;
-        }
-
-        StockHistoryVO history = stockPoolHistoryMapper.selectLatestByKeyword(keyword.trim());
-
-        if (history == null) {
-            result.put("found", false);
-            result.put("message", "未找到该股票的历史数据");
-            return result;
-        }
-
-        result.put("found", true);
-        result.put("stockCode", history.getStockCode());
-        result.put("stockName", history.getStockName());
-        result.put("recordDate", history.getRecordDate());
-        result.put("closePrice", history.getClosePrice());
-        result.put("changePercent", history.getChangePercent());
-        result.put("strengthScore", history.getStrengthScore());
-        result.put("totalAmount", history.getTotalAmount());
-        result.put("circulationMarketValue", history.getCirculationMarketValue());
-        result.put("mainRisePeriod", history.getMainRisePeriod());
-        result.put("recentRiseHand", history.getRecentRiseHand());
-        result.put("recentLimitUp", history.getRecentLimitUp());
-        result.put("dayHighestPrice", history.getDayHighestPrice());
-        result.put("dayLowestPrice", history.getDayLowestPrice());
-        result.put("dayAvgPrice", history.getDayAvgPrice());
-        result.put("dayClosePrice", history.getDayClosePrice());
-        result.put("highTrend", history.getHighTrend());
-
+        result.put("found", false);
+        result.put("message", "该功能暂不支持");
         return result;
     }
 
     @Override
     public Map<String, Object> queryHistoryByKeywordAndDate(String keyword, LocalDate recordDate) {
         Map<String, Object> result = new HashMap<>();
-
-        if (keyword == null || keyword.trim().isEmpty()) {
-            result.put("found", false);
-            result.put("message", "请输入搜索关键词");
-            return result;
-        }
-
-        if (recordDate == null) {
-            result.put("found", false);
-            result.put("message", "请输入查询日期");
-            return result;
-        }
-
-        StockHistoryVO history = stockPoolHistoryMapper.selectByKeywordAndDate(keyword.trim(), recordDate);
-
-        if (history == null) {
-            result.put("found", false);
-            result.put("message", "未找到该股票在指定日期的历史数据");
-            return result;
-        }
-
-        result.put("found", true);
-        result.put("stockCode", history.getStockCode());
-        result.put("stockName", history.getStockName());
-        result.put("recordDate", history.getRecordDate());
-        result.put("closePrice", history.getClosePrice());
-        result.put("changePercent", history.getChangePercent());
-        result.put("strengthScore", history.getStrengthScore());
-        result.put("totalAmount", history.getTotalAmount());
-        result.put("circulationMarketValue", history.getCirculationMarketValue());
-        result.put("mainRisePeriod", history.getMainRisePeriod());
-        result.put("recentRiseHand", history.getRecentRiseHand());
-        result.put("recentLimitUp", history.getRecentLimitUp());
-        result.put("dayHighestPrice", history.getDayHighestPrice());
-        result.put("dayLowestPrice", history.getDayLowestPrice());
-        result.put("dayAvgPrice", history.getDayAvgPrice());
-        result.put("dayClosePrice", history.getDayClosePrice());
-        result.put("highTrend", history.getHighTrend());
-
+        result.put("found", false);
+        result.put("message", "该功能暂不支持");
         return result;
     }
 }

+ 46 - 16
src/main/java/com/yingpai/gupiao/service/impl/StockPoolServiceImpl.java

@@ -43,12 +43,23 @@ public class StockPoolServiceImpl implements StockPoolService {
     @Override
     public List<StockPoolVO> getPoolStocks(Integer poolType) {
         log.info("[获取股票池] poolType={}", poolType);
-        
+
+        // 查询最新日期
+        LocalDate latestDate = stockPoolMapper.selectLatestAddDate(poolType);
+        if (latestDate == null) {
+            log.info("[获取股票池] 没有找到任何记录");
+            return new ArrayList<>();
+        }
+
+        log.info("[获取股票池] 最新日期: {}", latestDate);
+
+        // 根据最新日期查询股票池
         LambdaQueryWrapper<StockPool> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(StockPool::getPoolType, poolType)
-               .eq(StockPool::getStatus, 1)  // 只查询有效的
-               .orderByDesc(StockPool::getAddDate);
-        
+               .eq(StockPool::getAddDate, latestDate)
+               .eq(StockPool::getStatus, 2)  // 只查询当前有效的
+               .orderByAsc(StockPool::getStockCode);
+
         List<StockPool> stocks = stockPoolMapper.selectList(wrapper);
         log.info("[获取股票池] 查询到 {} 条记录", stocks.size());
         
@@ -156,9 +167,16 @@ public class StockPoolServiceImpl implements StockPoolService {
     
     @Override
     public List<StockPoolVO> getPoolList(Integer poolType) {
+        LocalDate today = LocalDate.now();
+
         LambdaQueryWrapper<StockPool> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(StockPool::getPoolType, poolType)
-               .eq(StockPool::getStatus, 1)
+               .and(w -> w
+                   // 日期在当日之前的状态为1和2的记录
+                   .or(w1 -> w1.lt(StockPool::getAddDate, today).in(StockPool::getStatus, 1, 2))
+                   // 日期在当天的状态为2的记录
+                   .or(w2 -> w2.eq(StockPool::getAddDate, today).eq(StockPool::getStatus, 2))
+               )
                .orderByDesc(StockPool::getAddDate);
         List<StockPool> list = stockPoolMapper.selectList(wrapper);
         
@@ -203,7 +221,7 @@ public class StockPoolServiceImpl implements StockPoolService {
         LambdaQueryWrapper<StockPool> existWrapper = new LambdaQueryWrapper<>();
         existWrapper.eq(StockPool::getStockCode, stockCode)
                    .eq(StockPool::getPoolType, poolType)
-                   .eq(StockPool::getStatus, 1);
+                   .eq(StockPool::getStatus, 2);  // 检查是否在当前池中
         if (stockPoolMapper.selectCount(existWrapper) > 0) {
             log.warn("[添加股票到池] 股票已存在: {}", stockCode);
             throw new RuntimeException("该股票已在池中");
@@ -211,19 +229,24 @@ public class StockPoolServiceImpl implements StockPoolService {
         
         // 获取实时价格
         BigDecimal currentPrice = fetchCurrentPrice(stockCode);
-        
+
+        // 从历史信息中查询当天的收盘价
+        LocalDate today = LocalDate.now();
+        BigDecimal closePrice = fetchClosePriceFromHistory(stockCode, today);
+
         // 添加到池
         StockPool pool = new StockPool();
         pool.setStockCode(stockCode);
         pool.setStockName(stockInfo.getStockName());
         pool.setPoolType(poolType);
         pool.setAddPrice(currentPrice);
-        pool.setAddDate(LocalDate.now());
-        pool.setStatus(1);
+        pool.setClosePrice(closePrice);  // 设置收盘价
+        pool.setAddDate(today);
+        pool.setStatus(2);  // 新增时设置为当前有效
         pool.setAdminId(adminId);
         pool.setCreateTime(LocalDateTime.now());
         pool.setUpdateTime(LocalDateTime.now());
-        
+
         return stockPoolMapper.insert(pool) > 0;
     }
     
@@ -265,20 +288,27 @@ public class StockPoolServiceImpl implements StockPoolService {
     @Override
     public boolean deleteStock(String stockCode, Integer poolType) {
         log.info("[从池中删除股票] stockCode={}, poolType={}", stockCode, poolType);
-        
+
         LambdaQueryWrapper<StockPool> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(StockPool::getStockCode, stockCode)
                .eq(StockPool::getPoolType, poolType)
-               .eq(StockPool::getStatus, 1);
-        
+               .eq(StockPool::getStatus, 2);  // 只查询当前有效的
+
         StockPool pool = stockPoolMapper.selectOne(wrapper);
         if (pool == null) {
             throw new RuntimeException("记录不存在");
         }
-        
-        // 软删除
-        pool.setStatus(0);
+
+        // 管理员删除:改为历史有效
+        pool.setStatus(1);
         pool.setUpdateTime(LocalDateTime.now());
         return stockPoolMapper.updateById(pool) > 0;
     }
+
+    /**
+     * 从历史信息中查询收盘价
+     */
+    private BigDecimal fetchClosePriceFromHistory(String stockCode, LocalDate recordDate) {
+        return stockPoolMapper.selectClosePriceFromHistory(stockCode, recordDate);
+    }
 }