auto_trade_sys/docs/配置值格式统一方案.md
薇薇安 9fe028d704 a
2026-01-27 10:36:56 +08:00

11 KiB
Raw Permalink Blame History

配置值格式统一方案

🎯 问题分析

当前问题

数据库中的配置值(百分比形式):

  • TRAILING_STOP_ACTIVATION = 30表示30%
  • TRAILING_STOP_PROTECT = 15表示15%
  • MIN_VOLATILITY = 3表示3%

代码期望的格式(比例形式):

  • TRAILING_STOP_ACTIVATION = 0.30表示30%
  • TRAILING_STOP_PROTECT = 0.15表示15%
  • MIN_VOLATILITY = 0.03表示3%

临时修复

  • 在代码中添加格式转换逻辑(如果值>1除以100
  • 问题:代码逻辑复杂,容易出错,维护困难

更好的解决方案

方案:统一数据格式(推荐)

原则

  • 数据库存储统一使用比例形式0.30表示30%
  • 前端输入用户输入30前端转换为0.30存储
  • 前端显示从数据库读取0.30显示为30
  • 代码逻辑:直接使用比例形式,不需要格式转换

优势

  1. 数据格式统一:避免混乱
  2. 代码逻辑清晰:不需要到处做格式转换
  3. 减少出错避免格式不一致导致的bug
  4. 易于维护:统一的格式,更容易理解和维护

🔧 实施步骤

步骤1检查前端格式转换逻辑

当前前端逻辑frontend/src/components/ConfigPanel.jsx:1588-1594

// 常规比例型:前端按"百分比"输入0~100存储为 0~1
if (processedValue < 0 || processedValue > 100) {
    setLocalValue(getInitialDisplayValue(value))
    return
}
processedValue = processedValue / 100  // ✅ 前端已经转换为比例形式

结论 前端已经正确转换用户输入30会转换为0.30存储


步骤2检查后端验证逻辑

当前后端验证backend/api/routes/config.py:843-848

# 特殊验证百分比配置应该在0-1之间
if ('PERCENT' in key or 'PCT' in key) and config_type == 'number':
    if not (0 <= float(item.value) <= 1):
        raise HTTPException(
            status_code=400, 
            detail=f"{key} must be between 0 and 1 (0% to 100%)"
        )

结论 后端已经正确验证只接受0-1之间的值


步骤3数据迁移修复现有数据

问题数据库中可能已经有旧数据是百分比形式30而不是0.30

解决方案:创建数据迁移脚本,将百分比形式转换为比例形式

需要迁移的配置项

  • TRAILING_STOP_ACTIVATION(如果>1除以100
  • TRAILING_STOP_PROTECT(如果>1除以100
  • MIN_VOLATILITY(如果>1除以100
  • TAKE_PROFIT_PERCENT(如果>1除以100
  • STOP_LOSS_PERCENT(如果>1除以100
  • 其他百分比配置项

步骤4移除代码中的格式转换可选

当前代码backend/config_manager.py:735-758

# ⚠️ 关键修复:百分比配置值格式转换
if isinstance(value, (int, float)) and value is not None:
    percent_keys = [...]
    if key in percent_keys:
        if value > 1:
            value = value / 100.0  # 格式转换

建议

  • 数据迁移完成后,可以移除格式转换逻辑
  • 或者保留作为兼容性处理(标记为临时方案)

📝 数据迁移脚本

SQL迁移脚本

-- 迁移百分比配置项:将百分比形式(>1转换为比例形式除以100

-- 1. 迁移 trading_config 表
UPDATE trading_config 
SET config_value = CAST(config_value AS DECIMAL(10, 4)) / 100.0
WHERE config_key IN (
    'TRAILING_STOP_ACTIVATION',
    'TRAILING_STOP_PROTECT',
    'MIN_VOLATILITY',
    'TAKE_PROFIT_PERCENT',
    'STOP_LOSS_PERCENT',
    'MIN_STOP_LOSS_PRICE_PCT',
    'MIN_TAKE_PROFIT_PRICE_PCT',
    'FIXED_RISK_PERCENT',
    'MAX_POSITION_PERCENT',
    'MAX_TOTAL_POSITION_PERCENT',
    'MIN_POSITION_PERCENT'
)
AND config_type = 'number'
AND CAST(config_value AS DECIMAL(10, 4)) > 1;

-- 2. 迁移 global_strategy_config 表
UPDATE global_strategy_config 
SET config_value = CAST(config_value AS DECIMAL(10, 4)) / 100.0
WHERE config_key IN (
    'TRAILING_STOP_ACTIVATION',
    'TRAILING_STOP_PROTECT',
    'MIN_VOLATILITY',
    'TAKE_PROFIT_PERCENT',
    'STOP_LOSS_PERCENT',
    'MIN_STOP_LOSS_PRICE_PCT',
    'MIN_TAKE_PROFIT_PRICE_PCT',
    'FIXED_RISK_PERCENT',
    'MAX_POSITION_PERCENT',
    'MAX_TOTAL_POSITION_PERCENT',
    'MIN_POSITION_PERCENT'
)
AND config_type = 'number'
AND CAST(config_value AS DECIMAL(10, 4)) > 1;

🔍 验证步骤

1. 检查数据库中的配置值

-- 检查 trading_config 表中的百分比配置项
SELECT config_key, config_value, config_type
FROM trading_config
WHERE config_key IN (
    'TRAILING_STOP_ACTIVATION',
    'TRAILING_STOP_PROTECT',
    'MIN_VOLATILITY',
    'TAKE_PROFIT_PERCENT',
    'STOP_LOSS_PERCENT'
)
AND config_type = 'number';

-- 检查 global_strategy_config 表中的百分比配置项
SELECT config_key, config_value, config_type
FROM global_strategy_config
WHERE config_key IN (
    'TRAILING_STOP_ACTIVATION',
    'TRAILING_STOP_PROTECT',
    'MIN_VOLATILITY',
    'TAKE_PROFIT_PERCENT',
    'STOP_LOSS_PERCENT'
)
AND config_type = 'number';

2. 执行数据迁移

# 执行SQL迁移脚本
mysql -u username -p database_name < migrate_percent_configs.sql

3. 验证迁移结果

-- 验证所有百分比配置项应该在0-1之间
SELECT config_key, config_value
FROM trading_config
WHERE config_key IN (
    'TRAILING_STOP_ACTIVATION',
    'TRAILING_STOP_PROTECT',
    'MIN_VOLATILITY',
    'TAKE_PROFIT_PERCENT',
    'STOP_LOSS_PERCENT'
)
AND config_type = 'number'
AND (CAST(config_value AS DECIMAL(10, 4)) < 0 OR CAST(config_value AS DECIMAL(10, 4)) > 1);
-- 应该返回0行

4. 清除Redis缓存

# 清除Redis缓存让系统重新加载配置
redis-cli FLUSHDB
# 或者只清除配置相关的key
redis-cli DEL "config:trading_config:*"
redis-cli DEL "config:global_strategy_config:*"

🎯 实施建议

方案A立即迁移数据推荐

步骤

  1. 创建数据迁移脚本
  2. 执行数据迁移
  3. 验证迁移结果
  4. 清除Redis缓存
  5. ⚠️ 保留代码中的格式转换作为兼容性处理(标记为临时方案)

优势

  • 数据格式统一,避免混乱
  • 代码逻辑清晰
  • 减少出错

风险

  • 需要确保迁移脚本正确
  • 需要备份数据库

方案B保留格式转换临时方案

步骤

  1. 保留代码中的格式转换逻辑
  2. 标记为临时兼容性处理
  3. ⚠️ 后续逐步迁移数据

优势

  • 不需要立即迁移数据
  • 系统可以继续运行

劣势

  • 代码逻辑复杂
  • 容易出错
  • 维护困难

📊 对比分析

当前方案(代码中格式转换)

优点

  • 不需要立即迁移数据
  • 系统可以继续运行

缺点

  • 代码逻辑复杂,需要到处做格式转换
  • 容易出错(忘记转换)
  • 维护困难
  • 数据格式不统一

统一数据格式方案

优点

  • 数据格式统一,避免混乱
  • 代码逻辑清晰,不需要格式转换
  • 减少出错,易于维护
  • 前端和后端验证逻辑一致

缺点

  • ⚠️ 需要数据迁移
  • ⚠️ 需要备份数据库

最终建议

推荐方案:统一数据格式

理由

  1. 架构更清晰:数据格式统一,代码逻辑简单
  2. 易于维护:不需要到处做格式转换
  3. 减少出错避免格式不一致导致的bug
  4. 长期收益:虽然需要一次性迁移,但长期收益更大

实施步骤

  1. 创建数据迁移脚本
  2. 备份数据库
  3. 执行数据迁移
  4. 验证迁移结果
  5. 清除Redis缓存
  6. 保留代码中的格式转换作为兼容性处理(标记为临时方案,后续可以移除)

📝 数据迁移脚本(完整版)

-- ============================================================
-- 配置值格式统一迁移脚本
-- 将百分比形式(>1转换为比例形式除以100
-- ============================================================

-- 1. 备份表(可选,但强烈推荐)
CREATE TABLE trading_config_backup AS SELECT * FROM trading_config;
CREATE TABLE global_strategy_config_backup AS SELECT * FROM global_strategy_config;

-- 2. 迁移 trading_config 表
UPDATE trading_config 
SET config_value = CAST(config_value AS DECIMAL(10, 4)) / 100.0
WHERE config_key IN (
    'TRAILING_STOP_ACTIVATION',
    'TRAILING_STOP_PROTECT',
    'MIN_VOLATILITY',
    'TAKE_PROFIT_PERCENT',
    'STOP_LOSS_PERCENT',
    'MIN_STOP_LOSS_PRICE_PCT',
    'MIN_TAKE_PROFIT_PRICE_PCT',
    'FIXED_RISK_PERCENT',
    'MAX_POSITION_PERCENT',
    'MAX_TOTAL_POSITION_PERCENT',
    'MIN_POSITION_PERCENT'
)
AND config_type = 'number'
AND CAST(config_value AS DECIMAL(10, 4)) > 1;

-- 3. 迁移 global_strategy_config 表
UPDATE global_strategy_config 
SET config_value = CAST(config_value AS DECIMAL(10, 4)) / 100.0
WHERE config_key IN (
    'TRAILING_STOP_ACTIVATION',
    'TRAILING_STOP_PROTECT',
    'MIN_VOLATILITY',
    'TAKE_PROFIT_PERCENT',
    'STOP_LOSS_PERCENT',
    'MIN_STOP_LOSS_PRICE_PCT',
    'MIN_TAKE_PROFIT_PRICE_PCT',
    'FIXED_RISK_PERCENT',
    'MAX_POSITION_PERCENT',
    'MAX_TOTAL_POSITION_PERCENT',
    'MIN_POSITION_PERCENT'
)
AND config_type = 'number'
AND CAST(config_value AS DECIMAL(10, 4)) > 1;

-- 4. 验证迁移结果
-- 检查是否还有>1的百分比配置项
SELECT 'trading_config' as table_name, config_key, config_value
FROM trading_config
WHERE config_key IN (
    'TRAILING_STOP_ACTIVATION',
    'TRAILING_STOP_PROTECT',
    'MIN_VOLATILITY',
    'TAKE_PROFIT_PERCENT',
    'STOP_LOSS_PERCENT'
)
AND config_type = 'number'
AND CAST(config_value AS DECIMAL(10, 4)) > 1
UNION ALL
SELECT 'global_strategy_config' as table_name, config_key, config_value
FROM global_strategy_config
WHERE config_key IN (
    'TRAILING_STOP_ACTIVATION',
    'TRAILING_STOP_PROTECT',
    'MIN_VOLATILITY',
    'TAKE_PROFIT_PERCENT',
    'STOP_LOSS_PERCENT'
)
AND config_type = 'number'
AND CAST(config_value AS DECIMAL(10, 4)) > 1;
-- 应该返回0行

🎯 总结

当前方案的问题

代码中格式转换

  • 代码逻辑复杂
  • 需要到处做格式转换
  • 容易出错
  • 维护困难

更好的方案

统一数据格式

  • 数据库存储比例形式0.30表示30%
  • 前端输入时转换为比例形式
  • 前端显示时转换为百分比形式
  • 代码逻辑直接使用比例形式

实施建议

  1. 立即执行数据迁移:统一数据格式
  2. 保留格式转换作为兼容性处理:标记为临时方案
  3. 后续可以移除格式转换:数据格式统一后,可以移除