feat: 回测任务支持价格区间过滤

- 后端:
  - BacktestTask 实体类添加 minPrice 和 maxPrice 字段
  - BacktestDto 添加价格区间参数和配置字段
  - BacktestService 支持创建和查询价格区间配置
  - BacktestExecutionService 在 taskToCopyTrading 中设置价格区间
  - 添加数据库迁移脚本 V32__add_backtest_price_range_filter.sql

- 前端:
  - BacktestList 添加价格区间输入表单(最低价、最高价)
  - 详情页面显示价格区间配置
  - 一键创建跟单配置时包含价格区间
  - 添加中英繁三语言翻译
  - 修复价格输入框精度显示问题(0.4 不再显示为 0.40000000)

功能说明:
- 价格区间过滤与跟单配置保持一致,确保回测结果能准确反映实际跟单效果
- 支持只设置最低价、只设置最高价、或同时设置两者
- 留空表示不限制价格

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
WrBug
2026-02-11 23:54:49 +08:00
co-authored by Cursor
parent 99c4328830
commit a067a20a02
9 changed files with 108 additions and 5 deletions
@@ -22,6 +22,8 @@ data class BacktestCreateRequest(
val keywordFilterMode: String? = null, // 关键字过滤模式:DISABLED(不启用)、WHITELIST(白名单)、BLACKLIST(黑名单)
val keywords: List<String>? = null, // 关键字列表
val maxPositionValue: String? = null, // 最大仓位金额(USDC),NULL表示不启用
val minPrice: String? = null, // 最低价格(可选),NULL表示不限制最低价
val maxPrice: String? = null, // 最高价格(可选),NULL表示不限制最高价
val pageForResume: Int? = null // 用于恢复中断任务,从指定页码开始获取历史数据(从1开始)
)
@@ -166,7 +168,9 @@ data class BacktestConfigDto(
val supportSell: Boolean,
val keywordFilterMode: String?,
val keywords: List<String>?,
val maxPositionValue: String?
val maxPositionValue: String?,
val minPrice: String?, // 最低价格(可选),NULL表示不限制最低价
val maxPrice: String? // 最高价格(可选),NULL表示不限制最高价
)
/**
@@ -76,6 +76,12 @@ data class BacktestTask(
@Column(name = "max_position_value", precision = 20, scale = 8)
val maxPositionValue: BigDecimal? = null, // 最大仓位金额(USDC),NULL表示不启用
@Column(name = "min_price", precision = 20, scale = 8)
val minPrice: BigDecimal? = null, // 最低价格(可选),NULL表示不限制最低价
@Column(name = "max_price", precision = 20, scale = 8)
val maxPrice: BigDecimal? = null, // 最高价格(可选),NULL表示不限制最高价
// 统计字段
@Column(name = "avg_holding_time")
var avgHoldingTime: Long? = null, // 平均持仓时间(毫秒)
@@ -73,6 +73,8 @@ class BacktestExecutionService(
minOrderDepth = null, // 回测无实时订单簿数据
maxSpread = null, // 回测无实时价差数据
maxPositionValue = task.maxPositionValue,
minPrice = task.minPrice, // 最低价格
maxPrice = task.maxPrice, // 最高价格
keywordFilterMode = task.keywordFilterMode,
keywords = task.keywords,
configName = null,
@@ -82,7 +82,9 @@ class BacktestService(
} else {
null
},
maxPositionValue = request.maxPositionValue?.toSafeBigDecimal()
maxPositionValue = request.maxPositionValue?.toSafeBigDecimal(),
minPrice = request.minPrice?.toSafeBigDecimal(),
maxPrice = request.maxPrice?.toSafeBigDecimal()
)
backtestTaskRepository.save(task)
@@ -192,7 +194,9 @@ class BacktestService(
} else {
emptyList()
},
maxPositionValue = task.maxPositionValue?.toPlainString()
maxPositionValue = task.maxPositionValue?.toPlainString(),
minPrice = task.minPrice?.toPlainString(),
maxPrice = task.maxPrice?.toPlainString()
)
val statistics = BacktestStatisticsDto(
@@ -379,7 +383,9 @@ class BacktestService(
supportSell = source.supportSell,
keywordFilterMode = source.keywordFilterMode,
keywords = source.keywords,
maxPositionValue = source.maxPositionValue
maxPositionValue = source.maxPositionValue,
minPrice = source.minPrice,
maxPrice = source.maxPrice
)
backtestTaskRepository.save(newTask)
@@ -0,0 +1,9 @@
-- ============================================
-- V32: 添加回测价格区间过滤字段
-- 用于配置价格区间,仅在指定价格区间内的订单才会跟单
-- ============================================
-- 添加价格区间字段到回测任务表
ALTER TABLE backtest_task
ADD COLUMN min_price DECIMAL(20, 8) NULL COMMENT '最低价格(可选),NULL表示不限制最低价',
ADD COLUMN max_price DECIMAL(20, 8) NULL COMMENT '最高价格(可选),NULL表示不限制最高价';