docs: Document entry price correction fix as Common Pitfall #33

Major Fix Summary:
- Position Manager was tracking wrong entry price after orphaned position restoration
- Used stale database value ($141.51) instead of Drift's actual entry ($141.31)
- 0.14% difference in stop loss placement - could mean profit vs loss difference
- Startup validation now queries Drift SDK for authoritative entry price

Impact: Critical for accurate P&L tracking and stop loss placement
Prevention: Always prefer on-chain data over cached DB values for trading params

Added to Common Pitfalls section with full bug sequence, fix code, and lessons learned.
This commit is contained in:
mindesbunister
2025-11-15 11:17:46 +01:00
parent 8163858b0d
commit 5fa946acbd

View File

@@ -1312,7 +1312,41 @@ trade.realizedPnL += actualRealizedPnL // NOT: result.realizedPnL from SDK
- **Impact:** Protects user from unlimited risk during unavailable hours. Phantom trades are rare edge cases (oracle issues, exchange rejections).
- **Database tracking:** `status='phantom'`, `exitReason='manual'`, enables analysis of phantom frequency and patterns
33. **Flip-flop price context using wrong data (CRITICAL - Fixed Nov 14, 2025):**
33. **Wrong entry price after orphaned position restoration (CRITICAL - Fixed Nov 15, 2025):**
- **Symptom:** Position Manager tracking SHORT at $141.51 entry, but Drift UI shows $141.31 actual entry
- **Root Cause:** Startup validation restored orphaned position but used OLD database entry price instead of querying Drift for real value
- **Bug sequence:**
1. Position opened at $141.317 (per Drift order history)
2. TP1 closed 70% at $140.942
3. Database incorrectly saved entry as $141.508 (maybe averaged or from previous position)
4. Container restart → startup validation found position on Drift
5. Reopened trade in DB but used stale `trade.entryPrice` from database
6. Position Manager tracked with wrong entry ($141.51 vs actual $141.31)
7. Stop loss calculated from wrong base: $141.08 instead of $140.89
- **Impact:** 0.14% difference ($0.20/SOL) in SL placement - could mean difference between small profit and small loss
- **Fix:** Query Drift SDK for actual entry price during orphaned position restoration
```typescript
// In lib/startup/init-position-manager.ts (line 121-144):
// When reopening closed trade found on Drift:
const currentPrice = await driftService.getOraclePrice(marketConfig.driftMarketIndex)
const positionSizeUSD = position.size * currentPrice
await prisma.trade.update({
where: { id: trade.id },
data: {
status: 'open',
exitReason: null,
entryPrice: position.entryPrice, // CRITICAL: Use Drift's actual entry price
positionSizeUSD: positionSizeUSD, // Update to current size (runner after TP1)
}
})
```
- **Drift SDK returns real entry:** `position.entryPrice` from `getPosition()` calculates from on-chain data (quoteAssetAmount / baseAssetAmount)
- **Future-proofed:** All orphaned position restorations now use authoritative Drift entry price, not stale DB value
- **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. **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
- **Real incident:** Nov 14, 06:05 CET - SHORT allowed with 0.2% flip-flop, lost -$1.56 in 5 minutes