Files
trading_bot_v4/VERIFICATION_CHECKLIST_NOV12.md
mindesbunister a21ae6d622 Add v7-momentum indicator (experimental, disabled)
- Created momentum scalper indicator for catching rapid price acceleration
- ROC-based detection: 2.0% threshold over 5 bars
- Volume confirmation: 2.0x spike (checks last 3 bars)
- ADX filter: Requires 12+ minimum directional movement
- Anti-chop filter: Blocks signals in dead markets
- Debug table: Real-time metric display for troubleshooting

Status: Functional but signal quality inferior to v6 HalfTrend
Decision: Shelved for now, continue with proven v6 strategy
File: docs/guides/MOMENTUM_INDICATOR_V1.pine (239 lines)

Lessons learned:
- Momentum indicators inherently noisy (40-50% WR expected)
- Signals either too early (false breakouts) or too late (miss move)
- Volume spike timing issue: Often lags price move by 1-2 bars
- Better to optimize proven strategy than add complexity

Related: Position Manager duplicate update bug fixed (awaiting verification)
2025-11-12 19:55:19 +01:00

233 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Verification Checklist - External Closure Duplicate Bug Fix
**Date:** November 12, 2025
**Issue:** Position Manager was recording external closures 5-8 times, compounding P&L
**Fix Applied:** Remove trade from `activeTrades` Map BEFORE database update
**Status:** 🔴 **UNVERIFIED** - Code deployed but not tested with real trade
---
## What Was Fixed
**File:** `lib/trading/position-manager.ts` (lines 493-530)
**The Bug:**
```typescript
// OLD (BROKEN):
await updateTradeExit({ realizedPnL: -$7.98 }) // Update DB
await this.removeTrade(trade.id) // Remove from monitoring
// Problem: Monitoring loop runs again before removal, processes AGAIN
```
**The Fix:**
```typescript
// NEW (SHOULD WORK):
this.activeTrades.delete(trade.id) // Remove FIRST
await updateTradeExit({ realizedPnL: -$7.98 }) // Then update DB
// If loop runs again, trade already gone, skips duplicate update
```
**Evidence of Bug:** Last trade (cmhvwlmcr0000r007g0sizd7s) showed:
- Dashboard: -$58.43 loss (WRONG - 8× actual)
- Drift Protocol: -$7.98 loss (CORRECT)
- Logs: 8 consecutive "External closure recorded" messages
---
## Manual Corrections Applied
**Database corrected for last trade:**
```sql
-- Entry price: $160.62259 → $160.512 (matches Drift)
-- Exit price: $160.09242 → $159.967 (matches Drift)
-- P&L: -$58.43 → -$7.98 (matches Drift -0.34%)
```
**Verification query:**
```bash
docker exec trading-bot-postgres psql -U postgres -d trading_bot_v4 -c \
"SELECT \"entryPrice\", \"exitPrice\", \"realizedPnL\" FROM \"Trade\"
WHERE id = 'cmhvwlmcr0000r007g0sizd7s';"
```
Result: `160.512 | 159.967 | -7.98` ✅ CORRECT
---
## Verification Requirements (Next External Closure)
### 1. Watch Docker Logs in Real-Time
**Command:**
```bash
docker logs -f trading-bot-v4 | grep -E "(External closure|DUPLICATE|Removed trade)"
```
**What to Look For:**
**CORRECT behavior (fix working):**
```
📊 SOL-PERP | Price: 160.0246 | P&L: -0.37%
🗑️ Removed trade cmh... from monitoring (BEFORE DB update to prevent duplicates)
Active trades remaining: 0
💾 External closure recorded: SL at $160.0246 | P&L: $-7.96
```
**Only ONE "External closure recorded" line!**
**BROKEN behavior (fix failed):**
```
💾 External closure recorded: SL at $160.0246 | P&L: $-7.96
💾 External closure recorded: SL at $160.0359 | P&L: $-15.92 ← DUPLICATE!
💾 External closure recorded: SL at $160.0472 | P&L: $-23.88 ← DUPLICATE!
```
**Multiple "External closure recorded" = BUG STILL EXISTS**
🎯 **BEST outcome (proves fix caught duplicate attempt):**
```
🗑️ Removed trade cmh... from monitoring (BEFORE DB update to prevent duplicates)
💾 External closure recorded: SL at $160.0246 | P&L: $-7.96
⚠️ DUPLICATE PROCESSING PREVENTED: Trade cmh... already removed from monitoring
This is the bug fix working - without it, we'd update DB again with compounded P&L
```
---
### 2. Compare Database P&L to Drift Protocol
**After next external closure, run:**
```bash
# Get last trade from database
docker exec trading-bot-postgres psql -U postgres -d trading_bot_v4 -c \
"SELECT id, symbol, direction, \"entryPrice\", \"exitPrice\",
\"positionSizeUSD\", \"realizedPnL\", \"exitReason\",
TO_CHAR(\"exitTime\", 'HH24:MI:SS') as exit_time
FROM \"Trade\"
ORDER BY \"createdAt\" DESC LIMIT 1;"
```
**Then check Drift Protocol UI:**
- Go to Position History
- Find matching trade by timestamp
- Compare: Entry Price, Exit Price, P&L %
**Manual P&L calculation:**
```
For LONG: (exitPrice - entryPrice) × positionSize_in_tokens
For SHORT: (entryPrice - exitPrice) × positionSize_in_tokens
Example from last trade:
(159.967 - 160.512) × 13.3 SOL = -$7.25
Database showed: -$7.98 ✅ Close enough (slippage)
```
---
### 3. Count Database Updates
**Check how many times the trade was updated:**
```sql
-- Look for the trade ID in SystemEvent logs
SELECT "eventType", "message", "createdAt"
FROM "SystemEvent"
WHERE "message" LIKE '%cmh%' -- Replace with actual trade ID
ORDER BY "createdAt" DESC;
```
**Expected:** 1 update event per external closure
**Bug present:** 5-8 update events for same closure
---
### 4. Check for Price Mismatch
**Entry/exit prices should match Drift within 0.5%:**
```bash
# From Drift UI: Note actual fill prices
# From database: Compare with query above
Acceptable difference: < 0.5% (slippage)
Large difference (>1%): Indicates oracle price mismatch
```
---
## Verification Checklist
**Next trade that closes externally (TP1/TP2/SL on-chain order):**
- [ ] **Logs:** Only ONE "External closure recorded" message
- [ ] **Logs:** "Removed trade ... BEFORE DB update" appears once
- [ ] **Logs:** No multiple consecutive closure messages
- [ ] **Database P&L:** Matches Drift Protocol actual P&L (within 1%)
- [ ] **Entry/Exit Prices:** Match Drift order fills (within 0.5%)
- [ ] **No duplicate updates:** Trade ID appears once in recent database queries
**If all checks pass:** ✅ Fix is VERIFIED - update Common Pitfall #26 as "VERIFIED"
**If any check fails:** 🔴 Bug still exists - investigate further
---
## Additional Monitoring (Next 5 External Closures)
Track these trades to ensure fix is stable:
| Trade # | Symbol | Exit Time | DB P&L | Drift P&L | Match? | Logs OK? |
|---------|--------|-----------|--------|-----------|--------|----------|
| 1 | | | | | | |
| 2 | | | | | | |
| 3 | | | | | | |
| 4 | | | | | | |
| 5 | | | | | | |
**Once 5 consecutive trades verify correctly:** Update status to ✅ **VERIFIED & STABLE**
---
## Rollback Plan (If Fix Fails)
If verification fails and bug persists:
1. **Immediate:** Disable automated trading via settings UI
2. **Check:** Review Position Manager logs for error patterns
3. **Revert:** Restore previous version from git
4. **Debug:** Add more extensive logging before retry
5. **Document:** Update Common Pitfall #26 with findings
---
## Related Issues to Watch For
While monitoring, also check for:
- [ ] TP1 detection working correctly (75% close, 25% runner)
- [ ] SL moves to breakeven after TP1 as expected
- [ ] Trailing stop activates at TP2 trigger
- [ ] MAE/MFE tracking updates correctly
- [ ] No phantom trades (position size mismatches)
---
## Success Criteria
**Fix is considered successful when:**
1. Next 5 external closures show NO duplicate "External closure recorded" messages
2. Database P&L matches Drift Protocol within 1% for all 5 trades
3. No compounding losses (each trade recorded exactly once)
4. User confirms dashboard P&L matches expectations
**Then:** Mark VERIFICATION_CHECKLIST_NOV12.md as ✅ COMPLETE and update copilot-instructions.md
---
## Notes
- **Capital at risk:** $97.55 USDC (monitor closely during verification)
- **Current leverage:** 15x SOL, 1x ETH
- **Trade frequency:** ~2-5 trades/day expected
- **Verification timeline:** Should complete within 1-3 days
**Last Updated:** November 12, 2025 - Fix deployed, awaiting first test trade