Files
trading_bot_v3/app/components/PositionMonitor.tsx
mindesbunister c687562ecf 🏖️ BEACH MODE: Complete Autonomous Trading System
Features Added:
- 🤖 Autonomous AI Risk Management System
- 🛡️ Smart Stop Loss Proximity Monitoring
- 📊 Real-time Position Monitor with Dark Theme
- 🚨 Emergency Stop Buttons on All Pages
- 🏖️ Full Beach Mode Operation

- Emergency exit analysis (< 1% from SL)
- Position review and adjustments (1-2% from SL)
- Enhanced monitoring (2-5% from SL)
- Opportunity scanning (> 5% from SL)

- Beautiful dark theme Position Monitor
- Emergency stop buttons on automation pages
- Real-time P&L tracking with trend indicators
- Beach mode demo script

- Autonomous risk manager integration
- Position monitoring API endpoints
- Enhanced automation with AI leverage calculator
- CLI monitoring tools with enhanced display

Now you can truly relax on the beach while your AI handles everything! 🏖️🤖💰
2025-07-25 11:57:02 +02:00

302 lines
12 KiB
TypeScript
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.
'use client';
import { useState, useEffect } from 'react';
interface Position {
symbol: string;
side: string;
size: number;
entryPrice: number;
currentPrice: number;
unrealizedPnl: number;
notionalValue: number;
}
interface StopLossProximity {
stopLossPrice: number;
currentPrice: number;
distancePercent: string;
isNear: boolean;
}
interface MonitorData {
hasPosition: boolean;
position?: Position;
stopLossProximity?: StopLossProximity;
riskLevel: string;
nextAction: string;
recommendation: string;
}
interface AutomationStatus {
isActive: boolean;
mode: string;
symbol: string;
timeframes: string[];
totalCycles: number;
totalTrades: number;
lastActivity: string;
consecutiveErrors: number;
detailedStatus: string;
}
export default function PositionMonitor() {
const [monitorData, setMonitorData] = useState<MonitorData | null>(null);
const [automationStatus, setAutomationStatus] = useState<AutomationStatus | null>(null);
const [lastUpdate, setLastUpdate] = useState<Date>(new Date());
const [error, setError] = useState<string>('');
const fetchData = async () => {
try {
// Fetch position data
const positionResponse = await fetch('/api/automation/position-monitor');
const positionResult = await positionResponse.json();
// Fetch automation status
const statusResponse = await fetch('/api/automation/status');
const statusResult = await statusResponse.json();
if (positionResult.success) {
setMonitorData(positionResult.monitor);
}
setAutomationStatus(statusResult);
setLastUpdate(new Date());
setError('');
} catch (err) {
setError('Failed to fetch monitoring data');
console.error('Monitor error:', err);
}
};
useEffect(() => {
fetchData();
const interval = setInterval(fetchData, 10000); // Update every 10 seconds
return () => clearInterval(interval);
}, []);
const getRiskColor = (risk: string) => {
switch (risk) {
case 'HIGH': return 'text-red-500';
case 'MEDIUM': return 'text-yellow-500';
case 'LOW': return 'text-green-500';
default: return 'text-gray-500';
}
};
const getStopLossStatus = (distancePercent: string) => {
const distance = parseFloat(distancePercent);
if (distance <= 2) return { icon: '🚨', text: 'DANGER', color: 'text-red-600' };
if (distance <= 5) return { icon: '⚠️', text: 'WARNING', color: 'text-yellow-600' };
if (distance <= 10) return { icon: '🟡', text: 'CAUTION', color: 'text-yellow-500' };
return { icon: '✅', text: 'SAFE', color: 'text-green-500' };
};
if (error) {
return (
<div className="bg-red-50 border border-red-200 rounded-lg p-4">
<div className="flex items-center">
<span className="text-red-500 mr-2"></span>
<span className="text-red-700">{error}</span>
</div>
</div>
);
}
return (
<div className="space-y-6">
{/* Header */}
<div className="bg-gray-800 rounded-lg p-4 border border-gray-700">
<div className="flex justify-between items-center">
<h2 className="text-lg font-semibold text-white flex items-center">
<span className="mr-2">🔍</span>
Position Monitor
</h2>
<span className="text-sm text-gray-400">
Last update: {lastUpdate.toLocaleTimeString()}
</span>
</div>
</div>
{/* Position Status */}
{monitorData?.hasPosition && monitorData.position ? (
<div className="bg-gray-800 border border-gray-700 rounded-lg p-6">
<h3 className="text-lg font-medium text-white mb-4 flex items-center">
<span className="mr-2">📊</span>
Active Position
</h3>
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
<div className="bg-gray-900/50 p-3 rounded-lg">
<p className="text-sm text-gray-400">Symbol & Side</p>
<p className="font-medium text-white">{monitorData.position.symbol}</p>
<p className={`text-sm font-semibold ${monitorData.position.side === 'short' ? 'text-red-400' : 'text-green-400'}`}>
{monitorData.position.side.toUpperCase()}
</p>
</div>
<div className="bg-gray-900/50 p-3 rounded-lg">
<p className="text-sm text-gray-400">Size</p>
<p className="font-medium text-white">{monitorData.position.size} SOL</p>
</div>
<div className="bg-gray-900/50 p-3 rounded-lg">
<p className="text-sm text-gray-400">Entry Price</p>
<p className="font-medium text-white">${monitorData.position.entryPrice.toFixed(4)}</p>
</div>
<div className="bg-gray-900/50 p-3 rounded-lg">
<p className="text-sm text-gray-400">Current Price</p>
<p className="font-medium text-white">${monitorData.position.currentPrice.toFixed(4)}</p>
</div>
<div className="bg-gray-900/50 p-3 rounded-lg">
<p className="text-sm text-gray-400">P&L</p>
<p className={`font-medium ${monitorData.position.unrealizedPnl >= 0 ? 'text-green-400' : 'text-red-400'}`}>
{monitorData.position.unrealizedPnl >= 0 ? '+' : ''}${monitorData.position.unrealizedPnl.toFixed(2)}
</p>
</div>
<div className="bg-gray-900/50 p-3 rounded-lg">
<p className="text-sm text-gray-400">Notional Value</p>
<p className="font-medium text-white">${monitorData.position.notionalValue.toFixed(2)}</p>
</div>
</div>
{/* Stop Loss Section */}
{monitorData.stopLossProximity && (
<div className="mt-6 p-4 bg-gray-900/30 rounded-lg border border-gray-600">
<h4 className="font-medium text-white mb-3 flex items-center">
<span className="mr-2">🤖</span>
AI Autonomous Risk Management
</h4>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="bg-gray-800/50 p-3 rounded-lg">
<p className="text-sm text-gray-400">Stop Loss Price</p>
<p className="font-medium text-white">${monitorData.stopLossProximity.stopLossPrice.toFixed(4)}</p>
</div>
<div className="bg-gray-800/50 p-3 rounded-lg">
<p className="text-sm text-gray-400">Distance</p>
<p className="font-medium text-white">{monitorData.stopLossProximity.distancePercent}% away</p>
</div>
<div className="bg-gray-800/50 p-3 rounded-lg">
<p className="text-sm text-gray-400">AI Status</p>
{(() => {
const status = getStopLossStatus(monitorData.stopLossProximity.distancePercent);
const aiActions: Record<string, { text: string; color: string }> = {
'DANGER': { text: '🚨 Emergency Analysis', color: 'text-red-400' },
'WARNING': { text: '⚠️ Position Review', color: 'text-yellow-400' },
'CAUTION': { text: '🟡 Enhanced Watch', color: 'text-yellow-400' },
'SAFE': { text: '✅ Opportunity Scan', color: 'text-green-400' }
};
const aiAction = aiActions[status.text] || aiActions['SAFE'];
return (
<p className={`font-medium ${aiAction.color}`}>
{aiAction.text}
</p>
);
})()}
</div>
</div>
<div className="mt-3 bg-gray-800/30 p-3 rounded-lg">
<p className="text-sm text-gray-400">AI Action Plan</p>
<p className="font-medium text-blue-400">
{monitorData.nextAction || 'AI monitoring position autonomously'}
</p>
</div>
{monitorData.stopLossProximity.isNear && (
<div className="mt-4 p-3 bg-blue-900/30 border border-blue-500/30 rounded-lg">
<p className="text-blue-300 font-medium">🤖 AI TAKING ACTION: Autonomous risk management activated!</p>
<p className="text-blue-400 text-sm mt-1">No manual intervention required - enjoy your beach time! 🏖</p>
</div>
)}
</div>
)}
</div>
) : (
<div className="bg-gray-800 border border-gray-700 rounded-lg p-6">
<div className="text-center py-8">
<p className="text-gray-400 text-lg flex items-center justify-center">
<span className="mr-2">📊</span>
No Open Positions
</p>
<p className="text-gray-500 mt-2">Scanning for opportunities...</p>
</div>
</div>
)}
{/* Automation Status */}
<div className="bg-gray-800 border border-gray-700 rounded-lg p-6">
<h3 className="text-lg font-medium text-white mb-4 flex items-center">
<span className="mr-2">🤖</span>
Automation Status
</h3>
{automationStatus?.isActive ? (
<div className="space-y-4">
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<div className="bg-gray-900/50 p-3 rounded-lg">
<p className="text-sm text-gray-400">Status</p>
<p className="font-medium text-green-400 flex items-center">
<span className="w-2 h-2 bg-green-400 rounded-full mr-2"></span>
ACTIVE
</p>
</div>
<div className="bg-gray-900/50 p-3 rounded-lg">
<p className="text-sm text-gray-400">Mode</p>
<p className={`font-medium ${automationStatus.mode === 'LIVE' ? 'text-red-400' : 'text-blue-400'}`}>
{automationStatus.mode}
</p>
</div>
<div className="bg-gray-900/50 p-3 rounded-lg">
<p className="text-sm text-gray-400">Strategy</p>
<p className="font-medium text-white">Scalping</p>
</div>
<div className="bg-gray-900/50 p-3 rounded-lg">
<p className="text-sm text-gray-400">Symbol</p>
<p className="font-medium text-white">{automationStatus.symbol}</p>
</div>
</div>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<div className="bg-gray-900/50 p-3 rounded-lg">
<p className="text-sm text-gray-400">Timeframes</p>
<p className="font-medium text-cyan-400">{automationStatus.timeframes?.join(', ') || 'N/A'}</p>
</div>
<div className="bg-gray-900/50 p-3 rounded-lg">
<p className="text-sm text-gray-400">Cycles</p>
<p className="font-medium text-white">{automationStatus.totalCycles}</p>
</div>
<div className="bg-gray-900/50 p-3 rounded-lg">
<p className="text-sm text-gray-400">Trades</p>
<p className="font-medium text-white">{automationStatus.totalTrades}</p>
</div>
<div className="bg-gray-900/50 p-3 rounded-lg">
<p className="text-sm text-gray-400">Errors</p>
<p className={`font-medium ${automationStatus.consecutiveErrors > 0 ? 'text-yellow-400' : 'text-green-400'}`}>
{automationStatus.consecutiveErrors}/3
</p>
</div>
</div>
{automationStatus.lastActivity && (
<div className="bg-gray-900/30 p-3 rounded-lg">
<p className="text-sm text-gray-400">Last Activity</p>
<p className="font-medium text-white">
{new Date(automationStatus.lastActivity).toLocaleString()}
</p>
</div>
)}
</div>
) : (
<div className="text-center py-4">
<p className="text-red-400 font-medium flex items-center justify-center">
<span className="w-2 h-2 bg-red-400 rounded-full mr-2"></span>
STOPPED
</p>
<p className="text-gray-500 mt-2">{automationStatus?.detailedStatus}</p>
</div>
)}
</div>
</div>
);
}