docs: Document runner stop loss gap bug (Common Pitfall #34)

CRITICAL BUG DOCUMENTATION: Runner had ZERO stop loss protection between TP1-TP2

Context:
- User reported: 'runner close did not work. still open and the price is above 141,98'
- Investigation revealed Position Manager only checked SL before TP1 OR after TP2
- Runner between TP1-TP2 had NO stop loss checks = hours of unlimited loss exposure

Bug Impact:
- SHORT at $141.317, TP1 closed 70% at $140.942, runner had SL at $140.89
- Price rose to $141.98 (way above SL) → NO PROTECTION → Position stayed open
- Potential unlimited loss on 25-30% runner position

Fix Verification:
- After fix deployed: Runner closed at $141.133 with +$0.59 profit
- Database shows exitReason='SL', proving runner stop loss triggered correctly
- Log: '🔴 RUNNER STOP LOSS: SOL-PERP at 0.3% (profit lock triggered)'

Lesson: Every conditional branch in risk management MUST have explicit SL checks

Files: .github/copilot-instructions.md (added Common Pitfall #34)
This commit is contained in:
mindesbunister
2025-11-15 11:36:16 +01:00
parent ec5483041a
commit f8141009a8

View File

@@ -1346,6 +1346,48 @@ trade.realizedPnL += actualRealizedPnL // NOT: result.realizedPnL from SDK
- **Manual fix required once:** Had to manually UPDATE database for existing position, then restart container
- **Lesson:** Always prefer on-chain data over cached database values for critical trading parameters
34. **Runner stop loss gap - NO protection between TP1 and TP2 (CRITICAL - Fixed Nov 15, 2025):**
- **Symptom:** Runner position remained open despite price moving far above stop loss level
- **Root Cause:** Position Manager only checked stop loss BEFORE TP1 hit (line 693) OR AFTER TP2 hit (line 835), creating a gap
- **Bug sequence:**
1. SHORT opened at $141.317, TP1 hit at $140.942 (70% closed)
2. Runner (30% remaining, $12.70) had stop loss at $140.89 (profit lock)
3. Price rose to $141.98 (way above $140.89 SL) → NO STOP LOSS CHECK
4. Position exposed to unlimited loss for hours during TP1→TP2 window
5. User manually checked: "runner close did not work. still open and the price is above 141,98"
- **Impact:** Hours of unprotected runner exposure = potential unlimited loss on 25-30% remaining position
- **Code analysis:**
```typescript
// Line 693: Stop loss checked ONLY before TP1
if (!trade.tp1Hit && this.shouldStopLoss(currentPrice, trade)) {
console.log(`🔴 STOP LOSS: ${trade.symbol}`)
await this.executeExit(trade, 100, 'SL', currentPrice)
}
// Lines 706-831: TP1 and TP2 processing - NO STOP LOSS CHECK
// Line 835: Stop loss checked ONLY after TP2
if (trade.tp2Hit && this.config.useTrailingStop && this.shouldStopLoss(currentPrice, trade)) {
console.log(`🔴 TRAILING STOP: ${trade.symbol}`)
await this.executeExit(trade, 100, 'SL', currentPrice)
}
// BUG: Runner between TP1-TP2 has ZERO stop loss protection!
```
- **Fix:** Added explicit runner stop loss check at line ~795:
```typescript
// CRITICAL: Check stop loss for runner (after TP1, before TP2)
if (trade.tp1Hit && !trade.tp2Hit && this.shouldStopLoss(currentPrice, trade)) {
console.log(`🔴 RUNNER STOP LOSS: ${trade.symbol} at ${profitPercent.toFixed(2)}% (profit lock triggered)`)
await this.executeExit(trade, 100, 'SL', currentPrice)
return
}
```
- **Verification:** After fix deployed, runner closed at $141.133 with +$0.59 profit (+4.6% on $12.70 runner)
- **Database evidence:** Trade shows `exitReason='SL'`, proving runner stop loss triggered correctly
- **Why undetected:** Runner system relatively new (Nov 11), most trades hit TP2 quickly without price reversals
- **Lesson:** Every conditional branch in risk management MUST have explicit stop loss checks - never assume "it'll get caught somewhere"
34. **Flip-flop price context using wrong data (CRITICAL - Fixed Nov 14, 2025):**
- **Symptom:** Flip-flop detection showing "100% price move" when actual movement was 0.2%, allowing trades that should be blocked
- **Root Cause:** `currentPrice` parameter not available in check-risk endpoint (trade hasn't opened yet), so calculation used undefined/zero