diff --git a/app/automation-v2/page.js b/app/automation-v2/page.js
index 895e1dd..3ff0b91 100644
--- a/app/automation-v2/page.js
+++ b/app/automation-v2/page.js
@@ -20,16 +20,17 @@ export default function AutomationPageV2() {
timeframe: '1h', // Primary timeframe for backwards compatibility
selectedTimeframes: ['60'], // Multi-timeframe support
tradingAmount: 100,
+ balancePercentage: 50, // Default to 50% of available balance
maxLeverage: 5,
stopLossPercent: 2,
- takeProfitPercent: 6,
- riskPercentage: 2
+ takeProfitPercent: 6
})
const [status, setStatus] = useState(null)
const [balance, setBalance] = useState(null)
const [positions, setPositions] = useState([])
const [loading, setLoading] = useState(false)
+ const [nextAnalysisCountdown, setNextAnalysisCountdown] = useState(0)
useEffect(() => {
fetchStatus()
@@ -44,6 +45,51 @@ export default function AutomationPageV2() {
return () => clearInterval(interval)
}, [])
+ // Timer effect for countdown
+ useEffect(() => {
+ let countdownInterval = null
+
+ if (status?.isActive && status?.nextAnalysisIn > 0) {
+ setNextAnalysisCountdown(status.nextAnalysisIn)
+
+ countdownInterval = setInterval(() => {
+ setNextAnalysisCountdown(prev => {
+ if (prev <= 1) {
+ // Refresh status when timer reaches 0
+ fetchStatus()
+ return 0
+ }
+ return prev - 1
+ })
+ }, 1000)
+ } else {
+ setNextAnalysisCountdown(0)
+ }
+
+ return () => {
+ if (countdownInterval) {
+ clearInterval(countdownInterval)
+ }
+ }
+ }, [status?.nextAnalysisIn, status?.isActive])
+
+ // Helper function to format countdown time
+ const formatCountdown = (seconds) => {
+ if (seconds <= 0) return 'Analyzing now...'
+
+ const hours = Math.floor(seconds / 3600)
+ const minutes = Math.floor((seconds % 3600) / 60)
+ const secs = seconds % 60
+
+ if (hours > 0) {
+ return `${hours}h ${minutes}m ${secs}s`
+ } else if (minutes > 0) {
+ return `${minutes}m ${secs}s`
+ } else {
+ return `${secs}s`
+ }
+ }
+
const toggleTimeframe = (timeframe) => {
setConfig(prev => ({
...prev,
@@ -242,7 +288,7 @@ export default function AutomationPageV2() {
{/* Symbol and Position Size */}
-
+
-
-
-
- setConfig({...config, riskPercentage: parseFloat(e.target.value)})}
- disabled={status?.isActive}
- />
-
@@ -524,6 +544,172 @@ export default function AutomationPageV2() {
)}
+ {/* Analysis Progress */}
+ {status?.analysisProgress && (
+
+
+
Analysis Progress
+
+ Session: {status.analysisProgress.sessionId.split('-').pop()}
+
+
+
+ {/* Overall Progress */}
+
+ Step {status.analysisProgress.currentStep} of {status.analysisProgress.totalSteps}
+
+ {Math.round((status.analysisProgress.currentStep / status.analysisProgress.totalSteps) * 100)}%
+
+
+
+
+ {/* Timeframe Progress */}
+ {status.analysisProgress.timeframeProgress && (
+
+
+
+ Analyzing {status.analysisProgress.timeframeProgress.currentTimeframe || 'timeframes'}
+
+
+ {status.analysisProgress.timeframeProgress.current}/{status.analysisProgress.timeframeProgress.total}
+
+
+
+ )}
+
+ {/* Detailed Steps */}
+
+ {status.analysisProgress.steps.map((step, index) => (
+
+ {/* Status Icon */}
+
+ {step.status === 'active' ? '⏳' :
+ step.status === 'completed' ? '✓' :
+ step.status === 'error' ? '✗' :
+ index + 1}
+
+
+ {/* Step Info */}
+
+
+ {step.title}
+
+
+ {step.details || step.description}
+
+
+
+ {/* Duration */}
+ {step.duration && (
+
+ {(step.duration / 1000).toFixed(1)}s
+
+ )}
+
+ ))}
+
+
+
+ )}
+
+ {/* Analysis Timer */}
+ {status?.isActive && !status?.analysisProgress && (
+
+
+
Analysis Timer
+
+ Cycle #{status.currentCycle || 0}
+
+
+
+
+
+ {formatCountdown(nextAnalysisCountdown)}
+
+
+ {nextAnalysisCountdown > 0 ? 'Next Analysis In' : 'Analysis Starting Soon'}
+
+
+
+
0 ?
+ `${Math.max(0, 100 - (nextAnalysisCountdown / status.analysisInterval) * 100)}%` :
+ '0%'
+ }}
+ >
+
+
+ Analysis Interval: {Math.floor((status.analysisInterval || 0) / 60)}m
+
+
+
+ )}
+
+ {/* Individual Timeframe Results */}
+ {status?.individualTimeframeResults && status.individualTimeframeResults.length > 0 && (
+
+
Timeframe Analysis
+
+ {status.individualTimeframeResults.map((result, index) => (
+
+
+
+ {timeframes.find(tf => tf.value === result.timeframe)?.label || result.timeframe}
+
+
+ {result.recommendation}
+
+
+
+
+ {result.confidence}%
+
+
+ confidence
+
+
+
+ ))}
+
+
+
+ ✅ Last Updated: {status.individualTimeframeResults[0]?.timestamp ?
+ new Date(status.individualTimeframeResults[0].timestamp).toLocaleTimeString() :
+ 'N/A'
+ }
+
+
+
+ )}
+
{/* Trading Metrics */}
Trading Metrics