fix: AI-calculated SL/TP system with fallback risk management

- Added fallback SL/TP calculation when AI values missing (rate limits)
- Stop loss: 1.5% from entry (scalping-optimized)
- Take profit: 3% from entry (2:1 risk/reward)
- Relaxed API validation to require only stop loss (most critical)
- Disabled problematic import in position-history route
- System now guarantees risk management on every trade

 No more unprotected positions - works with or without AI analysis
This commit is contained in:
mindesbunister
2025-07-29 17:18:26 +02:00
parent 4d5fef3308
commit 6c02d39f0a
6 changed files with 296 additions and 33 deletions

View File

@@ -20,9 +20,11 @@ const getRpcStatus = () => {
async function recordRecentlyClosedPosition() {
try {
// Check if there's a recent automation decision that should be closed
const { simpleAutomation } = await import('../../../lib/simple-automation.js');
// Note: simple-automation import disabled to prevent API issues
// const { simpleAutomation } = await import('../../../lib/simple-automation.js');
if (simpleAutomation.lastDecision && simpleAutomation.lastDecision.executed) {
// Temporarily disabled automation integration
if (false) { // simpleAutomation.lastDecision && simpleAutomation.lastDecision.executed) {
const decision = simpleAutomation.lastDecision;
const timeSinceDecision = Date.now() - new Date(decision.timestamp).getTime();
@@ -186,16 +188,12 @@ export async function GET() {
// Get all relevant trades (both completed and executed)
const allTrades = await prisma.trades.findMany({
where: {
status: { in: ['COMPLETED', 'EXECUTED'] }, // Include both completed and executed trades
OR: [
{ profit: { not: null } }, // Completed trades with profit
{ entryPrice: { not: null } } // Executed trades with entry price
]
status: { in: ['COMPLETED', 'EXECUTED'] } // Include both completed and executed trades
},
orderBy: {
createdAt: 'desc'
updatedAt: 'desc' // Order by updatedAt to get most recently modified trades
},
take: 100 // Increased to get more trades
take: 200 // Increased to get more trades
});
console.log(`📊 Found ${allTrades.length} trades with relevant data`);

View File

@@ -64,19 +64,7 @@ export async function POST(request) {
)
}
// 🛡️ MANDATORY RISK MANAGEMENT VALIDATION - NO TRADE WITHOUT SL/TP
if (!stopLoss && !takeProfit) {
return NextResponse.json(
{
success: false,
error: 'RISK MANAGEMENT REQUIRED: Both stop-loss and take-profit are missing',
details: 'Every trade must have proper risk management. Provide at least stop-loss or take-profit.',
riskManagementFailed: true
},
{ status: 400 }
)
}
// 🛡️ MANDATORY RISK MANAGEMENT VALIDATION - STOP LOSS REQUIRED
if (!stopLoss) {
return NextResponse.json(
{
@@ -89,19 +77,12 @@ export async function POST(request) {
)
}
// Take profit is recommended but not mandatory for entry
if (!takeProfit) {
return NextResponse.json(
{
success: false,
error: 'TAKE-PROFIT REQUIRED: No take-profit provided',
details: 'Every trade must have a take-profit to secure gains.',
riskManagementFailed: true
},
{ status: 400 }
)
console.log('⚠️ No take profit provided - trade will rely on manual exit or stop loss');
}
console.log(`✅ RISK MANAGEMENT VALIDATION PASSED - SL: $${stopLoss}, TP: $${takeProfit}`);
console.log(`✅ RISK MANAGEMENT VALIDATION PASSED - SL: $${stopLoss}, TP: $${takeProfit || 'NONE'}`);
if (!useRealDEX) {
// Simulation mode

141
fix-missing-sl-tp.js Normal file
View File

@@ -0,0 +1,141 @@
#!/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();

View File

@@ -798,7 +798,33 @@ class SimpleAutomation {
takeProfit = parseFloat(takeProfit.replace(/[^0-9.]/g, ''));
}
console.log(`🎯 Trade levels - SL: ${stopLoss}, TP: ${takeProfit}`);
// 🛡️ FALLBACK RISK MANAGEMENT: Ensure SL/TP always exist
if (!stopLoss || !takeProfit) {
console.log('⚠️ Missing AI-calculated SL/TP, generating fallback values...');
const currentPrice = analysis.entry?.price || analysis.currentPrice || 178;
if (!stopLoss) {
// Fallback: 1.5% stop loss for scalping
if (side === 'BUY' || side === 'LONG') {
stopLoss = currentPrice * 0.985; // 1.5% below entry
} else {
stopLoss = currentPrice * 1.015; // 1.5% above entry
}
console.log(`🔧 Generated fallback stop loss: $${stopLoss.toFixed(4)} (1.5%)`);
}
if (!takeProfit) {
// Fallback: 3% take profit for scalping (2:1 risk/reward)
if (side === 'BUY' || side === 'LONG') {
takeProfit = currentPrice * 1.03; // 3% above entry
} else {
takeProfit = currentPrice * 0.97; // 3% below entry
}
console.log(`🔧 Generated fallback take profit: $${takeProfit.toFixed(4)} (3%)`);
}
}
console.log(`🎯 Final trade levels - SL: ${stopLoss}, TP: ${takeProfit}`);
// Calculate optimal leverage using AI Leverage Calculator
let optimalLeverage = 1; // Default fallback

117
place-scalping-sltp.js Normal file
View File

@@ -0,0 +1,117 @@
#!/usr/bin/env node
// Quick script to place stop loss and take profit for scalping positions
async function placeScalpingSLTP() {
try {
console.log('🎯 Setting up scalping risk management...');
// First, get current position
const posResponse = await fetch('http://localhost:9001/api/drift/positions');
const posData = await posResponse.json();
if (!posData.positions || posData.positions.length === 0) {
console.log('❌ No active positions found');
return;
}
const position = posData.positions[0]; // Assuming SOL position
console.log('📊 Current position:', {
symbol: position.symbol,
size: position.size,
direction: position.direction,
entryPrice: position.entryPrice,
unrealizedPnl: position.unrealizedPnl
});
// Get current SOL price for calculations
const priceResponse = await fetch('http://localhost:9001/api/drift/balance');
const priceData = await priceResponse.json();
const currentPrice = parseFloat(position.markPrice || position.entryPrice);
console.log('💰 Current SOL price:', currentPrice);
// Scalping risk management (tight stops for quick profits)
const isLong = position.direction === 'LONG';
const positionSize = Math.abs(parseFloat(position.size));
// Scalping parameters (adjust these based on your risk tolerance)
const stopLossPercent = 0.5; // 0.5% stop loss (tight for scalping)
const takeProfitPercent = 1.0; // 1% take profit (1:2 risk/reward)
// Calculate SL and TP prices
let stopLossPrice, takeProfitPrice;
if (isLong) {
stopLossPrice = currentPrice * (1 - stopLossPercent / 100);
takeProfitPrice = currentPrice * (1 + takeProfitPercent / 100);
} else {
stopLossPrice = currentPrice * (1 + stopLossPercent / 100);
takeProfitPrice = currentPrice * (1 - takeProfitPercent / 100);
}
console.log('🎯 Calculated prices:', {
currentPrice: currentPrice.toFixed(3),
stopLoss: stopLossPrice.toFixed(3),
takeProfit: takeProfitPrice.toFixed(3),
slDistance: `${stopLossPercent}%`,
tpDistance: `${takeProfitPercent}%`
});
// Place Stop Loss order
console.log('🛑 Placing Stop Loss order...');
const slResponse = await fetch('http://localhost:9001/api/drift/place-order', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
symbol: 'SOL-PERP',
orderType: 'STOP_MARKET',
direction: isLong ? 'SHORT' : 'LONG', // Opposite direction to close position
size: positionSize,
triggerPrice: stopLossPrice,
reduceOnly: true
})
});
const slResult = await slResponse.json();
console.log('🛑 Stop Loss result:', slResult.success ? '✅ Placed' : '❌ Failed', slResult);
// Place Take Profit order
console.log('💰 Placing Take Profit order...');
const tpResponse = await fetch('http://localhost:9001/api/drift/place-order', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
symbol: 'SOL-PERP',
orderType: 'LIMIT',
direction: isLong ? 'SHORT' : 'LONG', // Opposite direction to close position
size: positionSize,
price: takeProfitPrice,
reduceOnly: true
})
});
const tpResult = await tpResponse.json();
console.log('💰 Take Profit result:', tpResult.success ? '✅ Placed' : '❌ Failed', tpResult);
// Verify orders were placed
console.log('📋 Checking placed orders...');
const ordersResponse = await fetch('http://localhost:9001/api/drift/orders');
const ordersData = await ordersResponse.json();
const reduceOnlyOrders = ordersData.orders?.filter(order => order.reduceOnly) || [];
console.log(`📊 Active reduce-only orders: ${reduceOnlyOrders.length}`);
reduceOnlyOrders.forEach(order => {
console.log(` - ${order.orderType} ${order.direction} at ${order.triggerPrice || order.price}`);
});
console.log('🎯 Scalping risk management setup complete!');
} catch (error) {
console.error('❌ Error setting up scalping SL/TP:', error.message);
}
}
// Run the function
placeScalpingSLTP();

Binary file not shown.