🏖️ 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! 🏖️🤖💰
This commit is contained in:
258
components/PositionMonitoringDashboard.jsx
Normal file
258
components/PositionMonitoringDashboard.jsx
Normal file
@@ -0,0 +1,258 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { AlertCircle, Eye, TrendingUp, TrendingDown, Activity, Clock } from 'lucide-react';
|
||||
|
||||
const PositionMonitoringDashboard = () => {
|
||||
const [positionData, setPositionData] = useState(null);
|
||||
const [automationStatus, setAutomationStatus] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [lastUpdate, setLastUpdate] = useState(null);
|
||||
|
||||
const fetchPositionData = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/automation/position-monitor');
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
setPositionData(data.monitor);
|
||||
setLastUpdate(new Date().toLocaleTimeString());
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch position data:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const fetchAutomationStatus = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/automation/status');
|
||||
const data = await response.json();
|
||||
setAutomationStatus(data);
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch automation status:', error);
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchPositionData();
|
||||
fetchAutomationStatus();
|
||||
|
||||
// Update every 10 seconds
|
||||
const interval = setInterval(() => {
|
||||
fetchPositionData();
|
||||
fetchAutomationStatus();
|
||||
}, 10000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const getRiskColor = (riskLevel) => {
|
||||
switch (riskLevel) {
|
||||
case 'CRITICAL': return 'bg-red-500 text-white';
|
||||
case 'HIGH': return 'bg-orange-500 text-white';
|
||||
case 'MEDIUM': return 'bg-yellow-500 text-black';
|
||||
case 'LOW': return 'bg-green-500 text-white';
|
||||
default: return 'bg-gray-500 text-white';
|
||||
}
|
||||
};
|
||||
|
||||
const getAutomationModeColor = (mode) => {
|
||||
if (!automationStatus?.isActive) return 'bg-gray-500 text-white';
|
||||
if (automationStatus?.positionMonitoringActive) return 'bg-blue-500 text-white';
|
||||
return 'bg-green-500 text-white';
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<Card className="w-full">
|
||||
<CardContent className="p-6">
|
||||
<div className="flex items-center justify-center">
|
||||
<Activity className="h-6 w-6 animate-spin mr-2" />
|
||||
Loading monitoring data...
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
{/* Automation Status Header */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center justify-between">
|
||||
<span className="flex items-center">
|
||||
<Activity className="h-5 w-5 mr-2" />
|
||||
Position-Aware Automation
|
||||
</span>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Badge className={getAutomationModeColor()}>
|
||||
{automationStatus?.isActive ? (
|
||||
automationStatus?.positionMonitoringActive ? 'MONITORING POSITION' : 'SCANNING OPPORTUNITIES'
|
||||
) : 'STOPPED'}
|
||||
</Badge>
|
||||
{lastUpdate && (
|
||||
<span className="text-sm text-gray-500 flex items-center">
|
||||
<Clock className="h-4 w-4 mr-1" />
|
||||
{lastUpdate}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">Status</p>
|
||||
<p className="font-semibold">{automationStatus?.detailedStatus || 'Unknown'}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">Next Action</p>
|
||||
<p className="font-semibold">{automationStatus?.nextAction || 'None'}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">Total Cycles</p>
|
||||
<p className="font-semibold">{automationStatus?.totalCycles || 0}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">Errors</p>
|
||||
<p className="font-semibold">{automationStatus?.consecutiveErrors || 0}</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Position Status */}
|
||||
{positionData?.hasPosition ? (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center justify-between">
|
||||
<span className="flex items-center">
|
||||
{positionData.position.side === 'LONG' ?
|
||||
<TrendingUp className="h-5 w-5 mr-2 text-green-500" /> :
|
||||
<TrendingDown className="h-5 w-5 mr-2 text-red-500" />
|
||||
}
|
||||
Active Position: {positionData.position.symbol}
|
||||
</span>
|
||||
<Badge className={getRiskColor(positionData.riskLevel)}>
|
||||
{positionData.riskLevel} RISK
|
||||
</Badge>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-4">
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">Side</p>
|
||||
<p className="font-semibold">{positionData.position.side}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">Size</p>
|
||||
<p className="font-semibold">{positionData.position.size}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">Entry Price</p>
|
||||
<p className="font-semibold">${positionData.position.entryPrice}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">Unrealized PnL</p>
|
||||
<p className={`font-semibold ${positionData.position.unrealizedPnl >= 0 ? 'text-green-600' : 'text-red-600'}`}>
|
||||
${positionData.position.unrealizedPnl}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Stop Loss Proximity Alert */}
|
||||
{positionData.stopLossProximity && (
|
||||
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
|
||||
<div className="flex items-center mb-2">
|
||||
<AlertCircle className="h-5 w-5 text-yellow-600 mr-2" />
|
||||
<h4 className="font-semibold text-yellow-800">Stop Loss Proximity Alert</h4>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-4 text-sm">
|
||||
<div>
|
||||
<p className="text-yellow-600">Distance to SL</p>
|
||||
<p className="font-bold">{positionData.stopLossProximity.distancePercent}%</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-yellow-600">Stop Loss Price</p>
|
||||
<p className="font-bold">${positionData.stopLossProximity.stopLossPrice}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-yellow-600">Current Price</p>
|
||||
<p className="font-bold">${positionData.stopLossProximity.currentPrice}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Next Action */}
|
||||
<div className="mt-4 p-4 bg-blue-50 border border-blue-200 rounded-lg">
|
||||
<h4 className="font-semibold text-blue-800 mb-2">What Will Happen Next?</h4>
|
||||
<p className="text-blue-700">{positionData.nextAction}</p>
|
||||
<p className="text-blue-600 text-sm mt-1">{positionData.recommendation}</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
) : (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center">
|
||||
<Eye className="h-5 w-5 mr-2" />
|
||||
No Active Positions
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-center py-8">
|
||||
<p className="text-gray-600 mb-4">Currently scanning for trading opportunities</p>
|
||||
<div className="grid grid-cols-2 gap-4 text-sm">
|
||||
<div>
|
||||
<p className="text-gray-500">Mode</p>
|
||||
<p className="font-semibold">Opportunity Scanning</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-gray-500">Next Check</p>
|
||||
<p className="font-semibold">Every 10 minutes</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Automation Controls */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Controls</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex space-x-4">
|
||||
<Button
|
||||
onClick={() => window.location.reload()}
|
||||
variant="outline"
|
||||
>
|
||||
Refresh Data
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
if (automationStatus?.isActive) {
|
||||
fetch('/api/automation/stop', { method: 'POST' })
|
||||
.then(() => window.location.reload());
|
||||
} else {
|
||||
// Open start automation modal/form
|
||||
console.log('Start automation');
|
||||
}
|
||||
}}
|
||||
variant={automationStatus?.isActive ? "destructive" : "default"}
|
||||
>
|
||||
{automationStatus?.isActive ? 'Stop Automation' : 'Start Automation'}
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PositionMonitoringDashboard;
|
||||
Reference in New Issue
Block a user