Files
trading_bot_v3/drift-cleanup-manager.js
mindesbunister 81bf9f40fc 🧹 Integrate orphaned order cleanup into position monitoring
FEATURES:
- Position monitor now automatically detects orphaned orders when no positions
- Triggers cleanup only when hasPosition: false to eliminate redundant polling
- Provides detailed cleanup results in monitoring response
- Leverages existing frequent position checks vs separate timers

- Modified /app/api/automation/position-monitor/route.js to check for orphaned orders
- Calls existing /api/drift/cleanup-orders endpoint when no positions detected
- Returns cleanup status, success/failure, and summary in monitoring response
- Handles cleanup errors gracefully with detailed error reporting

- Eliminates need for separate 60-second cleanup polling
- Uses existing position monitoring infrastructure
- Only runs cleanup when positions close (triggered by hasPosition: false)
- Automatic handling of orphaned orders after SL/TP execution

- Added test-orphaned-cleanup-integration.js for verification
- Tests both position monitor integration and direct cleanup API
- Provides detailed feedback on cleanup operations

This completes the automation enhancement requested - no more manual cleanup needed!
2025-07-26 13:01:21 +02:00

140 lines
4.8 KiB
JavaScript

#!/usr/bin/env node
/**
* Drift Order Cleanup Management Script
* Easy commands to manage the automated cleanup service
*/
const { driftOrderCleanupService } = require('./lib/drift-order-cleanup-service.js')
const commands = {
status: async () => {
console.log('📊 Drift Order Cleanup Status')
console.log('============================')
const status = driftOrderCleanupService.getStatus()
console.log(`Running: ${status.isRunning ? '✅ YES' : '❌ NO'}`)
if (status.lastCleanupTime > 0) {
const ago = Math.floor((Date.now() - status.lastCleanupTime) / 1000)
console.log(`Last cleanup: ${ago}s ago`)
} else {
console.log('Last cleanup: Never')
}
if (status.cooldownRemaining > 0) {
console.log(`Cooldown: ${Math.floor(status.cooldownRemaining / 1000)}s remaining`)
}
// Get current positions and orders
try {
const [positionsRes, ordersRes] = await Promise.all([
fetch('http://localhost:9001/api/drift/positions'),
fetch('http://localhost:9001/api/drift/orders')
])
if (positionsRes.ok && ordersRes.ok) {
const positions = await positionsRes.json()
const orders = await ordersRes.json()
console.log(`\nCurrent: ${positions.positions?.length || 0} positions, ${orders.orders?.length || 0} orders`)
if (positions.positions?.length > 0) {
console.log('\nActive Positions:')
positions.positions.forEach(pos => {
console.log(` 📈 ${pos.symbol}: ${pos.size > 0 ? 'LONG' : 'SHORT'} ${Math.abs(pos.size)} ($${pos.value?.toFixed(2) || 'N/A'})`)
})
}
if (orders.orders?.length > 0) {
console.log('\nActive Orders:')
orders.orders.forEach(order => {
console.log(` 📋 ${order.symbol}: ${order.side} ${order.size} @ $${order.price} (${order.orderType})`)
})
}
}
} catch (error) {
console.log('⚠️ Could not fetch current positions/orders')
}
},
start: () => {
console.log('🚀 Starting automated cleanup service...')
driftOrderCleanupService.start()
console.log('✅ Service started! It will check for orphaned orders every 60 seconds.')
},
stop: () => {
console.log('🛑 Stopping automated cleanup service...')
driftOrderCleanupService.stop()
console.log('✅ Service stopped.')
},
cleanup: async () => {
console.log('🧹 Running manual cleanup...')
try {
const result = await driftOrderCleanupService.forceCleanup()
console.log('\n📊 Cleanup Results:')
console.log(` Positions: ${result.summary.activePositions}`)
console.log(` Orders: ${result.summary.activeOrders}`)
console.log(` Orphaned: ${result.summary.orphanedOrders}`)
console.log(` Conflicting: ${result.summary.conflictingOrders}`)
console.log(` ✅ Canceled: ${result.summary.totalCanceled}`)
console.log(` ❌ Failed: ${result.summary.totalFailed}`)
if (result.canceledOrders?.length > 0) {
console.log('\nCanceled Orders:')
result.canceledOrders.forEach(order => {
if (order.success) {
console.log(`${order.symbol} order ${order.orderId} (${order.reason})`)
} else {
console.log(` ❌ Order ${order.orderId}: ${order.error}`)
}
})
}
} catch (error) {
console.error('❌ Cleanup failed:', error.message)
}
},
help: () => {
console.log('🧹 Drift Order Cleanup Commands')
console.log('===============================')
console.log('')
console.log('Commands:')
console.log(' status - Show service status and current positions/orders')
console.log(' start - Start automated cleanup monitoring')
console.log(' stop - Stop automated cleanup monitoring')
console.log(' cleanup - Run manual cleanup now')
console.log(' help - Show this help')
console.log('')
console.log('Examples:')
console.log(' node drift-cleanup-manager.js status')
console.log(' node drift-cleanup-manager.js start')
console.log(' node drift-cleanup-manager.js cleanup')
console.log('')
console.log('What it does:')
console.log('• Detects orphaned orders (orders for markets with no position)')
console.log('• Finds conflicting reduce-only orders')
console.log('• Automatically cancels problematic orders')
console.log('• Prevents manual order management after SL/TP hits')
}
}
async function main() {
const command = process.argv[2] || 'help'
if (commands[command]) {
await commands[command]()
} else {
console.log(`❌ Unknown command: ${command}`)
console.log('Run "node drift-cleanup-manager.js help" for available commands')
}
}
if (require.main === module) {
main().catch(console.error)
}
module.exports = { commands }