#!/usr/bin/env node /** * Fix Missing Stop Loss and Take Profit Orders * This script analyzes the current position and places missing SL/TP orders * using the same AI calculation logic that should have worked initially. */ async function fixMissingSLTP() { try { console.log('🔍 Checking current position...'); // Get current position const posResponse = await fetch('http://localhost:3000/api/drift/positions'); const posData = await posResponse.json(); if (!posData.positions || posData.positions.length === 0) { console.log('❌ No positions found'); return; } const position = posData.positions[0]; console.log(`📊 Found position: ${position.side} ${position.size} SOL at $${position.entryPrice}`); // Check current orders const ordersResponse = await fetch('http://localhost:3000/api/drift/orders'); const ordersData = await ordersResponse.json(); const openOrders = ordersData.orders?.filter(o => o.status === 'OPEN') || []; console.log(`📋 Current open orders: ${openOrders.length}`); // Check if SL/TP already exist const hasStopLoss = openOrders.some(order => order.reduceOnly && (position.side.toLowerCase() === 'long' ? parseFloat(order.triggerPrice || order.price) < position.entryPrice : parseFloat(order.triggerPrice || order.price) > position.entryPrice) ); const hasTakeProfit = openOrders.some(order => order.reduceOnly && (position.side.toLowerCase() === 'long' ? parseFloat(order.triggerPrice || order.price) > position.entryPrice : parseFloat(order.triggerPrice || order.price) < position.entryPrice) ); console.log(`🛡️ Risk Management Status: SL=${hasStopLoss ? '✅' : '❌'}, TP=${hasTakeProfit ? '✅' : '❌'}`); if (hasStopLoss && hasTakeProfit) { console.log('✅ Position already has proper risk management!'); return; } // Calculate missing SL/TP using scalping-appropriate levels const currentPrice = position.markPrice || position.entryPrice; const isLong = position.side.toLowerCase() === 'long'; let stopLoss = null; let takeProfit = null; if (!hasStopLoss) { // 1.5% stop loss for scalping stopLoss = isLong ? currentPrice * 0.985 : // 1.5% below for long currentPrice * 1.015; // 1.5% above for short console.log(`🛑 Calculated stop loss: $${stopLoss.toFixed(4)} (1.5%)`); } if (!hasTakeProfit) { // 3% take profit for scalping (2:1 risk/reward) takeProfit = isLong ? currentPrice * 1.03 : // 3% above for long currentPrice * 0.97; // 3% below for short console.log(`🎯 Calculated take profit: $${takeProfit.toFixed(4)} (3%)`); } // Place missing orders if (stopLoss) { console.log('🛑 Placing stop loss order...'); try { const slResponse = await fetch('http://localhost:3000/api/drift/place-order', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ orderType: 'TRIGGER_LIMIT', direction: isLong ? 'SHORT' : 'LONG', baseAssetAmount: position.size, triggerPrice: stopLoss, price: stopLoss, reduceOnly: true, triggerCondition: isLong ? 'BELOW' : 'ABOVE' }) }); const slResult = await slResponse.json(); if (slResult.success) { console.log('✅ Stop loss order placed successfully'); } else { console.log('❌ Stop loss order failed:', slResult.error); } } catch (error) { console.log('❌ Stop loss placement error:', error.message); } } if (takeProfit) { console.log('🎯 Placing take profit order...'); try { const tpResponse = await fetch('http://localhost:3000/api/drift/place-order', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ orderType: 'TRIGGER_LIMIT', direction: isLong ? 'SHORT' : 'LONG', baseAssetAmount: position.size, triggerPrice: takeProfit, price: takeProfit, reduceOnly: true, triggerCondition: isLong ? 'ABOVE' : 'BELOW' }) }); const tpResult = await tpResponse.json(); if (tpResult.success) { console.log('✅ Take profit order placed successfully'); } else { console.log('❌ Take profit order failed:', tpResult.error); } } catch (error) { console.log('❌ Take profit placement error:', error.message); } } console.log('✅ Risk management fix complete!'); } catch (error) { console.error('❌ Error fixing SL/TP:', error.message); } } fixMissingSLTP();