feat: 添加 AI 扫描决策间隔配置支持

## 功能描述
在创建和编辑 Trader 时,支持配置 AI 扫描决策间隔(scan_interval_minutes),允许用户自定义 AI 决策的频率。
## 修改内容
### 后端修改 (api/server.go)
1. **CreateTraderRequest** 添加 `ScanIntervalMinutes` 字段
2. **UpdateTraderRequest** 添加 `ScanIntervalMinutes` 字段和 `SystemPromptTemplate` 字段
3. **handleCreateTrader** 处理扫描间隔默认值(默认 3 分钟)
4. **handleUpdateTrader** 支持更新扫描间隔
5. **handleGetTraderConfig** 返回中添加 `scan_interval_minutes` 字段
### 前端修改
#### web/src/types.ts
- `CreateTraderRequest` 添加 `scan_interval_minutes?` 可选字段
- `TraderConfigData` 添加 `scan_interval_minutes` 必填字段
#### web/src/components/TraderConfigModal.tsx
- 本地 `TraderConfigData` 接口添加 `scan_interval_minutes`
- 初始状态设置默认值为 3 分钟
- 添加 UI 输入框(范围 1-60 分钟)
- Label 优化为 "AI 扫描决策间隔 (分钟)"
#### web/src/components/AITradersPage.tsx
- `handleSaveEditTrader` 的更新请求中添加 `scan_interval_minutes`
#### web/src/components/landing/CommunitySection.tsx
- 修复 TypeScript 编译错误:定义 `CardProps` 接口
- 修正 `TestimonialCard` 组件的 prop 名称(author → authorName)
## 功能特性
-  支持 1-60 分钟的自定义间隔
-  默认值为 3 分钟
-  UI 提示建议范围:3-10 分钟
-  创建和编辑时均支持配置
-  后端验证和处理默认值
## 测试步骤
1. 创建新 Trader,设置自定义扫描间隔(如 10 分钟)
2. 验证 Trader 创建成功
3. 编辑现有 Trader,修改扫描间隔
4. 验证修改保存成功
5. 确认 AI 决策按照新的间隔执行
This commit is contained in:
Liu Xiang Qian
2025-11-03 21:55:26 +08:00
parent c5628293a3
commit 16bf34d56e
5 changed files with 100 additions and 43 deletions

View File

@@ -210,6 +210,7 @@ type CreateTraderRequest struct {
AIModelID string `json:"ai_model_id" binding:"required"`
ExchangeID string `json:"exchange_id" binding:"required"`
InitialBalance float64 `json:"initial_balance"`
ScanIntervalMinutes int `json:"scan_interval_minutes"`
BTCETHLeverage int `json:"btc_eth_leverage"`
AltcoinLeverage int `json:"altcoin_leverage"`
TradingSymbols string `json:"trading_symbols"`
@@ -332,6 +333,12 @@ func (s *Server) handleCreateTrader(c *gin.Context) {
systemPromptTemplate = req.SystemPromptTemplate
}
// 设置扫描间隔默认值
scanIntervalMinutes := req.ScanIntervalMinutes
if scanIntervalMinutes <= 0 {
scanIntervalMinutes = 3 // 默认3分钟
}
// 创建交易员配置(数据库实体)
trader := &config.TraderRecord{
ID: traderID,
@@ -349,7 +356,7 @@ func (s *Server) handleCreateTrader(c *gin.Context) {
OverrideBasePrompt: req.OverrideBasePrompt,
SystemPromptTemplate: systemPromptTemplate,
IsCrossMargin: isCrossMargin,
ScanIntervalMinutes: 3, // 默认3分钟
ScanIntervalMinutes: scanIntervalMinutes,
IsRunning: false,
}
@@ -379,16 +386,18 @@ func (s *Server) handleCreateTrader(c *gin.Context) {
// UpdateTraderRequest 更新交易员请求
type UpdateTraderRequest struct {
Name string `json:"name" binding:"required"`
AIModelID string `json:"ai_model_id" binding:"required"`
ExchangeID string `json:"exchange_id" binding:"required"`
InitialBalance float64 `json:"initial_balance"`
BTCETHLeverage int `json:"btc_eth_leverage"`
AltcoinLeverage int `json:"altcoin_leverage"`
TradingSymbols string `json:"trading_symbols"`
CustomPrompt string `json:"custom_prompt"`
OverrideBasePrompt bool `json:"override_base_prompt"`
IsCrossMargin *bool `json:"is_cross_margin"`
Name string `json:"name" binding:"required"`
AIModelID string `json:"ai_model_id" binding:"required"`
ExchangeID string `json:"exchange_id" binding:"required"`
InitialBalance float64 `json:"initial_balance"`
ScanIntervalMinutes int `json:"scan_interval_minutes"`
BTCETHLeverage int `json:"btc_eth_leverage"`
AltcoinLeverage int `json:"altcoin_leverage"`
TradingSymbols string `json:"trading_symbols"`
CustomPrompt string `json:"custom_prompt"`
OverrideBasePrompt bool `json:"override_base_prompt"`
SystemPromptTemplate string `json:"system_prompt_template"`
IsCrossMargin *bool `json:"is_cross_margin"`
}
// handleUpdateTrader 更新交易员配置
@@ -437,23 +446,36 @@ func (s *Server) handleUpdateTrader(c *gin.Context) {
if altcoinLeverage <= 0 {
altcoinLeverage = existingTrader.AltcoinLeverage // 保持原值
}
// 设置扫描间隔,允许更新
scanIntervalMinutes := req.ScanIntervalMinutes
if scanIntervalMinutes <= 0 {
scanIntervalMinutes = existingTrader.ScanIntervalMinutes // 保持原值
}
// 设置系统提示词模板,允许更新
systemPromptTemplate := req.SystemPromptTemplate
if systemPromptTemplate == "" {
systemPromptTemplate = existingTrader.SystemPromptTemplate // 保持原值
}
// 更新交易员配置
trader := &config.TraderRecord{
ID: traderID,
UserID: userID,
Name: req.Name,
AIModelID: req.AIModelID,
ExchangeID: req.ExchangeID,
InitialBalance: req.InitialBalance,
BTCETHLeverage: btcEthLeverage,
AltcoinLeverage: altcoinLeverage,
TradingSymbols: req.TradingSymbols,
CustomPrompt: req.CustomPrompt,
OverrideBasePrompt: req.OverrideBasePrompt,
IsCrossMargin: isCrossMargin,
ScanIntervalMinutes: existingTrader.ScanIntervalMinutes, // 保持原值
IsRunning: existingTrader.IsRunning, // 保持原值
ID: traderID,
UserID: userID,
Name: req.Name,
AIModelID: req.AIModelID,
ExchangeID: req.ExchangeID,
InitialBalance: req.InitialBalance,
BTCETHLeverage: btcEthLeverage,
AltcoinLeverage: altcoinLeverage,
TradingSymbols: req.TradingSymbols,
CustomPrompt: req.CustomPrompt,
OverrideBasePrompt: req.OverrideBasePrompt,
SystemPromptTemplate: systemPromptTemplate,
IsCrossMargin: isCrossMargin,
ScanIntervalMinutes: scanIntervalMinutes,
IsRunning: existingTrader.IsRunning, // 保持原值
}
// 更新数据库
@@ -805,20 +827,21 @@ func (s *Server) handleGetTraderConfig(c *gin.Context) {
aiModelID := traderConfig.AIModelID
result := map[string]interface{}{
"trader_id": traderConfig.ID,
"trader_name": traderConfig.Name,
"ai_model": aiModelID,
"exchange_id": traderConfig.ExchangeID,
"initial_balance": traderConfig.InitialBalance,
"btc_eth_leverage": traderConfig.BTCETHLeverage,
"altcoin_leverage": traderConfig.AltcoinLeverage,
"trading_symbols": traderConfig.TradingSymbols,
"custom_prompt": traderConfig.CustomPrompt,
"override_base_prompt": traderConfig.OverrideBasePrompt,
"is_cross_margin": traderConfig.IsCrossMargin,
"use_coin_pool": traderConfig.UseCoinPool,
"use_oi_top": traderConfig.UseOITop,
"is_running": isRunning,
"trader_id": traderConfig.ID,
"trader_name": traderConfig.Name,
"ai_model": aiModelID,
"exchange_id": traderConfig.ExchangeID,
"initial_balance": traderConfig.InitialBalance,
"scan_interval_minutes": traderConfig.ScanIntervalMinutes,
"btc_eth_leverage": traderConfig.BTCETHLeverage,
"altcoin_leverage": traderConfig.AltcoinLeverage,
"trading_symbols": traderConfig.TradingSymbols,
"custom_prompt": traderConfig.CustomPrompt,
"override_base_prompt": traderConfig.OverrideBasePrompt,
"is_cross_margin": traderConfig.IsCrossMargin,
"use_coin_pool": traderConfig.UseCoinPool,
"use_oi_top": traderConfig.UseOITop,
"is_running": isRunning,
}
c.JSON(http.StatusOK, result)