feat: auto_trade 每小时预测结果写入预测表并回填上一小时实际结果

- 导入 PredictionModel,预测完成后保存到 model_predictions 表
- 当前小时预测 actual_result/is_correct/close_price 留空(未收盘)
- 新增 _update_previous_prediction:每次整点回填上一小时实际涨跌(收盘价 vs 开盘价)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
crypto_predictorandClaude Opus 4.6 committed 2026-02-10 23:19:57 +08:00
1 parent e78836bf42
commit 84288a687a
1 file changed
+71 -3
+71 -3
View File
@@ -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("运行单次交易...")