docs: Bug #77 recurrence investigation summary
- Position Manager monitoring runs but condition checks never execute - Added 3 debug logs: STARTCHK, DRIFT, AGE to identify early return location - ,000+ losses from non-functional monitoring despite 'active' logs - Waiting for next trade to capture debug output and identify root cause - Related to previous Dec 13 fix (different early return location)
This commit is contained in:
202
docs/BUG_77_RECURRENCE_DEBUG_DEC15_2025.md
Normal file
202
docs/BUG_77_RECURRENCE_DEBUG_DEC15_2025.md
Normal file
@@ -0,0 +1,202 @@
|
||||
# Bug #77 Recurrence - Position Manager Condition Checks Never Execute (Dec 15, 2025)
|
||||
|
||||
## Status: 🔴 CRITICAL - UNDER INVESTIGATION
|
||||
|
||||
**Impact:** $1,000+ losses from 96% data loss ($32.98 actual profit vs $1.23 recorded in database)
|
||||
|
||||
## The Problem
|
||||
|
||||
Position Manager monitoring loop IS running:
|
||||
- ✅ Price checks every 2 seconds: `"🔍 Price check: SOL-PERP @ $124.47 (1 trades)"`
|
||||
- ✅ handlePriceUpdate() executes successfully (line 653-670)
|
||||
- ✅ Loop calls checkTradeConditions() for each trade (line 664-668)
|
||||
|
||||
BUT condition evaluation logic NEVER executes:
|
||||
- ❌ NO TP1 detection logs
|
||||
- ❌ NO TP2 detection logs
|
||||
- ❌ NO Stop Loss detection logs
|
||||
- ❌ NO executeExit() calls
|
||||
- ❌ NO P&L status logs (every 10 checks)
|
||||
|
||||
**Result:** All trades rely ONLY on on-chain LIMIT orders auto-filling. Position Manager is 100% non-functional despite monitoring showing active.
|
||||
|
||||
## Evidence Trail
|
||||
|
||||
### What We Know Works
|
||||
|
||||
**handlePriceUpdate() (lines 653-670):**
|
||||
```
|
||||
🔍 Price check: SOL-PERP @ $123.69 (1 trades)
|
||||
🔍 Price check: SOL-PERP @ $123.70 (1 trades)
|
||||
🔍 Price check: SOL-PERP @ $123.71 (1 trades)
|
||||
... repeating every 2 seconds
|
||||
```
|
||||
|
||||
This proves:
|
||||
- Pyth price monitor is calling handlePriceUpdate()
|
||||
- tradesForSymbol.filter() finds 1 trade
|
||||
- Loop at line 664 executes
|
||||
|
||||
### What We Know Doesn't Work
|
||||
|
||||
**checkTradeConditions() body (lines 677-1510):**
|
||||
- Trade ID "cmj7d25yu0002pe0754v8pd21" appears ZERO times in logs
|
||||
- No "⏭️ Skipping" logs (line 681 check passes)
|
||||
- No "⏳ Trade" logs (line 709 - trade age check)
|
||||
- No "⚠️ Position APPEARS closed" logs (line 718 - external closure detection)
|
||||
- No "📊" logs (line 1482 - status every 10 checks)
|
||||
- No condition evaluation logs (lines 1497+ - shouldEmergencyStop, shouldStopLoss, shouldTakeProfit1)
|
||||
|
||||
## Hypothesis: Early Return at Line 711
|
||||
|
||||
**Code:**
|
||||
```typescript
|
||||
// Line 702-711
|
||||
const tradeAgeSeconds = (Date.now() - trade.entryTime) / 1000
|
||||
|
||||
if (position === null || position.size === 0) {
|
||||
if (tradeAgeSeconds < 30) {
|
||||
logger.log(`⏳ Trade ${trade.symbol} is new (${tradeAgeSeconds.toFixed(1)}s old) - skipping external closure check`)
|
||||
return // Skip this check cycle, position might still be propagating
|
||||
}
|
||||
```
|
||||
|
||||
**Scenario:**
|
||||
1. Trade created at 16:21:13 (>6 hours ago) - age check SHOULD pass
|
||||
2. Drift position is CLOSED (sync-positions API returns empty) - `position.size === 0` is TRUE
|
||||
3. But trade age > 30 seconds, so should continue to double-check logic at line 714
|
||||
4. UNLESS: `getPosition()` is throwing an exception caught by outer try-catch
|
||||
|
||||
**Alternative Explanation:**
|
||||
- The outer try-catch at line 666 catches ALL exceptions from checkTradeConditions()
|
||||
- If ANY unhandled exception occurs, catch logs `"❌ Error checking trade ${trade.id}"`
|
||||
- But NO such logs exist in container output
|
||||
- So either:
|
||||
* Exception is being caught and silenced elsewhere
|
||||
* OR function is returning early without exception
|
||||
|
||||
## Debug Logging Added (Dec 15, 2025)
|
||||
|
||||
**New logs inserted at line 691:**
|
||||
```typescript
|
||||
console.log(`🔍 STARTCHK: ${trade.symbol} @ $${currentPrice.toFixed(2)} | Entry: $${trade.entryPrice.toFixed(2)} | Checks: ${trade.priceCheckCount}`)
|
||||
```
|
||||
|
||||
**New logs inserted at line 703:**
|
||||
```typescript
|
||||
console.log(`🔍 DRIFT: Position ${trade.symbol} | size=${position?.size || 'null'} | exists=${position !== null}`)
|
||||
```
|
||||
|
||||
**New logs inserted at line 708:**
|
||||
```typescript
|
||||
console.log(`🔍 AGE: ${trade.symbol} age=${tradeAgeSeconds.toFixed(1)}s | threshold=30s`)
|
||||
```
|
||||
|
||||
## What Debug Logs Will Reveal
|
||||
|
||||
**Case 1: STARTCHK appears but DRIFT doesn't**
|
||||
- Means: getPosition() is throwing exception
|
||||
- Location: Drift SDK call at line 700
|
||||
- Fix: Catch exception, log error, continue to condition checks
|
||||
|
||||
**Case 2: DRIFT appears, shows size=0, but AGE doesn't**
|
||||
- Means: Trade age check is failing somehow
|
||||
- Location: Line 702 calculation or line 706 condition
|
||||
- Fix: Investigate entryTime timestamp format
|
||||
|
||||
**Case 3: AGE appears, shows >30s, but condition checks still don't execute**
|
||||
- Means: Early return is happening between line 708 and line 1497
|
||||
- Location: Likely in double-check logic (lines 714-800)
|
||||
- Fix: Add more debug logs to find exact return location
|
||||
|
||||
**Case 4: None of the debug logs appear**
|
||||
- Means: Line 681 `activeTrades.has(trade.id)` is failing
|
||||
- Location: Map key mismatch between loop and Map
|
||||
- Fix: Investigate how trades are added to Map vs how they're checked
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Wait for next manual trade** (Telegram or TradingView)
|
||||
2. **Monitor docker logs** for new debug messages
|
||||
3. **Identify WHERE** checkTradeConditions() is returning early
|
||||
4. **Fix root cause** based on debug log evidence
|
||||
5. **Deploy fix** with verification
|
||||
6. **Remove debug logging** once fixed
|
||||
|
||||
## Historical Context
|
||||
|
||||
**Bug #77 Original (Dec 13, 2025):**
|
||||
- Drift service lazy initialization caused early return at line 692-696
|
||||
- Fixed by removing Drift init check, allowing graceful failure later
|
||||
- Commit: 01bd730 "critical: FIX Bug #77 - Position Manager monitoring stopped by Drift init check"
|
||||
|
||||
**Bug #77 Recurrence (Dec 15, 2025):**
|
||||
- DIFFERENT early return location
|
||||
- Monitoring loop works, but condition checks never reach
|
||||
- Same symptom (no TP1/TP2/SL detection) but different root cause
|
||||
- This investigation: Finding NEW early return location
|
||||
|
||||
## Related Bugs
|
||||
|
||||
- **Bug #76:** placeExitOrders() returns SUCCESS with missing SL order
|
||||
- **Bug #78:** Orphan detection removes active position orders
|
||||
- **Bug #73:** Service initialization never ran for 16 days
|
||||
- **Bug #82:** Drift State Verifier kills active position SL orders
|
||||
|
||||
All these bugs share common theme: **Silent failures** - system appears to work (logs say "monitoring" or "orders placed") but critical operations don't execute.
|
||||
|
||||
## Verification Commands
|
||||
|
||||
```bash
|
||||
# Check if debug logs appearing
|
||||
docker logs -f trading-bot-v4 2>&1 | grep -E "(🔍 STARTCHK|🔍 DRIFT|🔍 AGE)"
|
||||
|
||||
# Check current monitoring state
|
||||
curl -s http://localhost:3001/api/trading/sync-positions | jq '.'
|
||||
|
||||
# Check active trades in database
|
||||
docker exec trading-bot-postgres psql -U postgres -d trading_bot_v4 -c \
|
||||
"SELECT id, symbol, direction, entryPrice, createdAt FROM \"Trade\" WHERE exitReason IS NULL;"
|
||||
```
|
||||
|
||||
## Files Changed
|
||||
|
||||
- `lib/trading/position-manager.ts` (lines 691, 703, 708)
|
||||
* Added 3 console.log statements for debugging
|
||||
* NO LOGIC CHANGES - only observability
|
||||
|
||||
## Git Commits
|
||||
|
||||
- 0909846 "debug: Add comprehensive logging to Position Manager checkTradeConditions (Bug #77 recurrence)" (Dec 15, 2025)
|
||||
|
||||
## Current Container State (Dec 15, 2025 22:38 CET)
|
||||
|
||||
- Container: trading-bot-v4
|
||||
- Started: 2025-12-15 22:27:15 UTC
|
||||
- Build: Dec 15, 2025 22:24:51 CET (includes debug logging)
|
||||
- Status: ✅ Running, debug logs active
|
||||
- Active Trades: 0 (waiting for next trade to test)
|
||||
- Free Collateral: $159.34 (insufficient for test trade)
|
||||
|
||||
## User Impact
|
||||
|
||||
**Financial Loss:** $1,000+ from Bug #77 recurrence over past days/weeks
|
||||
- Position opened, monitored, but never hit TP1/TP2
|
||||
- All exits happened via on-chain LIMIT orders auto-filling
|
||||
- Position Manager 100% non-functional despite "monitoring active" logs
|
||||
|
||||
**User Quote:** "so the whole time all the development we did was not working and therefore we have lost 1000$...... i hope with the new test system this is an issue of the past"
|
||||
|
||||
## Resolution Plan
|
||||
|
||||
1. ✅ Debug logging added and deployed (Dec 15, 22:38 CET)
|
||||
2. ⏳ Waiting for next manual trade to trigger monitoring
|
||||
3. 🎯 Identify exact early return location from debug logs
|
||||
4. 🔧 Fix root cause (likely line 711 or exception handling)
|
||||
5. ✅ Deploy fix with verification
|
||||
6. 🧹 Remove debug logging once confirmed working
|
||||
7. 📝 Update Common Pitfalls section with full analysis
|
||||
|
||||
**Priority:** CRITICAL - System is trading but without proper monitoring
|
||||
**Timeline:** Fix ASAP (within next trade cycle)
|
||||
**Verification:** Must see STARTCHK, DRIFT, AGE logs + condition evaluation logs on next trade
|
||||
Reference in New Issue
Block a user