fix: 统一时区处理,准确率统计使用CST时间分组
- 增强 convert_to_cst() 函数,新增 source_tz 参数支持 UTC/ET/CST 输入 - 修改 get_monthly_stats() 使用 CONVERT_TZ 按 CST 月份统计 - 修改 get_daily_stats() 使用 CONVERT_TZ 按 CST 日期分组 - 修改 get_hourly_details() 按 CST 日期筛选和小时排序 - 交易记录使用 source_tz='CST' 避免重复转换 - 前端表头添加'(北京)'时区标注
This commit is contained in:
1 parent
6182630203
commit
8cdfb2a8e2
2 files changed
+44
-26
No files matched your search
+42
-24
@@ -17,12 +17,13 @@ TZ_ET = ZoneInfo('America/New_York') # 美东时间 (Polymarket)
|
||||
TZ_CST = ZoneInfo('Asia/Shanghai') # 中国标准时间 (前端显示)
|
||||
|
||||
|
||||
def convert_to_cst(timestamp_val) -> str:
|
||||
def convert_to_cst(timestamp_val, source_tz: str = 'UTC') -> str:
|
||||
"""
|
||||
将时间戳转换为 CST 时间字符串
|
||||
|
||||
Args:
|
||||
timestamp_val: datetime 对象或 ISO 格式时间戳字符串 (假设是 UTC)
|
||||
timestamp_val: datetime 对象或 ISO 格式时间戳字符串
|
||||
source_tz: 输入时区 - 'UTC'(默认,币安数据), 'ET'(Polymarket), 'CST'(已是北京时间)
|
||||
|
||||
Returns:
|
||||
CST 时间字符串 (YYYY-MM-DD HH:MM:SS)
|
||||
@@ -37,9 +38,19 @@ def convert_to_cst(timestamp_val) -> str:
|
||||
# 字符串格式
|
||||
dt = datetime.fromisoformat(str(timestamp_val).replace('Z', '+00:00'))
|
||||
|
||||
# 如果没有时区信息,假设是 UTC
|
||||
# 根据来源时区设置时区信息
|
||||
if dt.tzinfo is None:
|
||||
dt = dt.replace(tzinfo=TZ_UTC)
|
||||
if source_tz == 'ET':
|
||||
dt = dt.replace(tzinfo=TZ_ET)
|
||||
elif source_tz == 'CST':
|
||||
# 已经是 CST,直接格式化返回
|
||||
return dt.strftime('%Y-%m-%d %H:%M:%S')
|
||||
else: # 默认 UTC
|
||||
dt = dt.replace(tzinfo=TZ_UTC)
|
||||
|
||||
# 如果来源已经是 CST,直接格式化
|
||||
if source_tz == 'CST':
|
||||
return dt.strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# 转换为 CST
|
||||
dt_cst = dt.astimezone(TZ_CST)
|
||||
@@ -122,7 +133,8 @@ class TradeModel:
|
||||
row = cursor.fetchone()
|
||||
result = _dict_from_row(row)
|
||||
if result and result.get('timestamp'):
|
||||
result['timestamp_cst'] = convert_to_cst(result['timestamp'])
|
||||
# 交易记录时间已经是 CST,直接格式化
|
||||
result['timestamp_cst'] = convert_to_cst(result['timestamp'], source_tz='CST')
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
@@ -173,7 +185,8 @@ class TradeModel:
|
||||
for row in rows:
|
||||
item = _dict_from_row(row)
|
||||
if item and item.get('timestamp'):
|
||||
item['timestamp_cst'] = convert_to_cst(item['timestamp'])
|
||||
# 交易记录时间已经是 CST,直接格式化
|
||||
item['timestamp_cst'] = convert_to_cst(item['timestamp'], source_tz='CST')
|
||||
data_list.append(item)
|
||||
|
||||
return {
|
||||
@@ -292,7 +305,7 @@ class PredictionModel:
|
||||
SUM(CASE WHEN is_correct = 1 THEN 1 ELSE 0 END) as correct,
|
||||
SUM(CASE WHEN is_correct = 0 THEN 1 ELSE 0 END) as incorrect
|
||||
FROM model_predictions
|
||||
WHERE DATE_FORMAT(date, '%%Y-%%m') = %s
|
||||
WHERE DATE_FORMAT(CONVERT_TZ(timestamp, '+00:00', '+08:00'), '%%Y-%%m') = %s
|
||||
AND actual_result IS NOT NULL
|
||||
GROUP BY model_name
|
||||
"""
|
||||
@@ -333,16 +346,16 @@ class PredictionModel:
|
||||
|
||||
sql = """
|
||||
SELECT
|
||||
date,
|
||||
DATE(CONVERT_TZ(timestamp, '+00:00', '+08:00')) as date_cst,
|
||||
model_name,
|
||||
COUNT(*) as total,
|
||||
SUM(CASE WHEN is_correct = 1 THEN 1 ELSE 0 END) as correct,
|
||||
SUM(CASE WHEN is_correct = 0 THEN 1 ELSE 0 END) as incorrect
|
||||
FROM model_predictions
|
||||
WHERE DATE_FORMAT(date, '%%Y-%%m') = %s
|
||||
WHERE DATE_FORMAT(CONVERT_TZ(timestamp, '+00:00', '+08:00'), '%%Y-%%m') = %s
|
||||
AND actual_result IS NOT NULL
|
||||
GROUP BY date, model_name
|
||||
ORDER BY date DESC
|
||||
GROUP BY date_cst, model_name
|
||||
ORDER BY date_cst DESC
|
||||
"""
|
||||
cursor.execute(sql, (month,))
|
||||
|
||||
@@ -352,7 +365,7 @@ class PredictionModel:
|
||||
daily_data = {}
|
||||
for row in rows:
|
||||
row_dict = _dict_from_row(row)
|
||||
date = row_dict['date']
|
||||
date = str(row_dict['date_cst']) # CST 日期
|
||||
if date not in daily_data:
|
||||
daily_data[date] = {"date": date}
|
||||
|
||||
@@ -391,28 +404,33 @@ class PredictionModel:
|
||||
获取指定日期的每小时详情
|
||||
|
||||
Args:
|
||||
date: 日期 (YYYY-MM-DD)
|
||||
date: 日期 (YYYY-MM-DD, CST 北京时间)
|
||||
"""
|
||||
with get_db_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
# 按 CST 日期筛选,并获取 CST 小时
|
||||
cursor.execute("""
|
||||
SELECT * FROM model_predictions
|
||||
WHERE date = %s
|
||||
ORDER BY hour, model_name
|
||||
SELECT
|
||||
*,
|
||||
HOUR(CONVERT_TZ(timestamp, '+00:00', '+08:00')) as hour_cst,
|
||||
CONVERT_TZ(timestamp, '+00:00', '+08:00') as timestamp_cst_dt
|
||||
FROM model_predictions
|
||||
WHERE DATE(CONVERT_TZ(timestamp, '+00:00', '+08:00')) = %s
|
||||
ORDER BY hour_cst, model_name
|
||||
""", (date,))
|
||||
|
||||
rows = cursor.fetchall()
|
||||
|
||||
# 按小时重组数据
|
||||
# 按 CST 小时重组数据
|
||||
hourly_data = {}
|
||||
for row in rows:
|
||||
row_dict = _dict_from_row(row)
|
||||
hour = row_dict['hour']
|
||||
if hour not in hourly_data:
|
||||
# 将 timestamp 转换为 CST 时间
|
||||
hour_cst = row_dict['hour_cst'] # 使用 CST 小时
|
||||
if hour_cst not in hourly_data:
|
||||
# 将 timestamp 转换为 CST 时间字符串
|
||||
timestamp_cst = convert_to_cst(row_dict.get('timestamp', ''))
|
||||
hourly_data[hour] = {
|
||||
"hour": hour,
|
||||
hourly_data[hour_cst] = {
|
||||
"hour": hour_cst, # 返回 CST 小时
|
||||
"timestamp_et": row_dict['timestamp_et'],
|
||||
"timestamp_cst": timestamp_cst,
|
||||
"open_price": row_dict['open_price'],
|
||||
@@ -422,13 +440,13 @@ class PredictionModel:
|
||||
}
|
||||
|
||||
model = row_dict['model_name']
|
||||
hourly_data[hour]["models"][model] = {
|
||||
hourly_data[hour_cst]["models"][model] = {
|
||||
"prediction": row_dict['prediction'],
|
||||
"probability": row_dict['probability'],
|
||||
"is_correct": row_dict['is_correct']
|
||||
}
|
||||
|
||||
# 按小时排序返回
|
||||
# 按 CST 小时排序返回
|
||||
return [hourly_data[h] for h in sorted(hourly_data.keys())]
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -259,7 +259,7 @@
|
||||
<table class="table table-hover mb-0">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>日期</th>
|
||||
<th>日期 (北京)</th>
|
||||
<th>DLinear 预测</th>
|
||||
<th>DLinear 准确率</th>
|
||||
<th>TTM-R2 预测</th>
|
||||
@@ -341,7 +341,7 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
<i class="bi bi-clock"></i> {{ hourlyModal.date }} 每小时预测详情
|
||||
<i class="bi bi-clock"></i> {{ hourlyModal.date }} 每小时预测详情 (北京时间)
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user