From 7a70c037f93d1c330bd87cede475ba58bb83d413 Mon Sep 17 00:00:00 2001 From: lanyuanxiaoyao Date: Sun, 7 Sep 2025 21:27:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E7=AD=96=E7=95=A5?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E4=B8=93=E9=97=A8=E5=A4=84=E7=90=86=E7=AD=96?= =?UTF-8?q?=E7=95=A5=E7=A0=94=E7=A9=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/compiler.xml | 1 + .idea/encodings.xml | 2 + .../leopard/core/entity/Stock.java | 5 + .../leopard/core/entity/StockCollection.java | 37 ++++++++ .../leopard/server/Constants.java | 11 --- .../src/main/resources/logback-spring.xml | 46 +++++---- .../src/test/resources/tushare.http | 93 +++++++++++++++++++ leopard-strategy/pom.xml | 86 +++++++++++++++++ .../leopard/strategy/StrategyApplication.java | 69 ++++++++++++++ .../src/main/resources/logback-spring.xml | 23 +++++ .../leopard/strategy/TestMaCalculate.java | 22 +++++ pom.xml | 1 + 12 files changed, 368 insertions(+), 28 deletions(-) create mode 100644 leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/entity/StockCollection.java delete mode 100644 leopard-server/src/main/java/com/lanyuanxiaoyao/leopard/server/Constants.java create mode 100644 leopard-strategy/pom.xml create mode 100644 leopard-strategy/src/main/java/com/lanyuanxiaoyao/leopard/strategy/StrategyApplication.java create mode 100644 leopard-strategy/src/main/resources/logback-spring.xml create mode 100644 leopard-strategy/src/test/java/com/lanyuanxiaoyao/leopard/strategy/TestMaCalculate.java diff --git a/.idea/compiler.xml b/.idea/compiler.xml index bc15249..edd3629 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -96,6 +96,7 @@ + diff --git a/.idea/encodings.xml b/.idea/encodings.xml index 548bf63..04840fd 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -5,6 +5,8 @@ + + diff --git a/leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/entity/Stock.java b/leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/entity/Stock.java index 41c3c9f..eeb05e9 100644 --- a/leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/entity/Stock.java +++ b/leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/entity/Stock.java @@ -9,6 +9,7 @@ import jakarta.persistence.Entity; import jakarta.persistence.EntityListeners; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; +import jakarta.persistence.ManyToMany; import jakarta.persistence.OneToMany; import jakarta.persistence.Table; import java.time.LocalDate; @@ -61,6 +62,10 @@ public class Stock extends SimpleEntity { @ToString.Exclude private Set dailies; + @ManyToMany + @ToString.Exclude + private Set collections; + @Getter @AllArgsConstructor public enum Market implements SimpleEnum { diff --git a/leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/entity/StockCollection.java b/leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/entity/StockCollection.java new file mode 100644 index 0000000..531c8ac --- /dev/null +++ b/leopard-core/src/main/java/com/lanyuanxiaoyao/leopard/core/entity/StockCollection.java @@ -0,0 +1,37 @@ +package com.lanyuanxiaoyao.leopard.core.entity; + +import com.lanyuanxiaoyao.leopard.core.Constants; +import com.lanyuanxiaoyao.service.template.entity.SimpleEntity; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.Table; +import java.util.Set; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.FieldNameConstants; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +@Setter +@Getter +@ToString(callSuper = true) +@FieldNameConstants +@Entity +@DynamicUpdate +@DynamicInsert +@EntityListeners(AuditingEntityListener.class) +@Table(name = Constants.DATABASE_PREFIX + "stock_collection") +public class StockCollection extends SimpleEntity { + @Column(nullable = false) + private String name; + @Column(nullable = false) + private String description; + + @ManyToMany + @ToString.Exclude + private Set stocks; +} diff --git a/leopard-server/src/main/java/com/lanyuanxiaoyao/leopard/server/Constants.java b/leopard-server/src/main/java/com/lanyuanxiaoyao/leopard/server/Constants.java deleted file mode 100644 index 0b943d2..0000000 --- a/leopard-server/src/main/java/com/lanyuanxiaoyao/leopard/server/Constants.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.lanyuanxiaoyao.leopard.server; - -/** - * 静态字段 - * - * @author lanyuanxiaoyao - * @version 20250829 - */ -public interface Constants { - String DATABASE_PREFIX = "leopard_"; -} diff --git a/leopard-server/src/main/resources/logback-spring.xml b/leopard-server/src/main/resources/logback-spring.xml index dccdab5..56b1576 100644 --- a/leopard-server/src/main/resources/logback-spring.xml +++ b/leopard-server/src/main/resources/logback-spring.xml @@ -1,24 +1,36 @@ - + - - - + + + - - + + - - - %d{yyyy-MM-dd HH:mm:ss.SSS} %clr(%5p) %clr([${HOSTNAME}]){yellow} %clr([%t]){magenta} %clr(%logger{40}){cyan}: %m%n%wEx - - + + + %d{yyyy-MM-dd HH:mm:ss.SSS} %clr(%5p) %clr([${HOSTNAME}]){yellow} %clr([%t]){magenta} %clr(%logger{40}){cyan}: %m%n%wEx + + + - - - + + ${LOGGING_PARENT:-.}/${APP_NAME:-run}.log + + ${LOGGING_PARENT:-.}/archive/${APP_NAME:-run}-%d{yyyy-MM-dd}.gz + 7 + + + %d{yyyy-MM-dd HH:mm:ss.SSS} %p [${HOSTNAME}] [%t] %logger: %m%n%wEx + + - - - + + + + + + + \ No newline at end of file diff --git a/leopard-server/src/test/resources/tushare.http b/leopard-server/src/test/resources/tushare.http index 2732b0c..db97053 100644 --- a/leopard-server/src/test/resources/tushare.http +++ b/leopard-server/src/test/resources/tushare.http @@ -110,3 +110,96 @@ Content-Type: application/json "adj_factor" ] } + +### Get daily factor +POST {{api_url}} +Content-Type: application/json + +{ + "api_name": "stk_factor_pro", + "token": "{{api_key}}", + "params": { + "ts_code": "000001.SZ", + "trade_date": "20250225" + }, + "fields": [ + "ts_code", + "trade_date", + "close", + "close_qfq", + "close_hfq", + "ema_hfq_5" + ] +} + +### Get income +POST {{api_url}} +Content-Type: application/json + +{ + "api_name": "income", + "token": "{{api_key}}", + "params": { + "ts_code": "000001.SZ", + "period": "20241231" + }, + "fields": [ + "ts_code", + "ann_date", + "total_revenue", + "int_income" + ] +} + +### Get cashflow +POST {{api_url}} +Content-Type: application/json + +{ + "api_name": "cashflow", + "token": "{{api_key}}", + "params": { + "ts_code": "000002.SZ", + "period": "20231231" + }, + "fields": [ + "ann_date", + "n_cashflow_act" + ] +} + +### Get balancesheet +POST {{api_url}} +Content-Type: application/json + +{ + "api_name": "balancesheet", + "token": "{{api_key}}", + "params": { + "ts_code": "000002.SZ", + "period": "20231231" + }, + "fields": [ + "ann_date", + "total_cur_liab", + "oth_cur_liab" + ] +} + +### Get fina_indicator +POST {{api_url}} +Content-Type: application/json + +{ + "api_name": "fina_indicator", + "token": "{{api_key}}", + "params": { + "ts_code": "000002.SZ", + "period": "20231231" + }, + "fields": [ + "ann_date", + "ocf_to_shortdebt", + "currentdebt_to_debt" + ] +} diff --git a/leopard-strategy/pom.xml b/leopard-strategy/pom.xml new file mode 100644 index 0000000..25db35b --- /dev/null +++ b/leopard-strategy/pom.xml @@ -0,0 +1,86 @@ + + + 4.0.0 + + com.lanyuanxiaoyao + leopard + 1.0.0 + + + leopard-strategy + + + + com.lanyuanxiaoyao + leopard-core + + + org.springframework.boot + spring-boot-starter + + + io.github.ralfkonrad.quantlib_for_maven + quantlib + 1.39.0 + + + org.ta4j + ta4j-core + 0.17 + + + + org.springframework.boot + spring-boot-starter-test + + + + org.postgresql + postgresql + runtime + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.springframework.boot + spring-boot-configuration-processor + + + org.projectlombok + lombok + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + package + + repackage + + + + + + + \ No newline at end of file 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 new file mode 100644 index 0000000..9d88845 --- /dev/null +++ b/leopard-strategy/src/main/java/com/lanyuanxiaoyao/leopard/strategy/StrategyApplication.java @@ -0,0 +1,69 @@ +package com.lanyuanxiaoyao.leopard.strategy; + +import com.lanyuanxiaoyao.leopard.core.entity.Daily; +import com.lanyuanxiaoyao.leopard.core.entity.Daily_; +import com.lanyuanxiaoyao.leopard.core.entity.QDaily; +import com.lanyuanxiaoyao.leopard.core.repository.DailyRepository; +import com.lanyuanxiaoyao.leopard.core.repository.StockRepository; +import jakarta.annotation.Resource; +import jakarta.transaction.Transactional; +import java.time.Duration; +import java.time.ZoneId; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.ta4j.core.BaseBar; +import org.ta4j.core.BaseBarSeriesBuilder; +import org.ta4j.core.indicators.EMAIndicator; +import org.ta4j.core.indicators.helpers.ClosePriceIndicator; +import org.ta4j.core.num.DoubleNum; + +@Slf4j +@SpringBootApplication(scanBasePackages = "com.lanyuanxiaoyao.leopard") +@EnableJpaAuditing +public class StrategyApplication { + @Resource + private StockRepository stockRepository; + @Resource + private DailyRepository dailyRepository; + + public static void main(String[] args) { + SpringApplication.run(StrategyApplication.class, args); + } + + @Transactional(rollbackOn = Throwable.class) + @EventListener(ApplicationReadyEvent.class) + public void test() { + var dailies = dailyRepository.findAll(QDaily.daily.stock.code.eq("000001.SZ"), Sort.by(Daily_.TRADE_DATE)); + var series = new BaseBarSeriesBuilder() + .withNumTypeOf(DoubleNum.class) + .build(); + log.info("{}", dailies.size()); + for (Daily daily : dailies) { + series.addBar(new BaseBar( + Duration.ofDays(1), + daily.getTradeDate().plusDays(1).atStartOfDay(ZoneId.systemDefault()), + DoubleNum.valueOf(daily.getOpen() * daily.getFactor()), + DoubleNum.valueOf(daily.getHigh() * daily.getFactor()), + DoubleNum.valueOf(daily.getLow() * daily.getFactor()), + DoubleNum.valueOf(daily.getClose() * daily.getFactor()), + DoubleNum.valueOf(daily.getVolume()), + DoubleNum.valueOf(daily.getPriceChangeAmount()), + daily.getTurnover().longValue() + )); + } + var ema = new EMAIndicator(new ClosePriceIndicator(series), 5); + var emaValues = ema.stream().toList(); + log.info("{}", emaValues.size()); + + for (int index = 0; index < dailies.size(); index++) { + var daily = dailies.get(index); + var emaValue = emaValues.get(index); + log.info("{} {} {} {} {}", daily.getTradeDate().toString(), daily.getClose(), daily.getFactor(), daily.getClose() * daily.getFactor(), emaValue.doubleValue()); + } + } +} diff --git a/leopard-strategy/src/main/resources/logback-spring.xml b/leopard-strategy/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..732f71d --- /dev/null +++ b/leopard-strategy/src/main/resources/logback-spring.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} %clr(%5p) %clr([${HOSTNAME}]){yellow} %clr([%t]){magenta} %clr(%logger{40}){cyan}: %m%n%wEx + + + + + + + + + + \ No newline at end of file diff --git a/leopard-strategy/src/test/java/com/lanyuanxiaoyao/leopard/strategy/TestMaCalculate.java b/leopard-strategy/src/test/java/com/lanyuanxiaoyao/leopard/strategy/TestMaCalculate.java new file mode 100644 index 0000000..9069da9 --- /dev/null +++ b/leopard-strategy/src/test/java/com/lanyuanxiaoyao/leopard/strategy/TestMaCalculate.java @@ -0,0 +1,22 @@ +package com.lanyuanxiaoyao.leopard.strategy; + +import com.lanyuanxiaoyao.leopard.core.repository.StockRepository; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; + +@Slf4j +@DataJpaTest +public class TestMaCalculate { + private final StockRepository stockRepository; + + public TestMaCalculate(StockRepository stockRepository) { + this.stockRepository = stockRepository; + } + + @Test + public void test() { + var total = stockRepository.count(); + log.info("Total: {}", total); + } +} diff --git a/pom.xml b/pom.xml index 914defa..bf4b16f 100644 --- a/pom.xml +++ b/pom.xml @@ -12,6 +12,7 @@ leopard-core leopard-server + leopard-strategy