|
@@ -1,12 +1,14 @@
|
|
|
package com.yingpai.gupiao.service.impl;
|
|
package com.yingpai.gupiao.service.impl;
|
|
|
|
|
|
|
|
import com.yingpai.gupiao.domain.vo.StockHistoryVO;
|
|
import com.yingpai.gupiao.domain.vo.StockHistoryVO;
|
|
|
-import com.yingpai.gupiao.mapper.StockPoolMapper;
|
|
|
|
|
|
|
+import com.yingpai.gupiao.mapper.StockPoolHistoryMapper;
|
|
|
import com.yingpai.gupiao.service.StockHistoryService;
|
|
import com.yingpai.gupiao.service.StockHistoryService;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
|
|
+import java.math.RoundingMode;
|
|
|
import java.time.LocalDate;
|
|
import java.time.LocalDate;
|
|
|
import java.util.HashMap;
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
@@ -14,43 +16,30 @@ import java.util.Map;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 股票历史数据服务实现类(小程序端)
|
|
* 股票历史数据服务实现类(小程序端)
|
|
|
- * 查询stock_pool表中status为1和2的记录
|
|
|
|
|
*/
|
|
*/
|
|
|
@Slf4j
|
|
@Slf4j
|
|
|
@Service
|
|
@Service
|
|
|
@RequiredArgsConstructor
|
|
@RequiredArgsConstructor
|
|
|
public class StockHistoryServiceImpl implements StockHistoryService {
|
|
public class StockHistoryServiceImpl implements StockHistoryService {
|
|
|
-
|
|
|
|
|
- private final StockPoolMapper stockPoolMapper;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ private final StockPoolHistoryMapper stockPoolHistoryMapper;
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public Map<String, Object> queryHistoryPage(LocalDate startDate, LocalDate endDate, Integer poolType, int pageNum, int pageSize) {
|
|
public Map<String, Object> queryHistoryPage(LocalDate startDate, LocalDate endDate, Integer poolType, int pageNum, int pageSize) {
|
|
|
// 计算偏移量
|
|
// 计算偏移量
|
|
|
int offset = (pageNum - 1) * pageSize;
|
|
int offset = (pageNum - 1) * pageSize;
|
|
|
-
|
|
|
|
|
- // 查询stock_pool表中status为1和2的数据
|
|
|
|
|
- List<StockHistoryVO> list = stockPoolMapper.selectPoolHistory(
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 查询数据
|
|
|
|
|
+ List<StockHistoryVO> list = stockPoolHistoryMapper.selectHistoryWithNextDay(
|
|
|
startDate, endDate, poolType, offset, pageSize
|
|
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 = stockPoolMapper.countPoolHistory(startDate, endDate, poolType);
|
|
|
|
|
-
|
|
|
|
|
|
|
+ int total = stockPoolHistoryMapper.countHistory(startDate, endDate, poolType);
|
|
|
|
|
+
|
|
|
// 计算总页数
|
|
// 计算总页数
|
|
|
int pages = (total + pageSize - 1) / pageSize;
|
|
int pages = (total + pageSize - 1) / pageSize;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 构建返回结果
|
|
// 构建返回结果
|
|
|
Map<String, Object> result = new HashMap<>();
|
|
Map<String, Object> result = new HashMap<>();
|
|
|
result.put("list", list);
|
|
result.put("list", list);
|
|
@@ -59,74 +48,132 @@ public class StockHistoryServiceImpl implements StockHistoryService {
|
|
|
result.put("pageSize", pageSize);
|
|
result.put("pageSize", pageSize);
|
|
|
result.put("pages", pages);
|
|
result.put("pages", pages);
|
|
|
result.put("hasMore", pageNum < pages);
|
|
result.put("hasMore", pageNum < pages);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public Map<String, Object> queryHistoryStats(LocalDate startDate, LocalDate endDate, Integer poolType) {
|
|
public Map<String, Object> queryHistoryStats(LocalDate startDate, LocalDate endDate, Integer poolType) {
|
|
|
- // 查询所有数据(不分页)
|
|
|
|
|
- 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++;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ 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;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- 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);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 获取统计数据
|
|
|
|
|
+ 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() + "%";
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- Map<String, Object> result = new HashMap<>();
|
|
|
|
|
- result.put("totalCount", total);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 格式化平均收益
|
|
|
|
|
+ String avgTrendStr = (avgTrend.compareTo(BigDecimal.ZERO) >= 0 ? "+" : "") +
|
|
|
|
|
+ avgTrend.setScale(2, RoundingMode.HALF_UP).toPlainString() + "%";
|
|
|
|
|
+
|
|
|
|
|
+ result.put("totalCount", totalCount);
|
|
|
result.put("successCount", successCount);
|
|
result.put("successCount", successCount);
|
|
|
result.put("failCount", failCount);
|
|
result.put("failCount", failCount);
|
|
|
result.put("successRate", successRate);
|
|
result.put("successRate", successRate);
|
|
|
- result.put("avgTrend", avgTrend);
|
|
|
|
|
-
|
|
|
|
|
|
|
+ result.put("avgTrend", avgTrendStr);
|
|
|
|
|
+
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public Map<String, Object> queryLatestHistoryByKeyword(String keyword) {
|
|
public Map<String, Object> queryLatestHistoryByKeyword(String keyword) {
|
|
|
Map<String, Object> result = new HashMap<>();
|
|
Map<String, Object> result = new HashMap<>();
|
|
|
- result.put("found", false);
|
|
|
|
|
- result.put("message", "该功能暂不支持");
|
|
|
|
|
|
|
+
|
|
|
|
|
+ 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());
|
|
|
|
|
+
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public Map<String, Object> queryHistoryByKeywordAndDate(String keyword, LocalDate recordDate) {
|
|
public Map<String, Object> queryHistoryByKeywordAndDate(String keyword, LocalDate recordDate) {
|
|
|
Map<String, Object> result = new HashMap<>();
|
|
Map<String, Object> result = new HashMap<>();
|
|
|
- result.put("found", false);
|
|
|
|
|
- result.put("message", "该功能暂不支持");
|
|
|
|
|
|
|
+
|
|
|
|
|
+ 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());
|
|
|
|
|
+
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|