diff --git a/app/api/automation/learning-status/route.js b/app/api/automation/learning-status/route.js new file mode 100644 index 0000000..c5358ac --- /dev/null +++ b/app/api/automation/learning-status/route.js @@ -0,0 +1,71 @@ +// API route to get detailed learning system status and visibility +import { NextResponse } from 'next/server'; + +// Import the automation instance to get learning status +async function getAutomationInstance() { + try { + // Import the singleton automation instance + const { getAutomationInstance } = await import('../../../lib/automation-singleton.js'); + return getAutomationInstance(); + } catch (error) { + console.error('โŒ Could not get automation instance:', error); + return null; + } +} + +export async function GET() { + try { + const automation = await getAutomationInstance(); + + if (!automation) { + return NextResponse.json({ + success: false, + message: 'Automation instance not available' + }, { status: 503 }); + } + + // Check if automation has learning capabilities + if (typeof automation.getLearningStatus !== 'function') { + return NextResponse.json({ + success: true, + learningSystem: { + enabled: false, + message: 'Basic automation running - learning system not integrated', + recommendation: 'Restart automation to enable AI learning system' + } + }); + } + + // Get detailed learning status + const learningStatus = await automation.getLearningStatus(); + const automationStatus = automation.getStatus(); + + return NextResponse.json({ + success: true, + learningSystem: { + ...learningStatus, + automationRunning: automationStatus.isRunning, + totalCycles: automationStatus.stats.totalCycles, + totalTrades: automationStatus.stats.totalTrades + }, + visibility: { + decisionTrackingActive: learningStatus.activeDecisions > 0, + learningDatabaseConnected: learningStatus.enabled, + aiEnhancementsActive: learningStatus.learningActive, + lastUpdateTime: new Date().toISOString() + } + }); + + } catch (error) { + console.error('โŒ Error getting learning system status:', error); + + return NextResponse.json({ + success: false, + error: error.message, + learningSystem: { + enabled: false, + error: 'Failed to retrieve learning status' + } + }, { status: 500 }); + } +} diff --git a/app/api/automation/start/route.js b/app/api/automation/start/route.js index 6083b16..611829d 100644 --- a/app/api/automation/start/route.js +++ b/app/api/automation/start/route.js @@ -1,26 +1,52 @@ import { NextResponse } from 'next/server'; -import { simpleAutomation } from '@/lib/simple-automation'; + +// Import singleton automation manager +async function getAutomationInstance() { + try { + const { getAutomationInstance } = await import('../../../lib/automation-singleton.js'); + return await getAutomationInstance(); + } catch (error) { + console.error('โŒ Could not get automation instance:', error); + throw error; + } +} export async function POST(request) { try { const config = await request.json(); console.log('๐Ÿš€ AUTOMATION START: Received config:', JSON.stringify(config, null, 2)); + console.log('๐Ÿง  LEARNING SYSTEM: Attempting to start with AI learning integration'); - const result = await simpleAutomation.start(config); + const automation = await getAutomationInstance(); + const result = await automation.start(config); + + // Add learning system status to response + const response = { + ...result, + learningSystem: { + integrated: typeof automation.getLearningStatus === 'function', + type: automation.constructor.name + } + }; if (result.success) { - return NextResponse.json(result); + console.log('โœ… AUTOMATION STARTED:', response.learningSystem.integrated ? 'With AI Learning' : 'Basic Mode'); + return NextResponse.json(response); } else { - return NextResponse.json(result, { status: 400 }); + return NextResponse.json(response, { status: 400 }); } } catch (error) { - console.error('Start automation error:', error); + console.error('โŒ Start automation error:', error); return NextResponse.json({ success: false, error: 'Internal server error', - message: error.message + message: error.message, + learningSystem: { + integrated: false, + error: 'Failed to initialize' + } }, { status: 500 }); } } diff --git a/app/api/automation/status/route.js b/app/api/automation/status/route.js index 9ed9034..fa62b68 100644 --- a/app/api/automation/status/route.js +++ b/app/api/automation/status/route.js @@ -1,15 +1,56 @@ import { NextResponse } from 'next/server'; -import { simpleAutomation } from '@/lib/simple-automation'; + +// Import singleton automation manager +async function getAutomationInstance() { + try { + const { getAutomationInstance } = await import('../../../lib/automation-singleton.js'); + return await getAutomationInstance(); + } catch (error) { + console.error('โŒ Could not get automation instance:', error); + return null; + } +} export async function GET() { try { - const status = simpleAutomation.getStatus(); + const automation = await getAutomationInstance(); + + if (!automation) { + return NextResponse.json({ + error: 'No automation instance available', + isRunning: false, + learningSystem: { enabled: false } + }, { status: 503 }); + } + + const status = automation.getStatus(); + + // Add learning system status if available + if (typeof automation.getLearningStatus === 'function') { + try { + const learningStatus = await automation.getLearningStatus(); + status.learningSystem = learningStatus; + } catch (learningError) { + status.learningSystem = { + enabled: false, + error: learningError.message + }; + } + } else { + status.learningSystem = { + enabled: false, + message: 'Basic automation - learning not integrated' + }; + } + return NextResponse.json(status); } catch (error) { - console.error('Status error:', error); + console.error('โŒ Status error:', error); return NextResponse.json({ error: 'Failed to get status', - message: error.message + message: error.message, + isRunning: false, + learningSystem: { enabled: false, error: 'Status check failed' } }, { status: 500 }); } } diff --git a/app/api/automation/stop/route.js b/app/api/automation/stop/route.js index 5e900bd..4288055 100644 --- a/app/api/automation/stop/route.js +++ b/app/api/automation/stop/route.js @@ -1,10 +1,30 @@ -import { simpleAutomation } from '@/lib/simple-automation'; +// Import singleton automation manager +async function getAutomationInstance() { + try { + const { getAutomationInstance } = await import('../../../lib/automation-singleton.js'); + return await getAutomationInstance(); + } catch (error) { + console.error('โŒ Could not get automation instance:', error); + return null; + } +} export async function POST() { try { console.log('๐Ÿ›‘ AUTOMATION STOP: Request received'); - const result = await simpleAutomation.stop(); + const automation = await getAutomationInstance(); + let result = { success: false, message: 'No automation instance available' }; + + if (automation) { + result = await automation.stop(); + + // Check if learning system was active + if (typeof automation.getLearningStatus === 'function') { + const learningStatus = await automation.getLearningStatus(); + console.log('๐Ÿง  LEARNING SYSTEM: Stopped with', learningStatus.activeDecisions, 'active decisions'); + } + } // Additional cleanup try { @@ -17,7 +37,7 @@ export async function POST() { return Response.json(result); } catch (error) { - console.error('Stop automation error:', error); + console.error('โŒ Stop automation error:', error); return Response.json({ success: false, message: error.message diff --git a/app/automation-v2/page.js b/app/automation-v2/page.js index f6f4660..7e4bbbf 100644 --- a/app/automation-v2/page.js +++ b/app/automation-v2/page.js @@ -1,5 +1,6 @@ 'use client' import React, { useState, useEffect } from 'react' +import EnhancedAILearningPanel from '../../components/EnhancedAILearningPanel' // Available timeframes for automation (matching analysis page format) const timeframes = [ @@ -27,21 +28,18 @@ export default function AutomationPageV2() { const [positions, setPositions] = useState([]) const [loading, setLoading] = useState(false) const [monitorData, setMonitorData] = useState(null) - const [aiLearningData, setAiLearningData] = useState(null) useEffect(() => { fetchStatus() fetchBalance() fetchPositions() fetchMonitorData() - fetchAiLearningData() const interval = setInterval(() => { fetchStatus() fetchBalance() fetchPositions() fetchMonitorData() - fetchAiLearningData() }, 300000) // 5 minutes instead of 30 seconds return () => clearInterval(interval) }, []) @@ -107,18 +105,6 @@ export default function AutomationPageV2() { } } - const fetchAiLearningData = async () => { - try { - const response = await fetch('/api/ai-learning-status') - const data = await response.json() - if (data.success) { - setAiLearningData(data.data) - } - } catch (error) { - console.error('Failed to fetch AI learning data:', error) - } - } - const handleStart = async () => { console.log('๐Ÿš€ Starting automation...') setLoading(true) @@ -149,6 +135,9 @@ export default function AutomationPageV2() { if (data.success) { console.log('โœ… Automation started successfully') + if (data.learningSystem?.integrated) { + console.log('๐Ÿง  AI Learning System: Activated') + } fetchStatus() } else { console.error('Failed to start automation:', data.error) @@ -941,112 +930,8 @@ export default function AutomationPageV2() { - {/* Enhanced AI Learning Status Panel */} - {aiLearningData && ( -
-
-
- ๐Ÿง  -
-
-

AI Learning Status

-

{aiLearningData.phase} โ€ข Real-time learning progress

-
-
- - {/* Main Stats Grid */} -
-
-
{aiLearningData.avgAccuracy}%
-
Avg Accuracy
-
- -
-
{aiLearningData.winRate}%
-
Win Rate
-
- -
-
{aiLearningData.confidenceLevel}%
-
Confidence Level
-
- -
-
{aiLearningData.daysActive}
-
Days Active
-
-
- - {/* Trading Performance Section */} - {aiLearningData.statistics && aiLearningData.statistics.totalTrades > 0 && ( -
-

- ๐Ÿ“ŠTrading Performance -

- -
-
-
{aiLearningData.statistics.wins}
-
Wins
-
+${aiLearningData.statistics.winsPnl.toFixed(2)}
-
- -
-
{aiLearningData.statistics.losses}
-
Losses
-
${aiLearningData.statistics.lossesPnl.toFixed(2)}
-
- -
-
= 0 ? 'text-green-400' : 'text-red-400'}`}> - ${aiLearningData.statistics.totalPnl >= 0 ? '+' : ''}${aiLearningData.statistics.totalPnl.toFixed(2)} -
-
Total P&L
-
-
- - {/* Advanced Metrics */} -
-
-
Avg Win
-
${aiLearningData.statistics.avgWin.toFixed(2)}
-
- -
-
Avg Loss
-
${aiLearningData.statistics.avgLoss.toFixed(2)}
-
-
-
- )} - - {/* Learning Progress */} -
-
- Learning Progress - {aiLearningData.totalAnalyses} analyses -
-
-
-
-
- - {/* Next Milestone */} -
-
Next Milestone
-
{aiLearningData.nextMilestone}
-
- - {/* AI Recommendation */} -
-
AI Recommendation
-
{aiLearningData.recommendation}
-
-
- )} + {/* Enhanced AI Learning System Panel */} + {/* Enhanced AI Trading Analysis Panel */}
diff --git a/components/EnhancedAILearningPanel.tsx b/components/EnhancedAILearningPanel.tsx new file mode 100644 index 0000000..108ff75 --- /dev/null +++ b/components/EnhancedAILearningPanel.tsx @@ -0,0 +1,264 @@ +import React, { useState, useEffect } from 'react'; + +interface LearningData { + learningSystem: { + enabled: boolean; + learningActive?: boolean; + activeDecisions?: number; + message?: string; + recommendation?: string; + report?: { + summary?: { + totalDecisions?: number; + successRate?: number; + systemConfidence?: number; + }; + insights?: { + thresholds?: any; + confidenceLevel?: number; + }; + recommendations?: string[]; + }; + }; + visibility?: { + decisionTrackingActive?: boolean; + learningDatabaseConnected?: boolean; + aiEnhancementsActive?: boolean; + lastUpdateTime?: string; + }; + automationStatus?: any; +} + +const EnhancedAILearningPanel = () => { + const [learningData, setLearningData] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + const fetchLearningStatus = async () => { + try { + setLoading(true); + + // Get both learning status and automation status + const [learningResponse, statusResponse] = await Promise.all([ + fetch('/api/automation/learning-status'), + fetch('/api/automation/status') + ]); + + const learningData = await learningResponse.json(); + const statusData = await statusResponse.json(); + + setLearningData({ + ...learningData, + automationStatus: statusData + }); + + setError(null); + } catch (err) { + console.error('Error fetching learning status:', err); + setError(err instanceof Error ? err.message : 'Unknown error'); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + fetchLearningStatus(); + + // Refresh every 30 seconds + const interval = setInterval(fetchLearningStatus, 30000); + return () => clearInterval(interval); + }, []); + + if (loading) { + return ( +
+
+
+

+ ๐Ÿง  AI Learning System +

+
+
Loading learning status...
+
+ ); + } + + if (error) { + return ( +
+
+
+

+ ๐Ÿง  AI Learning System +

+
+
Error: {error}
+ +
+ ); + } + + if (!learningData) { + return null; + } + + const { learningSystem, visibility } = learningData; + + const renderLearningStatus = () => { + if (!learningSystem.enabled) { + return ( +
+
+
+ Learning System Not Active +
+ +
+
+ {learningSystem.message || 'The AI learning system is not currently integrated with the automation.'} +
+ {learningSystem.recommendation && ( +
+ ๐Ÿ’ก {learningSystem.recommendation} +
+ )} +
+ +
+ โ€ข Decision recording: Not active
+ โ€ข Learning database: Not connected
+ โ€ข AI enhancements: Not applied +
+
+ ); + } + + return ( +
+
+
+ AI Learning Active +
+ + {learningSystem.report && ( +
+
+
Total Decisions
+
+ {learningSystem.report.summary?.totalDecisions || 0} +
+
+ +
+
Success Rate
+
+ {learningSystem.report.summary?.successRate || 0}% +
+
+ +
+
Confidence
+
+ {learningSystem.report.summary?.systemConfidence || 0}% +
+
+
+ )} + +
+
๐Ÿ” Learning Visibility
+
+
+
+ + Decision Tracking + +
+
+
+ + Database Connected + +
+
+
+ + AI Enhancements + +
+
+
0 ? 'bg-blue-500' : 'bg-gray-500'}`}>
+ 0 ? 'text-blue-400' : 'text-gray-400'}> + Active Decisions ({learningSystem.activeDecisions || 0}) + +
+
+
+ + {learningSystem.report?.insights && ( +
+
๐ŸŽฏ Learning Insights
+
+ {learningSystem.report.insights.thresholds && ( +
Current Thresholds: {JSON.stringify(learningSystem.report.insights.thresholds)}
+ )} + {learningSystem.report.insights.confidenceLevel && ( +
Confidence Level: {learningSystem.report.insights.confidenceLevel}%
+ )} +
+
+ )} + + {learningSystem.report?.recommendations && learningSystem.report.recommendations.length > 0 && ( +
+
๐Ÿ’ก AI Recommendations
+
+ {learningSystem.report.recommendations.map((rec: string, index: number) => ( +
+ โ€ข {rec} +
+ ))} +
+
+ )} +
+ ); + }; + + return ( +
+
+
+
+

+ ๐Ÿง  AI Learning System +

+
+ + +
+ + {renderLearningStatus()} + + {visibility?.lastUpdateTime && ( +
+
+ Last updated: {new Date(visibility.lastUpdateTime).toLocaleTimeString()} +
+
+ )} +
+ ); +}; + +export default EnhancedAILearningPanel; diff --git a/lib/automation-singleton.js b/lib/automation-singleton.js new file mode 100644 index 0000000..1c6f605 --- /dev/null +++ b/lib/automation-singleton.js @@ -0,0 +1,46 @@ +// Singleton automation instance manager with learning integration +let automationInstance = null; + +async function createAutomationInstance() { + try { + // Try to import the learning-enhanced automation first + const AutomationWithLearning = require('./automation-with-learning-v2.js'); + console.log('โœ… Creating automation instance with AI learning system'); + return new AutomationWithLearning(); + } catch (error) { + console.warn('โš ๏ธ Learning-enhanced automation not available, falling back to basic automation'); + console.warn('Error:', error.message); + + // Fallback to basic automation + try { + const { simpleAutomation } = await import('./simple-automation.js'); + console.log('โœ… Creating basic automation instance'); + return simpleAutomation; + } catch (fallbackError) { + console.error('โŒ Could not create any automation instance:', fallbackError); + throw new Error('No automation system available'); + } + } +} + +function getAutomationInstance() { + if (!automationInstance) { + automationInstance = createAutomationInstance(); + } + return automationInstance; +} + +function resetAutomationInstance() { + if (automationInstance) { + console.log('๐Ÿ”„ Resetting automation instance'); + if (typeof automationInstance.stop === 'function') { + automationInstance.stop(); + } + } + automationInstance = null; +} + +module.exports = { + getAutomationInstance, + resetAutomationInstance +}; diff --git a/lib/automation-with-learning-v2.js b/lib/automation-with-learning-v2.js new file mode 100644 index 0000000..a20e622 --- /dev/null +++ b/lib/automation-with-learning-v2.js @@ -0,0 +1,448 @@ +// Enhanced automation with integrated AI learning system + +// Dynamic import for ES6 modules +async function importSimpleAutomation() { + try { + const module = await import('./simple-automation.js'); + // Extract the class from the singleton instance + return module.simpleAutomation.constructor; + } catch (error) { + console.warn('โš ๏ธ Could not import SimpleAutomation, using fallback'); + // Fallback - create a basic class structure + return class BasicAutomation { + constructor() { + this.isRunning = false; + this.config = null; + this.stats = { totalCycles: 0, totalTrades: 0 }; + } + + async start(config) { + return { success: false, message: 'Base automation not available' }; + } + + async stop() { + return { success: true, message: 'Stopped' }; + } + + getStatus() { + return { isRunning: this.isRunning, stats: this.stats }; + } + }; + } +} + +// Import learning system +async function importSimplifiedStopLossLearner() { + try { + const { SimplifiedStopLossLearner } = await import('./simplified-stop-loss-learner-fixed.js'); + return SimplifiedStopLossLearner; + } catch (error) { + console.warn('โš ๏ธ SimplifiedStopLossLearner not available, continuing without learning'); + return null; + } +} + +class AutomationWithLearning { + constructor() { + this.baseAutomation = null; + this.learner = null; + this.activeTrades = new Map(); // Track active trades for outcome assessment + this.learningDecisions = new Map(); // Track decisions for learning + this.learningEnabled = false; + this.isRunning = false; + this.config = null; + this.stats = { totalCycles: 0, totalTrades: 0 }; + } + + async initializeBaseAutomation() { + if (!this.baseAutomation) { + const SimpleAutomationClass = await importSimpleAutomation(); + this.baseAutomation = new SimpleAutomationClass(); + } + return this.baseAutomation; + } + + async initializeLearningSystem() { + try { + const SimplifiedStopLossLearnerClass = await importSimplifiedStopLossLearner(); + if (SimplifiedStopLossLearnerClass) { + this.learner = new SimplifiedStopLossLearnerClass(); + console.log('โœ… AI Learning System initialized successfully'); + + // Generate initial learning report + if (typeof this.learner.generateLearningReport === 'function') { + const report = await this.learner.generateLearningReport(); + console.log('๐Ÿ“Š Current Learning Status:', report.summary); + } + + return true; + } + } catch (error) { + console.warn('โš ๏ธ Could not initialize learning system:', error.message); + } + return false; + } + + async start(config) { + try { + // Initialize base automation + await this.initializeBaseAutomation(); + + // Initialize learning system + await this.initializeLearningSystem(); + + // Use base automation if available, otherwise implement basic functionality + let result; + if (this.baseAutomation && typeof this.baseAutomation.start === 'function') { + result = await this.baseAutomation.start(config); + } else { + // Basic start functionality + this.isRunning = true; + this.config = config; + result = { success: true, message: 'Basic automation started' }; + } + + if (result.success && this.learner) { + console.log('๐Ÿง  AI LEARNING SYSTEM: Activated and ready to learn from trades'); + console.log('๐Ÿ“Š The system will now record decisions and improve over time'); + this.learningEnabled = true; + } + + return result; + } catch (error) { + console.error('โŒ Error starting automation with learning:', error); + return { success: false, message: error.message }; + } + } + + async stop() { + try { + let result; + if (this.baseAutomation && typeof this.baseAutomation.stop === 'function') { + result = await this.baseAutomation.stop(); + } else { + this.isRunning = false; + result = { success: true, message: 'Basic automation stopped' }; + } + + this.learningEnabled = false; + return result; + } catch (error) { + console.error('โŒ Error stopping automation:', error); + return { success: false, message: error.message }; + } + } + + getStatus() { + let baseStatus; + if (this.baseAutomation && typeof this.baseAutomation.getStatus === 'function') { + baseStatus = this.baseAutomation.getStatus(); + } else { + baseStatus = { + isRunning: this.isRunning, + config: this.config, + stats: this.stats + }; + } + + return { + ...baseStatus, + learningSystem: { + enabled: this.learningEnabled, + hasLearner: !!this.learner, + activeDecisions: this.activeTrades.size, + trackedTrades: Array.from(this.activeTrades.keys()) + } + }; + } + + async getLearningStatus() { + if (!this.learningEnabled || !this.learner) { + return { + enabled: false, + message: 'Learning system not available' + }; + } + + try { + let report = null; + + // Try to get comprehensive learning report + if (typeof this.learner.generateLearningReport === 'function') { + report = await this.learner.generateLearningReport(); + } else if (typeof this.learner.getLearningStatus === 'function') { + report = await this.learner.getLearningStatus(); + } + + return { + enabled: true, + learningActive: this.learningEnabled, + activeDecisions: this.activeTrades.size, + report: report || { summary: { message: 'Learning system active but no data available yet' } } + }; + + } catch (error) { + console.error('โŒ Error getting learning status:', error); + return { + enabled: true, + learningActive: this.learningEnabled, + error: error.message + }; + } + } + + async executeTrade(analysis) { + try { + console.log('๐Ÿง  LEARNING-ENHANCED TRADE EXECUTION'); + + // Record decision before execution for learning + let decisionId = null; + if (this.learningEnabled && this.learner) { + decisionId = await this.recordTradingDecision(analysis); + } + + // Enhance analysis with learning-based adjustments + const enhancedAnalysis = await this.enhanceAnalysisWithLearning(analysis); + + // Execute the trade using enhanced analysis + let tradeResult; + if (this.baseAutomation && typeof this.baseAutomation.executeTrade === 'function') { + tradeResult = await this.baseAutomation.executeTrade(enhancedAnalysis); + } else { + // Basic trade execution simulation + tradeResult = { + success: true, + message: 'Trade simulated (learning system active)', + simulation: true + }; + } + + // Track trade for outcome assessment + if (tradeResult.success && decisionId) { + this.trackTradeForLearning(decisionId, tradeResult, enhancedAnalysis); + } + + return tradeResult; + + } catch (error) { + console.error('โŒ Error in learning-enhanced trade execution:', error); + return { success: false, error: error.message }; + } + } + + async recordTradingDecision(analysis) { + if (!this.learner || typeof this.learner.recordDecision !== 'function') { + return null; + } + + try { + const decisionData = { + symbol: this.config?.symbol || 'SOLUSD', + recommendation: analysis.recommendation, + confidence: analysis.confidence, + stopLoss: this.extractStopLoss(analysis), + takeProfit: this.extractTakeProfit(analysis), + entryPrice: analysis.entry?.price || analysis.currentPrice, + marketConditions: { + timeframe: this.config?.selectedTimeframes || ['1h'], + analysis: analysis.reasoning || analysis.summary + }, + timestamp: new Date().toISOString() + }; + + const decisionId = await this.learner.recordDecision(decisionData); + console.log(`๐Ÿ“ LEARNING: Recorded decision ${decisionId}`); + return decisionId; + + } catch (error) { + console.error('โŒ Error recording decision:', error); + return null; + } + } + + async enhanceAnalysisWithLearning(analysis) { + if (!this.learningEnabled || !this.learner) { + console.log('๐Ÿ“Š Using original analysis (learning not available)'); + return analysis; + } + + try { + // Get learning-based recommendations if available + if (typeof this.learner.getSmartRecommendation === 'function') { + const currentPrice = analysis.entry?.price || analysis.currentPrice || 178; + const originalStopLoss = this.extractStopLoss(analysis); + + if (originalStopLoss) { + const distanceFromSL = Math.abs(currentPrice - originalStopLoss); + + const learningRecommendation = await this.learner.getSmartRecommendation({ + symbol: this.config?.symbol || 'SOLUSD', + distanceFromSL, + marketConditions: { + recommendation: analysis.recommendation, + confidence: analysis.confidence, + timeframe: this.config?.selectedTimeframes || ['1h'] + } + }); + + if (learningRecommendation && learningRecommendation.confidence > 70) { + console.log(`๐Ÿง  LEARNING ENHANCEMENT: ${learningRecommendation.action} (${learningRecommendation.confidence}% confidence)`); + console.log(`๐Ÿ’ก Reasoning: ${learningRecommendation.reasoning}`); + + // Apply learning-based adjustments + if (learningRecommendation.action === 'TIGHTEN_STOP_LOSS') { + analysis = this.adjustStopLoss(analysis, learningRecommendation.suggestedValue); + } else if (learningRecommendation.action === 'ADJUST_TAKE_PROFIT') { + analysis = this.adjustTakeProfit(analysis, learningRecommendation.suggestedValue); + } + + // Add learning metadata to analysis + analysis.learningEnhanced = true; + analysis.learningConfidence = learningRecommendation.confidence; + analysis.learningReasoning = learningRecommendation.reasoning; + } + } + } + + return analysis; + + } catch (error) { + console.error('โŒ Error enhancing analysis with learning:', error); + return analysis; // Return original analysis if learning fails + } + } + + adjustStopLoss(analysis, newStopLoss) { + if (newStopLoss) { + if (analysis.stopLoss && typeof analysis.stopLoss === 'object') { + analysis.stopLoss.price = newStopLoss; + } else { + analysis.stopLoss = newStopLoss; + } + console.log(`๐Ÿ”ง LEARNING ADJUSTMENT: Stop-loss adjusted to $${newStopLoss}`); + } + return analysis; + } + + adjustTakeProfit(analysis, newTakeProfit) { + if (newTakeProfit) { + if (analysis.takeProfits && analysis.takeProfits.tp1) { + analysis.takeProfits.tp1.price = newTakeProfit; + } else if (analysis.takeProfit) { + analysis.takeProfit = newTakeProfit; + } else { + analysis.takeProfit = newTakeProfit; + } + console.log(`๐ŸŽฏ LEARNING ADJUSTMENT: Take-profit adjusted to $${newTakeProfit}`); + } + return analysis; + } + + trackTradeForLearning(decisionId, tradeResult, analysis) { + if (!decisionId) return; + + this.activeTrades.set(decisionId, { + tradeResult, + analysis, + timestamp: new Date().toISOString(), + symbol: this.config?.symbol || 'SOLUSD' + }); + + console.log(`๐Ÿ“Š LEARNING: Tracking trade ${decisionId} for outcome assessment`); + + // Set up outcome assessment check (will check position status later) + setTimeout(() => { + this.assessTradeOutcome(decisionId); + }, 300000); // Check after 5 minutes + } + + async assessTradeOutcome(decisionId) { + if (!this.learningEnabled || !this.learner || !this.activeTrades.has(decisionId)) { + return; + } + + try { + const tradeInfo = this.activeTrades.get(decisionId); + + // Check current position status via API + const baseUrl = process.env.INTERNAL_API_URL || 'http://localhost:3000'; + const response = await fetch(`${baseUrl}/api/automation/position-monitor`); + const positionData = await response.json(); + + let outcome = null; + let actualPnL = 0; + + if (positionData.success) { + // Determine outcome based on position status + if (!positionData.monitor.hasPosition) { + // Position closed - check if it was profitable + outcome = 'POSITION_CLOSED'; + + // Try to get actual P&L from position history + try { + const historyResponse = await fetch(`${baseUrl}/api/drift/position-history`); + const historyData = await historyResponse.json(); + + if (historyData.success && historyData.trades.length > 0) { + // Find the most recent trade + const recentTrade = historyData.trades[0]; + actualPnL = recentTrade.pnl; + outcome = actualPnL > 0 ? 'WIN' : 'LOSS'; + } + } catch (historyError) { + console.warn('โš ๏ธ Could not fetch trade history for outcome assessment'); + } + } else { + // Position still open - check if it's profitable + const currentPnL = positionData.monitor.position?.unrealizedPnl || 0; + actualPnL = currentPnL; + outcome = currentPnL > 0 ? 'CURRENTLY_PROFITABLE' : 'CURRENTLY_LOSING'; + } + } + + // Record outcome for learning + if (outcome && typeof this.learner.assessDecisionOutcome === 'function') { + const outcomeData = { + decisionId, + outcome, + actualPnL, + timestamp: new Date().toISOString(), + positionInfo: positionData.monitor + }; + + await this.learner.assessDecisionOutcome(outcomeData); + console.log(`๐Ÿง  LEARNING: Assessed outcome for decision ${decisionId}: ${outcome} (P&L: $${actualPnL.toFixed(2)})`); + + // Clean up tracked trade + this.activeTrades.delete(decisionId); + } + + } catch (error) { + console.error('โŒ Error assessing trade outcome:', error); + } + } + + extractStopLoss(analysis) { + if (analysis.stopLoss && typeof analysis.stopLoss === 'object') { + return analysis.stopLoss.price; + } else if (analysis.stopLoss && typeof analysis.stopLoss === 'number') { + return analysis.stopLoss; + } else if (analysis.levels?.stopLoss) { + return analysis.levels.stopLoss; + } + return null; + } + + extractTakeProfit(analysis) { + if (analysis.takeProfits && analysis.takeProfits.tp1?.price) { + return analysis.takeProfits.tp1.price; + } else if (analysis.takeProfit && typeof analysis.takeProfit === 'number') { + return analysis.takeProfit; + } else if (analysis.levels?.takeProfit) { + return analysis.levels.takeProfit; + } + return null; + } +} + +module.exports = AutomationWithLearning; diff --git a/lib/automation-with-learning.js b/lib/automation-with-learning.js new file mode 100644 index 0000000..32c7a60 --- /dev/null +++ b/lib/automation-with-learning.js @@ -0,0 +1,455 @@ +// Enhanced automation with integrated AI learning system + +// Dynamic import for ES6 modules +async function importSimpleAutomation() { + try { + const module = await import('./simple-automation.js'); + // Extract the class from the singleton instance + return module.simpleAutomation.constructor; + } catch (error) { + console.warn('โš ๏ธ Could not import SimpleAutomation, using fallback'); + // Fallback - create a basic class structure + return class BasicAutomation { + constructor() { + this.isRunning = false; + this.config = null; + this.stats = { totalCycles: 0, totalTrades: 0 }; + } + + async start(config) { + return { success: false, message: 'Base automation not available' }; + } + + async stop() { + return { success: true, message: 'Stopped' }; + } + + getStatus() { + return { isRunning: this.isRunning, stats: this.stats }; + } + }; + } +} + +// Import learning system +async function importSimplifiedStopLossLearner() { + try { + const { SimplifiedStopLossLearner } = await import('./simplified-stop-loss-learner-fixed.js'); + return SimplifiedStopLossLearner; + } catch (error) { + console.warn('โš ๏ธ SimplifiedStopLossLearner not available, continuing without learning'); + return null; + } +} + +class AutomationWithLearning { + constructor() { + this.baseAutomation = null; + this.learner = null; + this.activeTrades = new Map(); // Track active trades for outcome assessment + this.learningDecisions = new Map(); // Track decisions for learning + this.learningEnabled = false; + this.isRunning = false; + this.config = null; + this.stats = { totalCycles: 0, totalTrades: 0 }; + } + + async initializeBaseAutomation() { + if (!this.baseAutomation) { + const SimpleAutomationClass = await importSimpleAutomation(); + this.baseAutomation = new SimpleAutomationClass(); + } + return this.baseAutomation; + } + + async start(config) { + try { + // Initialize base automation + await this.initializeBaseAutomation(); + + // Initialize learning system + await this.initializeLearningSystem(); + + // Use base automation if available, otherwise implement basic functionality + let result; + if (this.baseAutomation && typeof this.baseAutomation.start === 'function') { + result = await this.baseAutomation.start(config); + } else { + // Basic start functionality + this.isRunning = true; + this.config = config; + result = { success: true, message: 'Basic automation started' }; + } + + if (result.success && this.learner) { + console.log('๐Ÿง  AI LEARNING SYSTEM: Activated and ready to learn from trades'); + console.log('๐Ÿ“Š The system will now record decisions and improve over time'); + this.learningEnabled = true; + } + + return result; + } catch (error) { + console.error('โŒ Error starting automation with learning:', error); + return { success: false, message: error.message }; + } + } + + async stop() { + try { + let result; + if (this.baseAutomation && typeof this.baseAutomation.stop === 'function') { + result = await this.baseAutomation.stop(); + } else { + this.isRunning = false; + result = { success: true, message: 'Basic automation stopped' }; + } + + this.learningEnabled = false; + return result; + } catch (error) { + console.error('โŒ Error stopping automation:', error); + return { success: false, message: error.message }; + } + } + + getStatus() { + let baseStatus; + if (this.baseAutomation && typeof this.baseAutomation.getStatus === 'function') { + baseStatus = this.baseAutomation.getStatus(); + } else { + baseStatus = { + isRunning: this.isRunning, + config: this.config, + stats: this.stats + }; + } + + return { + ...baseStatus, + learningSystem: { + enabled: this.learningEnabled, + hasLearner: !!this.learner, + activeDecisions: this.activeTrades.size, + trackedTrades: Array.from(this.activeTrades.keys()) + } + }; + } + +module.exports = AutomationWithLearning; + + async initializeLearningSystem() { + try { + const SimplifiedStopLossLearnerClass = await importSimplifiedStopLossLearner(); + if (SimplifiedStopLossLearnerClass) { + this.learner = new SimplifiedStopLossLearnerClass(); + console.log('โœ… AI Learning System initialized successfully'); + + // Generate initial learning report + if (typeof this.learner.generateLearningReport === 'function') { + const report = await this.learner.generateLearningReport(); + console.log('๐Ÿ“Š Current Learning Status:', report.summary); + } + + return true; + } + } catch (error) { + console.warn('โš ๏ธ Could not initialize learning system:', error.message); + } + return false; + } + + async executeTrade(analysis) { + try { + console.log('๐Ÿง  LEARNING-ENHANCED TRADE EXECUTION'); + + // Record decision before execution for learning + let decisionId = null; + if (this.learningEnabled && this.learner) { + decisionId = await this.recordTradingDecision(analysis); + } + + // Enhance analysis with learning-based adjustments + const enhancedAnalysis = await this.enhanceAnalysisWithLearning(analysis); + + // Execute the trade using enhanced analysis + const tradeResult = await super.executeTrade(enhancedAnalysis); + + // Track trade for outcome assessment + if (tradeResult.success && decisionId) { + this.trackTradeForLearning(decisionId, tradeResult, enhancedAnalysis); + } + + return tradeResult; + + } catch (error) { + console.error('โŒ Error in learning-enhanced trade execution:', error); + return { success: false, error: error.message }; + } + } + + async recordTradingDecision(analysis) { + if (!this.learner || typeof this.learner.recordDecision !== 'function') { + return null; + } + + try { + const decisionData = { + symbol: this.config.symbol, + recommendation: analysis.recommendation, + confidence: analysis.confidence, + stopLoss: this.extractStopLoss(analysis), + takeProfit: this.extractTakeProfit(analysis), + entryPrice: analysis.entry?.price || analysis.currentPrice, + marketConditions: { + timeframe: this.config.selectedTimeframes, + analysis: analysis.reasoning || analysis.summary + }, + timestamp: new Date().toISOString() + }; + + const decisionId = await this.learner.recordDecision(decisionData); + console.log(`๐Ÿ“ LEARNING: Recorded decision ${decisionId}`); + return decisionId; + + } catch (error) { + console.error('โŒ Error recording decision:', error); + return null; + } + } + + async enhanceAnalysisWithLearning(analysis) { + if (!this.learningEnabled || !this.learner) { + console.log('๐Ÿ“Š Using original analysis (learning not available)'); + return analysis; + } + + try { + // Get learning-based recommendations if available + if (typeof this.learner.getSmartRecommendation === 'function') { + const currentPrice = analysis.entry?.price || analysis.currentPrice || 178; + const originalStopLoss = this.extractStopLoss(analysis); + + if (originalStopLoss) { + const distanceFromSL = Math.abs(currentPrice - originalStopLoss); + + const learningRecommendation = await this.learner.getSmartRecommendation({ + symbol: this.config.symbol, + distanceFromSL, + marketConditions: { + recommendation: analysis.recommendation, + confidence: analysis.confidence, + timeframe: this.config.selectedTimeframes + } + }); + + if (learningRecommendation && learningRecommendation.confidence > 70) { + console.log(`๐Ÿง  LEARNING ENHANCEMENT: ${learningRecommendation.action} (${learningRecommendation.confidence}% confidence)`); + console.log(`๐Ÿ’ก Reasoning: ${learningRecommendation.reasoning}`); + + // Apply learning-based adjustments + if (learningRecommendation.action === 'TIGHTEN_STOP_LOSS') { + analysis = this.adjustStopLoss(analysis, learningRecommendation.suggestedValue); + } else if (learningRecommendation.action === 'ADJUST_TAKE_PROFIT') { + analysis = this.adjustTakeProfit(analysis, learningRecommendation.suggestedValue); + } + + // Add learning metadata to analysis + analysis.learningEnhanced = true; + analysis.learningConfidence = learningRecommendation.confidence; + analysis.learningReasoning = learningRecommendation.reasoning; + } + } + } + + return analysis; + + } catch (error) { + console.error('โŒ Error enhancing analysis with learning:', error); + return analysis; // Return original analysis if learning fails + } + } + + adjustStopLoss(analysis, newStopLoss) { + if (newStopLoss) { + if (analysis.stopLoss && typeof analysis.stopLoss === 'object') { + analysis.stopLoss.price = newStopLoss; + } else { + analysis.stopLoss = newStopLoss; + } + console.log(`๐Ÿ”ง LEARNING ADJUSTMENT: Stop-loss adjusted to $${newStopLoss}`); + } + return analysis; + } + + adjustTakeProfit(analysis, newTakeProfit) { + if (newTakeProfit) { + if (analysis.takeProfits && analysis.takeProfits.tp1) { + analysis.takeProfits.tp1.price = newTakeProfit; + } else if (analysis.takeProfit) { + analysis.takeProfit = newTakeProfit; + } else { + analysis.takeProfit = newTakeProfit; + } + console.log(`๐ŸŽฏ LEARNING ADJUSTMENT: Take-profit adjusted to $${newTakeProfit}`); + } + return analysis; + } + + trackTradeForLearning(decisionId, tradeResult, analysis) { + if (!decisionId) return; + + this.activeTrades.set(decisionId, { + tradeResult, + analysis, + timestamp: new Date().toISOString(), + symbol: this.config.symbol + }); + + console.log(`๐Ÿ“Š LEARNING: Tracking trade ${decisionId} for outcome assessment`); + + // Set up outcome assessment check (will check position status later) + setTimeout(() => { + this.assessTradeOutcome(decisionId); + }, 300000); // Check after 5 minutes + } + + async assessTradeOutcome(decisionId) { + if (!this.learningEnabled || !this.learner || !this.activeTrades.has(decisionId)) { + return; + } + + try { + const tradeInfo = this.activeTrades.get(decisionId); + + // Check current position status via API + const baseUrl = process.env.INTERNAL_API_URL || 'http://localhost:3000'; + const response = await fetch(`${baseUrl}/api/automation/position-monitor`); + const positionData = await response.json(); + + let outcome = null; + let actualPnL = 0; + + if (positionData.success) { + // Determine outcome based on position status + if (!positionData.monitor.hasPosition) { + // Position closed - check if it was profitable + outcome = 'POSITION_CLOSED'; + + // Try to get actual P&L from position history + try { + const historyResponse = await fetch(`${baseUrl}/api/drift/position-history`); + const historyData = await historyResponse.json(); + + if (historyData.success && historyData.trades.length > 0) { + // Find the most recent trade + const recentTrade = historyData.trades[0]; + actualPnL = recentTrade.pnl; + outcome = actualPnL > 0 ? 'WIN' : 'LOSS'; + } + } catch (historyError) { + console.warn('โš ๏ธ Could not fetch trade history for outcome assessment'); + } + } else { + // Position still open - check if it's profitable + const currentPnL = positionData.monitor.position?.unrealizedPnl || 0; + actualPnL = currentPnL; + outcome = currentPnL > 0 ? 'CURRENTLY_PROFITABLE' : 'CURRENTLY_LOSING'; + } + } + + // Record outcome for learning + if (outcome && typeof this.learner.assessDecisionOutcome === 'function') { + const outcomeData = { + decisionId, + outcome, + actualPnL, + timestamp: new Date().toISOString(), + positionInfo: positionData.monitor + }; + + await this.learner.assessDecisionOutcome(outcomeData); + console.log(`๐Ÿง  LEARNING: Assessed outcome for decision ${decisionId}: ${outcome} (P&L: $${actualPnL.toFixed(2)})`); + + // Clean up tracked trade + this.activeTrades.delete(decisionId); + } + + } catch (error) { + console.error('โŒ Error assessing trade outcome:', error); + } + } + + extractStopLoss(analysis) { + if (analysis.stopLoss && typeof analysis.stopLoss === 'object') { + return analysis.stopLoss.price; + } else if (analysis.stopLoss && typeof analysis.stopLoss === 'number') { + return analysis.stopLoss; + } else if (analysis.levels?.stopLoss) { + return analysis.levels.stopLoss; + } + return null; + } + + extractTakeProfit(analysis) { + if (analysis.takeProfits && analysis.takeProfits.tp1?.price) { + return analysis.takeProfits.tp1.price; + } else if (analysis.takeProfit && typeof analysis.takeProfit === 'number') { + return analysis.takeProfit; + } else if (analysis.levels?.takeProfit) { + return analysis.levels.takeProfit; + } + return null; + } + + async getLearningStatus() { + if (!this.learningEnabled || !this.learner) { + return { + enabled: false, + message: 'Learning system not available' + }; + } + + try { + let report = null; + + // Try to get comprehensive learning report + if (typeof this.learner.generateLearningReport === 'function') { + report = await this.learner.generateLearningReport(); + } else if (typeof this.learner.getLearningStatus === 'function') { + report = await this.learner.getLearningStatus(); + } + + return { + enabled: true, + learningActive: this.learningEnabled, + activeDecisions: this.activeTrades.size, + report: report || { summary: { message: 'Learning system active but no data available yet' } } + }; + + } catch (error) { + console.error('โŒ Error getting learning status:', error); + return { + enabled: true, + learningActive: this.learningEnabled, + error: error.message + }; + } + } + + // Override getStatus to include learning information + getStatus() { + const baseStatus = super.getStatus(); + + return { + ...baseStatus, + learningSystem: { + enabled: this.learningEnabled, + hasLearner: !!this.learner, + activeDecisions: this.activeTrades.size, + trackedTrades: Array.from(this.activeTrades.keys()) + } + }; + } +} + +module.exports = AutomationWithLearning; diff --git a/test-learning-integration.js b/test-learning-integration.js new file mode 100644 index 0000000..ed7e3d3 --- /dev/null +++ b/test-learning-integration.js @@ -0,0 +1,98 @@ +// Test script to verify AI learning system integration +const path = require('path'); + +async function testLearningIntegration() { + console.log('๐Ÿงช Testing AI Learning System Integration...\n'); + + try { + // Test 1: Check if learning-enhanced automation can be imported + console.log('1๏ธโƒฃ Testing automation with learning import...'); + const AutomationWithLearning = require('./lib/automation-with-learning.js'); + console.log('โœ… AutomationWithLearning imported successfully'); + + // Test 2: Create automation instance + console.log('\n2๏ธโƒฃ Creating automation instance...'); + const automation = new AutomationWithLearning(); + console.log('โœ… Automation instance created'); + console.log(' - Has learner property:', 'learner' in automation); + console.log(' - Has learning methods:', typeof automation.getLearningStatus === 'function'); + + // Test 3: Check if SimplifiedStopLossLearner can be imported + console.log('\n3๏ธโƒฃ Testing SimplifiedStopLossLearner import...'); + try { + const { SimplifiedStopLossLearner } = await import('./lib/simplified-stop-loss-learner-fixed.js'); + console.log('โœ… SimplifiedStopLossLearner imported successfully'); + + // Test creating learner instance + const learner = new SimplifiedStopLossLearner(); + console.log('โœ… SimplifiedStopLossLearner instance created'); + console.log(' - Available methods:', Object.getOwnPropertyNames(Object.getPrototypeOf(learner)).filter(name => name !== 'constructor')); + + } catch (learnerError) { + console.log('โŒ SimplifiedStopLossLearner import failed:', learnerError.message); + } + + // Test 4: Initialize learning system + console.log('\n4๏ธโƒฃ Testing learning system initialization...'); + try { + const initialized = await automation.initializeLearningSystem(); + console.log('โœ… Learning system initialization result:', initialized); + console.log(' - Learner created:', !!automation.learner); + + if (automation.learner) { + console.log(' - Learner type:', automation.learner.constructor.name); + + // Test learning status + if (typeof automation.getLearningStatus === 'function') { + const status = await automation.getLearningStatus(); + console.log(' - Learning status:', status); + } + } + + } catch (initError) { + console.log('โŒ Learning system initialization failed:', initError.message); + } + + // Test 5: Test singleton manager + console.log('\n5๏ธโƒฃ Testing singleton automation manager...'); + try { + const { getAutomationInstance } = require('./lib/automation-singleton.js'); + const singletonInstance = await getAutomationInstance(); + console.log('โœ… Singleton automation instance retrieved'); + console.log(' - Instance type:', singletonInstance.constructor.name); + console.log(' - Has learning capabilities:', typeof singletonInstance.getLearningStatus === 'function'); + + } catch (singletonError) { + console.log('โŒ Singleton manager test failed:', singletonError.message); + } + + // Test 6: Test database connection + console.log('\n6๏ธโƒฃ Testing database connection...'); + try { + const { getDB } = require('./lib/db.js'); + const db = await getDB(); + console.log('โœ… Database connection successful'); + + // Test if learning tables exist + const tables = await db.$queryRaw` + SELECT name FROM sqlite_master + WHERE type='table' AND name LIKE '%learning%' + `; + console.log(' - Learning-related tables:', tables.map(t => t.name)); + + } catch (dbError) { + console.log('โŒ Database connection failed:', dbError.message); + } + + console.log('\n๐ŸŽฏ Integration Test Summary:'); + console.log('๐Ÿ“Š The AI learning system integration appears to be working'); + console.log('๐Ÿ”— Key components are properly connected'); + console.log('๐Ÿ’ก Learning system should now enhance trading decisions when automation starts'); + + } catch (error) { + console.error('โŒ Integration test failed:', error); + } +} + +// Run the test +testLearningIntegration().catch(console.error);