1
0

feat: 一些细小的调整

This commit is contained in:
2025-09-13 00:55:44 +08:00
parent acab6978d4
commit 7fa524b8d5
7 changed files with 102 additions and 83 deletions

View File

@@ -22,7 +22,6 @@ spring:
startup-delay: 30s startup-delay: 30s
job-store-type: jdbc job-store-type: jdbc
jdbc: jdbc:
# platform: mysql
platform: postgres platform: postgres
# initialize-schema: always # initialize-schema: always
properties: properties:

View File

@@ -30,12 +30,8 @@
<logger name="com.zaxxer.hikari" level="ERROR"/> <logger name="com.zaxxer.hikari" level="ERROR"/>
<!--<logger name="org.hibernate.SQL" level="DEBUG"/>--> <!--<logger name="org.hibernate.SQL" level="DEBUG"/>-->
<springProfile name="build">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFile"/>
</springProfile>
<root level="INFO"> <root level="INFO">
<appender-ref ref="Console"/> <appender-ref ref="Console"/>
<appender-ref ref="RollingFile"/>
</root> </root>
</configuration> </configuration>

View File

@@ -144,18 +144,15 @@ POST {{api_url}}
Content-Type: application/json Content-Type: application/json
{ {
"api_name": "income", "api_name": "income_vip",
"token": "{{api_key}}", "token": "{{api_key}}",
"params": { "params": {
"ts_code": "000001.SZ", "ts_code": "000799.SZ",
"period": "20241231" "period": "20191231"
}, },
"fields": [ "fields": [
"ts_code", "revenue",
"ann_date", "total_revenue"
"total_revenue",
"total_cogs",
"n_income"
] ]
} }
@@ -196,41 +193,14 @@ Content-Type: application/json
"api_name": "balancesheet_vip", "api_name": "balancesheet_vip",
"token": "{{api_key}}", "token": "{{api_key}}",
"params": { "params": {
"ts_code": "000001.SZ", "ts_code": "000799.SZ",
"period": "20241231" "period": "20191231"
}, },
"fields": [ "fields": [
"ts_code",
"total_share",
"cap_rese",
"undistr_porfit",
"money_cap",
"accounts_receiv", "accounts_receiv",
"inventories",
"total_cur_assets",
"lt_eqt_invest",
"lt_rec",
"fix_assets",
"r_and_d",
"goodwill",
"total_nca",
"total_assets",
"lt_borr",
"st_borr",
"acct_payable",
"adv_receipts",
"total_cur_liab",
"total_ncl",
"total_liab",
"total_hldr_eqy_exc_min_int",
"total_hldr_eqy_inc_min_int",
"total_liab_hldr_eqy",
"acc_receivable",
"payables",
"accounts_receiv_bill", "accounts_receiv_bill",
"accounts_pay",
"oth_rcv_total", "oth_rcv_total",
"fix_assets_total" "acc_receivable"
] ]
} }

View File

@@ -1,26 +1,26 @@
package com.lanyuanxiaoyao.leopard.strategy; package com.lanyuanxiaoyao.leopard.strategy;
import com.lanyuanxiaoyao.leopard.core.entity.Daily; import cn.hutool.core.util.NumberUtil;
import com.lanyuanxiaoyao.leopard.core.entity.Daily_; import cn.hutool.core.util.ObjectUtil;
import com.lanyuanxiaoyao.leopard.core.entity.QDaily; import com.lanyuanxiaoyao.leopard.core.entity.BalanceSheet;
import com.lanyuanxiaoyao.leopard.core.entity.CashFlow;
import com.lanyuanxiaoyao.leopard.core.entity.Income;
import com.lanyuanxiaoyao.leopard.core.entity.QBalanceSheet;
import com.lanyuanxiaoyao.leopard.core.entity.QCashFlow;
import com.lanyuanxiaoyao.leopard.core.entity.QIncome;
import com.lanyuanxiaoyao.leopard.core.repository.BalanceSheetRepository;
import com.lanyuanxiaoyao.leopard.core.repository.CashFlowRepository;
import com.lanyuanxiaoyao.leopard.core.repository.DailyRepository; import com.lanyuanxiaoyao.leopard.core.repository.DailyRepository;
import com.lanyuanxiaoyao.leopard.core.repository.IncomeRepository;
import com.lanyuanxiaoyao.leopard.core.repository.StockRepository; import com.lanyuanxiaoyao.leopard.core.repository.StockRepository;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.transaction.Transactional; import jakarta.transaction.Transactional;
import java.time.Duration;
import java.time.ZoneId;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 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 @Slf4j
@SpringBootApplication(scanBasePackages = "com.lanyuanxiaoyao.leopard") @SpringBootApplication(scanBasePackages = "com.lanyuanxiaoyao.leopard")
@@ -30,6 +30,12 @@ public class StrategyApplication {
private StockRepository stockRepository; private StockRepository stockRepository;
@Resource @Resource
private DailyRepository dailyRepository; private DailyRepository dailyRepository;
@Resource
private BalanceSheetRepository balanceSheetRepository;
@Resource
private IncomeRepository incomeRepository;
@Resource
private CashFlowRepository cashFlowRepository;
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(StrategyApplication.class, args); SpringApplication.run(StrategyApplication.class, args);
@@ -38,32 +44,76 @@ public class StrategyApplication {
@Transactional(rollbackOn = Throwable.class) @Transactional(rollbackOn = Throwable.class)
@EventListener(ApplicationReadyEvent.class) @EventListener(ApplicationReadyEvent.class)
public void test() { public void test() {
var dailies = dailyRepository.findAll(QDaily.daily.stock.code.eq("000001.SZ"), Sort.by(Daily_.TRADE_DATE)); var code = "000799.SZ";
var series = new BaseBarSeriesBuilder() for (int year = 2019; year <= 2019; year++) {
.withNumTypeOf(DoubleNum.class) var balance = balanceSheetRepository.findOne(
.build(); QBalanceSheet.balanceSheet.stock.code.eq(code)
log.info("{}", dailies.size()); .and(QBalanceSheet.balanceSheet.year.eq(year))
for (Daily daily : dailies) { ).orElseThrow();
series.addBar(new BaseBar( var income = incomeRepository.findOne(
Duration.ofDays(1), QIncome.income.stock.code.eq(code)
daily.getTradeDate().plusDays(1).atStartOfDay(ZoneId.systemDefault()), .and(QIncome.income.year.eq(year))
DoubleNum.valueOf(daily.getOpen() * daily.getFactor()), ).orElseThrow();
DoubleNum.valueOf(daily.getHigh() * daily.getFactor()), var cashflow = cashFlowRepository.findOne(
DoubleNum.valueOf(daily.getLow() * daily.getFactor()), QCashFlow.cashFlow.stock.code.eq(code)
DoubleNum.valueOf(daily.getClose() * daily.getFactor()), .and(QCashFlow.cashFlow.year.eq(year))
DoubleNum.valueOf(daily.getVolume()), ).orElseThrow();
DoubleNum.valueOf(daily.getPriceChangeAmount()), log.info("{} {}", year, calculateFinanceIndicator(balance, income, cashflow));
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++) { private FinanceIndicator calculateFinanceIndicator(BalanceSheet balance, Income income, CashFlow cashflow) {
var daily = dailies.get(index); return new FinanceIndicator(
var emaValue = emaValues.get(index); safeDiv(balance.getTotalLiabilities(), balance.getTotalAssets()),
log.info("{} {} {} {} {}", daily.getTradeDate().toString(), daily.getClose(), daily.getFactor(), daily.getClose() * daily.getFactor(), emaValue.doubleValue()); safeDiv(balance.getTotalAssets(), balance.getTotalNonCurrentAssets()),
safeDiv(balance.getTotalCurrentAssets(), balance.getTotalCurrentLiabilities()),
safeDiv(safeMinus(balance.getTotalCurrentAssets(), balance.getInventories()), balance.getTotalCurrentLiabilities()),
safeDiv(income.getOperatingRevenue(), balance.getNotesAndAccountsReceivable()),
safeDiv(360.0, safeDiv(income.getOperatingRevenue(), balance.getNotesAndAccountsReceivable())),
safeDiv(income.getTotalOperatingCost(), balance.getInventories())
);
}
private Double safePlus(Double a, Double b) {
if (ObjectUtil.isNull(a) || ObjectUtil.isNull(b)) {
return null;
}
return a + b;
}
private Double safeMinus(Double a, Double b) {
if (ObjectUtil.isNull(a) || ObjectUtil.isNull(b)) {
return null;
}
return a - b;
}
private Double safeDiv(Double a, Double b) {
if (ObjectUtil.isNull(a) || ObjectUtil.isNull(b) || b == 0) {
return null;
}
return NumberUtil.div(a, b, 4);
}
public record FinanceIndicator(
Double debtToAssetRatio,
Double longTermFundsToRealEstateRatio,
Double currentRatio,
Double quickRatio,
Double accountsReceivableTurnoverRate,
Double averageCashCollectionDays,
Double inventoryTurnoverRate
) {
@Override
public String toString() {
return "负债占资产比率=" + debtToAssetRatio +
", 长期资金占固定资产比率=" + longTermFundsToRealEstateRatio +
", 流动比率=" + currentRatio +
", 速动比率=" + quickRatio +
", 应收账款周转率=" + accountsReceivableTurnoverRate +
", 平均现金回收天数=" + averageCashCollectionDays +
", 库存周转率=" + inventoryTurnoverRate +
';';
} }
} }
} }

View File

@@ -2,9 +2,13 @@ spring:
application: application:
name: leopard-strategy name: leopard-strategy
datasource: datasource:
url: jdbc:postgresql://192.168.31.127:6785/leopard url: jdbc:postgresql://81.71.3.24:6785/leopard_dev
username: leopard username: leopard
password: '9NEzFzovnddf@PyEP?e*AYAWnCyd7UhYwQK$pJf>7?ccFiN^x4$eKEZ5~E<7<+~X' password: '9NEzFzovnddf@PyEP?e*AYAWnCyd7UhYwQK$pJf>7?ccFiN^x4$eKEZ5~E<7<+~X'
driver-class-name: org.postgresql.Driver driver-class-name: org.postgresql.Driver
jpa:
generate-ddl: false
main:
banner-mode: off
fenix: fenix:
print-banner: false print-banner: false

View File

@@ -14,10 +14,10 @@
</encoder> </encoder>
</appender> </appender>
<logger name="com.zaxxer.hikari" level="ERROR"/> <logger name="com.lanyuanxiaoyao.leopard" level="INFO"/>
<logger name="org.hibernate.SQL" level="DEBUG"/> <logger name="org.hibernate.SQL" level="DEBUG"/>
<root level="INFO"> <root level="ERROR">
<appender-ref ref="Console"/> <appender-ref ref="Console"/>
</root> </root>
</configuration> </configuration>

View File

@@ -49,7 +49,7 @@ const financePropertyLabel = (id: string | undefined, label: string, type: strin
actionType: 'dialog', actionType: 'dialog',
dialog: { dialog: {
title: `${label}五年趋势`, title: `${label}五年趋势`,
size: 'md', size: 'lg',
bodyClassName: 'p-0', bodyClassName: 'p-0',
...readOnlyDialogOptions(), ...readOnlyDialogOptions(),
body: { body: {