- New /api/trading/sync-positions endpoint (no auth) - Fetches actual Drift positions and compares with Position Manager - Removes stale tracking, adds missing positions with calculated TP/SL - Settings UI: Orange 'Sync Positions' button added - CLI script: scripts/sync-positions.sh for terminal access - Full documentation in docs/guides/POSITION_SYNC_GUIDE.md - Quick reference: POSITION_SYNC_QUICK_REF.md - Updated AI instructions with pitfall #23 Problem solved: Manual Telegram trades with partial fills can cause Position Manager to lose tracking, leaving positions without software- based stop loss protection. This feature restores dual-layer protection. Note: Docker build not picking up route yet (cache issue), needs investigation
3.8 KiB
3.8 KiB
Position Re-Sync Feature
Problem Solved
When manual Telegram trades are partially closed by on-chain orders, the Position Manager can lose tracking of the remaining position. This leaves the position without software-based stop loss protection, creating risk.
Solution
Created /api/trading/sync-positions endpoint that:
- Fetches all actual open positions from Drift
- Compares against Position Manager's tracked trades
- Removes tracking for positions that don't exist on Drift (cleanup)
- Adds tracking for positions that exist on Drift but aren't being monitored
Usage
Via UI (Settings Page)
- Go to http://localhost:3001/settings
- Click "🔄 Sync Positions" button (orange button next to Restart Bot)
- View sync results in success message
Via Terminal
cd /home/icke/traderv4
bash scripts/sync-positions.sh
Via API
curl -X POST http://localhost:3001/api/trading/sync-positions \
-H "Authorization: Bearer $API_SECRET_KEY" \
| jq '.'
Response Format
{
"success": true,
"message": "Position sync complete",
"results": {
"drift_positions": 1,
"tracked_positions": 0,
"added": ["SOL-PERP"],
"removed": [],
"unchanged": [],
"errors": []
},
"details": {
"drift_positions": [
{
"symbol": "SOL-PERP",
"direction": "short",
"size": 4.93,
"entry": 167.38,
"pnl": 8.15
}
],
"now_tracking": [
{
"symbol": "SOL-PERP",
"direction": "short",
"entry": 167.38
}
]
}
}
When to Use
- After Telegram manual trades - If position remains open but isn't being tracked
- After bot restarts - If Position Manager lost in-memory state
- After partial fills - When on-chain orders close position in chunks
- Rate limiting issues - If 429 errors prevented proper monitoring
- Manual interventions - If you modified position directly on Drift
How It Works
- Queries Drift for all open positions (SOL-PERP, BTC-PERP, ETH-PERP)
- Gets current oracle price for each position
- Calculates TP/SL targets based on current config
- Creates ActiveTrade objects with synthetic IDs (since we don't know original TX)
- Adds to Position Manager for monitoring
- Position Manager then protects position with emergency stop, trailing stop, etc.
Limitations
- Entry time unknown - Assumes position opened 1 hour ago (doesn't affect TP/SL logic)
- Signal quality metrics missing - No ATR/ADX data (only matters for scaling)
- Original config unknown - Uses current config, not config when trade opened
- Synthetic position ID - Uses
manual-{timestamp}instead of actual TX signature
Safety Notes
- No auth required (same as test endpoint) - internal use only
- Won't open new positions - only adds tracking for existing ones
- Cleans up tracking for positions that were closed externally
- Marks cleaned positions as "sync_cleanup" in database
Files Changed
app/api/trading/sync-positions/route.ts- Main endpointapp/settings/page.tsx- Added UI button and sync functionscripts/sync-positions.sh- CLI helper script
Example Scenario (Today's Issue)
Before Sync:
- Drift: 4.93 SOL SHORT position open at $167.38
- Position Manager: 0 active trades
- Database: Position marked as "closed"
- Result: NO STOP LOSS PROTECTION ⚠️
After Sync:
- Position Manager detects 4.93 SOL SHORT
- Calculates SL at $168.89 (-0.9%)
- Calculates TP1 at $166.71 (+0.4%)
- Starts monitoring every 2 seconds
- Result: DUAL-LAYER PROTECTION RESTORED ✅
Future Improvements
- Auto-sync on startup (currently manual only)
- Periodic auto-sync every N minutes
- Alert if positions drift out of sync
- Restore original signal quality metrics from database
- Better handling of partial fill history