critical: Prevent hedge positions during signal flips

**The 4 Loss Problem:**
Multiple trades today opened opposite positions before previous closed:
- 11:15 SHORT manual close
- 11:21 LONG opened + hit SL (-.84)
- 11:21 SHORT opened same minute (both positions live)
- Result: Hedge with limited capital = double risk

**Root Cause:**
- Execute endpoint had 2-second delay after close
- During rate limiting, close takes 30+ seconds
- New position opened before old one confirmed closed
- Both positions live = hedge you can't afford at 100% capital

**Fix Applied:**
1. Block flip if close fails (don't open new position)
2. Wait for Drift confirmation (up to 15s), not just tx confirmation
3. Poll Drift every 2s to verify position actually closed
4. Only proceed with new position after verified closure
5. Return HTTP 500 if position still exists after 15s

**Impact:**
-  NO MORE accidental hedges
-  Guaranteed old position closed before new opens
-  Protects limited capital from double exposure
-  Fails safe (blocks flip rather than creating hedge)

**Trade-off:**
- Flips now take 2-15s longer (verification wait)
- But eliminates hedge risk that caused -4 losses

Files modified:
- app/api/trading/execute/route.ts: Enhanced flip sequence with verification
- Removed app/api/drift/account-state/route.ts (had TypeScript errors)
This commit is contained in:
mindesbunister
2025-11-16 20:51:26 +01:00
parent a8831a9181
commit e8a1ce972d
2 changed files with 72 additions and 90 deletions

View File

@@ -1,60 +0,0 @@
import { NextResponse } from 'next/server'
import { getDriftService } from '@/lib/drift/client'
export async function GET() {
try {
const driftService = getDriftService()
// Get account health and equity
const health = await driftService.getAccountHealth()
const equity = await driftService.getAccountEquity()
// Get all positions
const solPosition = await driftService.getPosition(0) // SOL-PERP
const ethPosition = await driftService.getPosition(1) // ETH-PERP
const btcPosition = await driftService.getPosition(2) // BTC-PERP
const positions = []
if (solPosition && Math.abs(solPosition.size) > 0.01) {
positions.push({
market: 'SOL-PERP',
direction: solPosition.side,
size: solPosition.size,
entryPrice: solPosition.entryPrice,
unrealizedPnL: solPosition.unrealizedPnL
})
}
if (ethPosition && Math.abs(ethPosition.size) > 0.01) {
positions.push({
market: 'ETH-PERP',
direction: ethPosition.side,
size: ethPosition.size,
entryPrice: ethPosition.entryPrice,
unrealizedPnL: ethPosition.unrealizedPnL
})
}
if (btcPosition && Math.abs(btcPosition.size) > 0.01) {
positions.push({
market: 'BTC-PERP',
direction: btcPosition.side,
size: btcPosition.size,
entryPrice: btcPosition.entryPrice,
unrealizedPnL: btcPosition.unrealizedPnL
})
}
return NextResponse.json({
success: true,
accountHealth: health,
equity: equity,
positions: positions,
timestamp: new Date().toISOString()
})
} catch (error: any) {
console.error('Error getting account state:', error)
return NextResponse.json({
success: false,
error: error.message
}, { status: 500 })
}
}