- Created comprehensive AI learning system documentation (AI_LEARNING_SYSTEM.md) - Implemented real-time AI learning status tracking service (lib/ai-learning-status.ts) - Added AI learning status API endpoint (/api/ai-learning-status) - Enhanced dashboard with AI learning status indicators - Added detailed AI learning status section to automation page - Learning phase tracking (INITIAL → PATTERN_RECOGNITION → ADVANCED → EXPERT) - Real-time performance metrics (accuracy, win rate, confidence level) - Progress tracking with milestones and recommendations - Strengths and improvement areas identification - Realistic progression based on actual trading data - Dashboard overview: AI learning status card with key metrics - Automation page: Comprehensive learning breakdown with phase indicators - Real-time updates every 30 seconds - Color-coded phase indicators and performance metrics - Next milestone tracking and AI recommendations - TypeScript service for learning status calculation - RESTful API endpoint for programmatic access - Integration with existing database schema - Realistic progression algorithms based on analysis count - Accurate trade counting matching UI display (fixed from 1 to 4 trades) Features: Complete learning phase progression system Real-time performance tracking and metrics Intelligent recommendations based on AI performance Transparent learning process with clear milestones Enhanced user confidence through progress visibility Accurate trade count matching actual UI display (4 trades) Realistic win rate calculation (66.7% from demo data) Progressive accuracy and confidence improvements
921 lines
41 KiB
JavaScript
921 lines
41 KiB
JavaScript
'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)
|
||
|
||
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)
|
||
}
|
||
}
|
||
|
||
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 ${
|
||
status.winRate > 0.6 ? 'text-green-400' :
|
||
status.winRate > 0.4 ? 'text-yellow-400' : 'text-red-400'
|
||
}`}>
|
||
{(status.winRate * 100).toFixed(1)}%
|
||
</span>
|
||
</div>
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-300">Total P&L:</span>
|
||
<span className={`font-semibold ${
|
||
status.totalPnL > 0 ? 'text-green-400' :
|
||
status.totalPnL < 0 ? 'text-red-400' : 'text-gray-300'
|
||
}`}>
|
||
${status.totalPnL.toFixed(2)}
|
||
</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">
|
||
{/* 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={`px-2 py-1 rounded text-xs ${
|
||
trade.isActive ? 'bg-blue-600 text-white' :
|
||
trade.result === 'PROFIT' ? '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)}</div>
|
||
<div className="text-sm text-gray-400">{trade.confidence}% confidence</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Analysis Context */}
|
||
{trade.triggerAnalysis && (
|
||
<div className="mb-3 p-3 bg-gray-900 rounded border border-gray-600">
|
||
<h4 className="text-blue-400 font-semibold text-sm mb-2">📊 Trigger Analysis</h4>
|
||
<div className="space-y-1 text-xs">
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-300">Decision:</span>
|
||
<span className="text-white">{trade.triggerAnalysis.decision} ({trade.triggerAnalysis.confidence}%)</span>
|
||
</div>
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-300">Market Condition:</span>
|
||
<span className="text-white">{trade.triggerAnalysis.marketCondition}</span>
|
||
</div>
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-300">Expected R/R:</span>
|
||
<span className="text-white">{trade.triggerAnalysis.riskReward}</span>
|
||
</div>
|
||
<div className="mt-2">
|
||
<span className="text-gray-300">Key Signals:</span>
|
||
<ul className="text-white ml-2 mt-1">
|
||
{trade.triggerAnalysis.keySignals.map((signal, signalIdx) => (
|
||
<li key={signalIdx} className="text-xs">• {signal}</li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* Current Metrics (Active Trades) */}
|
||
{trade.isActive && trade.currentMetrics && (
|
||
<div className="mb-3 p-3 bg-blue-900/20 rounded border border-blue-600/30">
|
||
<h4 className="text-blue-400 font-semibold text-sm mb-2">📈 Current Status</h4>
|
||
<div className="grid grid-cols-2 gap-2 text-xs">
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-300">Current Price:</span>
|
||
<span className="text-white">${trade.currentMetrics.currentPrice.toFixed(2)}</span>
|
||
</div>
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-300">Price Change:</span>
|
||
<span className={`${trade.currentMetrics.priceChange > 0 ? 'text-green-400' : 'text-red-400'}`}>
|
||
{trade.currentMetrics.priceChange > 0 ? '+' : ''}${trade.currentMetrics.priceChange.toFixed(2)}
|
||
</span>
|
||
</div>
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-300">Unrealized P&L:</span>
|
||
<span className={`${trade.currentMetrics.unrealizedPnL > 0 ? 'text-green-400' : 'text-red-400'}`}>
|
||
{trade.currentMetrics.unrealizedPnL > 0 ? '+' : ''}${trade.currentMetrics.unrealizedPnL.toFixed(2)}
|
||
</span>
|
||
</div>
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-300">Time in Trade:</span>
|
||
<span className="text-white">{trade.currentMetrics.timeInTrade}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* Exit Metrics (Completed Trades) */}
|
||
{!trade.isActive && trade.exitMetrics && (
|
||
<div className="mb-3 p-3 bg-gray-900/50 rounded border border-gray-600">
|
||
<h4 className="text-gray-400 font-semibold text-sm mb-2">📊 Exit Analysis</h4>
|
||
<div className="space-y-1 text-xs">
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-300">Exit Reason:</span>
|
||
<span className="text-white">{trade.exitMetrics.exitReason}</span>
|
||
</div>
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-300">Exit Price:</span>
|
||
<span className="text-white">${trade.exitMetrics.exitPrice.toFixed(2)}</span>
|
||
</div>
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-300">Analysis Accuracy:</span>
|
||
<span className={`${trade.exitMetrics.analysisAccuracy.includes('Excellent') ? 'text-green-400' :
|
||
trade.exitMetrics.analysisAccuracy.includes('Good') ? 'text-yellow-400' : 'text-red-400'}`}>
|
||
{trade.exitMetrics.analysisAccuracy}
|
||
</span>
|
||
</div>
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-300">Actual R/R:</span>
|
||
<span className="text-white">{trade.exitMetrics.actualRiskReward}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* Trade Summary */}
|
||
<div className="flex justify-between items-center text-xs border-t border-gray-700 pt-2">
|
||
<div className="text-gray-400">
|
||
{trade.duration}
|
||
</div>
|
||
<div className="flex items-center space-x-4">
|
||
<div className="text-gray-400">
|
||
SL: ${trade.stopLoss} | TP: ${trade.takeProfit}
|
||
</div>
|
||
<div className={`font-semibold ${
|
||
trade.isActive ?
|
||
(trade.unrealizedPnl > 0 ? 'text-green-400' : 'text-red-400') :
|
||
(trade.pnl > 0 ? 'text-green-400' : 'text-red-400')
|
||
}`}>
|
||
{trade.isActive ?
|
||
`P&L: ${trade.unrealizedPnl > 0 ? '+' : ''}${trade.unrealizedPnl}` :
|
||
`P&L: ${trade.pnl > 0 ? '+' : ''}${trade.pnl}`
|
||
}
|
||
</div>
|
||
</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>
|
||
)}
|
||
|
||
{/* 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>
|
||
)}
|
||
</div>
|
||
)
|
||
}
|