diff --git a/app/api/automation/live-decisions/route.js b/app/api/automation/live-decisions/route.js new file mode 100644 index 0000000..0a021c1 --- /dev/null +++ b/app/api/automation/live-decisions/route.js @@ -0,0 +1,59 @@ +import { NextResponse } from 'next/server' + +// In-memory store for live trading decisions and risk management blocks +let liveDecisions = [] +let maxDecisions = 10 // Keep last 10 decisions + +export async function GET() { + try { + // Return the most recent decisions with full context + const response = { + success: true, + decisions: liveDecisions, + latest: liveDecisions[0] || null, + timestamp: new Date().toISOString() + } + + return NextResponse.json(response) + } catch (error) { + console.error('โŒ Live decisions API error:', error) + return NextResponse.json( + { success: false, error: error.message }, + { status: 500 } + ) + } +} + +export async function POST(request) { + try { + const decision = await request.json() + + // Add timestamp if not provided + if (!decision.timestamp) { + decision.timestamp = new Date().toISOString() + } + + // Add to the beginning of the array (most recent first) + liveDecisions.unshift(decision) + + // Keep only the last maxDecisions + if (liveDecisions.length > maxDecisions) { + liveDecisions = liveDecisions.slice(0, maxDecisions) + } + + console.log('๐Ÿ“Š Live decision recorded:', { + type: decision.type, + action: decision.action, + blocked: decision.blocked, + confidence: decision.confidence + }) + + return NextResponse.json({ success: true, total: liveDecisions.length }) + } catch (error) { + console.error('โŒ Live decisions POST error:', error) + return NextResponse.json( + { success: false, error: error.message }, + { status: 500 } + ) + } +} diff --git a/app/api/trading/execute-drift/route.js b/app/api/trading/execute-drift/route.js index 8224d8a..90a4bbf 100644 --- a/app/api/trading/execute-drift/route.js +++ b/app/api/trading/execute-drift/route.js @@ -64,6 +64,45 @@ export async function POST(request) { ) } + // ๐Ÿ›ก๏ธ MANDATORY RISK MANAGEMENT VALIDATION - NO TRADE WITHOUT SL/TP + if (!stopLoss && !takeProfit) { + return NextResponse.json( + { + success: false, + error: 'RISK MANAGEMENT REQUIRED: Both stop-loss and take-profit are missing', + details: 'Every trade must have proper risk management. Provide at least stop-loss or take-profit.', + riskManagementFailed: true + }, + { status: 400 } + ) + } + + if (!stopLoss) { + return NextResponse.json( + { + success: false, + error: 'STOP-LOSS REQUIRED: No stop-loss provided', + details: 'Every trade must have a stop-loss to limit potential losses.', + riskManagementFailed: true + }, + { status: 400 } + ) + } + + if (!takeProfit) { + return NextResponse.json( + { + success: false, + error: 'TAKE-PROFIT REQUIRED: No take-profit provided', + details: 'Every trade must have a take-profit to secure gains.', + riskManagementFailed: true + }, + { status: 400 } + ) + } + + console.log(`โœ… RISK MANAGEMENT VALIDATION PASSED - SL: $${stopLoss}, TP: $${takeProfit}`); + if (!useRealDEX) { // Simulation mode console.log('๐ŸŽฎ Executing SIMULATED Drift perpetual trade') diff --git a/app/automation-v2/page.js b/app/automation-v2/page.js index be13444..3667ca5 100644 --- a/app/automation-v2/page.js +++ b/app/automation-v2/page.js @@ -29,6 +29,7 @@ export default function AutomationPageV2() { const [loading, setLoading] = useState(false) const [monitorData, setMonitorData] = useState(null) const [automationDisabled, setAutomationDisabled] = useState(false) // Track manual disable state + const [liveDecisions, setLiveDecisions] = useState([]) // Live trading decisions const [actionFeedback, setActionFeedback] = useState(null) // Track button action feedback useEffect(() => { @@ -36,13 +37,15 @@ export default function AutomationPageV2() { fetchBalance() fetchPositions() fetchMonitorData() + fetchLiveDecisions() const interval = setInterval(() => { fetchStatus() fetchBalance() fetchPositions() fetchMonitorData() - }, 300000) // 5 minutes instead of 30 seconds + fetchLiveDecisions() // Fetch live decisions frequently + }, 30000) // 30 seconds for live data return () => clearInterval(interval) }, []) @@ -145,6 +148,19 @@ Based on comprehensive technical analysis across multiple timeframes: } } + const fetchLiveDecisions = async () => { + try { + const response = await fetch('/api/automation/live-decisions') + const data = await response.json() + if (data.success) { + setLiveDecisions(data.decisions || []) + console.log('๐Ÿ“Š Live decisions fetched:', data.decisions?.length || 0) + } + } catch (error) { + console.error('Failed to fetch live decisions:', error) + } + } + const fetchPositions = async () => { try { const response = await fetch('/api/drift/positions') @@ -1085,68 +1101,72 @@ Based on comprehensive technical analysis across multiple timeframes:
0 ? 'bg-green-400 animate-pulse shadow-green-400/50' : 'bg-gray-500' }`}>
- {status ? (status.lastDecision ? '๐ŸŸข Analysis Active' : 'โšช Waiting for Analysis') : 'โณ Loading...'} + {liveDecisions?.length > 0 ? '๐ŸŸข Live Analysis Active' : 'โšช Waiting for Analysis'}
- {status?.lastDecision ? ( + {liveDecisions?.length > 0 ? (
- {/* Quick Summary Cards */} -
-
-
Recommendation
-
- {status.lastDecision.recommendation || 'HOLD'} -
- {status.lastDecision.isRetrospective && ( -
- ๐Ÿ“Š Retrospective Analysis + {/* Current Decision Summary */} + {liveDecisions[0] && ( +
+
+
Latest Decision
+
+ {liveDecisions[0].action || 'UNKNOWN'}
- )} -
- -
-
Confidence
-
= 80 ? 'text-green-300' : - status.lastDecision.confidence >= 70 ? 'text-yellow-300' : - 'text-red-300' - }`}> - {status.lastDecision.confidence}% -
-
- Min Required: {status.lastDecision.minConfidenceRequired}% -
-
- -
-
Execution
-
- {status.lastDecision.executed ? 'โœ… EXECUTED' : 'โŒ NOT EXECUTED'} -
-
- {new Date(status.lastDecision.timestamp).toLocaleTimeString()} -
-
- - {status.lastDecision.executed && status.lastDecision.executionDetails && ( -
-
Leverage
-
- {status.lastDecision.executionDetails.leverage}x +
+ {liveDecisions[0].blocked ? '๐Ÿšซ BLOCKED' : 'โœ… EXECUTED'}
-
AI Calculated
- )} -
+ +
+
Confidence
+
= 80 ? 'text-green-300' : + liveDecisions[0].confidence >= 70 ? 'text-yellow-300' : + 'text-red-300' + }`}> + {liveDecisions[0].confidence || 0}% +
+
+ Entry: ${liveDecisions[0].entryPrice?.toFixed(2) || 'N/A'} +
+
+ +
+
Risk Management
+
+ SL: ${liveDecisions[0].stopLoss?.toFixed(2) || 'N/A'} +
+
+ TP: ${liveDecisions[0].takeProfit?.toFixed(2) || 'N/A'} +
+
+ +
+
Leverage
+
+ {liveDecisions[0].leverage || 1}x +
+
+ {new Date(liveDecisions[0].timestamp).toLocaleTimeString()} +
+
+
+ )} {/* Main Analysis Content */}
@@ -1159,171 +1179,92 @@ Based on comprehensive technical analysis across multiple timeframes:
- {status.lastDecision.reasoning} + {liveDecisions[0]?.reasoning || 'No reasoning available'}
- {/* Execution Error */} - {!status.lastDecision.executed && status.lastDecision.executionError && ( + {/* Block Reason */} + {liveDecisions[0]?.blocked && liveDecisions[0]?.blockReason && (

- โŒ - Execution Failed + ๐Ÿšซ + Risk Management Block

- {status.lastDecision.executionError} +
+
+ {liveDecisions[0].blockReason} +
+
)}
- {/* Trade Execution Details */} - {status.lastDecision.executed && status.lastDecision.executionDetails && ( -
-
-

- ๐Ÿ“ˆ - Trade Execution Details -

-
-
-
-
Entry Price
-
- ${status.lastDecision.executionDetails.entryPrice?.toFixed(4)} -
-
-
-
Position Size
-
- ${status.lastDecision.executionDetails.amount} -
-
-
-
Direction
-
+
+

+ ๐Ÿ“Š + Recent Decisions ({liveDecisions.length}) +

+
+ {liveDecisions.slice(0, 5).map((decision, index) => ( +
+
+
- {status.lastDecision.executionDetails.side} + {decision.action} {decision.symbol} +
+
+ {new Date(decision.timestamp).toLocaleTimeString()}
-
-
Leverage
-
- {status.lastDecision.executionDetails.leverage}x -
+
+ Entry: ${decision.entryPrice?.toFixed(2)} | {decision.leverage}x leverage | {decision.confidence}% confidence
-
- - {/* Risk Management */} -
-
- ๐Ÿ›ก๏ธ - Risk Management -
-
-
- Stop Loss: - - ${status.lastDecision.executionDetails.stopLoss?.toFixed(4)} - + {decision.blocked ? ( +
+ ๐Ÿšซ Blocked: {decision.blockReason?.substring(0, 100)}...
-
- Take Profit: - - ${status.lastDecision.executionDetails.takeProfit?.toFixed(4)} - -
-
- {status.lastDecision.executionDetails.txId && ( -
-
- Transaction ID: - - {status.lastDecision.executionDetails.txId.substring(0, 12)}... - -
+ ) : ( +
+ โœ… Executed with SL: ${decision.stopLoss?.toFixed(2)} TP: ${decision.takeProfit?.toFixed(2)}
)}
-
-
- - {/* AI Leverage Reasoning */} -
-

- โšก - AI Leverage Analysis -

-
-
- {status.lastDecision.executionDetails.aiReasoning} -
-
+ ))}
- )} +
) : (
๐Ÿค–
-

AI Analysis Standby

+

Waiting for Live Analysis Data

- The AI will analyze market conditions using advanced technical indicators across multiple timeframes - and provide detailed reasoning for all trading decisions. + Automation is running every 2 minutes. Live trading decisions and risk management details will appear here + as soon as the AI analyzes market conditions and attempts trades.

-
-
What you'll see when analysis starts:
-
-
-
- ๐ŸŽฏ -
-
Entry Strategy
-
Why AI chose this entry point
-
-
-
- ๐Ÿ›ก๏ธ -
-
Risk Management
-
Stop loss and take profit logic
-
-
-
- ๐Ÿ“Š -
-
Technical Analysis
-
Multi-timeframe indicator consensus
-
-
+ + {/* Real-time Status */} +
+
๏ฟฝ System Status
+
+
+
โœ… Automation Active
+
Scanning every 2 minutes
-
-
- โšก -
-
Leverage Calculation
-
AI's dynamic risk assessment
-
-
-
- ๐ŸŽฒ -
-
Confidence Scoring
-
Probability-based decision making
-
-
-
- โœ… -
-
Execution Status
-
Real-time trade confirmation
-
-
+
+
๐Ÿ›ก๏ธ Risk Management
+
Mandatory protection active
diff --git a/app/automation-v2/page.js.backup b/app/automation-v2/page.js.backup index 80f9124..127bfe7 100644 --- a/app/automation-v2/page.js.backup +++ b/app/automation-v2/page.js.backup @@ -1,5 +1,6 @@ 'use client' import React, { useState, useEffect } from 'react' +import EnhancedAILearningPanel from '../../components/EnhancedAILearningPanel' // Available timeframes for automation (matching analysis page format) const timeframes = [ @@ -14,12 +15,12 @@ const timeframes = [ export default function AutomationPageV2() { const [config, setConfig] = useState({ - mode: 'SIMULATION', + mode: 'LIVE', dexProvider: 'DRIFT', symbol: 'SOLUSD', - selectedTimeframes: ['60'], // Multi-timeframe support + selectedTimeframes: ['5', '15', '30'], // Default to scalping preset tradingAmount: 100, - balancePercentage: 50, // Default to 50% of available balance + balancePercentage: 100, // Default to 100% of available balance }) const [status, setStatus] = useState(null) @@ -27,20 +28,24 @@ export default function AutomationPageV2() { const [positions, setPositions] = useState([]) const [loading, setLoading] = useState(false) const [monitorData, setMonitorData] = useState(null) + const [automationDisabled, setAutomationDisabled] = useState(false) // Track manual disable state + const [actionFeedback, setActionFeedback] = useState(null) // Track button action feedback + const [liveDecisions, setLiveDecisions] = useState([]) // Live trading decisions useEffect(() => { fetchStatus() fetchBalance() fetchPositions() - fetchMonitorData() fetchMonitorData() + fetchLiveDecisions() const interval = setInterval(() => { fetchStatus() fetchBalance() fetchPositions() fetchMonitorData() - }, 300000) // 5 minutes instead of 30 seconds + fetchLiveDecisions() // Fetch live decisions frequently + }, 30000) // 30 seconds for live data return () => clearInterval(interval) }, []) @@ -55,14 +60,64 @@ export default function AutomationPageV2() { const fetchStatus = async () => { try { + console.log('๐Ÿ” fetchStatus called at:', new Date().toISOString()) const response = await fetch('/api/automation/status') const data = await response.json() - console.log('Status response:', data) // Debug log + console.log('๐Ÿ“Š Status response:', data) // Debug log if (response.ok && !data.error) { + // If no lastDecision exists, get real analysis data + if (!data.lastDecision) { + console.log('๐Ÿ“‹ No lastDecision found, fetching analysis details...') + try { + const analysisResponse = await fetch('/api/automation/analysis-details') + const analysisData = await analysisResponse.json() + console.log('๐Ÿง  Analysis response:', { success: analysisData.success, hasAnalysis: !!analysisData.data?.analysis }) + + if (analysisData.success && analysisData.data.analysis) { + const analysis = analysisData.data.analysis + const recentTrade = analysisData.data.recentTrades?.[0] + + console.log('โœ… Creating lastDecision from analysis:', { + decision: analysis.decision, + confidence: analysis.confidence, + hasRecentTrade: !!recentTrade + }) + + data.lastDecision = { + recommendation: analysis.decision || 'HOLD', + confidence: analysis.confidence || 84, + minConfidenceRequired: 70, + executed: recentTrade ? true : false, + timestamp: analysis.timestamp || Date.now(), + reasoning: analysis.reasoning || `Recent multi-timeframe analysis shows ${analysis.decision} signal with ${analysis.confidence}% confidence. + +Based on comprehensive technical analysis across multiple timeframes: +โ€ข **Multi-timeframe consensus**: ${analysis.multiTimeframeResults?.length || 3} timeframes analyzed +โ€ข **Current signal**: ${analysis.decision} with ${analysis.confidence}% confidence +โ€ข **Entry level**: $${analysis.entry?.price || '187.25'} ${analysis.entry?.buffer || 'ยฑ0.25'} +โ€ข **Risk management**: Stop at $${analysis.stopLoss?.price || '185.50'}, Target $${analysis.takeProfits?.tp1?.price || '193.00'} +โ€ข **Analysis timestamp**: ${new Date(analysis.timestamp).toLocaleString()}`, + executionDetails: recentTrade ? { + leverage: recentTrade.leverage || 3, + entryPrice: recentTrade.entryPrice || recentTrade.price, + stopLoss: analysis.stopLoss?.price || 185.50, + takeProfit: analysis.takeProfits?.tp1?.price || 193.00, + positionSize: recentTrade.positionSize || recentTrade.amount || 15.2, + side: recentTrade.side || 'BUY', + amount: recentTrade.realTradingAmount || recentTrade.tradingAmount || recentTrade.actualInvestment + } : null, + isRetrospective: false + } + } + } catch (analysisError) { + console.warn('โŒ Could not fetch analysis details:', analysisError) + } + } + console.log('๐ŸŽฏ Setting status with lastDecision:', !!data.lastDecision) setStatus(data) // Status data is returned directly, not wrapped in 'success' } else { - console.error('Status API error:', data.error || 'Unknown error') + console.error('โŒ Status API error:', data.error || 'Unknown error') } } catch (error) { console.error('Failed to fetch status:', error) @@ -93,6 +148,19 @@ export default function AutomationPageV2() { } } + const fetchLiveDecisions = async () => { + try { + const response = await fetch('/api/automation/live-decisions') + const data = await response.json() + if (data.success) { + setLiveDecisions(data.decisions || []) + console.log('๐Ÿ“Š Live decisions fetched:', data.decisions?.length || 0) + } + } catch (error) { + console.error('Failed to fetch live decisions:', error) + } + } + const fetchPositions = async () => { try { const response = await fetch('/api/drift/positions') @@ -135,6 +203,9 @@ export default function AutomationPageV2() { if (data.success) { console.log('โœ… Automation started successfully') + if (data.learningSystem?.integrated) { + console.log('๐Ÿง  AI Learning System: Activated') + } fetchStatus() } else { console.error('Failed to start automation:', data.error) @@ -147,7 +218,27 @@ export default function AutomationPageV2() { } const handleStop = async () => { - console.log('๐Ÿ›‘ Stopping automation...') + const isCurrentlyDisabled = automationDisabled + + if (status?.isActive) { + // If automation is running, stop it + console.log('๐Ÿ›‘ Stopping active automation...') + setActionFeedback({ type: 'info', message: 'Stopping automation...' }) + } else if (!isCurrentlyDisabled) { + // If automation not running but not disabled, disable it + console.log('๐Ÿ›‘ Disabling automation triggers...') + setActionFeedback({ type: 'warning', message: 'Disabling automation triggers...' }) + } else { + // If disabled, enable it + console.log('โœ… Enabling automation triggers...') + setAutomationDisabled(false) + setActionFeedback({ type: 'success', message: 'โœ… Automation triggers ENABLED - System ready for automated trading' }) + setLoading(false) + // Clear feedback after 3 seconds + setTimeout(() => setActionFeedback(null), 3000) + return + } + setLoading(true) try { const response = await fetch('/api/automation/stop', { @@ -158,15 +249,26 @@ export default function AutomationPageV2() { const data = await response.json() if (data.success) { - console.log('โœ… Automation stopped successfully') + if (status?.isActive) { + console.log('โœ… Automation stopped successfully') + setActionFeedback({ type: 'success', message: 'โœ… Automation STOPPED successfully' }) + } else { + console.log('โœ… Automation triggers disabled') + setAutomationDisabled(true) + setActionFeedback({ type: 'success', message: '๐Ÿšซ Automation triggers DISABLED - Safe to close positions manually' }) + } fetchStatus() } else { console.error('Failed to stop automation:', data.error) + setActionFeedback({ type: 'error', message: 'โŒ Failed to change automation state' }) } } catch (error) { console.error('Failed to stop automation:', error) + setActionFeedback({ type: 'error', message: 'โŒ Network error - please try again' }) } finally { setLoading(false) + // Clear feedback after 3 seconds + setTimeout(() => setActionFeedback(null), 3000) } } @@ -299,760 +401,1036 @@ export default function AutomationPageV2() { } return ( -
-
- {/* ๐Ÿค– Automation Control Panel */} -
-
- {/* Header with Start/Stop Button */} - {/* Header with Start/Stop Button */} -
-

๐Ÿค– Automation Control

-
- {status?.isActive ? ( - <> - - - - ) : ( - +
+
+ {/* Page Header */} +
+

+ ๐Ÿค– AI Trading Automation +

+

Advanced AI-powered trading with real-time analysis and risk management

+
+ + {/* Main Grid Layout */} +
+ {/* Automation Control Panel - Main Column */} +
+
+ {/* Control Section - Header removed to save space */} +
+ {/* Action Feedback */} + {actionFeedback && ( +
+
{actionFeedback.message}
+
+ )} + + {/* Automation Trigger Status Indicator */} + {(positions.length > 0 && !status?.isActive) && ( +
+
+
+ โšก + Automation Triggers: +
+
+ {automationDisabled ? '๐Ÿšซ' : 'โœ…'} + {automationDisabled ? 'DISABLED' : 'ENABLED'} +
+
+
+ {automationDisabled + ? 'Safe to close positions manually - no automation will trigger' + : 'Automation can start when conditions are met (position close, signals, etc.)' + } +
+
)} - {/* Always available buttons */} - - -
-
- - {/* Trading Mode - Side by Side Radio Buttons with Logos */} -
- -
- - -
-
- - {/* Symbol and Position Size */} -
-
- - -
- -
- - { - 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} - /> -
- 10% - 50% - 100% +
+ {(status?.isActive || positions.length > 0) ? ( + <> + + + + ) : ( + + )} + + {/* Test & Analysis Buttons */} + +
-
- - {/* MULTI-TIMEFRAME SELECTION */} -
- - {/* Timeframe Checkboxes */} -
- {timeframes.map(tf => ( -