Files
trading_bot_v3/app/automation/page.js
mindesbunister 55cea00e5e Fix automated trading display calculations
Fixed position size calculation: 00 investment now shows 00 position (was 04.76)
 Fixed token amount display: Now shows correct tokens (~0.996) for 00 investment (was 2.04)
 Corrected API route: /api/automation/analysis-details now returns 200 instead of 405

Technical changes:
- Updated route calculation logic: tradingAmount / trade.price for correct token amounts
- Fixed displayPositionSize to show intended investment amount
- Used Docker Compose v2 for container management
- Resolved Next.js module export issues

The API now correctly displays trade details matching user investment intentions.
2025-07-20 22:32:16 +02:00

1237 lines
56 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
import React, { useState, useEffect } from 'react'
export default function AutomationPage() {
const [config, setConfig] = useState({
mode: 'SIMULATION',
symbol: 'SOLUSD',
timeframe: '1h',
tradingAmount: 100,
maxLeverage: 3,
stopLossPercent: 2,
takeProfitPercent: 6,
maxDailyTrades: 5,
riskPercentage: 2
})
const [status, setStatus] = useState(null)
const [isLoading, setIsLoading] = useState(false)
const [learningInsights, setLearningInsights] = useState(null)
const [aiLearningStatus, setAiLearningStatus] = useState(null)
const [recentTrades, setRecentTrades] = useState([])
const [analysisDetails, setAnalysisDetails] = useState(null)
const [selectedTrade, setSelectedTrade] = useState(null)
const [tradeModalOpen, setTradeModalOpen] = useState(false)
useEffect(() => {
fetchStatus()
fetchLearningInsights()
fetchAiLearningStatus()
fetchRecentTrades()
fetchAnalysisDetails()
// Auto-refresh every 30 seconds
const interval = setInterval(() => {
fetchStatus()
fetchAnalysisDetails()
fetchAiLearningStatus()
}, 30000)
return () => clearInterval(interval)
}, [])
const fetchAnalysisDetails = async () => {
try {
const response = await fetch('/api/automation/analysis-details')
const data = await response.json()
if (data.success) {
setAnalysisDetails(data.data)
// Also update recent trades from the same endpoint
if (data.data.recentTrades) {
setRecentTrades(data.data.recentTrades)
}
}
} catch (error) {
console.error('Failed to fetch analysis details:', error)
}
}
const fetchStatus = async () => {
try {
const response = await fetch('/api/automation/status')
const data = await response.json()
if (data.success) {
setStatus(data.status)
}
} catch (error) {
console.error('Failed to fetch status:', error)
}
}
const fetchLearningInsights = async () => {
try {
const response = await fetch('/api/automation/learning-insights')
const data = await response.json()
if (data.success) {
setLearningInsights(data.insights)
}
} catch (error) {
console.error('Failed to fetch learning insights:', error)
}
}
const fetchAiLearningStatus = async () => {
try {
const response = await fetch('/api/ai-learning-status')
const data = await response.json()
if (data.success) {
setAiLearningStatus(data.data)
}
} catch (error) {
console.error('Failed to fetch AI learning status:', error)
}
}
const fetchRecentTrades = async () => {
try {
// Get enhanced trade data from analysis-details instead of recent-trades
const response = await fetch('/api/automation/analysis-details')
const data = await response.json()
if (data.success && data.data.recentTrades) {
setRecentTrades(data.data.recentTrades)
}
} catch (error) {
console.error('Failed to fetch recent trades:', error)
}
}
const handleStart = async () => {
setIsLoading(true)
try {
const response = await fetch('/api/automation/start', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(config)
})
const data = await response.json()
if (data.success) {
fetchStatus()
} else {
alert('Failed to start automation: ' + data.error)
}
} catch (error) {
console.error('Failed to start automation:', error)
alert('Failed to start automation')
} finally {
setIsLoading(false)
}
}
const handleStop = async () => {
setIsLoading(true)
try {
const response = await fetch('/api/automation/stop', {
method: 'POST'
})
const data = await response.json()
if (data.success) {
fetchStatus()
} else {
alert('Failed to stop automation: ' + data.error)
}
} catch (error) {
console.error('Failed to stop automation:', error)
alert('Failed to stop automation')
} finally {
setIsLoading(false)
}
}
const handlePause = async () => {
setIsLoading(true)
try {
const response = await fetch('/api/automation/pause', {
method: 'POST'
})
const data = await response.json()
if (data.success) {
fetchStatus()
} else {
alert('Failed to pause automation: ' + data.error)
}
} catch (error) {
console.error('Failed to pause automation:', error)
alert('Failed to pause automation')
} finally {
setIsLoading(false)
}
}
const handleResume = async () => {
setIsLoading(true)
try {
const response = await fetch('/api/automation/resume', {
method: 'POST'
})
const data = await response.json()
if (data.success) {
fetchStatus()
} else {
alert('Failed to resume automation: ' + data.error)
}
} catch (error) {
console.error('Failed to resume automation:', error)
alert('Failed to resume automation')
} finally {
setIsLoading(false)
}
}
const openTradeModal = async (tradeId) => {
try {
const response = await fetch(`/api/automation/trade-details/${tradeId}`)
const data = await response.json()
if (data.success) {
setSelectedTrade(data.data)
setTradeModalOpen(true)
} else {
alert('Failed to load trade details')
}
} catch (error) {
console.error('Failed to load trade details:', error)
alert('Failed to load trade details')
}
}
const closeTradeModal = () => {
setTradeModalOpen(false)
setSelectedTrade(null)
}
// Calculate win rate from recent trades
const calculateWinRate = () => {
if (!recentTrades.length) return 0
const completedTrades = recentTrades.filter(t => t.status === 'COMPLETED')
if (!completedTrades.length) return 0
const winningTrades = completedTrades.filter(t => t.result === 'WIN')
return (winningTrades.length / completedTrades.length * 100).toFixed(1)
}
// Calculate total P&L from recent trades
const calculateTotalPnL = () => {
if (!recentTrades.length) return 0
return recentTrades
.filter(t => t.status === 'COMPLETED' && t.pnl)
.reduce((total, trade) => total + parseFloat(trade.pnl), 0)
.toFixed(2)
}
return (
<div className="space-y-8">
<div className="flex items-center justify-between">
<div>
<h1 className="text-3xl font-bold text-white">Automation Mode</h1>
<p className="text-gray-400 mt-2">
AI-powered automated trading on 1H timeframe with learning capabilities
</p>
</div>
<div className="flex space-x-4">
{status?.isActive ? (
<>
<button
onClick={handlePause}
disabled={isLoading}
className="px-4 py-2 bg-yellow-600 text-white rounded-lg hover:bg-yellow-700 transition-colors disabled:opacity-50"
>
{isLoading ? 'Pausing...' : 'Pause'}
</button>
<button
onClick={handleStop}
disabled={isLoading}
className="px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 transition-colors disabled:opacity-50"
>
{isLoading ? 'Stopping...' : 'Stop'}
</button>
</>
) : (
<>
{status?.status === 'PAUSED' && (
<button
onClick={handleResume}
disabled={isLoading}
className="px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors disabled:opacity-50"
>
{isLoading ? 'Resuming...' : 'Resume'}
</button>
)}
<button
onClick={handleStart}
disabled={isLoading}
className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50"
>
{isLoading ? 'Starting...' : 'Start Automation'}
</button>
</>
)}
</div>
</div>
<div className="grid grid-cols-1 xl:grid-cols-2 gap-8">
{/* Configuration Panel */}
<div className="space-y-6">
<div className="card card-gradient p-6">
<h2 className="text-xl font-bold text-white mb-4">Configuration</h2>
<div className="space-y-4">
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
Trading Mode
</label>
<select
value={config.mode}
onChange={(e) => setConfig({...config, mode: e.target.value})}
className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
disabled={status?.isActive}
>
<option value="SIMULATION">Simulation (Paper Trading)</option>
<option value="LIVE">Live Trading (Jupiter DEX)</option>
</select>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
Symbol
</label>
<select
value={config.symbol}
onChange={(e) => setConfig({...config, symbol: e.target.value})}
className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
disabled={status?.isActive}
>
<option value="SOLUSD">SOL/USD</option>
<option value="BTCUSD">BTC/USD</option>
<option value="ETHUSD">ETH/USD</option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
Timeframe
</label>
<select
value={config.timeframe}
onChange={(e) => setConfig({...config, timeframe: e.target.value})}
className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
disabled={status?.isActive}
>
<option value="1h">1 Hour (Recommended)</option>
<option value="4h">4 Hours</option>
<option value="1d">1 Day</option>
</select>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
Trading Amount ($)
</label>
<input
type="number"
value={config.tradingAmount}
onChange={(e) => setConfig({...config, tradingAmount: parseFloat(e.target.value)})}
className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
disabled={status?.isActive}
min="10"
step="10"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
Max Leverage
</label>
<select
value={config.maxLeverage}
onChange={(e) => setConfig({...config, maxLeverage: parseFloat(e.target.value)})}
className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
disabled={status?.isActive}
>
<option value="1">1x (Spot)</option>
<option value="2">2x</option>
<option value="3">3x</option>
<option value="5">5x</option>
</select>
</div>
</div>
<div className="grid grid-cols-3 gap-4">
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
Stop Loss (%)
</label>
<input
type="number"
value={config.stopLossPercent}
onChange={(e) => setConfig({...config, stopLossPercent: parseFloat(e.target.value)})}
className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
disabled={status?.isActive}
min="1"
max="10"
step="0.5"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
Take Profit (%)
</label>
<input
type="number"
value={config.takeProfitPercent}
onChange={(e) => setConfig({...config, takeProfitPercent: parseFloat(e.target.value)})}
className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
disabled={status?.isActive}
min="2"
max="20"
step="1"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
Max Daily Trades
</label>
<input
type="number"
value={config.maxDailyTrades}
onChange={(e) => setConfig({...config, maxDailyTrades: parseInt(e.target.value)})}
className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
disabled={status?.isActive}
min="1"
max="20"
/>
</div>
</div>
</div>
</div>
{/* AI Learning Status */}
{aiLearningStatus && (
<div className="card card-gradient p-6">
<h2 className="text-xl font-bold text-white mb-4">🧠 AI Learning Status</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* Learning Phase */}
<div className="space-y-4">
<div className="flex items-center space-x-3">
<div className={`w-3 h-3 rounded-full ${
aiLearningStatus.phase === 'EXPERT' ? 'bg-green-500' :
aiLearningStatus.phase === 'ADVANCED' ? 'bg-blue-500' :
aiLearningStatus.phase === 'PATTERN_RECOGNITION' ? 'bg-yellow-500' :
'bg-gray-500'
}`}></div>
<div>
<div className="text-white font-semibold">{aiLearningStatus.phaseDescription}</div>
<div className="text-sm text-gray-400">Phase: {aiLearningStatus.phase.replace('_', ' ')}</div>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="text-center">
<div className="text-2xl font-bold text-white">{aiLearningStatus.totalAnalyses}</div>
<div className="text-xs text-gray-400">Total Analyses</div>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-white">{aiLearningStatus.totalTrades}</div>
<div className="text-xs text-gray-400">Total Trades</div>
</div>
</div>
</div>
{/* Performance Metrics */}
<div className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div className="text-center">
<div className="text-2xl font-bold text-green-400">{(aiLearningStatus.avgAccuracy * 100).toFixed(1)}%</div>
<div className="text-xs text-gray-400">Avg Accuracy</div>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-blue-400">{(aiLearningStatus.winRate * 100).toFixed(1)}%</div>
<div className="text-xs text-gray-400">Win Rate</div>
</div>
</div>
<div className="text-center">
<div className="text-lg font-bold text-white">{aiLearningStatus.confidenceLevel.toFixed(1)}%</div>
<div className="text-xs text-gray-400">Confidence Level</div>
</div>
</div>
</div>
{/* Strengths and Improvements */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mt-6">
<div>
<h3 className="text-green-400 font-semibold mb-2">Strengths</h3>
<ul className="space-y-1">
{aiLearningStatus.strengths.map((strength, idx) => (
<li key={idx} className="text-sm text-gray-300"> {strength}</li>
))}
</ul>
</div>
<div>
<h3 className="text-yellow-400 font-semibold mb-2">Areas for Improvement</h3>
<ul className="space-y-1">
{aiLearningStatus.improvements.map((improvement, idx) => (
<li key={idx} className="text-sm text-gray-300"> {improvement}</li>
))}
</ul>
</div>
</div>
{/* Next Milestone */}
<div className="mt-4 p-3 bg-blue-900/20 rounded-lg border border-blue-600/30">
<div className="text-sm font-medium text-blue-400">Next Milestone</div>
<div className="text-white">{aiLearningStatus.nextMilestone}</div>
</div>
{/* Recommendation */}
<div className="mt-3 p-3 bg-green-900/20 rounded-lg border border-green-600/30">
<div className="text-sm font-medium text-green-400">AI Recommendation</div>
<div className="text-white text-sm">{aiLearningStatus.recommendation}</div>
</div>
</div>
)}
{/* Learning Insights */}
{learningInsights && (
<div className="card card-gradient p-6">
<h2 className="text-xl font-bold text-white mb-4">AI Learning Insights</h2>
<div className="space-y-3">
<div className="flex justify-between">
<span className="text-gray-300">Total Analyses:</span>
<span className="text-white font-semibold">{learningInsights.totalAnalyses}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Avg Accuracy:</span>
<span className="text-white font-semibold">{(learningInsights.avgAccuracy * 100).toFixed(1)}%</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Best Timeframe:</span>
<span className="text-green-400 font-semibold">{learningInsights.bestTimeframe}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Worst Timeframe:</span>
<span className="text-red-400 font-semibold">{learningInsights.worstTimeframe}</span>
</div>
<div className="mt-4">
<h3 className="text-lg font-semibold text-white mb-2">Recommendations</h3>
<ul className="space-y-1">
{learningInsights.recommendations.map((rec, idx) => (
<li key={idx} className="text-sm text-gray-300"> {rec}</li>
))}
</ul>
</div>
</div>
</div>
)}
</div>
{/* Status and Performance */}
<div className="space-y-6">
{/* Status Panel */}
<div className="card card-gradient p-6">
<h2 className="text-xl font-bold text-white mb-4">Status</h2>
{status ? (
<div className="space-y-3">
<div className="flex items-center justify-between">
<span className="text-gray-300">Status:</span>
<span className={`font-semibold px-2 py-1 rounded ${
status.isActive ? 'bg-green-600 text-white' : 'bg-red-600 text-white'
}`}>
{status.isActive ? 'ACTIVE' : 'STOPPED'}
</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Mode:</span>
<span className={`font-semibold ${
status.mode === 'LIVE' ? 'text-red-400' : 'text-blue-400'
}`}>
{status.mode}
</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Symbol:</span>
<span className="text-white font-semibold">{status.symbol}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Timeframe:</span>
<span className="text-white font-semibold">{status.timeframe}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Total Trades:</span>
<span className="text-white font-semibold">{status.totalTrades}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Win Rate:</span>
<span className={`font-semibold ${
calculateWinRate() > 60 ? 'text-green-400' :
calculateWinRate() > 40 ? 'text-yellow-400' : 'text-red-400'
}`}>
{calculateWinRate()}%
</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Total P&L:</span>
<span className={`font-semibold ${
calculateTotalPnL() > 0 ? 'text-green-400' :
calculateTotalPnL() < 0 ? 'text-red-400' : 'text-gray-300'
}`}>
${calculateTotalPnL()}
</span>
</div>
{status.lastAnalysis && (
<div className="flex justify-between">
<span className="text-gray-300">Last Analysis:</span>
<span className="text-white font-semibold">
{new Date(status.lastAnalysis).toLocaleTimeString()}
</span>
</div>
)}
{status.errorCount > 0 && (
<div className="flex justify-between">
<span className="text-gray-300">Errors:</span>
<span className="text-red-400 font-semibold">{status.errorCount}</span>
</div>
)}
</div>
) : (
<p className="text-gray-400">No active automation session</p>
)}
</div>
{/* Recent Trades */}
<div className="card card-gradient p-6">
<h2 className="text-xl font-bold text-white mb-4">Recent Automated Trades</h2>
{recentTrades.length > 0 ? (
<div className="space-y-4">
{recentTrades.slice(0, 5).map((trade, idx) => (
<div
key={idx}
className="p-4 bg-gray-800 rounded-lg border border-gray-700 cursor-pointer hover:bg-gray-750 transition-colors"
onClick={() => openTradeModal(trade.id)}
>
{/* Trade Header */}
<div className="flex items-center justify-between mb-3">
<div className="flex items-center space-x-2">
<span className={`font-semibold px-2 py-1 rounded text-xs ${
trade.side === 'BUY' ? 'bg-green-600 text-white' : 'bg-red-600 text-white'
}`}>
{trade.side}
</span>
<span className="text-white font-semibold">{trade.amount}</span>
<span className="text-yellow-400 font-semibold">{trade.leverage}x</span>
<span className={`px-2 py-1 rounded text-xs ${
trade.isActive ? 'bg-blue-600 text-white' :
trade.result === 'WIN' ? 'bg-green-600 text-white' :
trade.result === 'LOSS' ? 'bg-red-600 text-white' :
'bg-gray-600 text-white'
}`}>
{trade.isActive ? 'ACTIVE' : trade.result}
</span>
</div>
<div className="text-right">
<div className="text-white font-semibold">${trade.entryPrice?.toFixed(2) || trade.price?.toFixed(2) || '0.00'}</div>
<div className="text-sm text-gray-400">{trade.confidence || 0}% confidence</div>
</div>
</div>
{/* Enhanced Timing Information */}
<div className="mb-3 p-3 bg-gray-900/30 rounded border border-gray-700">
<div className="grid grid-cols-2 gap-2 text-xs">
<div className="flex justify-between">
<span className="text-gray-300">Entry Time:</span>
<span className="text-white">{new Date(trade.entryTime).toLocaleTimeString()}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Exit Time:</span>
<span className="text-white">
{trade.exitTime ? new Date(trade.exitTime).toLocaleTimeString() : 'Active'}
</span>
</div>
<div className="flex justify-between col-span-2">
<span className="text-gray-300">Duration:</span>
<span className="text-white font-semibold">{trade.durationText}</span>
</div>
</div>
</div>
{/* Trading Details */}
<div className="mb-3 p-3 bg-gray-900/30 rounded border border-gray-700">
<div className="grid grid-cols-2 gap-2 text-xs">
<div className="flex justify-between">
<span className="text-gray-300">Trading Amount:</span>
<span className="text-white">${trade.tradingAmount}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Leverage:</span>
<span className="text-yellow-400">{trade.leverage}x</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Position Size:</span>
<span className="text-white">${trade.positionSize}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">{trade.isActive ? 'Current' : 'Exit'} Price:</span>
<span className="text-white">
${trade.isActive ? (trade.currentPrice?.toFixed(2) || '0.00') : (trade.exitPrice?.toFixed(2) || '0.00')}
</span>
</div>
</div>
</div>
{/* P&L Display */}
<div className="mb-3 p-3 bg-gray-900/50 rounded border border-gray-600">
<div className="flex justify-between items-center text-sm">
<span className="text-gray-300">P&L:</span>
<div className="flex items-center space-x-2">
<span className={`font-bold ${
trade.isActive ?
(trade.unrealizedPnl && parseFloat(trade.unrealizedPnl) > 0 ? 'text-green-400' : 'text-red-400') :
(trade.realizedPnl && parseFloat(trade.realizedPnl) > 0 ? 'text-green-400' : 'text-red-400')
}`}>
${trade.isActive ?
(trade.unrealizedPnl || '0.00') :
(trade.realizedPnl || '0.00')
}
</span>
{trade.pnlPercent && (
<span className={`text-xs ${
trade.isActive ?
(trade.unrealizedPnl && parseFloat(trade.unrealizedPnl) > 0 ? 'text-green-400' : 'text-red-400') :
(trade.realizedPnl && parseFloat(trade.realizedPnl) > 0 ? 'text-green-400' : 'text-red-400')
}`}>
({trade.pnlPercent})
</span>
)}
<span className="text-xs text-gray-400">
{trade.isActive ? '(Unrealized)' : '(Realized)'}
</span>
</div>
</div>
</div>
{/* Click hint */}
<div className="flex justify-between items-center text-xs border-t border-gray-700 pt-2">
<div className="text-gray-400">
SL: ${trade.stopLoss} | TP: ${trade.takeProfit}
</div>
<div className="text-blue-400 hover:text-blue-300">
📊 Click to view analysis
</div>
</div>
</div>
))}
</div>
) : (
<p className="text-gray-400">No recent trades</p>
)}
</div>
</div>
</div>
{/* Detailed AI Analysis Section */}
{analysisDetails?.analysis && (
<div className="space-y-6">
<h2 className="text-2xl font-bold text-white">Latest AI Analysis</h2>
<div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-6">
{/* Main Decision */}
<div className="card card-gradient p-6">
<h3 className="text-lg font-bold text-white mb-4">🎯 Trading Decision</h3>
<div className="space-y-3">
<div className="flex justify-between">
<span className="text-gray-300">Decision:</span>
<span className={`font-bold px-2 py-1 rounded ${
analysisDetails.analysis.decision === 'BUY' ? 'bg-green-600 text-white' :
analysisDetails.analysis.decision === 'SELL' ? 'bg-red-600 text-white' :
'bg-gray-600 text-white'
}`}>
{analysisDetails.analysis.decision}
</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Confidence:</span>
<span className={`font-semibold ${
analysisDetails.analysis.confidence > 80 ? 'text-green-400' :
analysisDetails.analysis.confidence > 60 ? 'text-yellow-400' :
'text-red-400'
}`}>
{analysisDetails.analysis.confidence}%
</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Market Sentiment:</span>
<span className={`font-semibold ${
analysisDetails.analysis.sentiment === 'BULLISH' ? 'text-green-400' :
analysisDetails.analysis.sentiment === 'BEARISH' ? 'text-red-400' :
'text-gray-400'
}`}>
{analysisDetails.analysis.sentiment}
</span>
</div>
<div className="mt-4 p-3 bg-gray-800 rounded-lg">
<p className="text-sm text-gray-300">
<strong>Summary:</strong> {analysisDetails.analysis.summary}
</p>
</div>
</div>
</div>
{/* Key Levels */}
<div className="card card-gradient p-6">
<h3 className="text-lg font-bold text-white mb-4">📊 Key Levels</h3>
<div className="space-y-3">
{analysisDetails.analysis.keyLevels?.support?.length > 0 && (
<div>
<h4 className="text-sm font-semibold text-green-400 mb-2">Support Levels</h4>
{analysisDetails.analysis.keyLevels.support.map((level, idx) => (
<div key={idx} className="flex justify-between text-sm">
<span className="text-gray-300">S{idx + 1}:</span>
<span className="text-green-400 font-mono">${level.toFixed(2)}</span>
</div>
))}
</div>
)}
{analysisDetails.analysis.keyLevels?.resistance?.length > 0 && (
<div>
<h4 className="text-sm font-semibold text-red-400 mb-2">Resistance Levels</h4>
{analysisDetails.analysis.keyLevels.resistance.map((level, idx) => (
<div key={idx} className="flex justify-between text-sm">
<span className="text-gray-300">R{idx + 1}:</span>
<span className="text-red-400 font-mono">${level.toFixed(2)}</span>
</div>
))}
</div>
)}
</div>
</div>
{/* Technical Indicators */}
<div className="card card-gradient p-6">
<h3 className="text-lg font-bold text-white mb-4">📈 Technical Indicators</h3>
<div className="space-y-2">
{analysisDetails.analysis.technicalIndicators && Object.entries(analysisDetails.analysis.technicalIndicators).map(([key, value]) => (
<div key={key} className="flex justify-between text-sm">
<span className="text-gray-300 capitalize">{key.replace(/([A-Z])/g, ' $1').trim()}:</span>
<span className="text-white font-mono">
{typeof value === 'number' ? value.toFixed(2) : value}
</span>
</div>
))}
</div>
</div>
</div>
{/* AI Reasoning */}
{analysisDetails.analysis.reasoning && (
<div className="card card-gradient p-6">
<h3 className="text-lg font-bold text-white mb-4">🤖 AI Reasoning</h3>
<div className="space-y-3">
<div className="p-4 bg-gray-800 rounded-lg">
<p className="text-gray-300">{analysisDetails.analysis.reasoning}</p>
</div>
{analysisDetails.analysis.executionPlan && (
<div className="p-4 bg-blue-900/20 border border-blue-500/20 rounded-lg">
<h4 className="text-blue-400 font-semibold mb-2">Execution Plan:</h4>
<p className="text-gray-300">{analysisDetails.analysis.executionPlan}</p>
</div>
)}
</div>
</div>
)}
{/* Risk Assessment */}
{analysisDetails.analysis.riskAssessment && (
<div className="card card-gradient p-6">
<h3 className="text-lg font-bold text-white mb-4"> Risk Assessment</h3>
<div className="space-y-3">
<div className="p-4 bg-yellow-900/20 border border-yellow-500/20 rounded-lg">
<p className="text-gray-300">{analysisDetails.analysis.riskAssessment}</p>
</div>
{analysisDetails.analysis.marketConditions && (
<div className="p-4 bg-gray-800 rounded-lg">
<h4 className="text-gray-400 font-semibold mb-2">Market Conditions:</h4>
<p className="text-gray-300">{analysisDetails.analysis.marketConditions}</p>
</div>
)}
</div>
</div>
)}
{/* Layout Analysis */}
{analysisDetails.analysis.layoutAnalysis && (
<div className="card card-gradient p-6">
<h3 className="text-lg font-bold text-white mb-4">🔍 Multi-Layout Analysis</h3>
<div className="space-y-4">
{Object.entries(analysisDetails.analysis.layoutAnalysis).map(([layout, analysis]) => (
<div key={layout} className="p-4 bg-gray-800 rounded-lg">
<h4 className="text-blue-400 font-semibold mb-2 capitalize">{layout} Layout:</h4>
<p className="text-gray-300 text-sm">{analysis}</p>
</div>
))}
</div>
</div>
)}
{/* Performance Metrics */}
<div className="card card-gradient p-6">
<h3 className="text-lg font-bold text-white mb-4">📊 Analysis Performance</h3>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<div className="text-center">
<div className="text-2xl font-bold text-blue-400">
{analysisDetails.analysis.timestamp ?
new Date(analysisDetails.analysis.timestamp).toLocaleTimeString() :
'N/A'
}
</div>
<div className="text-sm text-gray-400">Last Analysis</div>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-green-400">
{analysisDetails.analysis.processingTime ?
`${analysisDetails.analysis.processingTime}ms` :
'N/A'
}
</div>
<div className="text-sm text-gray-400">Processing Time</div>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-purple-400">
{analysisDetails.session?.totalTrades || 0}
</div>
<div className="text-sm text-gray-400">Total Trades</div>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-yellow-400">
{analysisDetails.session?.errorCount || 0}
</div>
<div className="text-sm text-gray-400">Errors</div>
</div>
</div>
</div>
</div>
)}
{/* Multi-Timeframe Analysis Results */}
{analysisDetails?.analysis?.multiTimeframeResults && analysisDetails.analysis.multiTimeframeResults.length > 0 && (
<div className="space-y-6">
<h2 className="text-2xl font-bold text-white">📊 Multi-Timeframe Analysis</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{analysisDetails.analysis.multiTimeframeResults.map((result, index) => (
<div key={result.timeframe} className="card card-gradient p-6">
<div className="flex items-center justify-between mb-4">
<h3 className="text-lg font-bold text-white flex items-center">
{result.analysisComplete ? (
<span className="text-green-400 mr-2"></span>
) : (
<span className="text-yellow-400 mr-2"></span>
)}
{result.timeframe} Timeframe
</h3>
<span className={`text-xs px-2 py-1 rounded ${
result.analysisComplete ? 'bg-green-600 text-white' : 'bg-yellow-600 text-white'
}`}>
{result.analysisComplete ? 'Complete' : 'In Progress'}
</span>
</div>
<div className="space-y-3">
<div className="flex justify-between">
<span className="text-gray-300">Decision:</span>
<span className={`font-bold px-2 py-1 rounded text-sm ${
result.decision === 'BUY' ? 'bg-green-600 text-white' :
result.decision === 'SELL' ? 'bg-red-600 text-white' :
'bg-gray-600 text-white'
}`}>
{result.decision}
</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Confidence:</span>
<span className={`font-semibold ${
result.confidence > 80 ? 'text-green-400' :
result.confidence > 60 ? 'text-yellow-400' :
'text-red-400'
}`}>
{result.confidence}%
</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Sentiment:</span>
<span className={`font-semibold ${
result.sentiment === 'BULLISH' ? 'text-green-400' :
result.sentiment === 'BEARISH' ? 'text-red-400' :
'text-gray-400'
}`}>
{result.sentiment}
</span>
</div>
{result.createdAt && (
<div className="mt-4 pt-3 border-t border-gray-700">
<div className="text-xs text-gray-500">
Analyzed: {new Date(result.createdAt).toLocaleString()}
</div>
</div>
)}
</div>
</div>
))}
</div>
{/* Multi-Timeframe Summary */}
<div className="card card-gradient p-6">
<h3 className="text-lg font-bold text-white mb-4">📈 Cross-Timeframe Consensus</h3>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="text-center">
<div className="text-2xl font-bold text-blue-400">
{analysisDetails.analysis.multiTimeframeResults.length}
</div>
<div className="text-sm text-gray-400">Timeframes Analyzed</div>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-green-400">
{analysisDetails.analysis.multiTimeframeResults.filter(r => r.analysisComplete).length}
</div>
<div className="text-sm text-gray-400">Completed</div>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-yellow-400">
{Math.round(
analysisDetails.analysis.multiTimeframeResults.reduce((sum, r) => sum + r.confidence, 0) /
analysisDetails.analysis.multiTimeframeResults.length
)}%
</div>
<div className="text-sm text-gray-400">Avg Confidence</div>
</div>
</div>
</div>
</div>
)}
{/* No Analysis Available */}
{!analysisDetails?.analysis && status?.isActive && (
<div className="card card-gradient p-6">
<h3 className="text-lg font-bold text-white mb-4">🤖 AI Analysis</h3>
<div className="text-center py-8">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500 mx-auto mb-4"></div>
<p className="text-gray-400">Waiting for first analysis...</p>
<p className="text-sm text-gray-500 mt-2">The AI will analyze the market every hour</p>
</div>
</div>
)}
{/* Trade Details Modal */}
{tradeModalOpen && selectedTrade && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
<div className="bg-gray-900 rounded-lg max-w-6xl max-h-[90vh] overflow-y-auto border border-gray-700">
{/* Modal Header */}
<div className="flex items-center justify-between p-6 border-b border-gray-700">
<div className="flex items-center space-x-4">
<h2 className="text-2xl font-bold text-white">Trade Analysis Details</h2>
<span className={`px-3 py-1 rounded text-sm font-semibold ${
selectedTrade.side === 'BUY' ? 'bg-green-600 text-white' : 'bg-red-600 text-white'
}`}>
{selectedTrade.side} {selectedTrade.amount} @ ${selectedTrade.price?.toFixed(2) || '0.00'}
</span>
<span className={`px-2 py-1 rounded text-xs ${
selectedTrade.status === 'OPEN' ? 'bg-blue-600 text-white' :
(selectedTrade.profit || 0) > 0 ? 'bg-green-600 text-white' : 'bg-red-600 text-white'
}`}>
{selectedTrade.status} {selectedTrade.profit && `(${selectedTrade.profit > 0 ? '+' : ''}$${selectedTrade.profit?.toFixed(2) || '0.00'})`}
</span>
</div>
<button
onClick={closeTradeModal}
className="text-gray-400 hover:text-white text-2xl"
>
×
</button>
</div>
{/* Modal Content */}
<div className="p-6 space-y-6">
{/* Trade Overview */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="bg-gray-800 p-4 rounded-lg">
<h3 className="text-lg font-semibold text-white mb-2">Trade Info</h3>
<div className="space-y-2 text-sm">
<div className="flex justify-between">
<span className="text-gray-300">Entry Time:</span>
<span className="text-white">{new Date(selectedTrade.entryTime).toLocaleString()}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Exit Time:</span>
<span className="text-white">
{selectedTrade.exitTime ? new Date(selectedTrade.exitTime).toLocaleString() : 'Active'}
</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Duration:</span>
<span className="text-white font-semibold">
{selectedTrade.exitTime ?
`${Math.floor((new Date(selectedTrade.exitTime) - new Date(selectedTrade.entryTime)) / (1000 * 60))}m` :
`${Math.floor((new Date() - new Date(selectedTrade.entryTime)) / (1000 * 60))}m (Active)`
}
</span>
</div>
</div>
</div>
<div className="bg-gray-800 p-4 rounded-lg">
<h3 className="text-lg font-semibold text-white mb-2">Position Details</h3>
<div className="space-y-2 text-sm">
<div className="flex justify-between">
<span className="text-gray-300">Trading Amount:</span>
<span className="text-white">${selectedTrade.tradingAmount}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Leverage:</span>
<span className="text-yellow-400">{selectedTrade.leverage}x</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Position Size:</span>
<span className="text-white">${selectedTrade.positionSize}</span>
</div>
</div>
</div>
<div className="bg-gray-800 p-4 rounded-lg">
<h3 className="text-lg font-semibold text-white mb-2">Risk Management</h3>
<div className="space-y-2 text-sm">
<div className="flex justify-between">
<span className="text-gray-300">Stop Loss:</span>
<span className="text-red-400">${selectedTrade.detailedAnalysis?.keyLevels?.stopLoss?.price || 'N/A'}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Take Profit:</span>
<span className="text-green-400">${selectedTrade.detailedAnalysis?.keyLevels?.takeProfit?.price || 'N/A'}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Risk/Reward:</span>
<span className="text-white">{selectedTrade.detailedAnalysis?.riskManagement?.riskReward || 'N/A'}</span>
</div>
</div>
</div>
</div>
{/* Analysis Screenshots */}
<div className="bg-gray-800 p-4 rounded-lg">
<h3 className="text-lg font-semibold text-white mb-4">📊 Analysis Screenshots</h3>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
{selectedTrade.screenshots && Object.entries(selectedTrade.screenshots).map(([key, screenshot]) => (
<div key={key} className="bg-gray-700 p-3 rounded-lg">
<h4 className="text-white font-semibold mb-2">{screenshot.title}</h4>
<div className="bg-gray-600 h-48 rounded-lg flex items-center justify-center text-gray-400 text-sm text-center">
<div>
📷 {screenshot.title}
<br />
<span className="text-xs">{screenshot.description}</span>
</div>
</div>
<p className="text-xs text-gray-400 mt-2">{screenshot.description}</p>
</div>
))}
</div>
</div>
{/* AI Analysis Details */}
{selectedTrade.detailedAnalysis && (
<div className="bg-gray-800 p-4 rounded-lg">
<h3 className="text-lg font-semibold text-white mb-4">🤖 AI Analysis</h3>
{/* Decision Summary */}
<div className="mb-6 p-4 bg-gray-700 rounded-lg">
<div className="flex items-center justify-between mb-2">
<h4 className="text-blue-400 font-semibold">Decision Summary</h4>
<span className={`px-2 py-1 rounded text-xs ${
selectedTrade.detailedAnalysis.decision === 'BUY' ? 'bg-green-600 text-white' : 'bg-red-600 text-white'
}`}>
{selectedTrade.detailedAnalysis.decision} ({selectedTrade.detailedAnalysis.confidence}%)
</span>
</div>
<p className="text-gray-300 text-sm whitespace-pre-line">{selectedTrade.detailedAnalysis.aiReasoning}</p>
</div>
{/* Multi-timeframe Analysis */}
<div className="mb-6">
<h4 className="text-yellow-400 font-semibold mb-3">Multi-timeframe Analysis</h4>
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
{selectedTrade.detailedAnalysis.timeframes && Object.entries(selectedTrade.detailedAnalysis.timeframes).map(([tf, data]) => (
<div key={tf} className="bg-gray-700 p-3 rounded-lg">
<div className="flex items-center justify-between mb-2">
<span className="text-white font-semibold">{tf}</span>
<span className={`px-2 py-1 rounded text-xs ${
data.decision === 'BUY' ? 'bg-green-600 text-white' : 'bg-red-600 text-white'
}`}>
{data.decision}
</span>
</div>
<div className="text-xs text-gray-400 mb-1">
Confidence: {data.confidence}%
</div>
<div className="text-xs text-gray-300">
{data.signals.slice(0, 2).map((signal, idx) => (
<div key={idx}> {signal}</div>
))}
</div>
</div>
))}
</div>
</div>
{/* Technical Indicators */}
<div className="mb-6">
<h4 className="text-green-400 font-semibold mb-3">Technical Indicators</h4>
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
{selectedTrade.detailedAnalysis.technicalIndicators && Object.entries(selectedTrade.detailedAnalysis.technicalIndicators).map(([indicator, data]) => (
<div key={indicator} className="bg-gray-700 p-3 rounded-lg">
<div className="text-white font-semibold mb-1 capitalize">{indicator}</div>
<div className="text-yellow-400 text-sm">{data.value}</div>
<div className="text-xs text-gray-400 mt-1">{data.interpretation}</div>
</div>
))}
</div>
</div>
{/* Execution Plan */}
<div className="bg-gray-700 p-4 rounded-lg">
<h4 className="text-purple-400 font-semibold mb-3">Execution Plan</h4>
<div className="space-y-2 text-sm">
{selectedTrade.detailedAnalysis.executionPlan && Object.entries(selectedTrade.detailedAnalysis.executionPlan).map(([key, value]) => (
<div key={key} className="flex">
<span className="text-gray-300 capitalize w-24">{key}:</span>
<span className="text-white">{value}</span>
</div>
))}
</div>
</div>
</div>
)}
</div>
</div>
</div>
)}
</div>
)
}