diff --git a/leopard-strategy/src/main/java/com/lanyuanxiaoyao/leopard/strategy/StrategyApplication.java b/leopard-strategy/src/main/java/com/lanyuanxiaoyao/leopard/strategy/StrategyApplication.java index 8a1f6ec..75c6bfb 100644 --- a/leopard-strategy/src/main/java/com/lanyuanxiaoyao/leopard/strategy/StrategyApplication.java +++ b/leopard-strategy/src/main/java/com/lanyuanxiaoyao/leopard/strategy/StrategyApplication.java @@ -1,5 +1,6 @@ package com.lanyuanxiaoyao.leopard.strategy; +import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjectUtil; import com.lanyuanxiaoyao.leopard.core.entity.FinanceIndicator; import com.lanyuanxiaoyao.leopard.core.entity.Stock; @@ -32,7 +33,7 @@ public class StrategyApplication { @Transactional(rollbackOn = Throwable.class) @EventListener(ApplicationReadyEvent.class) public void test() { - var stocks = stockRepository.findAllByIndicatorsSizeGreaterThanEqual(6); + var stocks = stockRepository.findAllByIndicatorsSizeGreaterThanEqual(5); var stocksMap = stocks.stream().collect(Collectors.toMap(Stock::getCode, stock -> stock)); var scores = stocks.stream().map(Stock::getCode).collect(Collectors.toMap(code -> code, code -> 0)); for (Stock stock : stocks) { @@ -41,9 +42,9 @@ public class StrategyApplication { .sorted((a, b) -> b.getYear() - a.getYear()) .limit(5) .toList(); - var latestIndicator = recentIndicators.get(0); + var latestIndicator = recentIndicators.getFirst(); - int roeScore = 0; + var roeScore = 0; if (recentIndicators.stream().noneMatch(indicator -> indicator.getReturnOnEquity() == null || indicator.getReturnOnEquity() < 0)) { var averageRoe = recentIndicators.stream() .map(FinanceIndicator::getReturnOnEquity) @@ -67,11 +68,10 @@ public class StrategyApplication { } scores.put(stock.getCode(), scores.get(stock.getCode()) + roeScore); - int roaScore = 0; + var roaScore = 0; if (recentIndicators.stream().noneMatch(indicator -> indicator.getReturnOnAssets() == null)) { var averageRoa = recentIndicators.stream() .map(FinanceIndicator::getReturnOnAssets) - .map(item -> ObjectUtil.defaultIfNull(item, 0.0)) .mapToDouble(Double::doubleValue) .average() .orElse(0.0); @@ -85,11 +85,10 @@ public class StrategyApplication { } scores.put(stock.getCode(), scores.get(stock.getCode()) + roaScore); - int netProfitScore = 0; + var netProfitScore = 0; if (recentIndicators.stream().noneMatch(indicator -> indicator.getNetProfit() == null)) { var averageNetProfit = recentIndicators.stream() .map(FinanceIndicator::getNetProfit) - .map(item -> ObjectUtil.defaultIfNull(item, 0.0)) .mapToDouble(Double::doubleValue) .average() .orElse(0.0); @@ -101,8 +100,14 @@ public class StrategyApplication { } scores.put(stock.getCode(), scores.get(stock.getCode()) + netProfitScore); - int cashScore = 0; - if (ObjectUtil.isNotNull(latestIndicator.getTotalAssetsTurnover()) && ObjectUtil.isNotNull(latestIndicator.getCashAndCashEquivalentsToTotalAssetsRatio()) && (latestIndicator.getTotalAssetsTurnover() > 0.8 && latestIndicator.getCashAndCashEquivalentsToTotalAssetsRatio() >= 0.1 || latestIndicator.getTotalAssetsTurnover() <= 0.8 && latestIndicator.getCashAndCashEquivalentsToTotalAssetsRatio() >= 0.2)) { + var cashScore = 0; + if ( + ArrayUtil.isAllNotNull(latestIndicator.getTotalAssetsTurnover(), latestIndicator.getCashAndCashEquivalentsToTotalAssetsRatio()) + && ( + latestIndicator.getTotalAssetsTurnover() > 0.8 && latestIndicator.getCashAndCashEquivalentsToTotalAssetsRatio() >= 0.1 + || latestIndicator.getTotalAssetsTurnover() <= 0.8 && latestIndicator.getCashAndCashEquivalentsToTotalAssetsRatio() >= 0.2 + ) + ) { cashScore = 50; } scores.put(stock.getCode(), scores.get(stock.getCode()) + cashScore); @@ -113,7 +118,7 @@ public class StrategyApplication { if (ObjectUtil.isNotNull(latestIndicator.getDaysInventoryTurnover()) && latestIndicator.getDaysInventoryTurnover() <= 30) { scores.put(stock.getCode(), scores.get(stock.getCode()) + 20); } - if (ObjectUtil.isNotNull(latestIndicator.getDaysAccountsReceivableTurnover()) && ObjectUtil.isNotNull(latestIndicator.getDaysInventoryTurnover())) { + if (ArrayUtil.isAllNotNull(latestIndicator.getDaysAccountsReceivableTurnover(), latestIndicator.getDaysInventoryTurnover())) { if (latestIndicator.getDaysAccountsReceivableTurnover() + latestIndicator.getDaysInventoryTurnover() <= 40) { scores.put(stock.getCode(), scores.get(stock.getCode()) + 20); } else if (latestIndicator.getDaysAccountsReceivableTurnover() + latestIndicator.getDaysInventoryTurnover() <= 60) { @@ -131,6 +136,73 @@ public class StrategyApplication { scores.put(stock.getCode(), scores.get(stock.getCode()) + 50); } } + + var operatingSafeMarginScore = 0; + if (ObjectUtil.isNotNull(latestIndicator.getOperatingSafetyMarginRatio())) { + if (latestIndicator.getOperatingSafetyMarginRatio() >= 70) { + operatingSafeMarginScore = 50; + } else if (latestIndicator.getOperatingSafetyMarginRatio() >= 50) { + operatingSafeMarginScore = 30; + } else if (latestIndicator.getOperatingSafetyMarginRatio() >= 30) { + operatingSafeMarginScore = 10; + } + } + scores.put(stock.getCode(), scores.get(stock.getCode()) + operatingSafeMarginScore); + + var netProfitAscendingScore = 0; + if (recentIndicators.stream().noneMatch(indicator -> indicator.getNetProfit() == null)) { + if (recentIndicators.get(0).getNetProfit() > recentIndicators.get(1).getNetProfit()) { + netProfitAscendingScore += 30; + } else { + netProfitAscendingScore -= 30; + } + if (recentIndicators.get(1).getNetProfit() > recentIndicators.get(2).getNetProfit()) { + netProfitAscendingScore += 25; + } else { + netProfitAscendingScore -= 25; + } + + if (recentIndicators.get(2).getNetProfit() > recentIndicators.get(3).getNetProfit()) { + netProfitAscendingScore += 20; + } else { + netProfitAscendingScore -= 20; + } + + if (recentIndicators.get(3).getNetProfit() > recentIndicators.get(4).getNetProfit()) { + netProfitAscendingScore += 15; + } else { + netProfitAscendingScore -= 15; + } + } + scores.put(stock.getCode(), scores.get(stock.getCode()) + netProfitAscendingScore); + + var cashAscendingScore = 0; + if (recentIndicators.stream().noneMatch(indicator -> indicator.getCashAndCashEquivalents() == null)) { + if (recentIndicators.get(0).getCashAndCashEquivalents() > recentIndicators.get(1).getCashAndCashEquivalents()) { + cashAscendingScore += 30; + } else { + cashAscendingScore -= 30; + } + + if (recentIndicators.get(1).getCashAndCashEquivalents() > recentIndicators.get(2).getCashAndCashEquivalents()) { + cashAscendingScore += 25; + } else { + cashAscendingScore -= 25; + } + + if (recentIndicators.get(2).getCashAndCashEquivalents() > recentIndicators.get(3).getCashAndCashEquivalents()) { + cashAscendingScore += 20; + } else { + cashAscendingScore -= 20; + } + + if (recentIndicators.get(3).getCashAndCashEquivalents() > recentIndicators.get(4).getCashAndCashEquivalents()) { + cashAscendingScore += 15; + } else { + cashAscendingScore -= 15; + } + } + scores.put(stock.getCode(), scores.get(stock.getCode()) + cashAscendingScore); } scores.entrySet() .stream()