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

142 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 时区处理修复总结
## ✅ 已完成的修改
### 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_time``exit_time` 从UTC时间或服务器本地时间转换为北京时间UTC+8
- 提供了三种转换方法:
1. 直接加8小时如果旧数据是UTC时间
2. 根据服务器时区调整(如果旧数据是服务器本地时间)
3. 使用MySQL时区转换函数需要加载时区数据
**使用方法**
```sql
-- 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.py``open_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. 检查新数据
```sql
-- 查看最近几条记录的入场时间
SELECT id, symbol, entry_time, exit_time, status
FROM trades
ORDER BY id DESC
LIMIT 10;
```
### 2. 检查时间是否合理
```sql
-- 检查是否有异常的时间(例如未来时间或很久以前的时间)
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. 检查持续时间计算
```sql
-- 检查持仓持续时间是否合理
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/Shanghai``UTC+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存储和计算。