Files
trading_bot_v3/app/automation-v2/page.js
mindesbunister 4f68593682 feat: enhance position display with proper formatting and value calculation
- Fix price formatting to show exactly 2 decimal places
- Display position size in SOL units (16.40 SOL) instead of incorrect dollar amount
- Add new Value field showing total dollar value of position (Size × Current Price)
- Improve Open Positions section with accurate financial data display
- Maintain enhanced styling and responsive layout
- All prices now formatted professionally with consistent decimal places
2025-07-27 10:32:27 +02:00

1195 lines
60 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: 'LIVE',
dexProvider: 'DRIFT',
symbol: 'SOLUSD',
selectedTimeframes: ['5', '15', '30'], // Default to scalping preset
tradingAmount: 100,
balancePercentage: 100, // Default to 100% 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="min-h-screen bg-gradient-to-br from-slate-900 via-purple-900/20 to-slate-900 p-6">
<div className="max-w-7xl mx-auto space-y-8">
{/* Page Header */}
<div className="text-center mb-8">
<h1 className="text-4xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-blue-400 via-purple-400 to-blue-400 mb-2">
🤖 AI Trading Automation
</h1>
<p className="text-gray-400 text-lg">Advanced AI-powered trading with real-time analysis and risk management</p>
</div>
{/* Main Grid Layout */}
<div className="grid grid-cols-1 xl:grid-cols-4 gap-8">
{/* Automation Control Panel - Main Column */}
<div className="xl:col-span-3 space-y-8">
<div className="bg-gradient-to-br from-gray-900/90 via-slate-800/80 to-gray-900/90 backdrop-blur-xl p-8 rounded-2xl border border-gray-600/30 shadow-2xl">
{/* Control Header with Enhanced Buttons */}
<div className="flex items-center justify-between mb-8">
<div className="flex items-center space-x-4">
<div className="w-12 h-12 bg-gradient-to-br from-blue-500 to-purple-600 rounded-xl flex items-center justify-center">
<span className="text-2xl">🤖</span>
</div>
<div>
<h3 className="text-2xl font-bold text-white">Automation Control</h3>
<p className="text-gray-400">Configure and manage your AI trading bot</p>
</div>
</div>
<div className="flex space-x-4">
{status?.isActive ? (
<>
<button
onClick={handleStop}
disabled={loading}
className="px-8 py-4 bg-gradient-to-r from-red-600 to-red-700 text-white rounded-xl hover:from-red-700 hover:to-red-800 transition-all duration-200 disabled:opacity-50 font-semibold shadow-lg shadow-red-500/25 transform hover:scale-105"
>
{loading ? (
<div className="flex items-center space-x-2">
<div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin"></div>
<span>Stopping...</span>
</div>
) : (
<div className="flex items-center space-x-2">
<span>🛑</span>
<span>STOP</span>
</div>
)}
</button>
<button
onClick={handleEmergencyStop}
disabled={loading}
className="px-6 py-4 bg-gradient-to-r from-red-800 to-red-900 text-white rounded-xl hover:from-red-900 hover:to-red-950 transition-all duration-200 disabled:opacity-50 font-semibold border-2 border-red-600/50 shadow-lg shadow-red-900/50 transform hover:scale-105"
title="Emergency Stop - Closes all positions immediately"
>
<div className="flex items-center space-x-2">
<span>🚨</span>
<span>EMERGENCY</span>
</div>
</button>
</>
) : (
<button
onClick={handleStart}
disabled={loading}
className="px-8 py-4 bg-gradient-to-r from-green-600 to-green-700 text-white rounded-xl hover:from-green-700 hover:to-green-800 transition-all duration-200 disabled:opacity-50 font-semibold shadow-lg shadow-green-500/25 transform hover:scale-105"
>
{loading ? (
<div className="flex items-center space-x-2">
<div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin"></div>
<span>Starting...</span>
</div>
) : (
<div className="flex items-center space-x-2">
<span>{status?.rateLimitHit ? '🔄' : '🚀'}</span>
<span>{status?.rateLimitHit ? 'RESTART' : 'START'}</span>
</div>
)}
</button>
)}
{/* Test & Analysis Buttons */}
<button
onClick={generateTestDecision}
disabled={loading}
className="px-6 py-4 bg-gradient-to-r from-purple-600 to-purple-700 text-white rounded-xl hover:from-purple-700 hover:to-purple-800 transition-all duration-200 disabled:opacity-50 font-semibold border-2 border-purple-500/50 shadow-lg shadow-purple-500/25 transform hover:scale-105"
title="Generate Test AI Decision - Shows reasoning panel"
>
<div className="flex items-center space-x-2">
<span>🧪</span>
<span>TEST AI</span>
</div>
</button>
<button
onClick={analyzeExistingPosition}
disabled={loading}
className="px-6 py-4 bg-gradient-to-r from-blue-600 to-blue-700 text-white rounded-xl hover:from-blue-700 hover:to-blue-800 transition-all duration-200 disabled:opacity-50 font-semibold border-2 border-blue-500/50 shadow-lg shadow-blue-500/25 transform hover:scale-105"
title="Analyze Current Position - Generate AI reasoning for existing position"
>
<div className="flex items-center space-x-2">
<span>🔍</span>
<span>ANALYZE</span>
</div>
</button>
</div>
</div>
{/* Trading Mode Selection - Enhanced Cards */}
<div className="mb-8">
<label className="block text-lg font-bold text-blue-400 mb-4 flex items-center">
<span className="mr-2"></span>
Trading Mode
</label>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<label className="group relative cursor-pointer">
<input
type="radio"
className="sr-only"
name="mode"
checked={config.mode === 'SIMULATION'}
onChange={() => setConfig({...config, mode: 'SIMULATION'})}
disabled={status?.isActive}
/>
<div className={`p-6 rounded-2xl border-2 transition-all duration-200 ${
config.mode === 'SIMULATION'
? 'border-blue-500 bg-gradient-to-br from-blue-500/20 to-purple-500/10 shadow-lg shadow-blue-500/25'
: status?.isActive
? 'border-gray-600 bg-gray-800/30 cursor-not-allowed opacity-50'
: 'border-gray-600 bg-gray-800/30 hover:border-blue-400 hover:bg-blue-500/10 hover:shadow-lg hover:shadow-blue-500/10'
}`}>
<div className="flex items-center space-x-4">
<div className="w-16 h-16 bg-gradient-to-br from-blue-500 to-purple-600 rounded-2xl flex items-center justify-center shadow-lg">
<span className="text-3xl">📊</span>
</div>
<div>
<h4 className="text-xl font-bold text-white mb-1">Paper Trading</h4>
<p className="text-gray-400">Practice with virtual funds</p>
<div className="text-sm text-blue-400 mt-2 font-medium">Risk-free testing environment</div>
</div>
</div>
{config.mode === 'SIMULATION' && (
<div className="absolute top-2 right-2 w-4 h-4 bg-blue-500 rounded-full flex items-center justify-center">
<div className="w-2 h-2 bg-white rounded-full"></div>
</div>
)}
</div>
</label>
<label className="group relative cursor-pointer">
<input
type="radio"
className="sr-only"
name="mode"
checked={config.mode === 'LIVE'}
onChange={() => setConfig({...config, mode: 'LIVE'})}
disabled={status?.isActive}
/>
<div className={`p-6 rounded-2xl border-2 transition-all duration-200 ${
config.mode === 'LIVE'
? 'border-green-500 bg-gradient-to-br from-green-500/20 to-yellow-500/10 shadow-lg shadow-green-500/25'
: status?.isActive
? 'border-gray-600 bg-gray-800/30 cursor-not-allowed opacity-50'
: 'border-gray-600 bg-gray-800/30 hover:border-green-400 hover:bg-green-500/10 hover:shadow-lg hover:shadow-green-500/10'
}`}>
<div className="flex items-center space-x-4">
<div className="w-16 h-16 bg-gradient-to-br from-green-500 to-yellow-600 rounded-2xl flex items-center justify-center shadow-lg">
<span className="text-3xl">💰</span>
</div>
<div>
<h4 className="text-xl font-bold text-white mb-1">Live Trading</h4>
<p className="text-gray-400">Real money transactions</p>
<div className="text-sm text-green-400 mt-2 font-medium"> Use real funds carefully</div>
</div>
</div>
{config.mode === 'LIVE' && (
<div className="absolute top-2 right-2 w-4 h-4 bg-green-500 rounded-full flex items-center justify-center">
<div className="w-2 h-2 bg-white rounded-full"></div>
</div>
)}
</div>
</label>
</div>
</div>
{/* Symbol and Balance Configuration */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-8">
<div className="space-y-4">
<label className="block text-lg font-bold text-purple-400 flex items-center">
<span className="mr-2">🎯</span>
Trading Symbol
</label>
<div className="relative">
<select
className="w-full p-4 bg-gradient-to-r from-gray-800 to-gray-700 border-2 border-gray-600 rounded-xl text-white focus:border-purple-500 focus:ring-2 focus:ring-purple-500/20 transition-all duration-200 appearance-none text-lg font-medium"
value={config.symbol}
onChange={(e) => setConfig({...config, symbol: e.target.value})}
disabled={status?.isActive}
>
<option value="SOLUSD">SOL/USD - Solana</option>
<option value="BTCUSD">BTC/USD - Bitcoin</option>
<option value="ETHUSD">ETH/USD - Ethereum</option>
<option value="APTUSD">APT/USD - Aptos</option>
<option value="AVAXUSD">AVAX/USD - Avalanche</option>
<option value="DOGEUSD">DOGE/USD - Dogecoin</option>
</select>
<div className="absolute inset-y-0 right-0 flex items-center pr-4 pointer-events-none">
<svg className="w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 9l-7 7-7-7"></path>
</svg>
</div>
</div>
</div>
<div className="space-y-4">
<label className="block text-lg font-bold text-yellow-400 flex items-center">
<span className="mr-2">💳</span>
Balance Usage: {config.balancePercentage}%
{balance && (
<span className="ml-2 text-green-400 font-mono">
${(parseFloat(balance.availableBalance) * config.balancePercentage / 100).toFixed(2)}
</span>
)}
</label>
<div className="space-y-3">
<div className="relative">
<input
type="range"
className="w-full h-3 bg-gray-700 rounded-lg appearance-none cursor-pointer slider"
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>
<div className="flex justify-between text-sm text-gray-400">
<span className="flex items-center">
<span className="w-2 h-2 bg-yellow-500 rounded-full mr-2"></span>
Conservative (10%)
</span>
<span className="flex items-center">
<span className="w-2 h-2 bg-orange-500 rounded-full mr-2"></span>
Balanced (50%)
</span>
<span className="flex items-center">
<span className="w-2 h-2 bg-red-500 rounded-full mr-2"></span>
Aggressive (100%)
</span>
</div>
</div>
</div>
</div>
{/* Enhanced Multi-Timeframe Selection */}
<div className="mb-8">
<label className="block text-xl font-bold text-cyan-400 mb-6 flex items-center">
<span className="mr-3"></span>
Analysis Timeframes
<span className="ml-4 text-sm text-cyan-300 bg-cyan-500/20 px-3 py-1 rounded-full border border-cyan-500/30">
{config.selectedTimeframes.length} selected
</span>
{config.selectedTimeframes.length === 0 && (
<span className="ml-4 text-sm text-red-400 bg-red-500/20 px-3 py-1 rounded-full border border-red-500/30 animate-pulse">
Select at least one timeframe
</span>
)}
</label>
{/* Timeframe Selection Grid */}
<div className="grid grid-cols-4 lg:grid-cols-7 gap-3 mb-6">
{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={`relative p-4 rounded-xl border-2 transition-all duration-200 text-center font-bold ${
config.selectedTimeframes.includes(tf.value)
? 'border-cyan-500 bg-gradient-to-br from-cyan-500/30 to-blue-500/20 text-cyan-300 shadow-lg shadow-cyan-500/30 transform scale-105'
: status?.isActive
? 'border-gray-700 bg-gray-800/30 text-gray-500 cursor-not-allowed opacity-50'
: 'border-gray-700 bg-gray-800/30 text-gray-400 hover:border-cyan-400 hover:bg-cyan-500/10 hover:text-cyan-300 hover:shadow-lg hover:shadow-cyan-500/20 hover:scale-105'
}`}>
<div className="text-lg">{tf.label}</div>
{config.selectedTimeframes.includes(tf.value) && (
<div className="absolute -top-1 -right-1 w-5 h-5 bg-gradient-to-br from-cyan-400 to-blue-500 rounded-full flex items-center justify-center shadow-lg">
<svg className="w-3 h-3 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="3" d="M5 13l4 4L19 7"></path>
</svg>
</div>
)}
</div>
</label>
))}
</div>
{/* Selected Timeframes Display */}
{config.selectedTimeframes.length > 0 && (
<div className="p-4 bg-gradient-to-r from-cyan-900/30 to-blue-900/30 rounded-xl border border-cyan-500/30 mb-6">
<div className="flex items-center justify-between">
<div className="text-sm">
<span className="text-gray-400">Selected Timeframes:</span>
<span className="ml-2 text-cyan-400 font-medium">
{config.selectedTimeframes.map(tf => timeframes.find(t => t.value === tf)?.label || tf).filter(Boolean).join(', ')}
</span>
</div>
<div className="text-xs text-cyan-300 bg-cyan-500/20 px-2 py-1 rounded-lg">
💡 Multi-timeframe analysis
</div>
</div>
</div>
)}
{/* Trading Style Presets - Enhanced Cards */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<button
type="button"
onClick={() => setConfig({...config, selectedTimeframes: ['5', '15', '30']})}
disabled={status?.isActive}
className="group p-6 rounded-xl bg-gradient-to-br from-green-600/20 to-emerald-600/10 border-2 border-green-600/30 hover:border-green-500/50 hover:from-green-600/30 hover:to-emerald-600/20 transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed text-left hover:scale-105"
>
<div className="flex items-center justify-between mb-3">
<div className="text-3xl group-hover:scale-110 transition-transform duration-200">📈</div>
<div className="text-xs text-green-400 bg-green-500/20 px-2 py-1 rounded-lg">FAST</div>
</div>
<h4 className="text-lg font-bold text-green-300 mb-2">Scalping</h4>
<p className="text-sm text-gray-300 mb-3">Quick trades on short timeframes</p>
<div className="text-xs text-green-400/80 font-mono bg-green-900/30 px-2 py-1 rounded">
5m 15m 30m
</div>
</button>
<button
type="button"
onClick={() => setConfig({...config, selectedTimeframes: ['60', '120']})}
disabled={status?.isActive}
className="group p-6 rounded-xl bg-gradient-to-br from-blue-600/20 to-indigo-600/10 border-2 border-blue-600/30 hover:border-blue-500/50 hover:from-blue-600/30 hover:to-indigo-600/20 transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed text-left hover:scale-105"
>
<div className="flex items-center justify-between mb-3">
<div className="text-3xl group-hover:scale-110 transition-transform duration-200"></div>
<div className="text-xs text-blue-400 bg-blue-500/20 px-2 py-1 rounded-lg">MEDIUM</div>
</div>
<h4 className="text-lg font-bold text-blue-300 mb-2">Day Trading</h4>
<p className="text-sm text-gray-300 mb-3">Intraday momentum strategies</p>
<div className="text-xs text-blue-400/80 font-mono bg-blue-900/30 px-2 py-1 rounded">
1h 2h
</div>
</button>
<button
type="button"
onClick={() => setConfig({...config, selectedTimeframes: ['240', 'D']})}
disabled={status?.isActive}
className="group p-6 rounded-xl bg-gradient-to-br from-purple-600/20 to-violet-600/10 border-2 border-purple-600/30 hover:border-purple-500/50 hover:from-purple-600/30 hover:to-violet-600/20 transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed text-left hover:scale-105"
>
<div className="flex items-center justify-between mb-3">
<div className="text-3xl group-hover:scale-110 transition-transform duration-200">🎯</div>
<div className="text-xs text-purple-400 bg-purple-500/20 px-2 py-1 rounded-lg">SLOW</div>
</div>
<h4 className="text-lg font-bold text-purple-300 mb-2">Swing Trading</h4>
<p className="text-sm text-gray-300 mb-3">Long-term trend following</p>
<div className="text-xs text-purple-400/80 font-mono bg-purple-900/30 px-2 py-1 rounded">
4h 1d
</div>
</button>
</div>
</div>
</div>
</div>
{/* Enhanced Sidebar */}
<div className="space-y-6">
{/* Unified Trading Dashboard Card */}
<div className="bg-gradient-to-br from-gray-900/90 via-slate-800/80 to-gray-900/90 backdrop-blur-xl p-6 rounded-2xl border border-gray-600/30 shadow-2xl">
<div className="flex items-center space-x-3 mb-6">
<div className={`w-14 h-14 rounded-xl flex items-center justify-center ${
status?.isActive
? 'bg-gradient-to-br from-green-500 to-emerald-600 shadow-lg shadow-green-500/25'
: 'bg-gradient-to-br from-gray-600 to-gray-700'
}`}>
<span className="text-2xl">{status?.isActive ? '🟢' : '⚪'}</span>
</div>
<div>
<h3 className="text-xl font-bold text-white">Trading Dashboard</h3>
<p className="text-gray-400">Status Positions Risk Monitor</p>
</div>
</div>
{/* Bot Status Section */}
<div className="mb-6">
<h4 className="text-lg font-semibold text-blue-400 mb-3 flex items-center">
<span className="mr-2">🤖</span>Bot Status
</h4>
<div className="space-y-3">
<div className="flex justify-between items-center p-3 bg-black/20 rounded-lg">
<span className="text-gray-400 font-medium">Status:</span>
<span className={`px-3 py-1 rounded-lg text-sm font-bold ${
status?.isActive
? 'bg-green-500/20 text-green-300 border border-green-500/30'
: 'bg-gray-600/20 text-gray-300 border border-gray-600/30'
}`}>
{status?.isActive ? 'RUNNING' : 'STOPPED'}
</span>
</div>
{status?.isActive && (
<>
<div className="flex justify-between items-center p-3 bg-black/20 rounded-lg">
<span className="text-gray-400 font-medium">Symbol:</span>
<span className="text-white font-bold">{status.symbol}</span>
</div>
<div className="flex justify-between items-center p-3 bg-black/20 rounded-lg">
<span className="text-gray-400 font-medium">Mode:</span>
<span className={`px-3 py-1 rounded-lg text-sm font-bold border ${
status.mode === 'LIVE'
? 'bg-red-500/20 text-red-300 border-red-500/30'
: 'bg-blue-500/20 text-blue-300 border-blue-500/30'
}`}>
{status.mode}
</span>
</div>
<div className="p-3 bg-black/20 rounded-lg">
<div className="text-gray-400 font-medium mb-2">Timeframes:</div>
<div className="flex flex-wrap gap-1">
{status.timeframes?.map((tf, index) => (
<span key={index} className="text-xs bg-cyan-500/20 text-cyan-300 px-2 py-1 rounded border border-cyan-500/30">
{timeframes.find(t => t.value === tf)?.label || tf}
</span>
))}
</div>
</div>
</>
)}
{/* Rate Limit Warning */}
{status?.rateLimitHit && (
<div className="p-3 bg-gradient-to-br from-red-900/50 to-red-800/30 border border-red-600/50 rounded-lg">
<div className="flex items-center space-x-2 mb-1">
<span className="text-red-400 font-bold"></span>
<span className="text-red-300 font-bold text-sm">Rate Limit Reached</span>
</div>
{status.rateLimitMessage && (
<p className="text-red-200 text-xs mb-1">{status.rateLimitMessage}</p>
)}
<p className="text-red-100 text-xs">
Automation stopped. Recharge OpenAI account to continue.
</p>
</div>
)}
</div>
</div>
{/* Position Monitor Section */}
{monitorData && (
<div className="mb-6">
<h4 className="text-lg font-semibold text-purple-400 mb-3 flex items-center">
<span className="mr-2">📊</span>Position Monitor
</h4>
<div className="space-y-3">
<div className="flex justify-between items-center p-3 bg-black/20 rounded-lg">
<span className="text-gray-400 font-medium">Has Position:</span>
<span className={`px-3 py-1 rounded-lg text-sm font-bold border ${
monitorData.hasPosition
? 'bg-green-500/20 text-green-300 border-green-500/30'
: 'bg-gray-600/20 text-gray-300 border-gray-600/30'
}`}>
{monitorData.hasPosition ? '✅ YES' : '❌ NO'}
</span>
</div>
<div className="flex justify-between items-center p-3 bg-black/20 rounded-lg">
<span className="text-gray-400 font-medium">Risk Level:</span>
<span className={`px-3 py-1 rounded-lg text-sm font-bold border ${
monitorData.riskLevel === 'HIGH' ? 'bg-red-500/20 text-red-300 border-red-500/30' :
monitorData.riskLevel === 'MEDIUM' ? 'bg-yellow-500/20 text-yellow-300 border-yellow-500/30' :
'bg-green-500/20 text-green-300 border-green-500/30'
}`}>
{monitorData.riskLevel}
</span>
</div>
<div className="p-3 bg-black/20 rounded-lg">
<div className="text-gray-400 text-sm mb-1">Next Action:</div>
<div className="text-white text-sm">{monitorData.nextAction}</div>
</div>
{monitorData.orphanedOrderCleanup && (
<div className={`p-3 rounded-lg border ${
monitorData.orphanedOrderCleanup.success
? 'bg-green-900/30 border-green-600/50'
: 'bg-red-900/30 border-red-600/50'
}`}>
<div className="text-sm font-semibold mb-1">
{monitorData.orphanedOrderCleanup.success ? '✅ Cleanup Success' : '❌ Cleanup Failed'}
</div>
<div className="text-xs text-gray-300">
{monitorData.orphanedOrderCleanup.message}
</div>
</div>
)}
</div>
</div>
)}
{/* Open Positions Section */}
{positions.length > 0 && (
<div className="mb-6">
<h4 className="text-lg font-semibold text-yellow-400 mb-3 flex items-center">
<span className="mr-2">📈</span>Open Positions
<span className="ml-2 text-sm bg-yellow-500/20 text-yellow-300 px-2 py-1 rounded-lg border border-yellow-500/30">
{positions.length}
</span>
</h4>
<div className="space-y-3">
{positions.map((position, index) => (
<div key={index} className="p-4 bg-gradient-to-r from-gray-800/50 to-gray-700/30 rounded-xl border border-gray-600/30">
<div className="flex justify-between items-center mb-3">
<span className="text-white font-bold">{position.symbol}</span>
<span className={`px-2 py-1 rounded-lg text-xs font-bold border ${
position.side === 'LONG'
? 'bg-green-500/20 text-green-300 border-green-500/30'
: 'bg-red-500/20 text-red-300 border-red-500/30'
}`}>
{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 font-semibold">
{position.symbol?.includes('SOL') ?
`${parseFloat(position.size).toFixed(2)} SOL` :
`$${parseFloat(position.size).toFixed(2)}`
}
</span>
</div>
<div className="flex justify-between">
<span className="text-gray-400">Value:</span>
<span className="text-green-400 font-bold">
${((parseFloat(position.size) || 0) * (parseFloat(position.markPrice) || parseFloat(position.entryPrice) || 0)).toFixed(2)}
</span>
</div>
{position.entryPrice && (
<div className="flex justify-between">
<span className="text-gray-400">Entry:</span>
<span className="text-white font-mono">${parseFloat(position.entryPrice).toFixed(2)}</span>
</div>
)}
{position.markPrice && (
<div className="flex justify-between">
<span className="text-gray-400">Mark:</span>
<span className="text-white font-mono">${parseFloat(position.markPrice).toFixed(2)}</span>
</div>
)}
{position.pnl !== undefined && (
<div className="flex justify-between">
<span className="text-gray-400">PnL:</span>
<span className={`font-bold ${
position.pnl >= 0 ? 'text-green-400' : 'text-red-400'
}`}>
${position.pnl >= 0 ? '+' : ''}${parseFloat(position.pnl).toFixed(2)}
</span>
</div>
)}
</div>
</div>
))}
</div>
</div>
)}
</div>
{/* Account Balance Card */}
{balance && (
<div className="bg-gradient-to-br from-gray-900/90 via-slate-800/80 to-gray-900/90 backdrop-blur-xl p-6 rounded-2xl border border-gray-600/30 shadow-2xl">
<div className="flex items-center space-x-3 mb-6">
<div className="w-12 h-12 bg-gradient-to-br from-green-500 to-emerald-600 rounded-xl flex items-center justify-center shadow-lg shadow-green-500/25">
<span className="text-2xl">💰</span>
</div>
<div>
<h3 className="text-xl font-bold text-white">Account Balance</h3>
<p className="text-gray-400">Live Drift Protocol data</p>
</div>
</div>
<div className="space-y-4">
<div className="p-4 bg-gradient-to-r from-green-900/30 to-emerald-900/20 rounded-xl border border-green-500/30">
<div className="text-gray-400 text-sm mb-1">Available Balance</div>
<div className="text-green-400 font-bold text-2xl">${parseFloat(balance.availableBalance).toFixed(2)}</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="p-3 bg-black/20 rounded-lg">
<div className="text-gray-400 text-xs mb-1">Total Collateral</div>
<div className="text-white font-semibold">${parseFloat(balance.totalCollateral).toFixed(2)}</div>
</div>
<div className="p-3 bg-black/20 rounded-lg">
<div className="text-gray-400 text-xs mb-1">Total Positions</div>
<div className="text-yellow-400 font-semibold">{balance.positions || 0}</div>
</div>
</div>
</div>
</div>
)}
</div>
</div>
{/* Enhanced AI Trading Analysis Panel */}
<div className="bg-gradient-to-br from-purple-900/40 via-blue-900/30 to-purple-900/40 backdrop-blur-xl p-8 rounded-2xl border-2 border-purple-500/40 shadow-2xl shadow-purple-500/20">
<div className="flex items-center justify-between mb-8">
<div className="flex items-center space-x-4">
<div className="w-16 h-16 bg-gradient-to-br from-purple-500 to-blue-600 rounded-2xl flex items-center justify-center shadow-lg shadow-purple-500/30">
<span className="text-3xl">🧠</span>
</div>
<div>
<h3 className="text-3xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-purple-400 to-blue-400">
AI Trading Analysis
</h3>
<p className="text-gray-300 text-lg">Real-time market intelligence and decision reasoning</p>
</div>
</div>
<div className="flex items-center space-x-4">
<div className={`w-4 h-4 rounded-full shadow-lg ${
status?.lastDecision ? 'bg-green-400 animate-pulse shadow-green-400/50' : 'bg-gray-500'
}`}></div>
<span className="text-lg text-gray-300 font-medium">
{status?.lastDecision ? '🟢 Analysis Active' : '⚪ Waiting for Analysis'}
</span>
</div>
</div>
{status?.lastDecision ? (
<div className="space-y-8">
{/* Quick Summary Cards */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-6">
<div className="bg-black/40 backdrop-blur-sm rounded-2xl p-6 border border-purple-500/30 shadow-lg">
<div className="text-purple-400 text-sm uppercase tracking-wide mb-2 font-bold">Recommendation</div>
<div className={`text-2xl font-bold mb-2 ${
status.lastDecision.recommendation?.toLowerCase().includes('buy') ? 'text-green-300' :
status.lastDecision.recommendation?.toLowerCase().includes('sell') ? 'text-red-300' :
'text-gray-300'
}`}>
{status.lastDecision.recommendation || 'HOLD'}
</div>
{status.lastDecision.isRetrospective && (
<div className="text-sm text-orange-300 bg-orange-500/20 px-2 py-1 rounded-lg border border-orange-500/30">
📊 Retrospective Analysis
</div>
)}
</div>
<div className="bg-black/40 backdrop-blur-sm rounded-2xl p-6 border border-purple-500/30 shadow-lg">
<div className="text-purple-400 text-sm uppercase tracking-wide mb-2 font-bold">Confidence</div>
<div className={`text-2xl font-bold mb-2 ${
status.lastDecision.confidence >= 80 ? 'text-green-300' :
status.lastDecision.confidence >= 70 ? 'text-yellow-300' :
'text-red-300'
}`}>
{status.lastDecision.confidence}%
</div>
<div className="text-sm text-gray-400">
Min Required: {status.lastDecision.minConfidenceRequired}%
</div>
</div>
<div className="bg-black/40 backdrop-blur-sm rounded-2xl p-6 border border-purple-500/30 shadow-lg">
<div className="text-purple-400 text-sm uppercase tracking-wide mb-2 font-bold">Execution</div>
<div className={`text-xl font-bold mb-2 ${status.lastDecision.executed ? 'text-green-300' : 'text-red-300'}`}>
{status.lastDecision.executed ? '✅ EXECUTED' : '❌ NOT EXECUTED'}
</div>
<div className="text-sm text-gray-400">
{new Date(status.lastDecision.timestamp).toLocaleTimeString()}
</div>
</div>
{status.lastDecision.executed && status.lastDecision.executionDetails && (
<div className="bg-black/40 backdrop-blur-sm rounded-2xl p-6 border border-yellow-500/30 shadow-lg">
<div className="text-yellow-400 text-sm uppercase tracking-wide mb-2 font-bold">Leverage</div>
<div className="text-2xl font-bold text-yellow-300 mb-2">
{status.lastDecision.executionDetails.leverage}x
</div>
<div className="text-sm text-gray-400">AI Calculated</div>
</div>
)}
</div>
{/* Main Analysis Content */}
<div className="grid grid-cols-1 xl:grid-cols-2 gap-8">
{/* AI Reasoning */}
<div className="space-y-6">
<div className="bg-black/30 backdrop-blur-sm rounded-2xl p-6 border border-purple-500/30 shadow-lg">
<h4 className="text-purple-300 font-bold text-xl mb-4 flex items-center">
<span className="mr-3 text-2xl">🎯</span>
Market Analysis & Reasoning
</h4>
<div className="bg-gradient-to-br from-gray-900/80 to-purple-900/20 rounded-xl p-6 border-l-4 border-purple-500 shadow-inner">
<div className="text-gray-200 leading-relaxed whitespace-pre-line text-lg">
{status.lastDecision.reasoning}
</div>
</div>
</div>
{/* Execution Error */}
{!status.lastDecision.executed && status.lastDecision.executionError && (
<div className="bg-red-900/30 border-2 border-red-600/40 rounded-2xl p-6 backdrop-blur-sm">
<h4 className="text-red-400 font-bold text-lg mb-3 flex items-center">
<span className="mr-2"></span>
Execution Failed
</h4>
<span className="text-red-300 text-lg">{status.lastDecision.executionError}</span>
</div>
)}
</div>
{/* Trade Execution Details */}
{status.lastDecision.executed && status.lastDecision.executionDetails && (
<div className="space-y-6">
<div className="bg-black/30 backdrop-blur-sm rounded-2xl p-6 border border-blue-500/30 shadow-lg">
<h4 className="text-blue-300 font-bold text-xl mb-6 flex items-center">
<span className="mr-3 text-2xl">📈</span>
Trade Execution Details
</h4>
<div className="grid grid-cols-1 gap-6">
<div className="grid grid-cols-2 gap-4">
<div className="bg-blue-900/20 rounded-xl p-4 border border-blue-500/30">
<div className="text-blue-400 text-sm mb-1 font-medium">Entry Price</div>
<div className="text-white font-mono text-xl font-bold">
${status.lastDecision.executionDetails.currentPrice?.toFixed(4)}
</div>
</div>
<div className="bg-green-900/20 rounded-xl p-4 border border-green-500/30">
<div className="text-green-400 text-sm mb-1 font-medium">Position Size</div>
<div className="text-white font-bold text-xl">
${status.lastDecision.executionDetails.amount}
</div>
</div>
<div className={`rounded-xl p-4 border ${
status.lastDecision.executionDetails.side === 'BUY'
? 'bg-green-900/20 border-green-500/30'
: 'bg-red-900/20 border-red-500/30'
}`}>
<div className="text-gray-400 text-sm mb-1 font-medium">Direction</div>
<div className={`font-bold text-xl ${
status.lastDecision.executionDetails.side === 'BUY' ? 'text-green-300' : 'text-red-300'
}`}>
{status.lastDecision.executionDetails.side}
</div>
</div>
<div className="bg-yellow-900/20 rounded-xl p-4 border border-yellow-500/30">
<div className="text-yellow-400 text-sm mb-1 font-medium">Leverage</div>
<div className="text-white font-bold text-xl">
{status.lastDecision.executionDetails.leverage}x
</div>
</div>
</div>
{/* Risk Management */}
<div className="bg-gray-900/40 rounded-xl p-4 border border-gray-600/30">
<h5 className="text-gray-300 font-bold mb-3 flex items-center">
<span className="mr-2">🛡</span>
Risk Management
</h5>
<div className="grid grid-cols-2 gap-4">
<div className="flex justify-between items-center">
<span className="text-red-400 font-medium">Stop Loss:</span>
<span className="text-red-300 font-mono text-lg font-bold">
${status.lastDecision.executionDetails.stopLoss?.toFixed(4)}
</span>
</div>
<div className="flex justify-between items-center">
<span className="text-green-400 font-medium">Take Profit:</span>
<span className="text-green-300 font-mono text-lg font-bold">
${status.lastDecision.executionDetails.takeProfit?.toFixed(4)}
</span>
</div>
</div>
{status.lastDecision.executionDetails.txId && (
<div className="mt-3 pt-3 border-t border-gray-600/30">
<div className="flex justify-between items-center">
<span className="text-gray-400 text-sm">Transaction ID:</span>
<span className="text-blue-400 font-mono text-sm">
{status.lastDecision.executionDetails.txId.substring(0, 12)}...
</span>
</div>
</div>
)}
</div>
</div>
</div>
{/* AI Leverage Reasoning */}
<div className="bg-black/30 backdrop-blur-sm rounded-2xl p-6 border border-yellow-500/30 shadow-lg">
<h4 className="text-yellow-300 font-bold text-xl mb-4 flex items-center">
<span className="mr-3 text-2xl"></span>
AI Leverage Analysis
</h4>
<div className="bg-gradient-to-br from-yellow-900/40 to-orange-900/20 rounded-xl p-6 border-l-4 border-yellow-500 shadow-inner">
<div className="text-yellow-100 leading-relaxed whitespace-pre-line text-lg">
{status.lastDecision.executionDetails.aiReasoning}
</div>
</div>
</div>
</div>
)}
</div>
</div>
) : (
<div className="text-center py-16">
<div className="text-9xl mb-8 opacity-60">🤖</div>
<h4 className="text-3xl text-purple-300 font-bold mb-6">AI Analysis Standby</h4>
<p className="text-gray-300 mb-8 text-xl max-w-3xl mx-auto leading-relaxed">
The AI will analyze market conditions using advanced technical indicators across multiple timeframes
and provide detailed reasoning for all trading decisions.
</p>
<div className="bg-purple-900/30 rounded-2xl p-8 border-2 border-purple-500/40 max-w-4xl mx-auto backdrop-blur-sm">
<div className="text-purple-300 font-bold text-xl mb-6">What you'll see when analysis starts:</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 text-left">
<div className="space-y-4">
<div className="flex items-center p-3 bg-purple-800/20 rounded-lg border border-purple-500/30">
<span className="text-purple-400 mr-3 text-xl">🎯</span>
<div>
<div className="text-white font-semibold">Entry Strategy</div>
<div className="text-gray-300 text-sm">Why AI chose this entry point</div>
</div>
</div>
<div className="flex items-center p-3 bg-purple-800/20 rounded-lg border border-purple-500/30">
<span className="text-purple-400 mr-3 text-xl">🛡️</span>
<div>
<div className="text-white font-semibold">Risk Management</div>
<div className="text-gray-300 text-sm">Stop loss and take profit logic</div>
</div>
</div>
<div className="flex items-center p-3 bg-purple-800/20 rounded-lg border border-purple-500/30">
<span className="text-purple-400 mr-3 text-xl">📊</span>
<div>
<div className="text-white font-semibold">Technical Analysis</div>
<div className="text-gray-300 text-sm">Multi-timeframe indicator consensus</div>
</div>
</div>
</div>
<div className="space-y-4">
<div className="flex items-center p-3 bg-purple-800/20 rounded-lg border border-purple-500/30">
<span className="text-purple-400 mr-3 text-xl">⚡</span>
<div>
<div className="text-white font-semibold">Leverage Calculation</div>
<div className="text-gray-300 text-sm">AI's dynamic risk assessment</div>
</div>
</div>
<div className="flex items-center p-3 bg-purple-800/20 rounded-lg border border-purple-500/30">
<span className="text-purple-400 mr-3 text-xl">🎲</span>
<div>
<div className="text-white font-semibold">Confidence Scoring</div>
<div className="text-gray-300 text-sm">Probability-based decision making</div>
</div>
</div>
<div className="flex items-center p-3 bg-purple-800/20 rounded-lg border border-purple-500/30">
<span className="text-purple-400 mr-3 text-xl"></span>
<div>
<div className="text-white font-semibold">Execution Status</div>
<div className="text-gray-300 text-sm">Real-time trade confirmation</div>
</div>
</div>
</div>
</div>
</div>
</div>
)}
</div>
</div>
</div>
)
}