1
0

feat: 增加简单回测

This commit is contained in:
2025-10-16 23:19:56 +08:00
parent e2c5729f87
commit 83574e1229
2 changed files with 112 additions and 10 deletions

View File

@@ -1,7 +1,9 @@
package com.lanyuanxiaoyao.leopard.strategy;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lanyuanxiaoyao.leopard.core.entity.Daily;
import com.lanyuanxiaoyao.leopard.core.entity.QStock;
import com.lanyuanxiaoyao.leopard.core.repository.DailyRepository;
import com.lanyuanxiaoyao.leopard.core.repository.StockRepository;
@@ -9,10 +11,14 @@ import com.lanyuanxiaoyao.leopard.core.service.AssessmentService;
import com.lanyuanxiaoyao.leopard.core.service.StockService;
import com.lanyuanxiaoyao.leopard.core.service.TuShareService;
import com.lanyuanxiaoyao.leopard.core.service.selector.PyramidStockSelector;
import com.lanyuanxiaoyao.leopard.core.strategy.TradeEngine;
import jakarta.annotation.Resource;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDate;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
@@ -39,6 +45,8 @@ public class StrategyApplication {
private StockRepository stockRepository;
@Resource
private StockService stockService;
@Resource
private TradeEngine tradeEngine;
public static void main(String[] args) {
SpringApplication.run(StrategyApplication.class, args);
@@ -279,9 +287,41 @@ public class StrategyApplication {
@EventListener(ApplicationReadyEvent.class)
public void test() {
var stock = stockRepository.findOne(QStock.stock.code.eq("000001.SZ")).orElseThrow();
var weeklies = stockService.findWeeklyRecent(stock.getId(), 2);
for (var weekly : weeklies) {
log.info("{}", weekly);
var asset = tradeEngine.backtest(
List.of(stock.getId()),
(now, currentAsset, dailies) -> {
return dailies.entrySet()
.stream()
.map(entry -> {
var stockId = entry.getKey();
var stockDailies = entry.getValue()
.stream()
.sorted(Comparator.comparing(Daily::getTradeDate))
.toList();
var yesterday = stockDailies.getLast();
if (yesterday.getHfqClose() > yesterday.getHfqOpen()) {
log.info("{} Buy for price {} {}", now, yesterday.getHfqOpen(), yesterday.getHfqClose());
return new TradeEngine.Trade(now, stockId, 100);
} else if (yesterday.getHfqClose() < yesterday.getHfqOpen()) {
var hold = currentAsset.getStocks().getOrDefault(stockId, 0);
if (hold > 0) {
log.info("{} Sell for price {} {}", now, yesterday.getHfqOpen(), yesterday.getHfqClose());
return new TradeEngine.Trade(now, stockId, -1 * hold);
}
} else {
log.info("{} Hold for price {} {}", now, yesterday.getHfqOpen(), yesterday.getHfqClose());
}
return null;
})
.filter(ObjectUtil::isNotNull)
.toList();
},
LocalDate.of(2024, 12, 1),
LocalDate.of(2024, 12, 31)
);
log.info("Final Cash: {}", asset.getCash());
for (var history : asset.getHistories()) {
log.info("Date: {} Cash: {} Trade: {}", history.date(), history.cash(), history.trades().values());
}
}
}