Files
trading_bot_v3/app/automation-v2/page.js
mindesbunister 6b5b955589 feat: add retroactive position analysis functionality
New Features:
- 🔍 ANALYZE button to generate AI reasoning for existing positions
- Retroactive AI analysis API endpoint for positions opened outside automation
- Enhanced reasoning display with RETROACTIVE indicator
- Smart position analysis that handles missing stop loss data

- /api/automation/analyze-position endpoint for retroactive analysis
- analyzeExistingPosition() function in automation-v2 UI
- Automatic estimation of stop loss when not visible in position data
- Enhanced AI reasoning panel with retroactive analysis support

- Analyzes entry strategy, risk management, and leverage calculations
- Generates detailed AI reasoning for existing positions
- Shows estimated vs actual stop loss levels
- Calculates risk/reward ratios and leverage estimates
- Displays position status (profitable/underwater) with safety metrics

- RETROACTIVE badge for analyzed existing positions
- Blue 🔍 ANALYZE button in automation controls
- Enhanced reasoning display with position-specific insights
- Comprehensive execution details with estimated vs actual data

Now users can see AI reasoning for any existing position, not just new automation trades!
2025-07-27 08:59:50 +02:00

1037 lines
47 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'
// Available timeframes for automation (matching analysis page format)
const timeframes = [
{ label: '5m', value: '5' },
{ label: '15m', value: '15' },
{ label: '30m', value: '30' },
{ label: '1h', value: '60' },
{ label: '2h', value: '120' },
{ label: '4h', value: '240' },
{ label: '1d', value: 'D' },
]
export default function AutomationPageV2() {
const [config, setConfig] = useState({
mode: 'SIMULATION',
dexProvider: 'DRIFT',
symbol: 'SOLUSD',
selectedTimeframes: ['60'], // Multi-timeframe support
tradingAmount: 100,
balancePercentage: 50, // Default to 50% of available balance
})
const [status, setStatus] = useState(null)
const [balance, setBalance] = useState(null)
const [positions, setPositions] = useState([])
const [loading, setLoading] = useState(false)
const [monitorData, setMonitorData] = useState(null)
useEffect(() => {
fetchStatus()
fetchBalance()
fetchPositions()
fetchMonitorData()
fetchMonitorData()
const interval = setInterval(() => {
fetchStatus()
fetchBalance()
fetchPositions()
fetchMonitorData()
}, 300000) // 5 minutes instead of 30 seconds
return () => clearInterval(interval)
}, [])
const toggleTimeframe = (timeframe) => {
setConfig(prev => ({
...prev,
selectedTimeframes: prev.selectedTimeframes.includes(timeframe)
? prev.selectedTimeframes.filter(tf => tf !== timeframe)
: [...prev.selectedTimeframes, timeframe]
}))
}
const fetchStatus = async () => {
try {
const response = await fetch('/api/automation/status')
const data = await response.json()
console.log('Status response:', data) // Debug log
if (response.ok && !data.error) {
setStatus(data) // Status data is returned directly, not wrapped in 'success'
} else {
console.error('Status API error:', data.error || 'Unknown error')
}
} catch (error) {
console.error('Failed to fetch status:', error)
}
}
const fetchBalance = async () => {
try {
const response = await fetch('/api/drift/balance')
const data = await response.json()
if (data.success) {
setBalance(data)
}
} catch (error) {
console.error('Failed to fetch balance:', error)
}
}
const fetchMonitorData = async () => {
try {
const response = await fetch('/api/automation/position-monitor')
const data = await response.json()
if (data.success) {
setMonitorData(data.monitor)
}
} catch (error) {
console.error('Failed to fetch monitor data:', error)
}
}
const fetchPositions = async () => {
try {
const response = await fetch('/api/drift/positions')
const data = await response.json()
if (data.success) {
setPositions(data.positions || [])
}
} catch (error) {
console.error('Failed to fetch positions:', error)
}
}
const handleStart = async () => {
console.log('🚀 Starting automation...')
setLoading(true)
try {
if (config.selectedTimeframes.length === 0) {
console.error('No timeframes selected')
setLoading(false)
return
}
const automationConfig = {
symbol: config.symbol,
selectedTimeframes: config.selectedTimeframes,
mode: config.mode,
tradingAmount: config.tradingAmount,
leverage: config.leverage,
stopLoss: config.stopLoss,
takeProfit: config.takeProfit
}
const response = await fetch('/api/automation/start', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(automationConfig)
})
const data = await response.json()
if (data.success) {
console.log('✅ Automation started successfully')
fetchStatus()
} else {
console.error('Failed to start automation:', data.error)
}
} catch (error) {
console.error('Failed to start automation:', error)
} finally {
setLoading(false)
}
}
const handleStop = async () => {
console.log('🛑 Stopping automation...')
setLoading(true)
try {
const response = await fetch('/api/automation/stop', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
})
const data = await response.json()
if (data.success) {
console.log('✅ Automation stopped successfully')
fetchStatus()
} else {
console.error('Failed to stop automation:', data.error)
}
} catch (error) {
console.error('Failed to stop automation:', error)
} finally {
setLoading(false)
}
}
const handleEmergencyStop = async () => {
console.log('🚨 Emergency stop triggered!')
setLoading(true)
try {
const response = await fetch('/api/automation/emergency-stop', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
})
const data = await response.json()
if (data.success) {
console.log('✅ Emergency stop completed successfully')
fetchStatus()
fetchPositions()
fetchMonitorData()
fetchMonitorData()
} else {
console.error('Emergency stop failed:', data.error)
}
} catch (error) {
console.error('Emergency stop error:', error)
} finally {
setLoading(false)
}
}
const generateTestDecision = async () => {
console.log('🧪 Generating test AI decision...')
setLoading(true)
try {
const response = await fetch('/api/automation/test-decision', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
action: 'generate_test_decision',
analysis: {
recommendation: 'STRONG BUY',
confidence: 89,
reasoning: `🎯 BULLISH CONVERGENCE DETECTED:
📈 Technical Analysis:
• RSI bounced from oversold (28→54) showing strong recovery momentum
• MACD histogram turning positive with bullish crossover confirmed
• Price broke above key resistance at $185.40 with 3x normal volume
• 20 EMA (184.92) providing strong support, price trending above all major EMAs
📊 Market Structure:
• Higher lows pattern intact since yesterday's session
• Volume profile shows accumulation at current levels
• Order book depth favoring buyers (67% buy-side liquidity)
⚡ Entry Trigger:
• Breakout candle closed above $186.00 resistance with conviction
• Next resistance target: $189.75 (2.1% upside potential)
• Risk/Reward ratio: 1:2.3 (excellent risk management setup)
🛡️ Risk Management:
• Stop loss at $184.20 (1.0% below entry) protects against false breakout
• Position sizing optimized for 2% account risk tolerance`,
stopLoss: 184.20,
takeProfit: 189.75,
currentPrice: 186.12,
stopLossPercent: '1.0% protective stop'
},
config: {
selectedTimeframes: config.selectedTimeframes,
symbol: config.symbol,
mode: config.mode,
enableTrading: config.enableTrading,
tradingAmount: 62
}
})
})
const data = await response.json()
if (data.success) {
console.log('✅ Test decision generated successfully')
fetchStatus() // Refresh to show the decision
} else {
console.error('Failed to generate test decision:', data.error)
}
} catch (error) {
console.error('Test decision error:', error)
} finally {
setLoading(false)
}
}
const analyzeExistingPosition = async () => {
console.log('🔍 Analyzing existing position...')
setLoading(true)
try {
// First get the current position data
const positionResponse = await fetch('/api/automation/position-monitor')
const positionData = await positionResponse.json()
if (positionData.success && positionData.monitor.hasPosition) {
// Analyze the existing position
const response = await fetch('/api/automation/analyze-position', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
action: 'analyze_existing_position',
positionData: positionData.monitor.position
})
})
const data = await response.json()
if (data.success) {
console.log('✅ Position analysis generated successfully')
fetchStatus() // Refresh to show the analysis
} else {
console.error('Failed to analyze position:', data.error)
}
} else {
console.log(' No position found to analyze')
alert('No active position found to analyze')
}
} catch (error) {
console.error('Position analysis error:', error)
} finally {
setLoading(false)
}
}
return (
<div className="space-y-6">
<div className="grid grid-cols-1 xl:grid-cols-3 gap-6">
{/* 🤖 Automation Control Panel */}
<div className="xl:col-span-2 space-y-6">
<div className="bg-gray-800 p-6 rounded-lg border border-gray-700">
{/* Header with Start/Stop Button */}
{/* Header with Start/Stop Button */}
<div className="flex items-center justify-between mb-6">
<h3 className="text-xl font-bold text-white">🤖 Automation Control</h3>
<div className="flex space-x-3">
{status?.isActive ? (
<>
<button
onClick={handleStop}
disabled={loading}
className="px-6 py-3 bg-red-600 text-white rounded-lg hover:bg-red-700 transition-colors disabled:opacity-50 font-semibold"
>
{loading ? 'Stopping...' : '🛑 STOP'}
</button>
<button
onClick={handleEmergencyStop}
disabled={loading}
className="px-4 py-3 bg-red-800 text-white rounded-lg hover:bg-red-900 transition-colors disabled:opacity-50 font-semibold border-2 border-red-600"
title="Emergency Stop - Closes all positions immediately"
>
🚨 EMERGENCY
</button>
<button
onClick={generateTestDecision}
disabled={loading}
className="px-4 py-3 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors disabled:opacity-50 font-semibold border-2 border-purple-500"
title="Generate Test AI Decision - Shows reasoning panel"
>
🧪 TEST AI
</button>
<button
onClick={analyzeExistingPosition}
disabled={loading}
className="px-4 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50 font-semibold border-2 border-blue-500"
title="Analyze Current Position - Generate AI reasoning for existing position"
>
🔍 ANALYZE
</button>
</>
) : (
<button
onClick={handleStart}
disabled={loading}
className="px-6 py-3 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors disabled:opacity-50 font-semibold"
>
{loading ? 'Starting...' : status?.rateLimitHit ? '🔄 RESTART' : '🚀 START'}
</button>
)}
</div>
</div>
{/* Trading Mode - Side by Side Radio Buttons with Logos */}
<div className="mb-6">
<label className="block text-sm font-bold text-blue-400 mb-3">Trading Mode</label>
<div className="grid grid-cols-2 gap-4">
<label className="flex items-center space-x-3 cursor-pointer p-4 rounded-lg border border-gray-600 hover:border-blue-500 transition-colors">
<input
type="radio"
className="w-5 h-5 text-blue-600"
name="mode"
checked={config.mode === 'SIMULATION'}
onChange={() => setConfig({...config, mode: 'SIMULATION'})}
disabled={status?.isActive}
/>
<div className="flex items-center space-x-2">
<span className="text-2xl">📊</span>
<span className="text-white font-medium">Paper Trading</span>
</div>
</label>
<label className="flex items-center space-x-3 cursor-pointer p-4 rounded-lg border border-gray-600 hover:border-green-500 transition-colors">
<input
type="radio"
className="w-5 h-5 text-green-600"
name="mode"
checked={config.mode === 'LIVE'}
onChange={() => setConfig({...config, mode: 'LIVE'})}
disabled={status?.isActive}
/>
<div className="flex items-center space-x-2">
<span className="text-2xl">💰</span>
<span className="text-white font-semibold">Live Trading</span>
</div>
</label>
</div>
</div>
{/* Symbol and Position Size */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">Symbol</label>
<select
className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-blue-500"
value={config.symbol}
onChange={(e) => setConfig({...config, symbol: e.target.value})}
disabled={status?.isActive}
>
<option value="SOLUSD">SOL/USD</option>
<option value="BTCUSD">BTC/USD</option>
<option value="ETHUSD">ETH/USD</option>
<option value="APTUSD">APT/USD</option>
<option value="AVAXUSD">AVAX/USD</option>
<option value="DOGEUSD">DOGE/USD</option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
Balance to Use: {config.balancePercentage}%
{balance && ` ($${(parseFloat(balance.availableBalance) * config.balancePercentage / 100).toFixed(2)})`}
</label>
<input
type="range"
className="w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer"
style={{
background: `linear-gradient(to right, #3b82f6 0%, #3b82f6 ${config.balancePercentage}%, #374151 ${config.balancePercentage}%, #374151 100%)`
}}
min="10"
max="100"
step="5"
value={config.balancePercentage}
onChange={(e) => {
const percentage = parseFloat(e.target.value);
const newAmount = balance ? (parseFloat(balance.availableBalance) * percentage / 100) : 100;
setConfig({
...config,
balancePercentage: percentage,
tradingAmount: Math.round(newAmount)
});
}}
disabled={status?.isActive}
/>
<div className="flex justify-between text-xs text-gray-400 mt-1">
<span>10%</span>
<span>50%</span>
<span>100%</span>
</div>
</div>
</div>
{/* MULTI-TIMEFRAME SELECTION */}
<div className="mb-6">
<label className="block text-sm font-medium text-gray-300 mb-2">
Analysis Timeframes
<span className="text-xs text-cyan-400 ml-2">({config.selectedTimeframes.length} selected)</span>
{config.selectedTimeframes.length === 0 && (
<span className="text-xs text-red-400 ml-2"> At least one timeframe required</span>
)}
</label>
{/* Timeframe Checkboxes */}
<div className="grid grid-cols-4 gap-2 mb-3">
{timeframes.map(tf => (
<label key={tf.value} className="group relative cursor-pointer">
<input
type="checkbox"
checked={config.selectedTimeframes.includes(tf.value)}
onChange={() => toggleTimeframe(tf.value)}
disabled={status?.isActive}
className="sr-only"
/>
<div className={`flex items-center justify-center p-2 rounded-lg border transition-all text-xs font-medium ${
config.selectedTimeframes.includes(tf.value)
? 'border-cyan-500 bg-cyan-500/10 text-cyan-300 shadow-lg shadow-cyan-500/20'
: status?.isActive
? 'border-gray-700 bg-gray-800/30 text-gray-500 cursor-not-allowed'
: 'border-gray-700 bg-gray-800/30 text-gray-400 hover:border-gray-600 hover:bg-gray-800/50 hover:text-gray-300'
}`}>
{tf.label}
{config.selectedTimeframes.includes(tf.value) && (
<div className="absolute top-0.5 right-0.5 w-1.5 h-1.5 bg-cyan-400 rounded-full"></div>
)}
</div>
</label>
))}
</div>
{/* Selected Timeframes Display */}
{config.selectedTimeframes.length > 0 && (
<div className="p-2 bg-gray-800/30 rounded-lg mb-3">
<div className="text-xs text-gray-400">
Selected: <span className="text-cyan-400">
{config.selectedTimeframes.map(tf => timeframes.find(t => t.value === tf)?.label || tf).filter(Boolean).join(', ')}
</span>
</div>
<div className="text-xs text-gray-500 mt-1">
💡 Multiple timeframes provide more robust analysis
</div>
</div>
)}
{/* Quick Selection Buttons - Made Bigger */}
<div className="grid grid-cols-3 gap-3">
<button
type="button"
onClick={() => setConfig({...config, selectedTimeframes: ['5', '15', '30']})}
disabled={status?.isActive}
className="py-3 px-4 rounded-lg text-sm font-medium bg-green-600/20 text-green-300 hover:bg-green-600/30 transition-all disabled:opacity-50 disabled:cursor-not-allowed border border-green-600/30 hover:border-green-600/50"
>
<div className="text-lg mb-1">📈</div>
<div>Scalping</div>
<div className="text-xs opacity-75">5m, 15m, 30m</div>
</button>
<button
type="button"
onClick={() => setConfig({...config, selectedTimeframes: ['60', '120']})}
disabled={status?.isActive}
className="py-3 px-4 rounded-lg text-sm font-medium bg-blue-600/20 text-blue-300 hover:bg-blue-600/30 transition-all disabled:opacity-50 disabled:cursor-not-allowed border border-blue-600/30 hover:border-blue-600/50"
>
<div className="text-lg mb-1"></div>
<div>Day Trading</div>
<div className="text-xs opacity-75">1h, 2h</div>
</button>
<button
type="button"
onClick={() => setConfig({...config, selectedTimeframes: ['240', 'D']})}
disabled={status?.isActive}
className="py-3 px-4 rounded-lg text-sm font-medium bg-purple-600/20 text-purple-300 hover:bg-purple-600/30 transition-all disabled:opacity-50 disabled:cursor-not-allowed border border-purple-600/30 hover:border-purple-600/50"
>
<div className="text-lg mb-1">🎯</div>
<div>Swing Trading</div>
<div className="text-xs opacity-75">4h, 1d</div>
</button>
</div>
</div>
</div>
</div>
{/* Status and Info Panel */}
<div className="space-y-6">
{/* Status */}
<div className="bg-gray-800 p-6 rounded-lg border border-gray-700">
<h3 className="text-lg font-bold text-white mb-4">🤖 Bot Status</h3>
<div className="space-y-3">
<div className="flex justify-between items-center">
<span className="text-gray-400">Status:</span>
<span className={`px-2 py-1 rounded text-xs font-semibold ${
status?.isActive ? 'bg-green-600 text-white' : 'bg-gray-600 text-gray-300'
}`}>
{status?.isActive ? 'RUNNING' : 'STOPPED'}
</span>
</div>
{status?.isActive && (
<>
<div className="flex justify-between items-center">
<span className="text-gray-400">Symbol:</span>
<span className="text-white font-medium">{status.symbol}</span>
</div>
<div className="flex justify-between items-center">
<span className="text-gray-400">Mode:</span>
<span className={`px-2 py-1 rounded text-xs font-semibold ${
status.mode === 'LIVE' ? 'bg-red-600 text-white' : 'bg-blue-600 text-white'
}`}>
{status.mode}
</span>
</div>
<div className="flex justify-between items-center">
<span className="text-gray-400">Timeframes:</span>
<span className="text-cyan-400 text-xs">
{status.timeframes?.map(tf => timeframes.find(t => t.value === tf)?.label || tf).join(', ')}
</span>
</div>
</>
)}
{/* Rate Limit Notification */}
{status?.rateLimitHit && (
<div className="mt-4 p-3 bg-red-900 border border-red-600 rounded-lg">
<div className="flex items-center space-x-2">
<span className="text-red-400 font-semibold"> Rate Limit Reached</span>
</div>
{status.rateLimitMessage && (
<p className="text-red-300 text-sm mt-1">{status.rateLimitMessage}</p>
)}
<p className="text-red-200 text-xs mt-2">
Automation stopped automatically. Please recharge your OpenAI account to continue.
</p>
</div>
)}
</div>
</div>
{/* AI Reasoning & Decision Analysis Panel - Always Visible */}
<div className="bg-gradient-to-br from-purple-900/30 via-blue-900/20 to-purple-900/30 p-6 rounded-lg border-2 border-purple-500/30 shadow-lg">
<div className="flex items-center justify-between mb-4">
<h3 className="text-xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-purple-400 to-blue-400">
🧠 AI Trading Analysis
</h3>
<div className="flex items-center space-x-2">
<div className={`w-2 h-2 rounded-full ${status?.lastDecision ? 'bg-green-400 animate-pulse' : 'bg-gray-500'}`}></div>
<span className="text-xs text-gray-400">
{status?.lastDecision ? 'Analysis Available' : 'Waiting for Analysis'}
</span>
</div>
</div>
{status?.lastDecision ? (
<div className="space-y-6">
{/* Decision Summary */}
<div className="bg-black/20 rounded-lg p-4 border border-purple-500/20">
<div className="flex items-center justify-between mb-3">
<div className="flex items-center space-x-3">
<div className={`px-3 py-1 rounded-full text-sm font-bold ${
status.lastDecision.recommendation?.toLowerCase().includes('buy')
? 'bg-green-500/20 text-green-300 border border-green-500/30'
: status.lastDecision.recommendation?.toLowerCase().includes('sell')
? 'bg-red-500/20 text-red-300 border border-red-500/30'
: 'bg-gray-500/20 text-gray-300 border border-gray-500/30'
}`}>
{status.lastDecision.recommendation || 'HOLD'}
</div>
{status.lastDecision.isRetrospective && (
<div className="px-2 py-1 rounded-full text-xs font-bold bg-orange-500/20 text-orange-300 border border-orange-500/30">
📊 RETROACTIVE
</div>
)}
<div className="flex items-center space-x-2">
<span className="text-gray-400 text-sm">Confidence:</span>
<div className={`px-2 py-1 rounded text-sm font-bold ${
status.lastDecision.confidence >= 80 ? 'text-green-300' :
status.lastDecision.confidence >= 70 ? 'text-yellow-300' :
'text-red-300'
}`}>
{status.lastDecision.confidence}%
</div>
</div>
</div>
<div className="text-xs text-gray-500">
{new Date(status.lastDecision.timestamp).toLocaleString()}
</div>
</div>
{/* AI Reasoning - Prominent Display */}
<div className="mb-4">
<h4 className="text-purple-300 font-semibold mb-2 flex items-center">
<span className="mr-2">🎯</span>
Why This Decision?
</h4>
<div className="bg-gray-900/50 rounded-lg p-4 border-l-4 border-purple-500">
<p className="text-gray-200 leading-relaxed">
{status.lastDecision.reasoning}
</p>
</div>
</div>
{/* Execution Status */}
<div className="flex items-center justify-between p-3 bg-gray-800/50 rounded-lg border border-gray-700/50">
<div className="flex items-center space-x-2">
<span className={`w-3 h-3 rounded-full ${
status.lastDecision.executed ? 'bg-green-500' : 'bg-red-500'
}`}></span>
<span className="text-white font-medium">
{status.lastDecision.executed ? '✅ Trade Executed' : '❌ Not Executed'}
</span>
</div>
{!status.lastDecision.executed && status.lastDecision.executionError && (
<span className="text-red-400 text-sm">
{status.lastDecision.executionError}
</span>
)}
</div>
</div>
{/* Trade Details - If Executed */}
{status.lastDecision.executed && status.lastDecision.executionDetails && (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
{/* Entry & Exit Strategy */}
<div className="bg-black/20 rounded-lg p-4 border border-blue-500/20">
<h4 className="text-blue-300 font-semibold mb-3 flex items-center">
<span className="mr-2">📈</span>
Entry & Exit Strategy
</h4>
<div className="space-y-2 text-sm">
<div className="flex justify-between">
<span className="text-gray-400">Entry Price:</span>
<span className="text-white font-mono">${status.lastDecision.executionDetails.currentPrice?.toFixed(4)}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-400">Stop Loss:</span>
<span className="text-red-300 font-mono">${status.lastDecision.executionDetails.stopLoss?.toFixed(4)}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-400">Take Profit:</span>
<span className="text-green-300 font-mono">${status.lastDecision.executionDetails.takeProfit?.toFixed(4)}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-400">Position Size:</span>
<span className="text-white">${status.lastDecision.executionDetails.amount}</span>
</div>
</div>
</div>
{/* AI Leverage Calculation */}
<div className="bg-black/20 rounded-lg p-4 border border-yellow-500/20">
<h4 className="text-yellow-300 font-semibold mb-3 flex items-center">
<span className="mr-2"></span>
AI Leverage Decision
</h4>
<div className="space-y-2 text-sm mb-3">
<div className="flex justify-between">
<span className="text-gray-400">Leverage:</span>
<span className="text-yellow-300 font-bold text-lg">{status.lastDecision.executionDetails.leverage}x</span>
</div>
<div className="flex justify-between">
<span className="text-gray-400">Position Side:</span>
<span className={`font-semibold ${
status.lastDecision.executionDetails.side === 'BUY' ? 'text-green-300' : 'text-red-300'
}`}>
{status.lastDecision.executionDetails.side}
</span>
</div>
</div>
{status.lastDecision.executionDetails.aiReasoning && (
<div className="bg-yellow-900/20 rounded p-3 border-l-3 border-yellow-500">
<p className="text-yellow-100 text-xs leading-relaxed">
{status.lastDecision.executionDetails.aiReasoning}
</p>
</div>
)}
</div>
</div>
)}
</div>
) : (
<div className="text-center py-8">
<div className="text-6xl mb-4">🤖</div>
<h4 className="text-xl text-purple-300 font-semibold mb-2">AI Analysis Standby</h4>
<p className="text-gray-400 mb-4">
The AI will analyze market conditions and provide detailed reasoning for all trading decisions.
</p>
<div className="bg-purple-900/20 rounded-lg p-4 border border-purple-500/30">
<div className="text-purple-300 font-semibold mb-2">What you'll see when analysis starts:</div>
<ul className="text-sm text-gray-300 space-y-1 text-left max-w-md mx-auto">
<li>• <strong>Entry Strategy:</strong> Why AI chose this entry point</li>
<li>• <strong>Stop Loss Logic:</strong> Risk management reasoning</li>
<li>• <strong>Take Profit Target:</strong> Profit-taking strategy</li>
<li>• <strong>Leverage Calculation:</strong> AI's risk assessment</li>
<li> <strong>Confidence Analysis:</strong> Probability scoring</li>
</ul>
</div>
</div>
)}
</div>
{/* Legacy Last Decision Panel - Hidden when new panel is active */}
{status?.lastDecision && false && (
<div className="bg-gray-800 p-6 rounded-lg border border-gray-700">
<h3 className="text-lg font-bold text-white mb-4">🧠 Last Decision</h3>
<div className="space-y-4">
{/* Decision Header */}
<div className="flex justify-between items-center p-3 bg-gray-700 rounded-lg">
<div className="flex items-center space-x-2">
<span className={`w-3 h-3 rounded-full ${
status.lastDecision.executed ? 'bg-green-500' : 'bg-red-500'
}`}></span>
<span className="text-white font-semibold">
{status.lastDecision.executed ? '✅ EXECUTED' : '❌ NOT EXECUTED'}
</span>
</div>
<span className="text-xs text-gray-400">
{new Date(status.lastDecision.timestamp).toLocaleTimeString()}
</span>
</div>
{/* Analysis Details */}
<div className="space-y-3">
<div className="flex justify-between items-center">
<span className="text-gray-400">Recommendation:</span>
<span className={`px-2 py-1 rounded text-xs font-semibold ${
status.lastDecision.recommendation?.toLowerCase().includes('buy') ? 'bg-green-600 text-white' :
status.lastDecision.recommendation?.toLowerCase().includes('sell') ? 'bg-red-600 text-white' :
'bg-gray-600 text-gray-300'
}`}>
{status.lastDecision.recommendation || 'HOLD'}
</span>
</div>
<div className="flex justify-between items-center">
<span className="text-gray-400">Confidence:</span>
<div className="flex items-center space-x-2">
<span className={`text-sm font-semibold ${
status.lastDecision.confidence >= 80 ? 'text-green-400' :
status.lastDecision.confidence >= 70 ? 'text-yellow-400' :
'text-red-400'
}`}>
{status.lastDecision.confidence}%
</span>
<span className="text-xs text-gray-500">
(min: {status.lastDecision.minConfidenceRequired}%)
</span>
</div>
</div>
<div className="p-3 bg-gray-900 rounded-lg">
<span className="text-xs text-gray-400 block mb-1">Reasoning:</span>
<span className="text-sm text-gray-300">{status.lastDecision.reasoning}</span>
</div>
</div>
{/* Execution Details (if executed) */}
{status.lastDecision.executed && status.lastDecision.executionDetails && (
<div className="space-y-3 pt-3 border-t border-gray-700">
<h4 className="text-sm font-semibold text-cyan-400">💰 Execution Details</h4>
<div className="grid grid-cols-2 gap-3 text-sm">
<div className="flex justify-between">
<span className="text-gray-400">Side:</span>
<span className={`font-semibold ${
status.lastDecision.executionDetails.side === 'BUY' ? 'text-green-400' : 'text-red-400'
}`}>
{status.lastDecision.executionDetails.side}
</span>
</div>
<div className="flex justify-between">
<span className="text-gray-400">Amount:</span>
<span className="text-white">${status.lastDecision.executionDetails.amount}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-400">Entry:</span>
<span className="text-white">${status.lastDecision.executionDetails.currentPrice?.toFixed(2)}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-400">Leverage:</span>
<span className="text-white">{status.lastDecision.executionDetails.leverage}x</span>
</div>
</div>
{/* SL/TP Details */}
{(status.lastDecision.executionDetails.stopLoss || status.lastDecision.executionDetails.takeProfit) && (
<div className="p-3 bg-gray-900 rounded-lg">
<h5 className="text-xs font-semibold text-blue-400 mb-2">🛡 Risk Management</h5>
<div className="grid grid-cols-2 gap-3 text-xs">
{status.lastDecision.executionDetails.stopLoss && (
<div className="flex justify-between">
<span className="text-gray-400">Stop Loss:</span>
<span className="text-red-400 font-semibold">
${status.lastDecision.executionDetails.stopLoss.toFixed(2)}
{status.lastDecision.executionDetails.aiStopLossPercent && (
<span className="text-gray-500 ml-1">({status.lastDecision.executionDetails.aiStopLossPercent})</span>
)}
</span>
</div>
)}
{status.lastDecision.executionDetails.takeProfit && (
<div className="flex justify-between">
<span className="text-gray-400">Take Profit:</span>
<span className="text-green-400 font-semibold">
${status.lastDecision.executionDetails.takeProfit.toFixed(2)}
</span>
</div>
)}
</div>
{status.lastDecision.executionDetails.stopLoss && status.lastDecision.executionDetails.takeProfit && (
<div className="mt-2 text-xs text-gray-500">
Risk/Reward: 1:2 ratio
</div>
)}
</div>
)}
{/* AI Leverage Reasoning */}
{status.lastDecision.executionDetails.aiReasoning && (
<div className="p-3 bg-purple-900/20 rounded-lg border border-purple-700/30">
<h5 className="text-xs font-semibold text-purple-400 mb-2">🧠 AI Leverage Decision</h5>
<div className="text-xs text-gray-300 leading-relaxed">
{status.lastDecision.executionDetails.aiReasoning}
</div>
</div>
)}
{/* Transaction ID */}
{status.lastDecision.executionDetails.txId && (
<div className="text-xs">
<span className="text-gray-400">TX ID:</span>
<span className="text-blue-400 font-mono ml-2 break-all">
{status.lastDecision.executionDetails.txId.substring(0, 20)}...
</span>
</div>
)}
</div>
)}
{/* Execution Error (if failed) */}
{!status.lastDecision.executed && status.lastDecision.executionError && (
<div className="p-3 bg-red-900 border border-red-600 rounded-lg">
<h4 className="text-sm font-semibold text-red-400 mb-1"> Execution Failed</h4>
<span className="text-xs text-red-300">{status.lastDecision.executionError}</span>
</div>
)}
</div>
</div>
)}
{/* Position Monitor */}
{monitorData && (
<div className="bg-gray-800 p-6 rounded-lg border border-gray-700">
<h3 className="text-lg font-bold text-white mb-4">📊 Position Monitor</h3>
<div className="space-y-3">
<div className="flex justify-between items-center">
<span className="text-gray-400">Has Position:</span>
<span className={`px-2 py-1 rounded text-xs font-semibold ${
monitorData.hasPosition ? 'bg-green-600 text-white' : 'bg-gray-600 text-gray-300'
}`}>
{monitorData.hasPosition ? '✅ YES' : '❌ NO'}
</span>
</div>
<div className="flex justify-between items-center">
<span className="text-gray-400">Risk Level:</span>
<span className={`px-2 py-1 rounded text-xs font-semibold ${
monitorData.riskLevel === 'HIGH' ? 'bg-red-600 text-white' :
monitorData.riskLevel === 'MEDIUM' ? 'bg-yellow-600 text-white' :
'bg-green-600 text-white'
}`}>
{monitorData.riskLevel}
</span>
</div>
<div className="text-xs text-gray-400">
<strong>Next Action:</strong> {monitorData.nextAction}
</div>
{monitorData.orphanedOrderCleanup && (
<div className={`mt-3 p-2 rounded-lg ${
monitorData.orphanedOrderCleanup.success ? 'bg-green-900 border border-green-600' : 'bg-red-900 border border-red-600'
}`}>
<div className="text-xs font-semibold">
{monitorData.orphanedOrderCleanup.success ? '✅ Cleanup Success' : '❌ Cleanup Failed'}
</div>
<div className="text-xs mt-1">
{monitorData.orphanedOrderCleanup.message}
</div>
</div>
)}
</div>
</div>
)}
{/* Balance */}
{balance && (
<div className="bg-gray-800 p-6 rounded-lg border border-gray-700">
<h3 className="text-lg font-bold text-white mb-4"><EFBFBD> Account Balance</h3>
<div className="space-y-3">
<div className="flex justify-between items-center">
<span className="text-gray-400">Available:</span>
<span className="text-green-400 font-semibold">${parseFloat(balance.availableBalance).toFixed(2)}</span>
</div>
<div className="flex justify-between items-center">
<span className="text-gray-400">Total:</span>
<span className="text-white font-medium">${parseFloat(balance.totalCollateral).toFixed(2)}</span>
</div>
<div className="flex justify-between items-center">
<span className="text-gray-400">Positions:</span>
<span className="text-yellow-400">{balance.positions || 0}</span>
</div>
</div>
</div>
)}
{/* Positions */}
{positions.length > 0 && (
<div className="bg-gray-800 p-6 rounded-lg border border-gray-700">
<h3 className="text-lg font-bold text-white mb-4">📈 Open Positions</h3>
<div className="space-y-3">
{positions.map((position, index) => (
<div key={index} className="p-4 bg-gray-700 rounded-lg border border-gray-600">
<div className="flex justify-between items-center mb-2">
<span className="text-white font-semibold">{position.symbol}</span>
<span className={`px-2 py-1 rounded text-xs font-semibold ${
position.side === 'LONG' ? 'bg-green-600 text-white' : 'bg-red-600 text-white'
}`}>
{position.side}
</span>
</div>
<div className="grid grid-cols-2 gap-2 text-sm">
<div className="flex justify-between">
<span className="text-gray-400">Size:</span>
<span className="text-white">${position.size}</span>
</div>
{position.entryPrice && (
<div className="flex justify-between">
<span className="text-gray-400">Entry:</span>
<span className="text-white">${position.entryPrice}</span>
</div>
)}
{position.markPrice && (
<div className="flex justify-between">
<span className="text-gray-400">Mark:</span>
<span className="text-white">${position.markPrice}</span>
</div>
)}
{position.pnl !== undefined && (
<div className="flex justify-between">
<span className="text-gray-400">PnL:</span>
<span className={`font-semibold ${
position.pnl >= 0 ? 'text-green-400' : 'text-red-400'
}`}>
${position.pnl >= 0 ? '+' : ''}${position.pnl}
</span>
</div>
)}
</div>
</div>
))}
</div>
</div>
)}
</div>
</div>
</div>
)
}