diff --git a/auto_trade_polymarket.py b/auto_trade_polymarket.py index ee90f57..a5ca99b 100644 --- a/auto_trade_polymarket.py +++ b/auto_trade_polymarket.py @@ -35,6 +35,7 @@ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from data.fetcher import BinanceDataFetcher from data.trading_db import TradingDatabase +from api.models import PredictionModel load_dotenv() @@ -634,7 +635,11 @@ class PolymarketBTCTrader: logger.info(f" 上一K线时间: {prev_time} (用于预测)") logger.info(f" 上一收盘价: ${prev_close:,.2f}") logger.info(f" 当前K线时间: {current_time} (预测目标)") - logger.info(f" 当前收盘价: ${current_close:,.2f} (实际结果)") + logger.info(f" 当前收盘价: ${current_close:,.2f} (未收盘)") + + # 回填上一小时的实际结果 + # prev_time的K线已收盘,用它的收盘价(prev_close) vs 再前一根的收盘价来判断涨跌 + self._update_previous_prediction(df) # 用除最后一根外的数据进行预测(无create_labels,与test逻辑一致) df_for_prediction = df.iloc[:-1] @@ -659,9 +664,72 @@ class PolymarketBTCTrader: confidence = probability if prediction == 1 else 1 - probability logger.info(f"🤖 DLinear预测: {direction}") logger.info(f" 置信度: {confidence:.2%}") - + + # 保存预测结果到 model_predictions 表 + # 当前K线尚未收盘,actual_result 和 is_correct 留空,等收盘后更新 + try: + et_tz = ZoneInfo('America/New_York') + # current_time 是目标K线的UTC时间戳(当前正在进行的K线) + current_time_utc = pd.Timestamp(current_time) + current_time_et = current_time_utc.tz_localize('UTC').tz_convert(et_tz) + + 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, + "model_name": "DLinear", + "prediction": prediction, + "probability": probability, + "actual_result": None, + "is_correct": None, + "open_price": float(df['open'].iloc[-1]), + "close_price": None, + } + PredictionModel.save_prediction(prediction_data) + logger.info(f"💾 预测记录已保存 (ET {current_time_et.strftime('%Y-%m-%d %H:%M')})") + except Exception as e: + logger.error(f"保存预测记录失败: {e}") + return prediction, probability - + + def _update_previous_prediction(self, df: pd.DataFrame): + """回填上一小时预测的实际结果 + + df.iloc[-2] 是上一小时已收盘K线,收盘价 vs 开盘价即为实际涨跌。 + """ + if len(df) < 2: + return + + try: + et_tz = ZoneInfo('America/New_York') + prev_row = df.iloc[-2] + prev_utc = pd.Timestamp(prev_row['timestamp']) + prev_et = prev_utc.tz_localize('UTC').tz_convert(et_tz) + prev_date = prev_et.strftime('%Y-%m-%d') + prev_hour = prev_et.hour + + prev_open = float(prev_row['open']) + prev_close = float(prev_row['close']) + actual_result = 1 if prev_close > prev_open else 0 + + updated = PredictionModel.update_actual_result( + date=prev_date, + hour=prev_hour, + model_name="DLinear", + actual_result=actual_result, + close_price=prev_close + ) + if updated: + record = PredictionModel.get_prediction(prev_date, prev_hour, "DLinear") + is_correct = record.get('is_correct') if record else None + correct_str = '✅ 正确' if is_correct == 1 else '❌ 错误' if is_correct == 0 else '未知' + logger.info(f"📝 回填上一小时结果: ET {prev_date} {prev_hour}:00, " + f"开:{prev_open:.2f} 收:{prev_close:.2f} " + f"实际{'涨' if actual_result == 1 else '跌'}, {correct_str}") + except Exception as e: + logger.error(f"回填上一小时结果失败: {e}") + def run_once(self) -> Dict: """运行一次交易流程(不等待整点)""" logger.info("运行单次交易...")