142 lines
4.8 KiB
Markdown
142 lines
4.8 KiB
Markdown
# 时区处理修复总结
|
||
|
||
## ✅ 已完成的修改
|
||
|
||
### 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)存储和计算。
|