2025-03-17 10:46:29 +08:00
|
|
|
package com.diagnose.service;
|
|
|
|
|
|
2025-03-17 19:44:22 +08:00
|
|
|
import com.diagnose.common.handler.BizException;
|
|
|
|
|
import com.diagnose.common.result.ResponseStatus;
|
2025-03-17 10:46:29 +08:00
|
|
|
import com.diagnose.mapper.DiagnoseMapper;
|
|
|
|
|
import com.diagnose.mapper.FinanceMapper;
|
|
|
|
|
import com.diagnose.mapper.StockMapper;
|
|
|
|
|
import com.diagnose.vo.*;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.function.Function;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
@Service
|
|
|
|
|
public class StockService {
|
|
|
|
|
|
|
|
|
|
private static final long cacheExpires = 60 * 60 * 1000;
|
|
|
|
|
|
|
|
|
|
private static long cacheTime = 0;
|
|
|
|
|
|
2025-03-17 19:44:22 +08:00
|
|
|
private static final int kLineMonth = 3;
|
|
|
|
|
|
2025-03-17 10:46:29 +08:00
|
|
|
private List<StockVO> stockListCache = null;
|
|
|
|
|
|
|
|
|
|
private Map<Long, StockVO> stockMapCache = null; // <stkUniCode, StockVO>
|
|
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
|
private StockMapper stockMapper;
|
|
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
|
private FinanceMapper financeMapper;
|
|
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
|
private DiagnoseMapper diagnoseMapper;
|
|
|
|
|
|
|
|
|
|
public List<StockVO> selectAllStock() {
|
|
|
|
|
return stockMapper.selectAllStock();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public synchronized List<StockVO> selectALlStockCache () {
|
|
|
|
|
long now = System.currentTimeMillis();
|
|
|
|
|
if (stockListCache == null || now - cacheTime > cacheExpires) {
|
|
|
|
|
stockListCache = selectAllStock();
|
|
|
|
|
cacheTime = now;
|
|
|
|
|
}
|
|
|
|
|
return stockListCache;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public StockVO getStock(Long stkUniCode) {
|
|
|
|
|
if (stockMapCache == null) {
|
|
|
|
|
stockMapCache = selectALlStockCache().stream().collect(Collectors.toMap(StockVO::getSecUniCode, Function.identity()));
|
|
|
|
|
}
|
|
|
|
|
return stockMapCache.get(stkUniCode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public DiagnoseRankVO rank(StockVO stock) {
|
|
|
|
|
DiagnoseRankVO diagnoseRankVO = diagnoseMapper.selectRank(stock.getSecUniCode());
|
2025-03-17 19:44:22 +08:00
|
|
|
if (diagnoseRankVO == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2025-03-17 10:46:29 +08:00
|
|
|
Integer totalInduCount = diagnoseMapper.selectTotalInduCount(stock.getPlateUniCode());
|
|
|
|
|
Integer totalMktCount = diagnoseMapper.selectTotalMktCount();
|
|
|
|
|
diagnoseRankVO.setTotalInduCount(totalInduCount);
|
|
|
|
|
diagnoseRankVO.setTotalMktCount(totalMktCount);
|
|
|
|
|
return diagnoseRankVO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ComprehensiveEvaluationVO comprehensiveEvaluation(Long stkUniCode) {
|
|
|
|
|
StockVO stock = getStock(stkUniCode);
|
|
|
|
|
if (stock == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2025-03-17 19:44:22 +08:00
|
|
|
ComprehensiveEvaluationVO vo = new ComprehensiveEvaluationVO();
|
|
|
|
|
vo.setStock(stock);
|
2025-03-17 10:46:29 +08:00
|
|
|
DiagnoseRankVO diagnoseRankVO = rank(stock);
|
2025-03-17 19:44:22 +08:00
|
|
|
vo.setRank(diagnoseRankVO);
|
2025-03-17 10:46:29 +08:00
|
|
|
BigDecimal star = diagnoseRankVO.getTotalStar();
|
|
|
|
|
if (star == null) {
|
2025-03-17 19:44:22 +08:00
|
|
|
return vo;
|
2025-03-17 10:46:29 +08:00
|
|
|
}
|
|
|
|
|
List<DiagnoseBackTestVO> backTestList = diagnoseMapper.selectBackTest(star);
|
|
|
|
|
vo.setBackTestList(backTestList);
|
|
|
|
|
return vo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public FinancialValuationVO financialValuation(Long stkUniCode) {
|
|
|
|
|
StockVO stock = getStock(stkUniCode);
|
|
|
|
|
if (stock == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2025-03-17 19:44:22 +08:00
|
|
|
Long secUniCode = stock.getSecUniCode();
|
2025-03-17 10:46:29 +08:00
|
|
|
String secCode = stock.getSecCode();
|
|
|
|
|
Integer mktNum = stock.getMktNum();
|
2025-03-17 19:44:22 +08:00
|
|
|
// 总结性机器语 & 财务估值得分
|
2025-03-17 10:46:29 +08:00
|
|
|
FinancialValuationVO vo = financeMapper.selectFinancialValuation(secCode, mktNum);
|
2025-03-17 19:44:22 +08:00
|
|
|
if (vo == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
// 财务分析行业排名
|
|
|
|
|
FinanceRankVO financeRank = financeMapper.selectFinanceRank(secUniCode);
|
|
|
|
|
vo.setFinanceRank(financeRank);
|
|
|
|
|
// 估值分析
|
|
|
|
|
List<DiagnoseValuationVO> diagnoseValuationList = diagnoseMapper.selectDiagnoseValuation(secUniCode);
|
|
|
|
|
vo.setDiagnoseValuationList(diagnoseValuationList);
|
|
|
|
|
// 行情估值
|
|
|
|
|
String tableName = stock.getPriceTableName();
|
|
|
|
|
StockPriceVO stockPrice = stockMapper.selectLatestPrice(tableName, secUniCode);
|
|
|
|
|
vo.setStockPrice(stockPrice);
|
|
|
|
|
return vo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public FinancialValuationExtendVO financialValuationExtend(Long stkUniCode) {
|
|
|
|
|
StockVO stock = getStock(stkUniCode);
|
|
|
|
|
if (stock == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
String secCode = stock.getSecCode();
|
|
|
|
|
Integer mktNum = stock.getMktNum();
|
2025-03-17 10:46:29 +08:00
|
|
|
Integer secMarPar = stock.getSecMarPar();
|
2025-03-17 19:44:22 +08:00
|
|
|
// 总结性机器语 & 财务估值得分
|
|
|
|
|
FinancialValuationVO baseVO = financeMapper.selectFinancialValuation(secCode, mktNum);
|
|
|
|
|
if (baseVO != null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
FinancialValuationExtendVO vo = new FinancialValuationExtendVO();
|
|
|
|
|
vo.setFinSumMac(baseVO.getFinSumMac());
|
|
|
|
|
vo.setScore(baseVO.getScore());
|
|
|
|
|
// 财务指标分析列表
|
2025-03-17 10:46:29 +08:00
|
|
|
List<FinanceIndexAnalysisVO> financeIndexAnalysisList = financeMapper.selectFinanceIndexAnalysis(secCode, secMarPar);
|
|
|
|
|
financeIndexAnalysisList.forEach(fiaVO -> {
|
|
|
|
|
if (fiaVO.getEndDate() != null && fiaVO.getEndDate().length() > 10) {
|
|
|
|
|
fiaVO.setEndDate(fiaVO.getEndDate().substring(0, 10));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
vo.setFinanceIndexAnalysisList(financeIndexAnalysisList);
|
2025-03-17 19:44:22 +08:00
|
|
|
// 现金流量列表
|
2025-03-17 10:46:29 +08:00
|
|
|
List<FinanceCashShortVO> financeCashShortList = financeMapper.selectFinanceCashShort(secCode, secMarPar);
|
|
|
|
|
financeCashShortList.forEach(fcsVO -> {
|
|
|
|
|
if (fcsVO.getEndDate() != null && fcsVO.getEndDate().length() > 10) {
|
|
|
|
|
fcsVO.setEndDate(fcsVO.getEndDate().substring(0, 10));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
vo.setFinanceCashShortList(financeCashShortList);
|
|
|
|
|
return vo;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-17 19:44:22 +08:00
|
|
|
public List<ValuationAnalysisVO> financialValuationAnalysis(Long stkUniCode, Integer timeSpan, Integer type) {
|
|
|
|
|
StockVO stock = getStock(stkUniCode);
|
|
|
|
|
if (stock == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
String tableName = stock.getPriceTableName();
|
|
|
|
|
String stockValueColumn = getStockValueColumn(type);
|
|
|
|
|
Long plateUniCode = stock.getPlateUniCode();
|
|
|
|
|
List<ValuationAnalysisVO> list = stockMapper.selectFinancialValuationAnalysis(tableName, stockValueColumn, stkUniCode, plateUniCode, timeSpan, type);
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public QuantitativeAnalysisVO quantitativeAnalysis(Long stkUniCode) {
|
|
|
|
|
StockVO stock = getStock(stkUniCode);
|
|
|
|
|
if (stock == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
String secCode = stock.getSecCode();
|
|
|
|
|
Integer mktNum = stock.getMktNum();
|
|
|
|
|
QuantitativeAnalysisVO vo = diagnoseMapper.selectQuantitativeAnalysis(secCode, mktNum);
|
|
|
|
|
if (vo == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
String tableName = stock.getPriceTableName();
|
|
|
|
|
List<KLineVO> kLineList = stockMapper.selectKLine(tableName, stkUniCode, kLineMonth);
|
|
|
|
|
vo.setkLineList(kLineList);
|
|
|
|
|
return vo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String getStockValueColumn(Integer type) {
|
|
|
|
|
if (type == 2) {
|
|
|
|
|
return "stk_per_ttm";
|
|
|
|
|
} else if (type == 3) {
|
|
|
|
|
return "price_bookv_ratio";
|
|
|
|
|
}
|
|
|
|
|
throw new BizException(ResponseStatus.PARM_ERROR, "类型错误");
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-17 10:46:29 +08:00
|
|
|
}
|