- 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)
7.1 KiB
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:
// 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:
// 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:
-- 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:
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:
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:
# 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:
-- 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%:
# 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:
- Immediate: Disable automated trading via settings UI
- Check: Review Position Manager logs for error patterns
- Revert: Restore previous version from git
- Debug: Add more extensive logging before retry
- 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:
- Next 5 external closures show NO duplicate "External closure recorded" messages
- Database P&L matches Drift Protocol within 1% for all 5 trades
- No compounding losses (each trade recorded exactly once)
- 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