From aa8e9f130afd5146e99acf7ce725468214d2ce47 Mon Sep 17 00:00:00 2001 From: mindesbunister Date: Mon, 3 Nov 2025 08:33:46 +0100 Subject: [PATCH] docs: update AI agent instructions with recent fixes Added documentation for recent improvements: - MAE/MFE tracking for trade optimization - On-chain order synchronization after TP1 hits - Exit reason detection using trade state flags (not current price) - Per-symbol cooldown to avoid missing opportunities - Quality score integration in analytics dashboard Updated workflows and pitfalls sections with lessons learned from debugging session --- .github/copilot-instructions.md | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 2ceda08..52f4a25 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -15,6 +15,8 @@ **Signal Quality System:** Filters trades based on 5 metrics (ATR, ADX, RSI, volumeRatio, pricePosition) scored 0-100. Only trades scoring 60+ are executed. Scores stored in database for future optimization. +**MAE/MFE Tracking:** Every trade tracks Maximum Favorable Excursion (best profit %) and Maximum Adverse Excursion (worst loss %) updated every 2s. Used for data-driven optimization of TP/SL levels. + ## Critical Components ### 1. Position Manager (`lib/trading/position-manager.ts`) @@ -30,11 +32,13 @@ await positionManager.addTrade(activeTrade) - Tracks `ActiveTrade` objects in a Map - Three-tier exits: TP1 (75%), TP2 (80% of remaining), Runner (with trailing stop) - Dynamic SL adjustments: Moves to breakeven after TP1, locks profit at +1.2% +- **On-chain order synchronization:** After TP1 hits, calls `cancelAllOrders()` then `placeExitOrders()` with updated SL price at breakeven - Trailing stop: Activates after TP2, tracks `peakPrice` and trails by configured % - Closes positions via `closePosition()` market orders when targets hit - Acts as backup if on-chain orders don't fill - State persistence: Saves to database, restores on restart via `configSnapshot.positionManagerState` - **Grace period for new trades:** Skips "external closure" detection for positions <30 seconds old (Drift positions take 5-10s to propagate) +- **Exit reason detection:** Uses trade state flags (`tp1Hit`, `tp2Hit`) and realized P&L to determine exit reason, NOT current price (avoids misclassification when price moves after order fills) ### 2. Drift Client (`lib/drift/client.ts`) **Purpose:** Solana/Drift Protocol SDK wrapper for order execution @@ -97,9 +101,14 @@ Without this, the SDK returns signatures for transactions that never execute, ca **Important fields:** - `signalQualityScore` (Int?) - 0-100 score for data-driven optimization - `maxFavorableExcursion` / `maxAdverseExcursion` - Track best/worst P&L during trade lifetime +- `maxFavorablePrice` / `maxAdversePrice` - Track prices at MFE/MAE points - `configSnapshot` (Json) - Stores Position Manager state for crash recovery - `atr`, `adx`, `rsi`, `volumeRatio`, `pricePosition` - Context metrics from TradingView +**Per-symbol functions:** +- `getLastTradeTimeForSymbol(symbol)` - Get last trade time for specific coin (enables per-symbol cooldown) +- Each coin (SOL/ETH/BTC) has independent cooldown timer to avoid missed opportunities + ## Configuration System **Three-layer merge:** @@ -129,12 +138,12 @@ const driftSymbol = normalizeTradingViewSymbol(body.symbol) **Key endpoints:** - `/api/trading/execute` - Main entry point from n8n (production, requires auth) -- `/api/trading/check-risk` - Pre-execution validation (duplicate check, quality score, rate limits) +- `/api/trading/check-risk` - Pre-execution validation (duplicate check, quality score, **per-symbol cooldown**, rate limits) - `/api/trading/test` - Test trades from settings UI (no auth required) - `/api/trading/close` - Manual position closing - `/api/trading/positions` - Query open positions from Drift - `/api/settings` - Get/update config (writes to .env file) -- `/api/analytics/last-trade` - Fetch most recent trade details for dashboard +- `/api/analytics/last-trade` - Fetch most recent trade details for dashboard (includes quality score) - `/api/restart` - Create restart flag for watch-restart.sh script ## Critical Workflows @@ -159,15 +168,15 @@ TradingView alert → n8n Parse Signal Enhanced (extracts metrics) Position Manager every 2s: ↓ Verify on-chain position still exists (detect external closures) ↓ getPythPriceMonitor().getLatestPrice() - ↓ Calculate current P&L and update peakPrice + ↓ Calculate current P&L and update MAE/MFE metrics ↓ Check emergency stop (-2%) → closePosition(100%) ↓ Check SL hit → closePosition(100%) - ↓ Check TP1 hit → closePosition(75%), move SL to breakeven + ↓ Check TP1 hit → closePosition(75%), cancelAllOrders(), placeExitOrders() with SL at breakeven ↓ Check profit lock trigger (+1.2%) → move SL to +configured% ↓ Check TP2 hit → closePosition(80% of remaining), activate runner ↓ Check trailing stop (if runner active) → adjust SL dynamically based on peakPrice ↓ addPriceUpdate() [save to database every N checks] - ↓ saveTradeState() [persist Position Manager state for crash recovery] + ↓ saveTradeState() [persist Position Manager state + MAE/MFE for crash recovery] ``` ### Settings Update @@ -305,6 +314,10 @@ docker exec trading-bot-postgres psql -U postgres -d trading_bot_v4 -c "\dt" Always calculate: `minOrderSize × currentPrice` must exceed Drift's $4 minimum. Add buffer for price movement. +13. **Exit reason detection bug:** Position Manager was using current price to determine exit reason, but on-chain orders filled at a DIFFERENT price in the past. Now uses `trade.tp1Hit` / `trade.tp2Hit` flags and realized P&L to correctly identify whether TP1, TP2, or SL triggered. Prevents profitable trades being mislabeled as "SL" exits. + +14. **Per-symbol cooldown:** Cooldown period is per-symbol, NOT global. ETH trade at 10:00 does NOT block SOL trade at 10:01. Each coin (SOL/ETH/BTC) has independent cooldown timer to avoid missing opportunities on different assets. + ## File Conventions - **API routes:** `app/api/[feature]/[action]/route.ts` (Next.js 15 App Router)