auto_trade_sys/TIMEZONE_FIX_SUMMARY.md
薇薇安 11e3532ac3 a
2026-01-17 20:23:49 +08:00

4.8 KiB
Raw Permalink Blame History

时区处理修复总结

已完成的修改

1. trading_system/position_manager.py

修改内容

  • 导入 get_beijing_time 函数(从 database.models 或创建本地版本)
  • entryTime 的存储从 datetime.now() 改为 get_beijing_time()
  • 将所有计算持续时间的地方从 datetime.now() 改为 get_beijing_time()

修改位置

  • 第337行'entryTime': get_beijing_time() - 开仓时记录入场时间
  • 第464行及多处exit_dt = get_beijing_time() - 计算持仓持续时间时使用北京时间

2. backend/database/models.py

已确认

  • Trade.create() 方法已使用 get_beijing_time() 设置 entry_time
  • Trade.update_exit() 方法已使用 get_beijing_time() 设置 exit_time
  • 所有其他模型(AccountSnapshot, MarketScan, TradingSignal, TradeRecommendation)都已使用 get_beijing_time()

3. SQL更新脚本

文件backend/database/update_timezone_to_beijing.sql

功能

  • 将旧数据的 entry_timeexit_time 从UTC时间或服务器本地时间转换为北京时间UTC+8
  • 提供了三种转换方法:
    1. 直接加8小时如果旧数据是UTC时间
    2. 根据服务器时区调整(如果旧数据是服务器本地时间)
    3. 使用MySQL时区转换函数需要加载时区数据

使用方法

-- 1. 先备份数据库
mysqldump -u root -p auto_trade_sys > backup_$(date +%Y%m%d_%H%M%S).sql

-- 2. 根据实际情况调整SQL脚本中的时间偏移量
-- 3. 运行SQL脚本
mysql -u root -p auto_trade_sys < backend/database/update_timezone_to_beijing.sql

时间处理流程

开仓Entry Time

  1. position_manager.pyopen_position() 方法:
    • 内存中存储:'entryTime': get_beijing_time()
    • 数据库入库:Trade.create() → 使用 get_beijing_time() 设置 entry_time

平仓Exit Time

  1. position_manager.py 中各种平仓方法:
    • 计算持续时间:exit_dt = get_beijing_time()
    • 数据库更新:Trade.update_exit() → 使用 get_beijing_time() 设置 exit_time

时间格式

  • 数据库存储:TIMESTAMP 类型无时区信息MySQL默认
  • Python代码使用 datetime 对象,通过 get_beijing_time() 确保是北京时间UTC+8
  • 显示:前端可以根据需要转换为任何时区显示

验证方法

1. 检查新数据

-- 查看最近几条记录的入场时间
SELECT id, symbol, entry_time, exit_time, status
FROM trades
ORDER BY id DESC
LIMIT 10;

2. 检查时间是否合理

-- 检查是否有异常的时间(例如未来时间或很久以前的时间)
SELECT id, symbol, entry_time, exit_time
FROM trades
WHERE entry_time > NOW() 
   OR entry_time < '2020-01-01'
   OR (exit_time IS NOT NULL AND exit_time > NOW())
   OR (exit_time IS NOT NULL AND exit_time < entry_time);

3. 检查持续时间计算

-- 检查持仓持续时间是否合理
SELECT 
    id,
    symbol,
    entry_time,
    exit_time,
    TIMESTAMPDIFF(MINUTE, entry_time, COALESCE(exit_time, NOW())) as duration_minutes,
    duration_minutes as stored_duration
FROM trades
WHERE exit_time IS NOT NULL
ORDER BY id DESC
LIMIT 10;

注意事项

  1. 旧数据处理

    • 如果旧数据已经是北京时间不需要运行SQL更新脚本
    • 如果旧数据是UTC时间需要加8小时
    • 如果旧数据是其他时区,需要相应调整
  2. 时区一致性

    • 所有入库时间都使用北京时间UTC+8
    • 所有计算持续时间的地方也使用北京时间
    • 前端显示可以根据需要转换时区
  3. 数据库时区设置

    • MySQL的 TIMESTAMP 类型会根据服务器时区自动转换
    • 建议服务器时区设置为 Asia/ShanghaiUTC+8
    • 可以通过 SELECT @@global.time_zone, @@session.time_zone; 查看
  4. 代码时区处理

    • Python代码中使用 get_beijing_time() 确保时区一致
    • 不依赖系统时区设置,避免时区问题

测试建议

  1. 开仓测试

    • 开仓后检查数据库中的 entry_time 是否为北京时间
    • 检查内存中的 entryTime 是否为北京时间
  2. 平仓测试

    • 平仓后检查数据库中的 exit_time 是否为北京时间
    • 检查 duration_minutes 计算是否正确
  3. 时区转换测试

    • 在不同时区的服务器上测试(如果可能)
    • 验证时间显示是否正确

总结

所有入库时间已统一使用北京时间 所有计算持续时间的地方已使用北京时间 已提供SQL脚本更新旧数据 代码已通过语法检查

现在系统的时间处理已经完全统一所有时间都使用北京时间UTC+8存储和计算。