feat: 简化交易计算
This commit is contained in:
@@ -33,6 +33,12 @@
|
|||||||
<artifactId>hutool-http</artifactId>
|
<artifactId>hutool-http</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.icepear.echarts</groupId>
|
||||||
|
<artifactId>echarts-java</artifactId>
|
||||||
|
<version>1.1.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.github.ralfkonrad.quantlib_for_maven</groupId>
|
<groupId>io.github.ralfkonrad.quantlib_for_maven</groupId>
|
||||||
<artifactId>quantlib</artifactId>
|
<artifactId>quantlib</artifactId>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.lanyuanxiaoyao.leopard.core.repository.DailyRepository;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -50,9 +51,6 @@ public class TradeEngine {
|
|||||||
.filter(daily -> daily.getTradeDate().isBefore(currentDate))
|
.filter(daily -> daily.getTradeDate().isBefore(currentDate))
|
||||||
.toList()
|
.toList()
|
||||||
);
|
);
|
||||||
if (trade == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var daily = dailies.stream()
|
var daily = dailies.stream()
|
||||||
.filter(d -> ObjectUtil.equals(d.getTradeDate(), currentDate))
|
.filter(d -> ObjectUtil.equals(d.getTradeDate(), currentDate))
|
||||||
.findFirst()
|
.findFirst()
|
||||||
@@ -75,20 +73,46 @@ public class TradeEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getVolume() {
|
public int getVolume() {
|
||||||
|
return getVolume(trade -> true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVolume(LocalDate date) {
|
||||||
|
return getVolume(trade -> trade.date().isBefore(date) || trade.date().isEqual(date));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getVolume(Predicate<Trade> predicate) {
|
||||||
return trades.stream()
|
return trades.stream()
|
||||||
|
.filter(predicate)
|
||||||
.mapToInt(Trade::volume)
|
.mapToInt(Trade::volume)
|
||||||
.sum();
|
.sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getCash() {
|
public double getCash() {
|
||||||
|
return getCash(trade -> true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getCash(LocalDate date) {
|
||||||
|
return getCash(trade -> trade.date().isBefore(date) || trade.date().isEqual(date));
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getCash(Predicate<Trade> predicate) {
|
||||||
return trades.stream()
|
return trades.stream()
|
||||||
|
.filter(predicate)
|
||||||
.mapToDouble(trade -> -1 * trade.volume() * trade.price())
|
.mapToDouble(trade -> -1 * trade.volume() * trade.price())
|
||||||
.sum();
|
.sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getPrice() {
|
public double getPrice() {
|
||||||
int volume = getVolume();
|
return getPrice(trade -> true);
|
||||||
return volume == 0 ? 0 : getCash() / volume;
|
}
|
||||||
|
|
||||||
|
public double getPrice(LocalDate date) {
|
||||||
|
return getPrice(trade -> trade.date().isBefore(date) || trade.date().isEqual(date));
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getPrice(Predicate<Trade> predicate) {
|
||||||
|
int volume = getVolume(predicate);
|
||||||
|
return volume == 0 ? 0 : getCash(predicate) / volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Trade(
|
public record Trade(
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public class StrategyApplication {
|
|||||||
var startDate = LocalDate.of(2024, 12, 1);
|
var startDate = LocalDate.of(2024, 12, 1);
|
||||||
var endDate = LocalDate.of(2024, 12, 31);
|
var endDate = LocalDate.of(2024, 12, 31);
|
||||||
var charts = new ArrayList<Dict>();
|
var charts = new ArrayList<Dict>();
|
||||||
List.of("000048.SZ", "000333.SZ", "000568.SZ", "000596.SZ"/*, "000651.SZ", "000848.SZ", "000858.SZ", "000933.SZ", "002027.SZ", "002032.SZ", "002142.SZ", "002192.SZ", "002415.SZ", "002432.SZ", "002475.SZ", "002517.SZ", "002555.SZ", "002648.SZ", "002756.SZ", "002847.SZ", "600036.SH", "600096.SH", "600132.SH", "600188.SH", "600309.SH", "600426.SH", "600436.SH", "600519.SH", "600546.SH", "600563.SH", "600702.SH", "600779.SH", "600803.SH", "600809.SH", "600961.SH", "601001.SH", "601100.SH", "601138.SH", "601225.SH", "601899.SH", "601919.SH", "603195.SH", "603198.SH", "603288.SH", "603369.SH", "603444.SH", "603565.SH", "603568.SH", "603605.SH", "603688.SH"*/)
|
List.of("000048.SZ", "000333.SZ", "000568.SZ", "000596.SZ", "000651.SZ", "000848.SZ", "000858.SZ", "000933.SZ", "002027.SZ", "002032.SZ", "002142.SZ", "002192.SZ", "002415.SZ", "002432.SZ", "002475.SZ", "002517.SZ", "002555.SZ", "002648.SZ", "002756.SZ", "002847.SZ", "600036.SH", "600096.SH"/*, "600132.SH", "600188.SH", "600309.SH", "600426.SH", "600436.SH", "600519.SH", "600546.SH", "600563.SH", "600702.SH", "600779.SH", "600803.SH", "600809.SH", "600961.SH", "601001.SH", "601100.SH", "601138.SH", "601225.SH", "601899.SH", "601919.SH", "603195.SH", "603198.SH", "603288.SH", "603369.SH", "603444.SH", "603565.SH", "603568.SH", "603605.SH", "603688.SH"*/)
|
||||||
.parallelStream()
|
.parallelStream()
|
||||||
.forEach(code -> {
|
.forEach(code -> {
|
||||||
var stock = stockRepository.findOne(QStock.stock.code.eq(code)).orElseThrow();
|
var stock = stockRepository.findOne(QStock.stock.code.eq(code)).orElseThrow();
|
||||||
@@ -112,6 +112,7 @@ public class StrategyApplication {
|
|||||||
charts.add(
|
charts.add(
|
||||||
Dict.create()
|
Dict.create()
|
||||||
.set("title", code)
|
.set("title", code)
|
||||||
|
.set("type", "candle")
|
||||||
.set(
|
.set(
|
||||||
"data",
|
"data",
|
||||||
Dict.create()
|
Dict.create()
|
||||||
@@ -125,6 +126,7 @@ public class StrategyApplication {
|
|||||||
"points",
|
"points",
|
||||||
asset.getTrades()
|
asset.getTrades()
|
||||||
.stream()
|
.stream()
|
||||||
|
.filter(trade -> trade.volume() != 0)
|
||||||
.map(trade -> Dict.create()
|
.map(trade -> Dict.create()
|
||||||
.set("value", trade.volume())
|
.set("value", trade.volume())
|
||||||
.set("itemStyle", Dict.create()
|
.set("itemStyle", Dict.create()
|
||||||
|
|||||||
@@ -397,6 +397,11 @@
|
|||||||
type: 'tabs',
|
type: 'tabs',
|
||||||
tabsMode: 'vertical',
|
tabsMode: 'vertical',
|
||||||
tabs: data.map(item => {
|
tabs: data.map(item => {
|
||||||
|
let body = {}
|
||||||
|
if (item?.type === 'candle') {
|
||||||
|
body = Object.keys(item?.data ?? {})
|
||||||
|
.map(key => candleChart(key, item.data[key]))
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
title: item?.title,
|
title: item?.title,
|
||||||
body: Object.keys(item?.data ?? {})
|
body: Object.keys(item?.data ?? {})
|
||||||
|
|||||||
Reference in New Issue
Block a user