/** * Clear Manually Closed Trades * * Deletes all "open" trades from database when user manually closed them in Drift UI */ import { NextRequest, NextResponse } from 'next/server' import { getPrismaClient } from '@/lib/database/trades' import { initializeDriftService } from '@/lib/drift/client' import { getMarketConfig } from '@/config/trading' export async function POST(request: NextRequest) { try { // Initialize Drift to check actual positions const driftService = await initializeDriftService() const prisma = getPrismaClient() // Get all "open" trades from database const openTrades = await prisma.trade.findMany({ where: { status: 'open', }, select: { id: true, symbol: true, direction: true, entryPrice: true, positionId: true, }, }) if (openTrades.length === 0) { return NextResponse.json({ message: 'No open trades to clear', cleared: 0, }) } console.log(`🔍 Checking ${openTrades.length} open trades against Drift positions...`) // Check each trade against actual Drift position const toClear: string[] = [] for (const trade of openTrades) { try { const marketConfig = getMarketConfig(trade.symbol) const position = await driftService.getPosition(marketConfig.driftMarketIndex) if (position === null || position.size === 0) { // No position on Drift = manually closed console.log(`✅ Trade ${trade.symbol} has no Drift position - marking for deletion`) toClear.push(trade.id) } else { // Position exists - check if entry price matches (within 0.5%) const entryPriceDiff = Math.abs(position.entryPrice - trade.entryPrice) const entryPriceDiffPercent = (entryPriceDiff / trade.entryPrice) * 100 if (entryPriceDiffPercent > 0.5) { // Entry prices don't match = different position = old trade was closed console.log(`✅ Trade ${trade.symbol} entry mismatch (DB: $${trade.entryPrice.toFixed(4)}, Drift: $${position.entryPrice.toFixed(4)}) - marking for deletion`) toClear.push(trade.id) } else { console.log(`⏭️ Trade ${trade.symbol} still has matching position on Drift - keeping`) } } } catch (error) { console.error(`⚠️ Failed to check ${trade.symbol}:`, error) // On error, don't delete (safer to keep false positives than delete real trades) } } // Delete the orphaned trades if (toClear.length > 0) { const result = await prisma.trade.deleteMany({ where: { id: { in: toClear, }, }, }) console.log(`🗑️ Cleared ${result.count} manually closed trades`) return NextResponse.json({ message: `Cleared ${result.count} manually closed trade${result.count > 1 ? 's' : ''}`, cleared: result.count, tradeIds: toClear, }) } else { return NextResponse.json({ message: 'All open trades have matching positions on Drift', cleared: 0, }) } } catch (error) { console.error('❌ Failed to clear manually closed trades:', error) return NextResponse.json( { error: error instanceof Error ? error.message : 'Unknown error', }, { status: 500 } ) } }