import { NextResponse } from 'next/server'; export async function GET() { try { // Get current positions with real-time data const baseUrl = process.env.INTERNAL_API_URL || 'http://localhost:3000'; const positionsResponse = await fetch(`${baseUrl}/api/drift/positions`, { cache: 'no-store', // Force fresh data headers: { 'Cache-Control': 'no-cache' } }); const positionsData = await positionsResponse.json(); // Use real-time price from Drift positions data let currentPrice = 185.0; // Fallback price const result = { timestamp: new Date().toISOString(), hasPosition: false, position: null, stopLossProximity: null, riskLevel: 'NONE', nextAction: 'No position to monitor', recommendation: 'START_TRADING', orphanedOrderCleanup: null }; if (positionsData.success && positionsData.positions.length > 0) { const position = positionsData.positions[0]; // Use real-time mark price from Drift currentPrice = position.markPrice || position.entryPrice || currentPrice; result.hasPosition = true; result.position = { symbol: position.symbol, side: position.side, size: position.size, entryPrice: position.entryPrice, currentPrice: currentPrice, unrealizedPnl: position.unrealizedPnl, notionalValue: position.notionalValue }; // Calculate stop loss proximity (mock - you'd need actual SL from order data) let stopLossPrice; if (position.side === 'long') { stopLossPrice = position.entryPrice * 0.95; // 5% below entry } else { stopLossPrice = position.entryPrice * 1.05; // 5% above entry } const distanceToSL = Math.abs(currentPrice - stopLossPrice) / currentPrice; const proximityPercent = distanceToSL * 100; result.stopLossProximity = { stopLossPrice: stopLossPrice, currentPrice: currentPrice, distancePercent: proximityPercent.toFixed(2), isNear: proximityPercent < 2.0 // Within 2% = NEAR }; // Risk assessment if (proximityPercent < 1.0) { result.riskLevel = 'CRITICAL'; result.nextAction = 'IMMEDIATE ANALYSIS REQUIRED - Price very close to SL'; result.recommendation = 'EMERGENCY_ANALYSIS'; } else if (proximityPercent < 2.0) { result.riskLevel = 'HIGH'; result.nextAction = 'Enhanced monitoring - Analyze within 5 minutes'; result.recommendation = 'URGENT_MONITORING'; } else if (proximityPercent < 5.0) { result.riskLevel = 'MEDIUM'; result.nextAction = 'Regular monitoring - Check every 10 minutes'; result.recommendation = 'NORMAL_MONITORING'; } else { result.riskLevel = 'LOW'; result.nextAction = 'Standard monitoring - Check every 30 minutes'; result.recommendation = 'RELAXED_MONITORING'; } } else { // NO POSITION DETECTED - Check for orphaned orders and cleanup try { // Check for any remaining orders when we have no positions const ordersResponse = await fetch(`${baseUrl}/api/drift/orders`, { cache: 'no-store', headers: { 'Cache-Control': 'no-cache' } }); if (ordersResponse.ok) { const ordersData = await ordersResponse.json(); const activeOrders = ordersData.orders || []; if (activeOrders.length > 0) { console.log('📋 No active positions detected - checking for truly orphaned orders...'); // Filter for truly orphaned orders (non-reduce-only orders without positions) // Do NOT clean up reduce-only orders as these could be legitimate SL/TP from recently closed positions const trulyOrphanedOrders = activeOrders.filter(order => !order.reduceOnly); if (trulyOrphanedOrders.length > 0) { console.log(`🎯 Found ${trulyOrphanedOrders.length} truly orphaned orders (non-reduce-only) - triggering cleanup...`); // Trigger automated cleanup of truly orphaned orders only const cleanupResponse = await fetch(`${baseUrl}/api/drift/cleanup-orders`, { method: 'POST', headers: { 'Content-Type': 'application/json' } }); let cleanupResult = null; if (cleanupResponse.ok) { cleanupResult = await cleanupResponse.json(); if (cleanupResult.success) { console.log('✅ Orphaned order cleanup completed:', cleanupResult.summary); result.orphanedOrderCleanup = { triggered: true, success: true, summary: cleanupResult.summary, message: `Cleaned up ${cleanupResult.summary.totalCanceled} truly orphaned orders` }; result.nextAction = `Cleaned up ${cleanupResult.summary.totalCanceled} orphaned orders - Ready for new trade`; } else { console.error('❌ Orphaned order cleanup failed:', cleanupResult.error); result.orphanedOrderCleanup = { triggered: true, success: false, error: cleanupResult.error, message: 'Cleanup failed - Manual intervention may be needed' }; result.nextAction = 'Cleanup failed - Check orders manually'; } } else { console.error('❌ Failed to trigger cleanup API'); result.orphanedOrderCleanup = { triggered: false, success: false, error: 'Cleanup API unavailable', message: 'Could not trigger automatic cleanup' }; } } else { // All orders are reduce-only (likely SL/TP) - do not clean up console.log('✅ All remaining orders are reduce-only (likely SL/TP) - skipping cleanup to preserve risk management'); result.orphanedOrderCleanup = { triggered: false, success: true, message: 'All orders are reduce-only (SL/TP) - preserved for risk management' }; } } else { // Only log occasionally when no orders found (not every check) result.orphanedOrderCleanup = { triggered: false, success: true, message: 'No orphaned orders detected' }; } } } catch (cleanupError) { console.error('❌ Error during orphaned order check:', cleanupError); result.orphanedOrderCleanup = { triggered: false, success: false, error: cleanupError.message, message: 'Error checking for orphaned orders' }; } } // Auto-restart automation if no position and cleanup completed successfully if (!result.hasPosition && result.recommendation === 'START_TRADING') { try { console.log('🚀 AUTO-RESTART: No position detected with START_TRADING recommendation - checking if automation should restart'); // Check if automation is currently stopped const statusResponse = await fetch(`${baseUrl}/api/automation/status`); if (statusResponse.ok) { const statusData = await statusResponse.json(); if (!statusData.isRunning) { console.log('🔄 Automation is stopped - triggering auto-restart for new cycle'); result.autoRestart = { triggered: true, reason: 'No position + START_TRADING recommendation', message: 'System ready for new trading cycle' }; // Note: We don't automatically start here to avoid conflicts // The UI should detect this and offer restart option } else { console.log('✅ Automation already running - no restart needed'); result.autoRestart = { triggered: false, reason: 'Automation already active', message: 'System monitoring active' }; } } } catch (restartError) { console.warn('⚠️ Could not check automation status for auto-restart:', restartError.message); result.autoRestart = { triggered: false, error: restartError.message, message: 'Could not check restart requirements' }; } } return NextResponse.json({ success: true, monitor: result }); } catch (error) { console.error('Position monitor error:', error); return NextResponse.json({ success: false, error: 'Failed to get position monitoring data', message: error.message }, { status: 500 }); } }