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