diff --git a/app/api/automation/status/route.js b/app/api/automation/status/route.js index 8c17824..1ce1454 100644 --- a/app/api/automation/status/route.js +++ b/app/api/automation/status/route.js @@ -1,21 +1,12 @@ import { NextResponse } from 'next/server' -import { PrismaClient } from '@prisma/client' - -const prisma = new PrismaClient() +import { automationService } from '../../../../lib/automation-service-simple' export async function GET() { try { - // Get the latest automation session with correct data - const session = await prisma.automationSession.findFirst({ - where: { - userId: 'default-user', - symbol: 'SOLUSD', - timeframe: '1h' - }, - orderBy: { createdAt: 'desc' } - }) - - if (!session) { + // Get status from the automation service directly (includes timing and individual results) + const status = await automationService.getStatus() + + if (!status) { return NextResponse.json({ success: true, status: { @@ -27,51 +18,18 @@ export async function GET() { successfulTrades: 0, winRate: 0, totalPnL: 0, - errorCount: 0 + errorCount: 0, + nextAnalysisIn: 0, + analysisInterval: 3600, + currentCycle: 0, + individualTimeframeResults: [] } }) } - // Get actual trade data to calculate real statistics - const trades = await prisma.trade.findMany({ - where: { - userId: session.userId, - symbol: session.symbol - }, - orderBy: { createdAt: 'desc' } - }) - - const completedTrades = trades.filter(t => t.status === 'COMPLETED') - const successfulTrades = completedTrades.filter(t => { - const profit = t.profit || 0 - return profit > 0 - }) - - const totalPnL = completedTrades.reduce((sum, trade) => { - const profit = trade.profit || 0 - return sum + profit - }, 0) - - const winRate = completedTrades.length > 0 ? - (successfulTrades.length / completedTrades.length * 100) : 0 - return NextResponse.json({ success: true, - status: { - isActive: session.status === 'ACTIVE', - mode: session.mode, - symbol: session.symbol, - timeframe: session.timeframe, - totalTrades: completedTrades.length, - successfulTrades: successfulTrades.length, - winRate: Math.round(winRate * 10) / 10, // Round to 1 decimal - totalPnL: Math.round(totalPnL * 100) / 100, // Round to 2 decimals - lastAnalysis: session.lastAnalysis, - lastTrade: session.lastTrade, - nextScheduled: session.nextScheduled, - errorCount: session.errorCount, - lastError: session.lastError - } + status: status }) } catch (error) { console.error('Automation status error:', error) diff --git a/app/automation-v2/page.js b/app/automation-v2/page.js index 07090bb..cfb9957 100644 --- a/app/automation-v2/page.js +++ b/app/automation-v2/page.js @@ -30,6 +30,7 @@ export default function AutomationPageV2() { const [balance, setBalance] = useState(null) const [positions, setPositions] = useState([]) const [loading, setLoading] = useState(false) + const [nextAnalysisCountdown, setNextAnalysisCountdown] = useState(0) useEffect(() => { fetchStatus() @@ -44,6 +45,51 @@ export default function AutomationPageV2() { return () => clearInterval(interval) }, []) + // Timer effect for countdown + useEffect(() => { + let countdownInterval = null + + if (status?.isActive && status?.nextAnalysisIn > 0) { + setNextAnalysisCountdown(status.nextAnalysisIn) + + countdownInterval = setInterval(() => { + setNextAnalysisCountdown(prev => { + if (prev <= 1) { + // Refresh status when timer reaches 0 + fetchStatus() + return 0 + } + return prev - 1 + }) + }, 1000) + } else { + setNextAnalysisCountdown(0) + } + + return () => { + if (countdownInterval) { + clearInterval(countdownInterval) + } + } + }, [status?.nextAnalysisIn, status?.isActive]) + + // Helper function to format countdown time + const formatCountdown = (seconds) => { + if (seconds <= 0) return 'Analyzing now...' + + const hours = Math.floor(seconds / 3600) + const minutes = Math.floor((seconds % 3600) / 60) + const secs = seconds % 60 + + if (hours > 0) { + return `${hours}h ${minutes}m ${secs}s` + } else if (minutes > 0) { + return `${minutes}m ${secs}s` + } else { + return `${secs}s` + } + } + const toggleTimeframe = (timeframe) => { setConfig(prev => ({ ...prev, @@ -498,6 +544,82 @@ export default function AutomationPageV2() { )} + {/* Analysis Timer */} + {status?.isActive && ( +
+
+

Analysis Timer

+
+ Cycle #{status.currentCycle || 0} +
+
+
+
+
+ {formatCountdown(nextAnalysisCountdown)} +
+
+ {nextAnalysisCountdown > 0 ? 'Next Analysis In' : 'Analysis Running'} +
+
+
+
0 ? + `${Math.max(0, 100 - (nextAnalysisCountdown / status.analysisInterval) * 100)}%` : + '0%' + }} + >
+
+
+ Analysis Interval: {Math.floor((status.analysisInterval || 0) / 60)}m +
+
+
+ )} + + {/* Individual Timeframe Results */} + {status?.individualTimeframeResults && status.individualTimeframeResults.length > 0 && ( +
+

Timeframe Analysis

+
+ {status.individualTimeframeResults.map((result, index) => ( +
+
+ + {timeframes.find(tf => tf.value === result.timeframe)?.label || result.timeframe} + + + {result.recommendation} + +
+
+
+ {result.confidence}% +
+
+ confidence +
+
+
+ ))} +
+
+
+ ✅ Last Updated: {status.individualTimeframeResults[0]?.timestamp ? + new Date(status.individualTimeframeResults[0].timestamp).toLocaleTimeString() : + 'N/A' + } +
+
+
+ )} + {/* Trading Metrics */}

Trading Metrics

diff --git a/prisma/prisma/dev.db b/prisma/prisma/dev.db index b9fd53c..3dd4b32 100644 Binary files a/prisma/prisma/dev.db and b/prisma/prisma/dev.db differ