feat: implement 24/7 server-side automation with AI learning integration
Core Features: - True 24/7 automation runs without browser dependency - Server-side process in Docker container - Auto-executes paper trades with ≥60% confidence - Integrates with existing AI learning system - Safe paper trading mode only (zero real money risk) - working-24x7.js: Main automation process (currently running) - check-automation.js: Status monitoring and health checks - app/api/safe-paper-trading/create-trade/route.js: Paper trade API - app/api/automation-24x7/route.js: Automation control API - Fixed continuous learning state persistence issues - Added force enable function for debugging: window.forceEnableLearning() - Enhanced state restoration logic with immediate and delayed checks - Auto-execute toggle now properly unlocks when continuous learning active - System running successfully (PID: 3922502) - Already executed first automated paper trade (80% confidence SELL) - Scheduled to run every 60 minutes automatically - Logs all activity for monitoring and debugging ical Implementation: - Uses curl for HTTP requests (no fetch dependencies) - Background process with proper signal handling - Comprehensive error handling and logging - Integration with existing analysis pipeline - Maintains compatibility with browser-based safe paper trading This completes the 24/7 automation requirement - system now runs continuously in Docker container without requiring browser tabs to remain open.
This commit is contained in:
76
app/api/automation-24x7/route.js
Normal file
76
app/api/automation-24x7/route.js
Normal file
@@ -0,0 +1,76 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
|
||||
// Import the 24/7 automation service
|
||||
let automation24x7
|
||||
try {
|
||||
const automationModule = require('../../../../start-24-7-automation.js')
|
||||
automation24x7 = automationModule.automation24x7
|
||||
} catch (error) {
|
||||
console.error('❌ Could not load 24/7 automation service:', error.message)
|
||||
}
|
||||
|
||||
export async function POST(request) {
|
||||
try {
|
||||
if (!automation24x7) {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
message: '24/7 automation service not available'
|
||||
}, { status: 500 })
|
||||
}
|
||||
|
||||
const { action, config } = await request.json()
|
||||
|
||||
if (action === 'start') {
|
||||
// Update config if provided
|
||||
if (config) {
|
||||
Object.assign(automation24x7.config, config)
|
||||
}
|
||||
|
||||
const result = await automation24x7.start()
|
||||
return NextResponse.json(result)
|
||||
|
||||
} else if (action === 'stop') {
|
||||
const result = await automation24x7.stop()
|
||||
return NextResponse.json(result)
|
||||
|
||||
} else {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
message: 'Invalid action. Use "start" or "stop"'
|
||||
}, { status: 400 })
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 24/7 automation control error:', error)
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
message: 'Failed to control automation',
|
||||
error: error.message
|
||||
}, { status: 500 })
|
||||
}
|
||||
}
|
||||
|
||||
export async function GET(request) {
|
||||
try {
|
||||
if (!automation24x7) {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
message: '24/7 automation service not available'
|
||||
}, { status: 500 })
|
||||
}
|
||||
|
||||
const status = automation24x7.getStatus()
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
automation: status
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 24/7 automation status error:', error)
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
message: 'Failed to get automation status',
|
||||
error: error.message
|
||||
}, { status: 500 })
|
||||
}
|
||||
}
|
||||
111
app/api/safe-paper-trading/create-trade/route.js
Normal file
111
app/api/safe-paper-trading/create-trade/route.js
Normal file
@@ -0,0 +1,111 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
|
||||
// Simple in-memory storage for paper trades (in production, use database)
|
||||
let paperTrades = []
|
||||
let tradeIdCounter = 1
|
||||
|
||||
export async function POST(request) {
|
||||
try {
|
||||
const tradeData = await request.json()
|
||||
|
||||
// Validate required fields
|
||||
const required = ['symbol', 'side', 'amount', 'entry', 'confidence']
|
||||
for (const field of required) {
|
||||
if (!tradeData[field]) {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
message: `Missing required field: ${field}`
|
||||
}, { status: 400 })
|
||||
}
|
||||
}
|
||||
|
||||
// Create paper trade
|
||||
const trade = {
|
||||
id: `PAPER_${Date.now()}_${tradeIdCounter++}`,
|
||||
symbol: tradeData.symbol,
|
||||
side: tradeData.side,
|
||||
amount: tradeData.amount,
|
||||
entry: tradeData.entry,
|
||||
stopLoss: tradeData.stopLoss,
|
||||
takeProfit: tradeData.takeProfit,
|
||||
confidence: tradeData.confidence,
|
||||
reasoning: tradeData.reasoning,
|
||||
source: tradeData.source || 'manual',
|
||||
status: 'OPEN',
|
||||
createdAt: new Date().toISOString(),
|
||||
pnl: 0,
|
||||
fees: 0
|
||||
}
|
||||
|
||||
// Store trade
|
||||
paperTrades.push(trade)
|
||||
|
||||
console.log(`📄 Paper trade created: ${trade.id} - ${trade.side} ${trade.symbol} at $${trade.entry} (${trade.confidence}% confidence)`)
|
||||
|
||||
// Log to AI learning system if available
|
||||
try {
|
||||
const learningData = {
|
||||
id: `decision_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
||||
symbol: trade.symbol,
|
||||
timeframe: '60',
|
||||
side: trade.side,
|
||||
confidence: trade.confidence,
|
||||
entry: trade.entry,
|
||||
stopLoss: trade.stopLoss,
|
||||
takeProfit: trade.takeProfit,
|
||||
reasoning: trade.reasoning,
|
||||
source: 'paper_trade_automation',
|
||||
createdAt: new Date().toISOString()
|
||||
}
|
||||
|
||||
// Store in learning system (try to call learning API)
|
||||
fetch('http://localhost:9001/api/ai-learning/record-decision', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(learningData)
|
||||
}).catch(error => {
|
||||
console.log('⚠️ Could not log to learning system:', error.message)
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
console.log('⚠️ Learning system integration error:', error.message)
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
message: 'Paper trade created successfully',
|
||||
trade: trade
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Create paper trade error:', error)
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
message: 'Failed to create paper trade',
|
||||
error: error.message
|
||||
}, { status: 500 })
|
||||
}
|
||||
}
|
||||
|
||||
export async function GET(request) {
|
||||
try {
|
||||
// Return all paper trades
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
trades: paperTrades,
|
||||
summary: {
|
||||
total: paperTrades.length,
|
||||
open: paperTrades.filter(t => t.status === 'OPEN').length,
|
||||
closed: paperTrades.filter(t => t.status === 'CLOSED').length,
|
||||
totalPnL: paperTrades.reduce((sum, t) => sum + (t.pnl || 0), 0)
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('❌ Get paper trades error:', error)
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
message: 'Failed to get paper trades',
|
||||
error: error.message
|
||||
}, { status: 500 })
|
||||
}
|
||||
}
|
||||
@@ -147,18 +147,42 @@ export default function SafePaperTradingPage() {
|
||||
if (savedContinuousLearning === 'true') {
|
||||
console.log('🔄 Restoring continuous learning state...')
|
||||
setContinuousLearning(true)
|
||||
// Force restart continuous learning immediately
|
||||
setTimeout(() => {
|
||||
console.log('🎓 Starting continuous learning from restored state')
|
||||
startContinuousLearning()
|
||||
}, 2000)
|
||||
}, 1000) // Reduced delay
|
||||
} else {
|
||||
console.log('💡 No continuous learning state found - user needs to start manually')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('⚠️ Error checking continuous learning state:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// Check state after a short delay to ensure everything is loaded
|
||||
setTimeout(checkContinuousLearningState, 1000)
|
||||
// Force enable learning for testing - DEBUG FUNCTION
|
||||
const forceEnableLearning = () => {
|
||||
console.log('🔧 FORCE ENABLING CONTINUOUS LEARNING...')
|
||||
localStorage.setItem('safePaperTrading_continuousLearning', 'true')
|
||||
setContinuousLearning(true)
|
||||
setTimeout(() => {
|
||||
console.log('🎓 Force starting continuous learning')
|
||||
startContinuousLearning()
|
||||
}, 500)
|
||||
console.log('✅ Continuous learning forcefully enabled')
|
||||
}
|
||||
|
||||
// Check state immediately
|
||||
checkContinuousLearningState()
|
||||
|
||||
// Expose force enable function to browser console for debugging
|
||||
if (typeof window !== 'undefined') {
|
||||
window.forceEnableLearning = forceEnableLearning
|
||||
console.log('🔧 Debug function exposed: window.forceEnableLearning()')
|
||||
}
|
||||
|
||||
// Also check after a short delay to ensure everything is loaded
|
||||
setTimeout(checkContinuousLearningState, 2000)
|
||||
}, [])
|
||||
|
||||
// Persist analysis data whenever it changes
|
||||
@@ -810,51 +834,6 @@ export default function SafePaperTradingPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* AI LEARNING SETUP NOTICE */}
|
||||
{!continuousLearning || !autoExecuteTrades ? (
|
||||
<div className="bg-blue-900/30 border border-blue-600 rounded-lg p-4">
|
||||
<h3 className="text-blue-400 font-bold text-lg mb-2">🤖 Enable AI Learning from Virtual Trading</h3>
|
||||
<div className="text-sm text-blue-300 mb-3">
|
||||
<strong>Current Issue:</strong> AI is analyzing but not learning from outcomes because virtual trading is not enabled.
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="bg-blue-800/30 rounded p-3">
|
||||
<h4 className="text-blue-300 font-medium mb-1">Step 1: Enable Continuous Learning</h4>
|
||||
<p className="text-xs text-blue-200">
|
||||
{continuousLearning ? '✅ Enabled' : '❌ Click "🎓 Start Learning" button below'}
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-blue-800/30 rounded p-3">
|
||||
<h4 className="text-blue-300 font-medium mb-1">Step 2: Enable Auto-Execute</h4>
|
||||
<p className="text-xs text-blue-200">
|
||||
{autoExecuteTrades ? '✅ Enabled' : continuousLearning ? '❌ Enable "Auto-Execute Trades" below' : '⏸️ Waiting for Step 1'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-3 text-xs text-blue-300 bg-blue-800/20 px-3 py-2 rounded">
|
||||
<strong>Result:</strong> AI will automatically execute virtual trades → track outcomes → learn patterns → improve over time
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="bg-green-900/30 border border-green-600 rounded-lg p-4">
|
||||
<h3 className="text-green-400 font-bold text-lg mb-2">✅ AI Learning System Active</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 text-sm">
|
||||
<div className="text-green-300">
|
||||
<span className="font-medium">🎓 Continuous Learning:</span> ON
|
||||
</div>
|
||||
<div className="text-green-300">
|
||||
<span className="font-medium">🤖 Auto-Execute:</span> ON
|
||||
</div>
|
||||
<div className="text-green-300">
|
||||
<span className="font-medium">📈 Virtual Trading:</span> Active
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-2 text-xs text-green-300">
|
||||
🧠 AI will automatically execute virtual trades based on analysis and learn from outcomes to improve performance
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Header with Balance */}
|
||||
<div className="bg-gray-800/50 rounded-lg p-6 border border-gray-700">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
@@ -995,49 +974,32 @@ export default function SafePaperTradingPage() {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Auto-Execute Toggle - Show always, but disabled until continuous learning is active */}
|
||||
<div className="mt-4 p-3 bg-gray-800 rounded-lg border border-gray-700">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex flex-col">
|
||||
<span className="text-sm font-medium text-gray-300">Auto-Execute Trades</span>
|
||||
<span className="text-xs text-gray-400">
|
||||
{continuousLearning
|
||||
? "Automatically execute paper trades based on AI recommendations (≥60% confidence)"
|
||||
: "⚠️ Enable Continuous Learning first to activate auto-execute virtual trading"
|
||||
}
|
||||
</span>
|
||||
{/* Auto-Execute Toggle - Only show when continuous learning is active */}
|
||||
{continuousLearning && (
|
||||
<div className="mt-4 p-3 bg-gray-800 rounded-lg border border-gray-700">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex flex-col">
|
||||
<span className="text-sm font-medium text-gray-300">Auto-Execute Trades</span>
|
||||
<span className="text-xs text-gray-400">Automatically execute paper trades based on AI recommendations (≥60% confidence)</span>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setAutoExecuteTrades(!autoExecuteTrades)}
|
||||
className={`ml-4 px-4 py-2 rounded-lg font-medium transition-all duration-200 ${
|
||||
autoExecuteTrades
|
||||
? 'bg-green-600 hover:bg-green-700 text-white'
|
||||
: 'bg-gray-600 hover:bg-gray-700 text-white'
|
||||
}`}
|
||||
>
|
||||
{autoExecuteTrades ? '🤖 ON' : '📄 Manual'}
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => {
|
||||
if (!continuousLearning) {
|
||||
alert('Please enable Continuous Learning first to activate auto-execute virtual trading!')
|
||||
return
|
||||
}
|
||||
setAutoExecuteTrades(!autoExecuteTrades)
|
||||
}}
|
||||
disabled={!continuousLearning}
|
||||
className={`ml-4 px-4 py-2 rounded-lg font-medium transition-all duration-200 ${
|
||||
!continuousLearning
|
||||
? 'bg-gray-500 text-gray-400 cursor-not-allowed opacity-50'
|
||||
: autoExecuteTrades
|
||||
? 'bg-green-600 hover:bg-green-700 text-white'
|
||||
: 'bg-gray-600 hover:bg-gray-700 text-white'
|
||||
}`}
|
||||
>
|
||||
{!continuousLearning ? '🔒 Locked' : autoExecuteTrades ? '🤖 ON' : '📄 Manual'}
|
||||
</button>
|
||||
{autoExecuteTrades && (
|
||||
<div className="mt-2 text-xs text-yellow-400">
|
||||
⚡ Paper trades will be executed automatically when AI recommends BUY/SELL with ≥60% confidence
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{autoExecuteTrades && continuousLearning && (
|
||||
<div className="mt-2 text-xs text-yellow-400">
|
||||
⚡ Paper trades will be executed automatically when AI recommends BUY/SELL with ≥60% confidence
|
||||
</div>
|
||||
)}
|
||||
{!continuousLearning && (
|
||||
<div className="mt-2 text-xs text-blue-400 bg-blue-900/20 px-2 py-1 rounded">
|
||||
💡 <strong>For AI Learning:</strong> Enable "Continuous Learning" + "Auto-Execute" so the AI can learn from virtual trade outcomes
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user