feat: Add 'Mark as Traded' functionality for manual trade tracking

- Add markAsTraded() function to create virtual positions for follow-up analysis
- Enable follow-up assistant for manually executed trades on external platforms
- Add blue 'Mark Traded' buttons next to existing green 'Trade' buttons
- Prompt for trade amount and confirm entry price before creating position
- Automatically store analysis data (entry, SL, TP) with virtual position
- Optional direct access to Trade Follow-up Assistant after marking
- Solves issue where manual Drift trades couldn't use follow-up analysis
- Maintains existing automated trade execution functionality
This commit is contained in:
mindesbunister
2025-07-17 16:06:32 +02:00
parent e36cb1f47e
commit 348de31ac5

View File

@@ -504,6 +504,72 @@ export default function AIAnalysisPanel({ onAnalysisComplete }: AIAnalysisPanelP
setTradeModalOpen(true)
}
// Manual trade marking for follow-up (when trading manually on external platforms)
const markAsTraded = async (analysisData: any) => {
try {
console.log('📋 Marking analysis as manually traded for follow-up:', analysisData)
// Extract trade data from analysis
const analysis = analysisData.result?.analysis || analysisData.analysis
if (!analysis) {
alert('❌ No analysis data found to mark as traded')
return
}
// Create virtual position for follow-up tracking
const entryPrice = analysis.entry?.price || 0
const stopLoss = analysis.stopLoss?.price || null
const takeProfit = analysis.takeProfits?.tp1?.price || null
const side = analysis.recommendation === 'BUY' ? 'LONG' : analysis.recommendation === 'SELL' ? 'SHORT' : 'LONG'
if (!entryPrice) {
alert('❌ No entry price found in analysis')
return
}
// Prompt for trade details
const amount = prompt('Enter trade amount (size):')
if (!amount || parseFloat(amount) <= 0) return
const actualEntryPrice = prompt(`Confirm entry price (from analysis: $${entryPrice}):`, entryPrice.toString())
if (!actualEntryPrice) return
const response = await fetch('/api/trading/positions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
action: 'add',
symbol: symbol,
side: side,
amount: parseFloat(amount),
entryPrice: parseFloat(actualEntryPrice),
leverage: 1,
stopLoss: stopLoss,
takeProfit: takeProfit,
txId: `manual_${Date.now()}`,
notes: `Manual trade marked from AI analysis - ${analysis.summary?.substring(0, 100) || 'AI trading setup'}`
})
})
const result = await response.json()
if (result.success) {
alert(`✅ Position marked as traded!\n\n• ${side} ${amount} ${symbol}\n• Entry: $${actualEntryPrice}\n• Follow-up assistant now available`)
// Optional: Show follow-up panel
if (confirm('Open Trade Follow-up Assistant now?')) {
setFollowUpPanelOpen(true)
}
} else {
throw new Error(result.error || 'Failed to mark trade')
}
} catch (error) {
console.error('Error marking trade:', error)
alert(`❌ Failed to mark trade: ${error instanceof Error ? error.message : 'Unknown error'}`)
}
}
// Trade execution API call
const executeTrade = async (tradeData: any) => {
try {
@@ -1022,12 +1088,21 @@ export default function AIAnalysisPanel({ onAnalysisComplete }: AIAnalysisPanelP
</h5>
<div className="flex items-center space-x-2">
{timeframeResult.success && timeframeResult.result.analysis && (
<button
onClick={() => handleTradeClick(timeframeResult)}
className="px-3 py-1 bg-gradient-to-r from-green-500 to-green-600 text-white text-xs font-medium rounded hover:from-green-600 hover:to-green-700 transition-all transform hover:scale-105"
>
💰 Trade
</button>
<>
<button
onClick={() => handleTradeClick(timeframeResult)}
className="px-3 py-1 bg-gradient-to-r from-green-500 to-green-600 text-white text-xs font-medium rounded hover:from-green-600 hover:to-green-700 transition-all transform hover:scale-105"
>
💰 Trade
</button>
<button
onClick={() => markAsTraded(timeframeResult)}
className="px-3 py-1 bg-gradient-to-r from-blue-500 to-blue-600 text-white text-xs font-medium rounded hover:from-blue-600 hover:to-blue-700 transition-all transform hover:scale-105"
title="Mark as manually traded for follow-up analysis"
>
📋 Mark Traded
</button>
</>
)}
<span className="text-xs text-gray-400">
{timeframeResult.success ? 'Analysis Complete' : 'Failed'}
@@ -1125,12 +1200,21 @@ export default function AIAnalysisPanel({ onAnalysisComplete }: AIAnalysisPanelP
</h3>
<div className="flex items-center space-x-3">
{result.analysis && (
<button
onClick={() => handleTradeClick({ result, timeframeLabel: selectedTimeframes.map(tf => timeframes.find(t => t.value === tf)?.label).join(', ') })}
className="px-4 py-2 bg-gradient-to-r from-green-500 to-green-600 text-white text-sm font-medium rounded-lg hover:from-green-600 hover:to-green-700 transition-all transform hover:scale-105"
>
💰 Execute Trade
</button>
<>
<button
onClick={() => handleTradeClick({ result, timeframeLabel: selectedTimeframes.map(tf => timeframes.find(t => t.value === tf)?.label).join(', ') })}
className="px-4 py-2 bg-gradient-to-r from-green-500 to-green-600 text-white text-sm font-medium rounded-lg hover:from-green-600 hover:to-green-700 transition-all transform hover:scale-105"
>
💰 Execute Trade
</button>
<button
onClick={() => markAsTraded({ result, timeframeLabel: selectedTimeframes.map(tf => timeframes.find(t => t.value === tf)?.label).join(', ') })}
className="px-4 py-2 bg-gradient-to-r from-blue-500 to-blue-600 text-white text-sm font-medium rounded-lg hover:from-blue-600 hover:to-blue-700 transition-all transform hover:scale-105"
title="Mark as manually traded for follow-up analysis"
>
📋 Mark as Traded
</button>
</>
)}
{result.screenshots && (
<div className="text-xs text-gray-400">