Add /close command and auto-flip logic with order cleanup

- Added /close Telegram command for full position closure
- Updated /reduce to accept 10-100% (was 10-90%)
- Implemented auto-flip logic: automatically closes opposite position when signal reverses
- Fixed risk check to allow opposite direction trades (signal flips)
- Enhanced Position Manager to cancel orders when removing trades
- Added startup initialization for Position Manager (restores trades on restart)
- Fixed analytics to show stopped-out trades (manual DB update for orphaned trade)
- Updated reduce endpoint to route 100% closes through closePosition for proper cleanup
- All position closures now guarantee TP/SL order cancellation on Drift
This commit is contained in:
mindesbunister
2025-10-27 23:27:48 +01:00
parent a07bf9f4b2
commit 9bf83260c4
7 changed files with 264 additions and 19 deletions

View File

@@ -100,6 +100,38 @@ export async function POST(request: NextRequest): Promise<NextResponse<ExecuteTr
)
}
// AUTO-FLIP: Check for existing opposite direction position
const positionManager = await getInitializedPositionManager()
const existingTrades = Array.from(positionManager.getActiveTrades().values())
const oppositePosition = existingTrades.find(
trade => trade.symbol === driftSymbol && trade.direction !== body.direction
)
if (oppositePosition) {
console.log(`🔄 Signal flip detected! Closing ${oppositePosition.direction} to open ${body.direction}`)
// Close opposite position
const { closePosition } = await import('@/lib/drift/orders')
const closeResult = await closePosition({
symbol: driftSymbol,
percentToClose: 100,
slippageTolerance: config.slippageTolerance,
})
if (!closeResult.success) {
console.error('❌ Failed to close opposite position:', closeResult.error)
// Continue anyway - we'll try to open the new position
} else {
console.log(`✅ Closed ${oppositePosition.direction} position at $${closeResult.closePrice?.toFixed(4)} (P&L: $${closeResult.realizedPnL?.toFixed(2)})`)
// Position Manager will handle cleanup (including order cancellation)
// The executeExit method already removes the trade and updates database
}
// Small delay to ensure position is fully closed
await new Promise(resolve => setTimeout(resolve, 1000))
}
// Calculate position size with leverage
const positionSizeUSD = config.positionSize * config.leverage
@@ -211,8 +243,7 @@ export async function POST(request: NextRequest): Promise<NextResponse<ExecuteTr
lastUpdateTime: Date.now(),
}
// Add to position manager for monitoring
const positionManager = await getInitializedPositionManager()
// Add to position manager for monitoring (reuse positionManager from above)
await positionManager.addTrade(activeTrade)
console.log('✅ Trade added to position manager for monitoring')