Fix complete trading system: SL/TP working, live trading operational
- Fixed network connectivity and live trading mode - Updated Drift SDK integration with proper API methods - Fixed BN type conversions and minimum order size - Fixed stop loss & take profit conditional orders - Complete risk management system now functional
This commit is contained in:
0
lib/safe-parallel-automation.ts
Normal file
0
lib/safe-parallel-automation.ts
Normal file
@@ -9,7 +9,9 @@ class SimpleAutomation {
|
||||
totalTrades: 0,
|
||||
startTime: null,
|
||||
lastActivity: null,
|
||||
status: 'Stopped'
|
||||
status: 'Stopped',
|
||||
networkErrors: 0,
|
||||
consecutiveErrors: 0
|
||||
};
|
||||
}
|
||||
|
||||
@@ -30,6 +32,15 @@ class SimpleAutomation {
|
||||
this.stats.status = 'Running';
|
||||
this.stats.totalCycles = 0;
|
||||
|
||||
// Auto-enable trading when in LIVE mode
|
||||
if (config.mode === 'LIVE') {
|
||||
this.config.enableTrading = true;
|
||||
console.log('🔥 LIVE TRADING ENABLED: Real trades will be executed');
|
||||
} else {
|
||||
this.config.enableTrading = false;
|
||||
console.log('📊 SIMULATION MODE: Trades will be simulated only');
|
||||
}
|
||||
|
||||
// Detect strategy
|
||||
const timeframes = config.selectedTimeframes;
|
||||
let strategy = 'General';
|
||||
@@ -112,8 +123,9 @@ class SimpleAutomation {
|
||||
console.log(`🚀 This will capture ${this.config.selectedTimeframes.length * 2} screenshots in parallel (${this.config.selectedTimeframes.length} timeframes × 2 layouts)`);
|
||||
|
||||
try {
|
||||
// Use batch analysis API for true parallelism - captures all timeframes simultaneously
|
||||
const response = await fetch('http://localhost:3000/api/batch-analysis', {
|
||||
// Use internal container port for server-side API calls
|
||||
const baseUrl = process.env.INTERNAL_API_URL || 'http://localhost:3000';
|
||||
const response = await fetch(`${baseUrl}/api/batch-analysis`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
@@ -132,6 +144,9 @@ class SimpleAutomation {
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success && result.analysis) {
|
||||
// Reset consecutive error counter on success
|
||||
this.stats.consecutiveErrors = 0;
|
||||
|
||||
console.log(`✅ PARALLEL ANALYSIS COMPLETE: ${result.totalScreenshots} screenshots captured`);
|
||||
console.log(`📊 COMBINED Recommendation: ${result.analysis.recommendation}`);
|
||||
console.log(`🎯 COMBINED Confidence: ${result.analysis.confidence}%`);
|
||||
@@ -151,7 +166,17 @@ class SimpleAutomation {
|
||||
return this.performSequentialAnalysis();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`❌ PARALLEL ANALYSIS FAILED:`, error);
|
||||
// Track network errors
|
||||
this.stats.networkErrors++;
|
||||
this.stats.consecutiveErrors++;
|
||||
|
||||
console.error(`❌ PARALLEL ANALYSIS FAILED (Network Error #${this.stats.networkErrors}):`, error.message);
|
||||
|
||||
// If too many consecutive errors, slow down
|
||||
if (this.stats.consecutiveErrors >= 3) {
|
||||
console.warn(`⚠️ HIGH NETWORK ERROR COUNT: ${this.stats.consecutiveErrors} consecutive failures. System will continue but may slow down.`);
|
||||
}
|
||||
|
||||
console.log(`🔄 FALLBACK: Using sequential analysis...`);
|
||||
return this.performSequentialAnalysis();
|
||||
}
|
||||
@@ -169,7 +194,8 @@ class SimpleAutomation {
|
||||
console.log(`📊 ANALYZING: ${timeframe} timeframe...`);
|
||||
|
||||
// Use the enhanced screenshot API for each timeframe
|
||||
const response = await fetch('http://localhost:3000/api/enhanced-screenshot', {
|
||||
const baseUrl = process.env.INTERNAL_API_URL || 'http://localhost:3000';
|
||||
const response = await fetch(`${baseUrl}/api/enhanced-screenshot`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
@@ -259,10 +285,8 @@ class SimpleAutomation {
|
||||
}
|
||||
|
||||
shouldExecuteTrade(analysis) {
|
||||
if (this.config.mode !== 'LIVE') {
|
||||
console.log('📊 SIMULATION MODE: Would execute trade');
|
||||
return false;
|
||||
}
|
||||
// Always allow trade execution - the useRealDEX flag determines if it's real or simulated
|
||||
console.log(`<EFBFBD> TRADE MODE: ${this.config.mode || 'SIMULATION'} - Trading ${this.config.enableTrading ? 'ENABLED' : 'DISABLED'}`);
|
||||
|
||||
const recommendation = analysis.recommendation?.toLowerCase() || '';
|
||||
const confidence = analysis.confidence || 0;
|
||||
@@ -284,6 +308,7 @@ class SimpleAutomation {
|
||||
async executeTrade(analysis) {
|
||||
try {
|
||||
console.log('💰 EXECUTING TRADE...');
|
||||
console.log('📊 Analysis data:', JSON.stringify(analysis, null, 2));
|
||||
|
||||
// Map analysis recommendation to trading side
|
||||
const recommendation = analysis.recommendation?.toLowerCase() || '';
|
||||
@@ -297,20 +322,63 @@ class SimpleAutomation {
|
||||
console.log('❌ TRADE SKIP: Invalid recommendation - ' + recommendation);
|
||||
return { success: false, error: 'Invalid recommendation: ' + recommendation };
|
||||
}
|
||||
|
||||
// Extract stop loss and take profit from analysis
|
||||
let stopLoss = null;
|
||||
let takeProfit = null;
|
||||
|
||||
// Use the trading API with proper fields
|
||||
// Try to extract from the structured analysis format
|
||||
if (analysis.stopLoss && typeof analysis.stopLoss === 'object') {
|
||||
stopLoss = analysis.stopLoss.price;
|
||||
} else if (analysis.stopLoss && typeof analysis.stopLoss === 'number') {
|
||||
stopLoss = analysis.stopLoss;
|
||||
}
|
||||
|
||||
// Extract take profit - prefer tp1 if available
|
||||
if (analysis.takeProfits && typeof analysis.takeProfits === 'object') {
|
||||
if (analysis.takeProfits.tp1 && analysis.takeProfits.tp1.price) {
|
||||
takeProfit = analysis.takeProfits.tp1.price;
|
||||
} else if (analysis.takeProfits.tp2 && analysis.takeProfits.tp2.price) {
|
||||
takeProfit = analysis.takeProfits.tp2.price;
|
||||
}
|
||||
} else if (analysis.takeProfit && typeof analysis.takeProfit === 'number') {
|
||||
takeProfit = analysis.takeProfit;
|
||||
}
|
||||
|
||||
// Fallback: try to extract from nested levels object
|
||||
if (!stopLoss && analysis.levels) {
|
||||
stopLoss = analysis.levels.stopLoss || analysis.levels.stop;
|
||||
}
|
||||
if (!takeProfit && analysis.levels) {
|
||||
takeProfit = analysis.levels.takeProfit || analysis.levels.target;
|
||||
}
|
||||
|
||||
// Parse numeric values if they're strings
|
||||
if (stopLoss && typeof stopLoss === 'string') {
|
||||
stopLoss = parseFloat(stopLoss.replace(/[^0-9.]/g, ''));
|
||||
}
|
||||
if (takeProfit && typeof takeProfit === 'string') {
|
||||
takeProfit = parseFloat(takeProfit.replace(/[^0-9.]/g, ''));
|
||||
}
|
||||
|
||||
console.log(`🎯 Trade levels - SL: ${stopLoss}, TP: ${takeProfit}`);
|
||||
|
||||
// Use the trading API with proper fields for Drift
|
||||
const tradePayload = {
|
||||
symbol: this.config.symbol,
|
||||
side: side,
|
||||
amount: this.config.tradingAmount || 10, // Default to $10 if not set
|
||||
type: 'market',
|
||||
tradingMode: 'SPOT',
|
||||
amount: this.config.tradingAmount || 49, // Use available balance
|
||||
leverage: 1, // Default leverage
|
||||
stopLoss: stopLoss,
|
||||
takeProfit: takeProfit,
|
||||
useRealDEX: this.config.enableTrading === true, // Use real DEX when live trading enabled
|
||||
analysis: analysis // Include analysis for reference
|
||||
};
|
||||
|
||||
console.log('📊 TRADE PAYLOAD:', tradePayload);
|
||||
|
||||
const response = await fetch('http://localhost:3000/api/trading', {
|
||||
const baseUrl = process.env.INTERNAL_API_URL || 'http://localhost:3000';
|
||||
const response = await fetch(`${baseUrl}/api/trading/execute-drift`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(tradePayload)
|
||||
@@ -337,6 +405,8 @@ class SimpleAutomation {
|
||||
return {
|
||||
isActive: this.isRunning,
|
||||
mode: this.config?.mode || 'SIMULATION',
|
||||
enableTrading: this.config?.enableTrading || false,
|
||||
tradingStatus: this.config?.enableTrading ? 'REAL TRADES' : 'SIMULATED ONLY',
|
||||
symbol: this.config?.symbol || 'SOLUSD',
|
||||
timeframes: this.config?.selectedTimeframes || [],
|
||||
automationType: 'SIMPLE',
|
||||
|
||||
Reference in New Issue
Block a user