diff --git a/api/models.py b/api/models.py index b37fafa..c26a745 100644 --- a/api/models.py +++ b/api/models.py @@ -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 diff --git a/api/static/index.html b/api/static/index.html index 182f07e..cc38698 100644 --- a/api/static/index.html +++ b/api/static/index.html @@ -259,7 +259,7 @@ - + @@ -341,7 +341,7 @@
日期日期 (北京) DLinear 预测 DLinear 准确率 TTM-R2 预测