# V5.2 Development Task ## Context You are working on the `dev` branch of the ArbitrageEngine project. This is a quantitative trading signal system with: - Backend: Python (FastAPI + PostgreSQL) - Frontend: Next.js + shadcn/ui + Tailwind ## Database Connection - Host: 34.85.117.248 (Cloud SQL) - Port: 5432, DB: arb_engine, User: arb, Password: arb_engine_2026 ## What to Build (V5.2) ### 1. Strategy Configuration Framework Create `backend/strategies/` directory with JSON configs: **backend/strategies/v51_baseline.json:** ```json { "name": "v51_baseline", "version": "5.1", "threshold": 75, "weights": { "direction": 45, "crowding": 20, "environment": 15, "confirmation": 15, "auxiliary": 5 }, "accel_bonus": 5, "tp_sl": { "sl_multiplier": 2.0, "tp1_multiplier": 1.5, "tp2_multiplier": 3.0 }, "signals": ["cvd", "p99", "accel", "ls_ratio", "oi", "coinbase_premium"] } ``` **backend/strategies/v52_8signals.json:** ```json { "name": "v52_8signals", "version": "5.2", "threshold": 75, "weights": { "direction": 40, "crowding": 25, "environment": 15, "confirmation": 20, "auxiliary": 5 }, "accel_bonus": 5, "tp_sl": { "sl_multiplier": 2.0, "tp1_multiplier": 1.5, "tp2_multiplier": 3.0 }, "signals": ["cvd", "p99", "accel", "ls_ratio", "oi", "coinbase_premium", "funding_rate", "liquidation"] } ``` ### 2. Signal Engine Changes (signal_engine.py) #### 2a. Add FR scoring to evaluate_signal() After the crowding section, add funding_rate scoring: ```python # Funding Rate scoring (拥挤层加分) # Read from market_indicators table funding_rate = to_float(self.market_indicators.get("funding_rate")) fr_score = 0 if funding_rate is not None: fr_abs = abs(funding_rate) if fr_abs >= 0.001: # extreme ±0.1% # Extreme: penalize if going WITH the crowd if (direction == "LONG" and funding_rate > 0.001) or \ (direction == "SHORT" and funding_rate < -0.001): fr_score = -5 else: fr_score = 5 elif fr_abs >= 0.0003: # moderate ±0.03% # Moderate: reward going AGAINST the crowd if (direction == "LONG" and funding_rate < -0.0003) or \ (direction == "SHORT" and funding_rate > 0.0003): fr_score = 5 else: fr_score = 0 ``` #### 2b. Add liquidation scoring ```python # Liquidation scoring (确认层加分) liq_score = 0 liq_data = self.fetch_recent_liquidations() # new method if liq_data: liq_long_usd = liq_data.get("long_usd", 0) liq_short_usd = liq_data.get("short_usd", 0) # Thresholds by symbol thresholds = {"BTCUSDT": 500000, "ETHUSDT": 200000, "XRPUSDT": 100000, "SOLUSDT": 100000} threshold = thresholds.get(self.symbol, 100000) total = liq_long_usd + liq_short_usd if total >= threshold: if liq_short_usd > 0 and liq_long_usd > 0: ratio = liq_short_usd / liq_long_usd elif liq_short_usd > 0: ratio = float('inf') else: ratio = 0 if ratio >= 2.0 and direction == "LONG": liq_score = 5 # shorts getting liquidated, price going up elif ratio <= 0.5 and direction == "SHORT": liq_score = 5 # longs getting liquidated, price going down ``` #### 2c. Add fetch_recent_liquidations method to SymbolState ```python def fetch_recent_liquidations(self, window_ms=300000): """Fetch last 5min liquidation totals from liquidations table""" now_ms = int(time.time() * 1000) cutoff = now_ms - window_ms with get_sync_conn() as conn: with conn.cursor() as cur: cur.execute(""" SELECT COALESCE(SUM(CASE WHEN side='SELL' THEN usd_value ELSE 0 END), 0) as long_liq, COALESCE(SUM(CASE WHEN side='BUY' THEN usd_value ELSE 0 END), 0) as short_liq FROM liquidations WHERE symbol=%s AND trade_time >= %s """, (self.symbol, cutoff)) row = cur.fetchone() if row: return {"long_usd": row[0], "short_usd": row[1]} return None ``` #### 2d. Add funding_rate to fetch_market_indicators Add "funding_rate" to the indicator types: ```python for ind_type in ["long_short_ratio", "top_trader_position", "open_interest_hist", "coinbase_premium", "funding_rate"]: ``` And the extraction: ```python elif ind_type == "funding_rate": indicators[ind_type] = float(val.get("lastFundingRate", 0)) ``` #### 2e. Update total_score calculation Currently: ```python total_score = direction_score + accel_bonus + crowding_score + environment_score + confirmation_score + aux_score ``` Change to: ```python total_score = direction_score + accel_bonus + crowding_score + fr_score + environment_score + confirmation_score + liq_score + aux_score ``` #### 2f. Update factors dict Add fr_score and liq_score to the factors: ```python result["factors"] = { ...existing factors..., "funding_rate": {"score": fr_score, "value": funding_rate}, "liquidation": {"score": liq_score, "long_usd": liq_data.get("long_usd", 0) if liq_data else 0, "short_usd": liq_data.get("short_usd", 0) if liq_data else 0}, } ``` #### 2g. Change threshold from 60 to 75 In evaluate_signal, change: ```python # OLD elif total_score >= 60 and not no_direction and not in_cooldown: result["signal"] = direction result["tier"] = "light" # NEW: remove the 60 tier entirely, minimum is 75 ``` Also update reverse signal threshold from 60 to 75: In main() loop: ```python # OLD if existing_dir and eval_dir and existing_dir != eval_dir and result["score"] >= 60: # NEW if existing_dir and eval_dir and existing_dir != eval_dir and result["score"] >= 75: ``` ### 3. Strategy field in paper_trades Add SQL migration at top of init_schema() or in a migration: ```sql ALTER TABLE paper_trades ADD COLUMN IF NOT EXISTS strategy VARCHAR(32) DEFAULT 'v51_baseline'; ``` ### 4. AB Test: Both strategies evaluate each cycle In the main loop, evaluate signal twice (once per strategy config) and potentially open trades for both. Each trade records which strategy triggered it. ### 5. Frontend: Update paper/page.tsx - Show strategy column in trade history table - Show FR and liquidation scores in signal details - Add strategy filter/tab (v51 vs v52) ### 6. API: Add strategy stats endpoint In main.py, add `/api/paper/stats-by-strategy` that groups stats by strategy field. ## Important Notes - Keep ALL existing functionality working - Don't break the existing V5.1 scoring - it should still work as strategy "v51_baseline" - The FR data is already in market_indicators table (collected every 5min) - The liquidation data is already in liquidations table - Test with: `cd frontend && npm run build` to verify no frontend errors - Test backend: `python3 -c "from signal_engine import *; print('OK')"` to verify imports - Port for dev testing: API=8100, Frontend=3300 - Total score CAN exceed 100 (that's by design) ## Files to modify: 1. `backend/signal_engine.py` - core scoring changes 2. `backend/main.py` - new API endpoints 3. `backend/db.py` - add strategy column migration 4. `frontend/app/paper/page.tsx` - UI updates 5. NEW: `backend/strategies/v51_baseline.json` 6. NEW: `backend/strategies/v52_8signals.json` When completely finished, run this command to notify me: openclaw system event --text "Done: V5.2 core implementation complete - FR+liquidation scoring, threshold 75, strategy configs, AB test framework" --mode now