fix: timezone handling and prediction logic
- api/models.py: Fix timezone conversion in stats queries by calculating UTC ranges in Python instead of using SQL CONVERT_TZ. Ensure JSON serializable types.
- api/prediction_service.py:
- Update ensure_predictions_for_month to check previous day (ET) to cover CST month start.
- Update _generate_prediction_for_hour to skip saving unclosed candles (current hour).
- trader/auto_trade_polymarket.py: Update to use hourly_model_predictions (V2) table for storing live trading predictions.
This commit is contained in:
1 parent
2993014fa8
commit
99fa79cde4
4 files changed
+232
-111
No files matched your search
@@ -541,41 +541,43 @@ class PolymarketBTCTrader:
|
||||
final_probability = all_preds['dlinear']['probability']
|
||||
logger.warning("⚠️ 集成预测不可用,降级为 DLinear")
|
||||
|
||||
# 保存所有预测结果到 model_predictions 表
|
||||
# 保存所有预测结果到 hourly_model_predictions 表 (V2)
|
||||
try:
|
||||
et_tz = ZoneInfo('America/New_York')
|
||||
current_time_utc = pd.Timestamp(current_time)
|
||||
current_time_et = current_time_utc.tz_localize('UTC').tz_convert(et_tz)
|
||||
|
||||
common_data = {
|
||||
prediction_data = {
|
||||
"timestamp": current_time_utc.isoformat(),
|
||||
"timestamp_et": current_time_et.isoformat(),
|
||||
"date": current_time_et.strftime('%Y-%m-%d'),
|
||||
"hour": current_time_et.hour,
|
||||
"actual_result": None,
|
||||
"is_correct": None,
|
||||
"open_price": float(df['open'].iloc[-1]),
|
||||
"close_price": None,
|
||||
"actual_result": None,
|
||||
|
||||
# DLinear
|
||||
"dlinear_prediction": all_preds.get('dlinear', {}).get('prediction'),
|
||||
"dlinear_prob": all_preds.get('dlinear', {}).get('probability'),
|
||||
"dlinear_correct": None,
|
||||
|
||||
# N-BEATS
|
||||
"nbeats_prediction": all_preds.get('nbeats', {}).get('prediction'),
|
||||
"nbeats_prob": all_preds.get('nbeats', {}).get('probability'),
|
||||
"nbeats_correct": None,
|
||||
|
||||
# TTM-R2
|
||||
"ttm_prediction": all_preds.get('ttm', {}).get('prediction'),
|
||||
"ttm_prob": all_preds.get('ttm', {}).get('probability'),
|
||||
"ttm_correct": None,
|
||||
|
||||
# Ensemble
|
||||
"ensemble_prediction": all_preds.get('ensemble', {}).get('prediction'),
|
||||
"ensemble_votes": all_preds.get('ensemble', {}).get('votes'),
|
||||
"ensemble_correct": None,
|
||||
}
|
||||
|
||||
# 辅助函数
|
||||
def save_single_pred(name, pred_res):
|
||||
data = common_data.copy()
|
||||
data['model_name'] = name
|
||||
data['prediction'] = pred_res['prediction']
|
||||
data['probability'] = pred_res.get('probability', 0.5)
|
||||
PredictionModel.save_prediction(data)
|
||||
|
||||
if 'dlinear' in all_preds:
|
||||
save_single_pred("DLinear", all_preds['dlinear'])
|
||||
if 'nbeats' in all_preds:
|
||||
save_single_pred("N-BEATS", all_preds['nbeats'])
|
||||
if 'ttm' in all_preds:
|
||||
save_single_pred("TTM-R2", all_preds['ttm'])
|
||||
if 'ensemble' in all_preds and all_preds['ensemble']:
|
||||
# 集成也保存
|
||||
save_single_pred("Ensemble", all_preds['ensemble'])
|
||||
|
||||
PredictionModel.save_hourly_prediction(prediction_data)
|
||||
logger.info(f"💾 所有模型预测记录已保存 (ET {current_time_et.strftime('%Y-%m-%d %H:%M')})")
|
||||
except Exception as e:
|
||||
logger.error(f"保存预测记录失败: {e}")
|
||||
@@ -599,22 +601,17 @@ class PolymarketBTCTrader:
|
||||
prev_close = float(prev_row['close'])
|
||||
actual_result = 1 if prev_close > prev_open else 0
|
||||
|
||||
models_to_update = ["DLinear", "N-BEATS", "TTM-R2", "Ensemble"]
|
||||
# 使用 V2 更新方法 (宽表)
|
||||
updated = PredictionModel.update_actual_result_v2(
|
||||
date=prev_date,
|
||||
hour=prev_hour,
|
||||
actual_result=actual_result,
|
||||
close_price=prev_close
|
||||
)
|
||||
|
||||
for model_name in models_to_update:
|
||||
updated = PredictionModel.update_actual_result(
|
||||
date=prev_date,
|
||||
hour=prev_hour,
|
||||
model_name=model_name,
|
||||
actual_result=actual_result,
|
||||
close_price=prev_close
|
||||
)
|
||||
if updated:
|
||||
# 仅打印一条日志代表更新成功,避免刷屏
|
||||
pass
|
||||
|
||||
logger.info(f"📝 回填上一小时结果: ET {prev_date} {prev_hour}:00, "
|
||||
f"实际{'涨' if actual_result == 1 else '跌'} (O:{prev_open:.0f} C:{prev_close:.0f})")
|
||||
if updated:
|
||||
logger.info(f"📝 回填上一小时结果: ET {prev_date} {prev_hour}:00, "
|
||||
f"实际{'涨' if actual_result == 1 else '跌'} (O:{prev_open:.0f} C:{prev_close:.0f})")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"回填上一小时结果失败: {e}")
|
||||
@@ -801,30 +798,38 @@ class PolymarketBTCTrader:
|
||||
current_time_utc = pd.Timestamp(current_time)
|
||||
current_time_et = current_time_utc.tz_localize('UTC').tz_convert(et_tz)
|
||||
|
||||
# 1. 保存预测到 model_predictions
|
||||
common_data = {
|
||||
# 1. 保存预测到 hourly_model_predictions (V2)
|
||||
prediction_data = {
|
||||
"timestamp": current_time_utc.isoformat(),
|
||||
"timestamp_et": current_time_et.isoformat(),
|
||||
"date": current_time_et.strftime('%Y-%m-%d'),
|
||||
"hour": current_time_et.hour,
|
||||
"actual_result": None,
|
||||
"is_correct": None,
|
||||
"open_price": float(df['open'].iloc[-1]),
|
||||
"close_price": None,
|
||||
"actual_result": None,
|
||||
|
||||
# DLinear
|
||||
"dlinear_prediction": all_preds.get('dlinear', {}).get('prediction'),
|
||||
"dlinear_prob": all_preds.get('dlinear', {}).get('probability'),
|
||||
"dlinear_correct": None,
|
||||
|
||||
# N-BEATS
|
||||
"nbeats_prediction": all_preds.get('nbeats', {}).get('prediction'),
|
||||
"nbeats_prob": all_preds.get('nbeats', {}).get('probability'),
|
||||
"nbeats_correct": None,
|
||||
|
||||
# TTM-R2
|
||||
"ttm_prediction": all_preds.get('ttm', {}).get('prediction'),
|
||||
"ttm_prob": all_preds.get('ttm', {}).get('probability'),
|
||||
"ttm_correct": None,
|
||||
|
||||
# Ensemble
|
||||
"ensemble_prediction": all_preds.get('ensemble', {}).get('prediction'),
|
||||
"ensemble_votes": all_preds.get('ensemble', {}).get('votes'),
|
||||
"ensemble_correct": None,
|
||||
}
|
||||
|
||||
def save_single_pred(name, pred_res):
|
||||
data = common_data.copy()
|
||||
data['model_name'] = name
|
||||
data['prediction'] = pred_res['prediction']
|
||||
data['probability'] = pred_res.get('probability', 0.5)
|
||||
PredictionModel.save_prediction(data)
|
||||
|
||||
if 'dlinear' in all_preds: save_single_pred("DLinear", all_preds['dlinear'])
|
||||
if 'nbeats' in all_preds: save_single_pred("N-BEATS", all_preds['nbeats'])
|
||||
if 'ttm' in all_preds: save_single_pred("TTM-R2", all_preds['ttm'])
|
||||
if 'ensemble' in all_preds and all_preds['ensemble']: save_single_pred("Ensemble", all_preds['ensemble'])
|
||||
|
||||
PredictionModel.save_hourly_prediction(prediction_data)
|
||||
logger.info(f"💾 [Init] 初始预测已保存到数据库")
|
||||
|
||||
# 2. 记录当前监控状态到 trades (作为 'in_progress')
|
||||
|
||||
Reference in new issue
Block a user