Browse Source

历史数据导出模版

Zhangbw 3 months ago
parent
commit
79f198ae7d

+ 63 - 0
ruoyi-modules/yp-stock/src/main/java/com/yingpai/stock/controller/StockPoolHistoryController.java

@@ -1,9 +1,11 @@
 package com.yingpai.stock.controller;
 
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.idev.excel.EasyExcel;
 import com.yingpai.stock.domain.bo.StockPoolHistoryBo;
 import com.yingpai.stock.domain.vo.StockPoolHistoryVo;
 import com.yingpai.stock.service.IStockPoolHistoryService;
+import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.constraints.NotEmpty;
 import jakarta.validation.constraints.NotNull;
 import lombok.RequiredArgsConstructor;
@@ -18,6 +20,10 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -96,4 +102,61 @@ public class StockPoolHistoryController extends BaseController {
         String message = stockPoolHistoryService.importData(file, recordDate, updateSupport);
         return R.ok(message);
     }
+
+    /**
+     * 下载导入模版
+     * 格式:第一行为时间信息,第二行为标题,第三行开始为数据
+     */
+    @SaCheckPermission("stock:history:import")
+    @GetMapping("/downloadTemplate")
+    public void downloadTemplate(HttpServletResponse response) throws IOException {
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+        String fileName = URLEncoder.encode("股票池历史数据导入模版", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
+        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
+        
+        // 第一行:时间信息(类似图片中的格式)
+        String dateInfo = "历史行情 指标排序 全部A股 周期:日线 日期" + java.time.LocalDate.now().toString() + " 二 指标:强度打分 使用1000个数据 前复权 过滤50天内新股+北证A股+ST股票";
+        List<String> headerRow = new ArrayList<>();
+        headerRow.add(dateInfo);
+        
+        // 第二行:标题行
+        List<String> titleRow = new ArrayList<>();
+        titleRow.add("代码");
+        titleRow.add("名称");
+        titleRow.add("涨幅%");
+        titleRow.add("收盘");
+        titleRow.add("总金额");
+        titleRow.add("强度评分");
+        titleRow.add("流通市值");
+        titleRow.add("主升周期");
+        titleRow.add("近期换手");
+        titleRow.add("近期涨停");
+        titleRow.add("当天最高价");
+        titleRow.add("当天最低价");
+        titleRow.add("当天均价");
+        titleRow.add("当天收盘价");
+        
+        // 第三行:示例数据
+        List<String> dataRow = new ArrayList<>();
+        dataRow.add("000547");
+        dataRow.add("航天发展");
+        dataRow.add("0.59");
+        dataRow.add("22.13");
+        dataRow.add("1.37E+10");
+        dataRow.add("14");
+        dataRow.add("351.5");
+        dataRow.add("8");
+        dataRow.add("40.98");
+        dataRow.add("3");
+        dataRow.add("23");
+        dataRow.add("21.48");
+        dataRow.add("22.06");
+        dataRow.add("22.13");
+        
+        // 使用EasyExcel写入,不使用注解类
+        EasyExcel.write(response.getOutputStream())
+            .sheet("导入模版")
+            .doWrite(java.util.Arrays.asList(headerRow, titleRow, dataRow));
+    }
 }

+ 5 - 0
ruoyi-modules/yp-stock/src/main/java/com/yingpai/stock/domain/StockPoolHistory.java

@@ -96,6 +96,11 @@ public class StockPoolHistory {
      */
     private BigDecimal dayClosePrice;
 
+    /**
+     * 行情涨跌(最高涨幅 = (当日最高价-昨日收盘价)/昨日收盘价)
+     */
+    private BigDecimal highTrend;
+
     /**
      * 操作管理员ID
      */

+ 5 - 0
ruoyi-modules/yp-stock/src/main/java/com/yingpai/stock/domain/bo/StockPoolHistoryBo.java

@@ -91,6 +91,11 @@ public class StockPoolHistoryBo {
      */
     private BigDecimal dayClosePrice;
 
+    /**
+     * 行情涨跌(最高涨幅)= (当日最高价-昨日收盘价)/昨日收盘价
+     */
+    private BigDecimal highTrend;
+
     /**
      * 查询开始日期
      */

+ 5 - 0
ruoyi-modules/yp-stock/src/main/java/com/yingpai/stock/domain/vo/StockPoolHistoryVo.java

@@ -114,6 +114,11 @@ public class StockPoolHistoryVo {
     @ExcelProperty(index = 13)
     private BigDecimal dayClosePrice;
 
+    /**
+     * 行情涨跌(最高涨幅%)
+     */
+    private BigDecimal highTrend;
+
     /**
      * 操作管理员ID
      */

+ 16 - 0
ruoyi-modules/yp-stock/src/main/java/com/yingpai/stock/mapper/StockPoolHistoryMapper.java

@@ -2,10 +2,26 @@ package com.yingpai.stock.mapper;
 
 import com.yingpai.stock.domain.StockPoolHistory;
 import com.yingpai.stock.domain.vo.StockPoolHistoryVo;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
 import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
 
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
 /**
  * 股票池历史Mapper接口
  */
 public interface StockPoolHistoryMapper extends BaseMapperPlus<StockPoolHistory, StockPoolHistoryVo> {
+    
+    /**
+     * 查询指定股票在指定日期之前最近一天的收盘价
+     * @param stockCode 股票代码
+     * @param recordDate 当前记录日期
+     * @return 昨日收盘价,如果没有则返回null
+     */
+    @Select("SELECT day_close_price FROM stock_pool_history " +
+            "WHERE stock_code = #{stockCode} AND record_date < #{recordDate} " +
+            "ORDER BY record_date DESC LIMIT 1")
+    BigDecimal selectPreviousClosePrice(@Param("stockCode") String stockCode, @Param("recordDate") LocalDate recordDate);
 }

+ 35 - 0
ruoyi-modules/yp-stock/src/main/java/com/yingpai/stock/service/impl/StockPoolHistoryServiceImpl.java

@@ -26,6 +26,7 @@ import org.springframework.web.multipart.MultipartFile;
 import java.io.BufferedInputStream;
 import java.io.InputStream;
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.nio.charset.Charset;
 import java.time.LocalDate;
 import java.util.ArrayList;
@@ -363,6 +364,8 @@ public class StockPoolHistoryServiceImpl implements IStockPoolHistoryService {
                         existing.setDayLowestPrice(vo.getDayLowestPrice());
                         existing.setDayAvgPrice(vo.getDayAvgPrice());
                         existing.setDayClosePrice(vo.getDayClosePrice());
+                        // 计算行情涨跌(最高涨幅)
+                        existing.setHighTrend(calculateHighTrend(vo.getStockCode(), parsedRecordDate, vo.getDayHighestPrice()));
                         baseMapper.updateById(existing);
                         updateNum++;
                         successNum++;
@@ -377,6 +380,8 @@ public class StockPoolHistoryServiceImpl implements IStockPoolHistoryService {
                     StockPoolHistory entity = BeanUtil.toBean(vo, StockPoolHistory.class);
                     entity.setRecordDate(parsedRecordDate);
                     entity.setAdminId(LoginHelper.getUserId());
+                    // 计算行情涨跌(最高涨幅)
+                    entity.setHighTrend(calculateHighTrend(vo.getStockCode(), parsedRecordDate, vo.getDayHighestPrice()));
                     baseMapper.insert(entity);
                     successNum++;
                 }
@@ -493,6 +498,36 @@ public class StockPoolHistoryServiceImpl implements IStockPoolHistoryService {
         }
     }
 
+    /**
+     * 计算行情涨跌(最高涨幅)
+     * 公式:(当日最高价 - 昨日收盘价) / 昨日收盘价 * 100
+     * 如果找不到昨日数据则返回0
+     * 
+     * @param stockCode 股票代码
+     * @param recordDate 当前记录日期
+     * @param dayHighestPrice 当日最高价
+     * @return 最高涨幅百分比,保留2位小数
+     */
+    private BigDecimal calculateHighTrend(String stockCode, LocalDate recordDate, BigDecimal dayHighestPrice) {
+        if (dayHighestPrice == null) {
+            return BigDecimal.ZERO;
+        }
+        
+        // 查询昨日收盘价
+        BigDecimal previousClosePrice = baseMapper.selectPreviousClosePrice(stockCode, recordDate);
+        
+        if (previousClosePrice == null || previousClosePrice.compareTo(BigDecimal.ZERO) == 0) {
+            // 找不到昨日数据或昨日收盘价为0,返回0
+            return BigDecimal.ZERO;
+        }
+        
+        // 计算最高涨幅:(当日最高价 - 昨日收盘价) / 昨日收盘价 * 100
+        return dayHighestPrice.subtract(previousClosePrice)
+            .divide(previousClosePrice, 4, RoundingMode.HALF_UP)
+            .multiply(new BigDecimal("100"))
+            .setScale(2, RoundingMode.HALF_UP);
+    }
+
     /**
      * 构建查询条件
      */