diff --git a/backend/signal_engine.py b/backend/signal_engine.py index 5b73190..fc5860c 100644 --- a/backend/signal_engine.py +++ b/backend/signal_engine.py @@ -1023,6 +1023,62 @@ def save_indicator(ts: int, symbol: str, result: dict, strategy: str = "v52_8sig conn.commit() +def save_feature_event(ts: int, symbol: str, result: dict, strategy: str): + """ + V5.3 专用:每次评分后把 raw features + score 层写入 signal_feature_events。 + 只对 v53_alt / v53_btc 调用,其他策略跳过。 + """ + if strategy not in ("v53_alt", "v53_btc"): + return + f = result.get("factors") or {} + track = f.get("track", "ALT") + side = result.get("direction") or ("LONG" if result.get("score", 0) >= 0 else "SHORT") + # ALT层分 + score_direction = (f.get("direction") or {}).get("score", 0) if track == "ALT" else None + score_crowding = (f.get("crowding") or {}).get("score", 0) if track == "ALT" else None + score_env = (f.get("environment") or {}).get("score", 0) if track == "ALT" else None + score_aux = (f.get("auxiliary") or {}).get("score", 0) if track == "ALT" else None + gate_passed = f.get("gate_passed") if track == "BTC" else None + block_reason = f.get("block_reason") if track == "BTC" else None + + with get_sync_conn() as conn: + with conn.cursor() as cur: + cur.execute( + """ + INSERT INTO signal_feature_events + (ts, symbol, track, side, strategy, strategy_version, + cvd_fast_raw, cvd_mid_raw, cvd_day_raw, cvd_fast_slope_raw, + p95_qty_raw, p99_qty_raw, + atr_value, atr_percentile, + oi_delta_raw, ls_ratio_raw, top_pos_raw, coinbase_premium_raw, + obi_raw, tiered_cvd_whale_raw, + score_direction, score_crowding, score_environment, score_aux, score_total, + gate_passed, block_reason, price) + VALUES + (%s,%s,%s,%s,%s,%s, + %s,%s,%s,%s, + %s,%s, + %s,%s, + %s,%s,%s,%s, + %s,%s, + %s,%s,%s,%s,%s, + %s,%s,%s) + """, + ( + ts, symbol, track, side, strategy, "v5.3", + result.get("cvd_fast"), result.get("cvd_mid"), result.get("cvd_day"), result.get("cvd_fast_slope"), + result.get("p95"), result.get("p99"), + result.get("atr_value", result.get("atr")), result.get("atr_pct"), + result.get("oi_delta"), result.get("ls_ratio"), result.get("top_trader_position"), + (f.get("auxiliary") or {}).get("coinbase_premium"), + f.get("obi_raw"), f.get("whale_cvd_ratio"), + score_direction, score_crowding, score_env, score_aux, result.get("score", 0), + gate_passed, block_reason, result.get("price"), + ) + ) + conn.commit() + + def save_indicator_1m(ts: int, symbol: str, result: dict): bar_ts = (ts // 60000) * 60000 with get_sync_conn() as conn: @@ -1328,6 +1384,7 @@ def main(): for strategy_cfg, strategy_result in strategy_results: sname = strategy_cfg.get("name", "v51_baseline") save_indicator(now_ms, sym, strategy_result, strategy=sname) + save_feature_event(now_ms, sym, strategy_result, strategy=sname) # 1m表仍用primary(图表用) primary_result = strategy_results[0][1]