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
This commit is contained in:
mindesbunister
2025-11-03 08:33:46 +01:00
parent 0ed2e89c7e
commit aa8e9f130a

View File

@@ -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)