diff --git a/app/api/automation-insights/route.js b/app/api/automation-insights/route.js
index c07d81c..7f78d1f 100644
--- a/app/api/automation-insights/route.js
+++ b/app/api/automation-insights/route.js
@@ -67,6 +67,14 @@ export async function GET(request) {
take: 5
})
+ // Get actual total trades count for consistency
+ const totalTradesCount = await prisma.trade.count({
+ where: {
+ userId: 'default-user',
+ symbol: symbol
+ }
+ })
+
// Get recent market context
const allTrades = await prisma.trade.findMany({
where: {
@@ -103,7 +111,7 @@ export async function GET(request) {
marketContext: {
recentPnL,
winRate: winRate.toFixed(1),
- totalTrades: allTrades.length,
+ totalTrades: totalTradesCount, // Use actual total count
avgProfit: allTrades.length > 0 ? (recentPnL / allTrades.length).toFixed(2) : 0,
trend: sessions.length > 0 ? sessions[0].lastAnalysisData?.sentiment : 'NEUTRAL'
}
diff --git a/app/api/automation/analysis-details/route.js b/app/api/automation/analysis-details/route.js
index 06053d7..bc14c31 100644
--- a/app/api/automation/analysis-details/route.js
+++ b/app/api/automation/analysis-details/route.js
@@ -46,7 +46,7 @@ export async function GET() {
const totalPnL = completedTrades.reduce((sum, trade) => sum + (trade.profit || 0), 0)
const winRate = completedTrades.length > 0 ? (successfulTrades.length / completedTrades.length * 100) : 0
- const currentPrice = 175.82
+ const currentPrice = 189.50
const formattedTrades = recentTrades.map(trade => {
const priceChange = trade.side === 'BUY' ?
@@ -75,9 +75,51 @@ export async function GET() {
const tradingAmount = 100
const leverage = trade.leverage || 1
- const correctTokenAmount = tradingAmount / trade.price
- const displayAmount = correctTokenAmount
+ // Use real current price for calculation instead of stored wrong price
+ const correctTokenAmount = tradingAmount / currentPrice
+ const displayAmount = correctTokenAmount // Show corrected amount
const displayPositionSize = (tradingAmount * leverage).toFixed(2)
+
+ // Mark old trades with wrong data
+ const isOldWrongTrade = trade.price < 150 && trade.amount > 1.5 // Detect old wrong trades
+
+ // Enhanced entry/exit price handling
+ const entryPrice = trade.entryPrice || trade.price
+ let exitPrice = trade.exitPrice
+ let calculatedProfit = trade.profit
+
+ // If exit price is null but trade is completed, try to calculate from profit
+ if (trade.status === 'COMPLETED' && !exitPrice && calculatedProfit !== null && calculatedProfit !== undefined) {
+ // Calculate exit price from profit: profit = (exitPrice - entryPrice) * amount
+ if (trade.side === 'BUY') {
+ exitPrice = entryPrice + (calculatedProfit / trade.amount)
+ } else {
+ exitPrice = entryPrice - (calculatedProfit / trade.amount)
+ }
+ }
+
+ // If profit is null but we have both prices, calculate profit
+ if (trade.status === 'COMPLETED' && (calculatedProfit === null || calculatedProfit === undefined) && exitPrice && entryPrice) {
+ if (trade.side === 'BUY') {
+ calculatedProfit = (exitPrice - entryPrice) * trade.amount
+ } else {
+ calculatedProfit = (entryPrice - exitPrice) * trade.amount
+ }
+ }
+
+ // Determine result based on actual profit
+ let result = 'ACTIVE'
+ if (trade.status === 'COMPLETED') {
+ if (calculatedProfit === null || calculatedProfit === undefined) {
+ result = 'UNKNOWN' // When we truly don't have enough data
+ } else if (Math.abs(calculatedProfit) < 0.01) { // Within 1 cent
+ result = 'BREAKEVEN'
+ } else if (calculatedProfit > 0) {
+ result = 'WIN'
+ } else {
+ result = 'LOSS'
+ }
+ }
return {
id: trade.id,
@@ -98,21 +140,23 @@ export async function GET() {
actualDuration: durationMs,
durationText: formatDuration(durationMinutes) + (trade.status === 'OPEN' ? ' (Active)' : ''),
reason: `REAL: ${trade.side} signal with ${trade.confidence || 75}% confidence`,
- entryPrice: trade.entryPrice || trade.price,
- exitPrice: trade.exitPrice,
+ entryPrice: entryPrice,
+ exitPrice: exitPrice,
currentPrice: trade.status === 'OPEN' ? currentPrice : null,
unrealizedPnl: unrealizedPnL ? unrealizedPnL.toFixed(2) : null,
realizedPnl: realizedPnL ? realizedPnL.toFixed(2) : null,
+ calculatedProfit: calculatedProfit,
stopLoss: trade.stopLoss || (trade.side === 'BUY' ? (trade.price * 0.98).toFixed(2) : (trade.price * 1.02).toFixed(2)),
takeProfit: trade.takeProfit || (trade.side === 'BUY' ? (trade.price * 1.04).toFixed(2) : (trade.price * 0.96).toFixed(2)),
isActive: trade.status === 'OPEN' || trade.status === 'PENDING',
confidence: trade.confidence || 75,
- result: trade.status === 'COMPLETED' ?
- ((trade.profit || 0) > 0 ? 'WIN' : (trade.profit || 0) < 0 ? 'LOSS' : 'BREAKEVEN') :
- 'ACTIVE',
+ result: result,
resultDescription: trade.status === 'COMPLETED' ?
- `REAL: ${(trade.profit || 0) > 0 ? 'Profitable' : 'Loss'} ${trade.side} trade - Completed` :
- `REAL: ${trade.side} position active - ${formatDuration(durationMinutes)}`
+ `REAL: ${result === 'WIN' ? 'Profitable' : result === 'LOSS' ? 'Loss' : result} ${trade.side} trade - Completed` :
+ `REAL: ${trade.side} position active - ${formatDuration(durationMinutes)}`,
+ isOldWrongTrade: isOldWrongTrade,
+ correctedAmount: isOldWrongTrade ? correctTokenAmount.toFixed(4) : null,
+ originalStoredPrice: trade.price
}
})
diff --git a/app/api/automation/analysis-details/route.js.backup b/app/api/automation/analysis-details/route.js.backup
new file mode 100644
index 0000000..06053d7
--- /dev/null
+++ b/app/api/automation/analysis-details/route.js.backup
@@ -0,0 +1,207 @@
+import { NextResponse } from 'next/server'
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+export async function GET() {
+ try {
+ console.log('โ
API CORRECTED: Loading with fixed trade calculations...')
+
+ const sessions = await prisma.automationSession.findMany({
+ where: {
+ userId: 'default-user',
+ symbol: 'SOLUSD'
+ },
+ orderBy: { createdAt: 'desc' },
+ take: 10
+ })
+
+ if (sessions.length === 0) {
+ return NextResponse.json({
+ success: false,
+ message: 'No automation sessions found'
+ })
+ }
+
+ const latestSession = sessions[0]
+
+ const sessionsByTimeframe = {}
+ sessions.forEach(session => {
+ if (!sessionsByTimeframe[session.timeframe]) {
+ sessionsByTimeframe[session.timeframe] = session
+ }
+ })
+
+ const recentTrades = await prisma.trade.findMany({
+ where: {
+ userId: latestSession.userId,
+ symbol: latestSession.symbol
+ },
+ orderBy: { createdAt: 'desc' },
+ take: 10
+ })
+
+ const completedTrades = recentTrades.filter(t => t.status === 'COMPLETED')
+ const successfulTrades = completedTrades.filter(t => (t.profit || 0) > 0)
+ const totalPnL = completedTrades.reduce((sum, trade) => sum + (trade.profit || 0), 0)
+ const winRate = completedTrades.length > 0 ? (successfulTrades.length / completedTrades.length * 100) : 0
+
+ const currentPrice = 175.82
+
+ const formattedTrades = recentTrades.map(trade => {
+ const priceChange = trade.side === 'BUY' ?
+ (currentPrice - trade.price) :
+ (trade.price - currentPrice)
+ const realizedPnL = trade.status === 'COMPLETED' ? (trade.profit || 0) : null
+ const unrealizedPnL = trade.status === 'OPEN' ? (priceChange * trade.amount) : null
+
+ const entryTime = new Date(trade.createdAt)
+ const exitTime = trade.closedAt ? new Date(trade.closedAt) : null
+ const currentTime = new Date()
+
+ const durationMs = trade.status === 'COMPLETED' ?
+ (exitTime ? exitTime.getTime() - entryTime.getTime() : 0) :
+ (currentTime.getTime() - entryTime.getTime())
+
+ const durationMinutes = Math.floor(durationMs / (1000 * 60))
+ const formatDuration = (minutes) => {
+ if (minutes < 60) return `${minutes}m`
+ const hours = Math.floor(minutes / 60)
+ const mins = minutes % 60
+ return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`
+ }
+
+ // โ
CORRECTED CALCULATION: Fix position size for $100 investment
+ const tradingAmount = 100
+ const leverage = trade.leverage || 1
+
+ const correctTokenAmount = tradingAmount / trade.price
+ const displayAmount = correctTokenAmount
+ const displayPositionSize = (tradingAmount * leverage).toFixed(2)
+
+ return {
+ id: trade.id,
+ type: 'MARKET',
+ side: trade.side,
+ amount: displayAmount,
+ tradingAmount: tradingAmount,
+ leverage: leverage,
+ positionSize: displayPositionSize,
+ price: trade.price,
+ status: trade.status,
+ pnl: realizedPnL ? realizedPnL.toFixed(2) : (unrealizedPnL ? unrealizedPnL.toFixed(2) : '0.00'),
+ pnlPercent: realizedPnL ? `${((realizedPnL / tradingAmount) * 100).toFixed(2)}%` :
+ (unrealizedPnL ? `${((unrealizedPnL / tradingAmount) * 100).toFixed(2)}%` : '0.00%'),
+ createdAt: trade.createdAt,
+ entryTime: trade.createdAt,
+ exitTime: trade.closedAt,
+ actualDuration: durationMs,
+ durationText: formatDuration(durationMinutes) + (trade.status === 'OPEN' ? ' (Active)' : ''),
+ reason: `REAL: ${trade.side} signal with ${trade.confidence || 75}% confidence`,
+ entryPrice: trade.entryPrice || trade.price,
+ exitPrice: trade.exitPrice,
+ currentPrice: trade.status === 'OPEN' ? currentPrice : null,
+ unrealizedPnl: unrealizedPnL ? unrealizedPnL.toFixed(2) : null,
+ realizedPnl: realizedPnL ? realizedPnL.toFixed(2) : null,
+ stopLoss: trade.stopLoss || (trade.side === 'BUY' ? (trade.price * 0.98).toFixed(2) : (trade.price * 1.02).toFixed(2)),
+ takeProfit: trade.takeProfit || (trade.side === 'BUY' ? (trade.price * 1.04).toFixed(2) : (trade.price * 0.96).toFixed(2)),
+ isActive: trade.status === 'OPEN' || trade.status === 'PENDING',
+ confidence: trade.confidence || 75,
+ result: trade.status === 'COMPLETED' ?
+ ((trade.profit || 0) > 0 ? 'WIN' : (trade.profit || 0) < 0 ? 'LOSS' : 'BREAKEVEN') :
+ 'ACTIVE',
+ resultDescription: trade.status === 'COMPLETED' ?
+ `REAL: ${(trade.profit || 0) > 0 ? 'Profitable' : 'Loss'} ${trade.side} trade - Completed` :
+ `REAL: ${trade.side} position active - ${formatDuration(durationMinutes)}`
+ }
+ })
+
+ return NextResponse.json({
+ success: true,
+ data: {
+ session: {
+ id: latestSession.id,
+ symbol: latestSession.symbol,
+ timeframe: latestSession.timeframe,
+ status: latestSession.status,
+ mode: latestSession.mode,
+ createdAt: latestSession.createdAt,
+ lastAnalysisAt: latestSession.lastAnalysis || new Date().toISOString(),
+ totalTrades: completedTrades.length,
+ successfulTrades: successfulTrades.length,
+ errorCount: latestSession.errorCount,
+ totalPnL: totalPnL
+ },
+ multiTimeframeSessions: sessionsByTimeframe,
+ analysis: {
+ decision: "HOLD",
+ confidence: 84,
+ summary: `๐ฅ REAL DATABASE: ${completedTrades.length} trades, ${successfulTrades.length} wins (${winRate.toFixed(1)}% win rate), P&L: $${totalPnL.toFixed(2)}`,
+ sentiment: "NEUTRAL",
+ testField: "CORRECTED_CALCULATIONS",
+ analysisContext: {
+ currentSignal: "HOLD",
+ explanation: `๐ฏ REAL DATA: ${recentTrades.length} database trades shown with corrected calculations`
+ },
+ timeframeAnalysis: {
+ "15m": { decision: "HOLD", confidence: 75 },
+ "1h": { decision: "HOLD", confidence: 70 },
+ "2h": { decision: "HOLD", confidence: 70 },
+ "4h": { decision: "HOLD", confidence: 70 }
+ },
+ multiTimeframeResults: [
+ {
+ timeframe: "1h",
+ status: "ACTIVE",
+ decision: "BUY",
+ confidence: 85,
+ sentiment: "BULLISH",
+ analysisComplete: true
+ },
+ {
+ timeframe: "2h",
+ status: "ACTIVE",
+ decision: "BUY",
+ confidence: 78,
+ sentiment: "BULLISH",
+ analysisComplete: true
+ },
+ {
+ timeframe: "4h",
+ status: "ACTIVE",
+ decision: "BUY",
+ confidence: 82,
+ sentiment: "BULLISH",
+ analysisComplete: true
+ }
+ ],
+ layoutsAnalyzed: ["AI Layout", "DIY Layout"],
+ entry: {
+ price: currentPrice,
+ buffer: "ยฑ0.25",
+ rationale: "Current market level"
+ },
+ stopLoss: {
+ price: 174.5,
+ rationale: "Technical support level"
+ },
+ takeProfits: {
+ tp1: { price: 176.5, description: "First target" },
+ tp2: { price: 177.5, description: "Extended target" }
+ },
+ reasoning: `โ
CORRECTED DATA: ${completedTrades.length} completed trades, ${winRate.toFixed(1)}% win rate, $${totalPnL.toFixed(2)} P&L`,
+ timestamp: new Date().toISOString(),
+ processingTime: "~2.5 minutes"
+ },
+ recentTrades: formattedTrades
+ }
+ })
+ } catch (error) {
+ console.error('Error fetching analysis details:', error)
+ return NextResponse.json({
+ success: false,
+ error: 'Failed to fetch analysis details',
+ details: error.message
+ }, { status: 500 })
+ }
+}
diff --git a/app/api/automation/status/route.js b/app/api/automation/status/route.js
index 8c17824..122e145 100644
--- a/app/api/automation/status/route.js
+++ b/app/api/automation/status/route.js
@@ -33,6 +33,14 @@ export async function GET() {
}
// Get actual trade data to calculate real statistics
+ // Get ALL trades count for consistency
+ const totalTradesCount = await prisma.trade.count({
+ where: {
+ userId: session.userId,
+ symbol: session.symbol
+ }
+ })
+
const trades = await prisma.trade.findMany({
where: {
userId: session.userId,
@@ -62,7 +70,7 @@ export async function GET() {
mode: session.mode,
symbol: session.symbol,
timeframe: session.timeframe,
- totalTrades: completedTrades.length,
+ totalTrades: totalTradesCount, // Use actual total count
successfulTrades: successfulTrades.length,
winRate: Math.round(winRate * 10) / 10, // Round to 1 decimal
totalPnL: Math.round(totalPnL * 100) / 100, // Round to 2 decimals
diff --git a/app/api/enhanced-screenshot/route.js b/app/api/enhanced-screenshot/route.js
index 9fdfdcc..54e5ac3 100644
--- a/app/api/enhanced-screenshot/route.js
+++ b/app/api/enhanced-screenshot/route.js
@@ -2,43 +2,6 @@ import { NextResponse } from 'next/server'
import { enhancedScreenshotService } from '../../../lib/enhanced-screenshot'
import { aiAnalysisService } from '../../../lib/ai-analysis'
import { progressTracker } from '../../../lib/progress-tracker'
-import { PrismaClient } from '@prisma/client'
-
-const prisma = new PrismaClient()
-
-// ๐ง Generate enhanced recommendations based on automation insights
-function generateEnhancedRecommendation(automationContext) {
- if (!automationContext) return null
-
- const { multiTimeframeSignals, topPatterns, marketContext } = automationContext
-
- // Multi-timeframe consensus
- const signals = multiTimeframeSignals.filter(s => s.decision)
- const bullishSignals = signals.filter(s => s.decision === 'BUY').length
- const bearishSignals = signals.filter(s => s.decision === 'SELL').length
-
- // Pattern strength
- const avgWinRate = signals.length > 0 ?
- signals.reduce((sum, s) => sum + (s.winRate || 0), 0) / signals.length : 0
-
- // Profitability insights
- const avgProfit = topPatterns.length > 0 ?
- topPatterns.reduce((sum, p) => sum + Number(p.profitPercent || 0), 0) / topPatterns.length : 0
-
- let recommendation = '๐ค AUTOMATION-ENHANCED: '
-
- if (bullishSignals > bearishSignals) {
- recommendation += `BULLISH CONSENSUS (${bullishSignals}/${signals.length} timeframes)`
- if (avgWinRate > 60) recommendation += ` โ
Strong pattern (${avgWinRate.toFixed(1)}% win rate)`
- if (avgProfit > 3) recommendation += ` ๐ฐ High profit potential (~${avgProfit.toFixed(1)}%)`
- } else if (bearishSignals > bullishSignals) {
- recommendation += `BEARISH CONSENSUS (${bearishSignals}/${signals.length} timeframes)`
- } else {
- recommendation += 'NEUTRAL - Mixed signals across timeframes'
- }
-
- return recommendation
-}
export async function POST(request) {
try {
@@ -51,101 +14,14 @@ export async function POST(request) {
const sessionId = `analysis_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
console.log('๐ Created session ID:', sessionId)
- // ๐ง LEVERAGE AUTOMATION INSIGHTS FOR MANUAL ANALYSIS
- console.log('๐ค Gathering automation insights to enhance manual analysis...')
- let automationContext = null
- try {
- const targetSymbol = symbol || 'SOLUSD'
-
- // Get recent automation sessions for context
- const sessions = await prisma.automationSession.findMany({
- where: {
- userId: 'default-user',
- symbol: targetSymbol,
- lastAnalysisData: { not: null }
- },
- orderBy: { createdAt: 'desc' },
- take: 3
- })
-
- // Get top performing trades for pattern recognition
- const successfulTrades = await prisma.trade.findMany({
- where: {
- userId: 'default-user',
- symbol: targetSymbol,
- status: 'COMPLETED',
- profit: { gt: 0 }
- },
- orderBy: { profit: 'desc' },
- take: 5
- })
-
- // Get recent market context
- const allTrades = await prisma.trade.findMany({
- where: {
- userId: 'default-user',
- symbol: targetSymbol,
- status: 'COMPLETED'
- },
- orderBy: { createdAt: 'desc' },
- take: 10
- })
-
- const recentPnL = allTrades.reduce((sum, t) => sum + (t.profit || 0), 0)
- const winningTrades = allTrades.filter(t => (t.profit || 0) > 0)
- const winRate = allTrades.length > 0 ? (winningTrades.length / allTrades.length * 100) : 0
-
- automationContext = {
- multiTimeframeSignals: sessions.map(s => ({
- timeframe: s.timeframe,
- decision: s.lastAnalysisData?.decision,
- confidence: s.lastAnalysisData?.confidence,
- sentiment: s.lastAnalysisData?.sentiment,
- winRate: s.winRate,
- totalPnL: s.totalPnL,
- totalTrades: s.totalTrades
- })),
- topPatterns: successfulTrades.map(t => ({
- side: t.side,
- profit: t.profit,
- confidence: t.confidence,
- entryPrice: t.price,
- exitPrice: t.exitPrice,
- profitPercent: t.exitPrice ? ((t.exitPrice - t.price) / t.price * 100).toFixed(2) : null
- })),
- marketContext: {
- recentPnL,
- winRate: winRate.toFixed(1),
- totalTrades: allTrades.length,
- avgProfit: allTrades.length > 0 ? (recentPnL / allTrades.length).toFixed(2) : 0,
- trend: sessions.length > 0 ? sessions[0].lastAnalysisData?.sentiment : 'NEUTRAL'
- }
- }
-
- console.log('๐ง Automation insights gathered:', {
- timeframes: automationContext.multiTimeframeSignals.length,
- patterns: automationContext.topPatterns.length,
- winRate: automationContext.marketContext.winRate + '%'
- })
- } catch (error) {
- console.error('โ ๏ธ Could not gather automation insights:', error.message)
- automationContext = null
- }
-
// Create progress tracking session with initial steps
const initialSteps = [
{
id: 'init',
- title: 'Initializing Enhanced Analysis',
- description: 'Starting AI-powered trading analysis with automation insights...',
+ title: 'Initializing Analysis',
+ description: 'Starting AI-powered trading analysis...',
status: 'pending'
},
- {
- id: 'insights',
- title: 'Automation Intelligence',
- description: 'Gathering multi-timeframe signals and profitable patterns...',
- status: automationContext ? 'completed' : 'warning'
- },
{
id: 'auth',
title: 'TradingView Authentication',
@@ -172,8 +48,8 @@ export async function POST(request) {
},
{
id: 'analysis',
- title: 'Enhanced AI Analysis',
- description: 'Analyzing screenshots with automation-enhanced AI insights',
+ title: 'AI Analysis',
+ description: 'Analyzing screenshots with AI',
status: 'pending'
}
]
@@ -189,7 +65,6 @@ export async function POST(request) {
timeframe: timeframe || timeframes?.[0] || '60', // Use single timeframe, fallback to first of array, then default
layouts: layouts || selectedLayouts || ['ai'],
sessionId, // Pass session ID for progress tracking
- automationContext, // ๐ง Pass automation insights to enhance analysis
credentials: {
email: process.env.TRADINGVIEW_EMAIL,
password: process.env.TRADINGVIEW_PASSWORD
@@ -221,17 +96,6 @@ export async function POST(request) {
console.log('๐ธ Final screenshots:', screenshots)
- // โ ๏ธ DISABLED: Don't cleanup browsers immediately after screenshots
- // This was interrupting ongoing analysis processes
- // Cleanup will happen automatically via periodic cleanup or manual trigger
- // try {
- // console.log('๐งน Triggering browser cleanup after screenshot completion...')
- // await enhancedScreenshotService.cleanup()
- // console.log('โ
Browser cleanup completed after screenshots')
- // } catch (cleanupError) {
- // console.error('Error in browser cleanup after screenshots:', cleanupError)
- // }
-
const result = {
success: true,
sessionId, // Return session ID for progress tracking
@@ -246,46 +110,23 @@ export async function POST(request) {
timestamp: Date.now()
})),
analysis: analysis,
- // ๐ง ENHANCED: Include automation insights in response
- automationInsights: automationContext ? {
- multiTimeframeConsensus: automationContext.multiTimeframeSignals.length > 0 ?
- automationContext.multiTimeframeSignals[0].decision : null,
- avgConfidence: automationContext.multiTimeframeSignals.length > 0 ?
- (automationContext.multiTimeframeSignals.reduce((sum, s) => sum + (s.confidence || 0), 0) / automationContext.multiTimeframeSignals.length).toFixed(1) : null,
- marketTrend: automationContext.marketContext.trend,
- winRate: automationContext.marketContext.winRate + '%',
- profitablePattern: automationContext.topPatterns.length > 0 ?
- `${automationContext.topPatterns[0].side} signals with avg ${automationContext.topPatterns.reduce((sum, p) => sum + Number(p.profitPercent || 0), 0) / automationContext.topPatterns.length}% profit` : null,
- recommendation: generateEnhancedRecommendation(automationContext)
- } : null,
- message: `Successfully captured ${screenshots.length} screenshot(s)${analysis ? ' with automation-enhanced AI analysis' : ''}${automationContext ? ' leveraging multi-timeframe insights' : ''}`
+ message: `Successfully captured ${screenshots.length} screenshot(s)${analysis ? ' with AI analysis' : ''}`
}
- // โ ๏ธ DISABLED: Don't run post-analysis cleanup after every screenshot
- // This was killing browser processes during ongoing analysis
- // Cleanup should only happen after the ENTIRE automation cycle is complete
- // try {
- // const { default: aggressiveCleanup } = await import('../../../lib/aggressive-cleanup')
- // // Run cleanup in background, don't block the response
- // aggressiveCleanup.runPostAnalysisCleanup().catch(console.error)
- // } catch (cleanupError) {
- // console.error('Error triggering post-analysis cleanup:', cleanupError)
- // }
+ // Trigger post-analysis cleanup in development mode
+ if (process.env.NODE_ENV === 'development') {
+ try {
+ const { default: aggressiveCleanup } = await import('../../../lib/aggressive-cleanup')
+ // Run cleanup in background, don't block the response
+ aggressiveCleanup.runPostAnalysisCleanup().catch(console.error)
+ } catch (cleanupError) {
+ console.error('Error triggering post-analysis cleanup:', cleanupError)
+ }
+ }
return NextResponse.json(result)
} catch (error) {
console.error('Enhanced screenshot API error:', error)
-
- // โ ๏ธ DISABLED: Don't cleanup browsers on error during analysis
- // This can interrupt ongoing processes that might recover
- // try {
- // console.log('๐งน Triggering browser cleanup after API error...')
- // await enhancedScreenshotService.cleanup()
- // console.log('โ
Browser cleanup completed after API error')
- // } catch (cleanupError) {
- // console.error('Error in browser cleanup after API error:', cleanupError)
- // }
-
return NextResponse.json(
{
success: false,
diff --git a/app/automation/page.js b/app/automation/page.js
index 22f2be4..42036d1 100644
--- a/app/automation/page.js
+++ b/app/automation/page.js
@@ -616,10 +616,10 @@ export default function AutomationPage() {
{/* Recent Trades */}
-
Recent Automated Trades
+
Latest 4 Automated Trades
{recentTrades.length > 0 ? (
- {recentTrades.slice(0, 5).map((trade, idx) => (
+ {recentTrades.slice(0, 4).map((trade, idx) => (
Position Size:
${trade.positionSize}
+ {/* Entry Price - Always show for completed trades */}
+
+ Entry Price:
+ ${trade.entryPrice?.toFixed(2) || trade.price?.toFixed(2) || '0.00'}
+
+ {/* Exit Price or Current Price */}
{trade.isActive ? 'Current' : 'Exit'} Price:
- ${trade.isActive ? (trade.currentPrice?.toFixed(2) || '0.00') : (trade.exitPrice?.toFixed(2) || '0.00')}
+ {trade.isActive ?
+ `$${trade.currentPrice?.toFixed(2) || '0.00'}` :
+ (trade.exitPrice ?
+ `$${trade.exitPrice.toFixed(2)}` :
+ Not recorded
+ )
+ }
+ {/* Price difference for completed trades */}
+ {!trade.isActive && trade.exitPrice && trade.entryPrice && (
+
+ Price Difference:
+ 0 ? 'text-green-400' :
+ (trade.exitPrice - trade.entryPrice) < 0 ? 'text-red-400' :
+ 'text-gray-400'
+ }`}>
+ ${((trade.exitPrice - trade.entryPrice) >= 0 ? '+' : '')}${(trade.exitPrice - trade.entryPrice).toFixed(2)}
+
+
+ )}
@@ -702,7 +727,8 @@ export default function AutomationPage() {
0 ? 'text-green-400' : 'text-red-400') :
- (trade.realizedPnl && parseFloat(trade.realizedPnl) > 0 ? 'text-green-400' : 'text-red-400')
+ (trade.realizedPnl && parseFloat(trade.realizedPnl) > 0 ? 'text-green-400' :
+ trade.realizedPnl && parseFloat(trade.realizedPnl) < 0 ? 'text-red-400' : 'text-gray-400')
}`}>
${trade.isActive ?
(trade.unrealizedPnl || '0.00') :
@@ -713,7 +739,8 @@ export default function AutomationPage() {
0 ? 'text-green-400' : 'text-red-400') :
- (trade.realizedPnl && parseFloat(trade.realizedPnl) > 0 ? 'text-green-400' : 'text-red-400')
+ (trade.realizedPnl && parseFloat(trade.realizedPnl) > 0 ? 'text-green-400' :
+ trade.realizedPnl && parseFloat(trade.realizedPnl) < 0 ? 'text-red-400' : 'text-gray-400')
}`}>
({trade.pnlPercent})
@@ -723,6 +750,18 @@ export default function AutomationPage() {
+ {/* Debug info for missing data */}
+ {trade.result === 'UNKNOWN' && (
+
+ โ ๏ธ Missing exit data: {!trade.exitPrice ? 'Exit Price ' : ''}{trade.calculatedProfit === null ? 'Profit' : ''}
+
+ )}
+ {/* Warning for old incorrect trades */}
+ {trade.isOldWrongTrade && (
+
+ ๐ง Old trade with incorrect price data (stored: ${trade.originalStoredPrice?.toFixed(2)}, should be ~$189)
+
+ )}
{/* Click hint */}
diff --git a/check-trade-counts.js b/check-trade-counts.js
new file mode 100644
index 0000000..cf7c033
--- /dev/null
+++ b/check-trade-counts.js
@@ -0,0 +1,91 @@
+const { PrismaClient } = require('@prisma/client')
+
+const prisma = new PrismaClient()
+
+async function checkTradeCounts() {
+ try {
+ console.log('๐ Checking trade counts in database...')
+
+ // Total trades
+ const totalTrades = await prisma.trade.count({
+ where: {
+ userId: 'default-user',
+ symbol: 'SOLUSD'
+ }
+ })
+
+ // Completed trades
+ const completedTrades = await prisma.trade.count({
+ where: {
+ userId: 'default-user',
+ symbol: 'SOLUSD',
+ status: 'COMPLETED'
+ }
+ })
+
+ // Open/Active trades
+ const activeTrades = await prisma.trade.count({
+ where: {
+ userId: 'default-user',
+ symbol: 'SOLUSD',
+ status: 'OPEN'
+ }
+ })
+
+ // Pending trades
+ const pendingTrades = await prisma.trade.count({
+ where: {
+ userId: 'default-user',
+ symbol: 'SOLUSD',
+ status: 'PENDING'
+ }
+ })
+
+ console.log('\n๐ TRADE COUNTS:')
+ console.log(`Total Trades: ${totalTrades}`)
+ console.log(`Completed Trades: ${completedTrades}`)
+ console.log(`Active Trades: ${activeTrades}`)
+ console.log(`Pending Trades: ${pendingTrades}`)
+
+ // Get all trades with details
+ const allTrades = await prisma.trade.findMany({
+ where: {
+ userId: 'default-user',
+ symbol: 'SOLUSD'
+ },
+ orderBy: { createdAt: 'desc' },
+ select: {
+ id: true,
+ side: true,
+ amount: true,
+ price: true,
+ status: true,
+ createdAt: true,
+ leverage: true,
+ profit: true
+ }
+ })
+
+ console.log('\n๐ ALL TRADES:')
+ allTrades.forEach((trade, index) => {
+ console.log(`${index + 1}. ${trade.side} ${trade.amount} tokens @ $${trade.price} - ${trade.status} (${new Date(trade.createdAt).toLocaleString()})`)
+ })
+
+ // Check automation sessions
+ const sessions = await prisma.automationSession.count({
+ where: {
+ userId: 'default-user',
+ symbol: 'SOLUSD'
+ }
+ })
+
+ console.log(`\n๐ค Automation Sessions: ${sessions}`)
+
+ } catch (error) {
+ console.error('Error checking trade counts:', error)
+ } finally {
+ await prisma.$disconnect()
+ }
+}
+
+checkTradeCounts()
diff --git a/lib/aggressive-cleanup.ts b/lib/aggressive-cleanup.ts
index 783cbcf..369c8e3 100644
--- a/lib/aggressive-cleanup.ts
+++ b/lib/aggressive-cleanup.ts
@@ -55,16 +55,7 @@ class AggressiveCleanup {
}
async cleanupOrphanedProcesses(): Promise {
- if (this.isRunning) {
- console.log('๐ Cleanup already in progress, skipping...')
- return
- }
-
- // Check if auto cleanup is disabled (for development)
- if (process.env.DISABLE_AUTO_CLEANUP === 'true') {
- console.log('๐ซ Auto cleanup disabled via DISABLE_AUTO_CLEANUP environment variable')
- return
- }
+ if (this.isRunning) return
this.isRunning = true
const isDevelopment = process.env.NODE_ENV === 'development'
@@ -79,56 +70,24 @@ class AggressiveCleanup {
const activeSessions = progressTracker.getActiveSessions()
if (activeSessions.length > 0) {
- console.log(`โ ๏ธ Skipping cleanup - ${activeSessions.length} active analysis sessions detected:`)
- activeSessions.forEach(session => {
- const progress = progressTracker.getProgress(session)
- if (progress) {
- const activeStep = progress.steps.find(step => step.status === 'active')
- const currentStep = activeStep ? activeStep.title : 'Unknown'
- console.log(` - ${session}: ${currentStep} (Step ${progress.currentStep}/${progress.totalSteps})`)
- } else {
- console.log(` - ${session}: Session info not available`)
- }
- })
- console.log('โน๏ธ Will retry cleanup after analysis completes')
+ console.log(`โ ๏ธ Skipping cleanup - ${activeSessions.length} active analysis sessions: ${activeSessions.join(', ')}`)
return
}
- console.log('โ
No active analysis sessions detected, proceeding with cleanup')
+ console.log('โ
No active analysis sessions, proceeding with cleanup')
} catch (importError) {
- console.warn('โ ๏ธ Could not check active sessions, proceeding cautiously with cleanup')
- console.warn('Import error:', importError)
-
- // In case of import errors, be extra cautious - only clean very old processes
- if (isDevelopment) {
- console.log('๐ง Development mode with import issues - using aggressive cleanup to clear stuck processes')
- // In development, if we can't check sessions, assume they're stuck and clean aggressively
- }
+ console.error('โ Error importing progress tracker:', importError)
+ console.log('โ ๏ธ Skipping cleanup due to import error')
+ return
}
// Find and kill orphaned chromium processes
const chromiumProcesses = await this.findChromiumProcesses()
if (chromiumProcesses.length > 0) {
- console.log(`๐ Found ${chromiumProcesses.length} chromium processes, evaluating for cleanup...`)
+ console.log(`Found ${chromiumProcesses.length} chromium processes, cleaning up...`)
- // In development, be more selective about which processes to kill
- let processesToKill = chromiumProcesses
-
- if (isDevelopment) {
- // Only kill processes that are likely orphaned (older than 5 minutes)
- const oldProcesses = await this.filterOldProcesses(chromiumProcesses, 5 * 60 * 1000) // 5 minutes
- processesToKill = oldProcesses
-
- if (processesToKill.length === 0) {
- console.log('โ
All chromium processes appear to be recent and potentially active - skipping cleanup')
- return
- }
-
- console.log(`๐ง Development mode: Cleaning only ${processesToKill.length} old processes (older than 5 minutes)`)
- }
-
- for (const pid of processesToKill) {
+ for (const pid of chromiumProcesses) {
try {
if (isDevelopment) {
// In development, use gentler SIGTERM first
@@ -181,7 +140,6 @@ class AggressiveCleanup {
console.error(`Error in ${cleanupType} cleanup:`, error)
} finally {
this.isRunning = false
- console.log(`๐ ${cleanupType} cleanup completed`)
}
}
@@ -194,43 +152,6 @@ class AggressiveCleanup {
}
}
- private async filterOldProcesses(pids: string[], maxAgeMs: number): Promise {
- const oldProcesses: string[] = []
-
- for (const pid of pids) {
- try {
- // Get process start time
- const { stdout } = await execAsync(`ps -o pid,lstart -p ${pid} | tail -1`)
- const processInfo = stdout.trim()
-
- if (processInfo) {
- // Parse the process start time
- const parts = processInfo.split(/\s+/)
- if (parts.length >= 6) {
- // Format: PID Mon DD HH:MM:SS YYYY
- const startTimeStr = parts.slice(1).join(' ')
- const startTime = new Date(startTimeStr)
- const now = new Date()
- const processAge = now.getTime() - startTime.getTime()
-
- if (processAge > maxAgeMs) {
- console.log(`๐ Process ${pid} is ${Math.round(processAge / 60000)} minutes old - marked for cleanup`)
- oldProcesses.push(pid)
- } else {
- console.log(`๐ Process ${pid} is ${Math.round(processAge / 60000)} minutes old - keeping alive`)
- }
- }
- }
- } catch (error) {
- // If we can't get process info, assume it's old and safe to clean
- console.log(`โ Could not get age info for process ${pid} - assuming it's old`)
- oldProcesses.push(pid)
- }
- }
-
- return oldProcesses
- }
-
async forceCleanup(): Promise {
console.log('๐จ Force cleanup initiated...')
@@ -252,236 +173,14 @@ class AggressiveCleanup {
}
}
- // New method for on-demand cleanup after complete automation cycle
+ // New method for on-demand cleanup after analysis
async runPostAnalysisCleanup(): Promise {
- // Check if auto cleanup is disabled (for development)
- if (process.env.DISABLE_AUTO_CLEANUP === 'true') {
- console.log('๐ซ Post-analysis cleanup disabled via DISABLE_AUTO_CLEANUP environment variable')
- return
- }
+ console.log('๐งน Post-analysis cleanup triggered...')
- console.log('๐งน Post-cycle cleanup triggered (analysis + decision complete)...')
+ // Small delay to ensure analysis processes are fully closed
+ await new Promise(resolve => setTimeout(resolve, 2000))
- // Wait for all browser processes to fully close
- console.log('โณ Waiting 3 seconds for all processes to close gracefully...')
- await new Promise(resolve => setTimeout(resolve, 3000))
-
- // Always run cleanup after complete automation cycle - don't check for active sessions
- // since the analysis is complete and we need to ensure all processes are cleaned up
- console.log('๐งน Running comprehensive post-cycle cleanup (ignoring session status)...')
-
- try {
- // Find all chromium processes
- const chromiumProcesses = await this.findChromiumProcesses()
-
- if (chromiumProcesses.length === 0) {
- console.log('โ
No chromium processes found to clean up')
- return
- }
-
- console.log(`๐ Found ${chromiumProcesses.length} chromium processes for post-analysis cleanup`)
-
- // In post-analysis cleanup, we're more aggressive since analysis is complete
- // Try graceful shutdown first
- for (const pid of chromiumProcesses) {
- try {
- console.log(`๐ง Attempting graceful shutdown of process ${pid}`)
- await execAsync(`kill -TERM ${pid}`)
- } catch (error) {
- console.log(`โน๏ธ Process ${pid} may already be terminated`)
- }
- }
-
- // Wait for graceful shutdown
- await new Promise(resolve => setTimeout(resolve, 5000))
-
- // Check which processes are still running and force kill them
- const stillRunning = await this.findStillRunningProcesses(chromiumProcesses)
-
- if (stillRunning.length > 0) {
- console.log(`๐ก๏ธ Force killing ${stillRunning.length} stubborn processes`)
- for (const pid of stillRunning) {
- try {
- await execAsync(`kill -9 ${pid}`)
- console.log(`๐ Force killed process ${pid}`)
- } catch (error) {
- console.log(`โน๏ธ Process ${pid} already terminated`)
- }
- }
- } else {
- console.log('โ
All processes shut down gracefully')
- }
-
- // Clean up temp directories and shared memory
- try {
- await execAsync('rm -rf /tmp/puppeteer_dev_chrome_profile-* 2>/dev/null || true')
- await execAsync('rm -rf /dev/shm/.org.chromium.* 2>/dev/null || true')
- await execAsync('rm -rf /tmp/.org.chromium.* 2>/dev/null || true')
- console.log('โ
Cleaned up temporary files and shared memory')
- } catch (error) {
- console.error('Warning: Could not clean up temporary files:', error)
- }
-
- console.log('โ
Post-analysis cleanup completed successfully')
-
- } catch (error) {
- console.error('Error in post-analysis cleanup:', error)
- }
-
- // Clear any stuck progress sessions
- try {
- const { progressTracker } = await import('./progress-tracker')
- const activeSessions = progressTracker.getActiveSessions()
-
- if (activeSessions.length > 0) {
- console.log(`๐งน Force clearing ${activeSessions.length} potentially stuck sessions`)
- activeSessions.forEach(session => {
- console.log(`๐งน Force clearing session: ${session}`)
- progressTracker.deleteSession(session)
- })
- }
- } catch (error) {
- console.warn('Could not clear progress sessions:', error)
- }
- }
-
- // Signal that an analysis cycle is complete and all processes should be cleaned up
- async signalAnalysisCycleComplete(): Promise {
- console.log('๐ฏ Analysis cycle completion signal received')
-
- // Wait for graceful shutdown of analysis-related processes
- console.log('โณ Waiting 5 seconds for graceful process shutdown...')
- await new Promise(resolve => setTimeout(resolve, 5000))
-
- // Check if there are any active progress sessions first
- const activeSessions = await this.checkActiveAnalysisSessions()
- if (activeSessions > 0) {
- console.log(`โ ๏ธ Found ${activeSessions} active analysis sessions, skipping aggressive cleanup`)
- return
- }
-
- // Only run cleanup if no active sessions
- console.log('๐งน No active sessions detected, running post-analysis cleanup...')
- await this.cleanupPostAnalysisProcesses()
- }
-
- private async checkActiveAnalysisSessions(): Promise {
- // Check if progress tracker has any active sessions
- try {
- // This is a simple check - in a real scenario you might want to check actual session state
- const { stdout } = await execAsync('pgrep -f "automation-.*-.*" | wc -l')
- return parseInt(stdout.trim()) || 0
- } catch (error) {
- return 0
- }
- }
-
- private async cleanupPostAnalysisProcesses(): Promise {
- console.log('๐จ Post-analysis cleanup - targeting orphaned browser processes')
-
- try {
- // Find all chromium processes
- const chromiumProcesses = await this.findChromiumProcesses()
-
- if (chromiumProcesses.length === 0) {
- console.log('โ
No chromium processes found to clean up')
- return
- }
-
- console.log(`๐ Found ${chromiumProcesses.length} chromium processes`)
-
- // Filter out processes that are too new (less than 2 minutes old)
- const oldProcesses = await this.filterOldProcesses(chromiumProcesses, 2 * 60) // 2 minutes
-
- if (oldProcesses.length === 0) {
- console.log('โ
All chromium processes are recent, not cleaning up')
- return
- }
-
- console.log(`๐งน Cleaning up ${oldProcesses.length} old chromium processes`)
-
- // Try graceful shutdown first
- for (const pid of oldProcesses) {
- try {
- console.log(`๏ฟฝ Attempting graceful shutdown of process ${pid}`)
- await execAsync(`kill -TERM ${pid}`)
- } catch (error) {
- console.log(`โน๏ธ Process ${pid} may already be terminated`)
- }
- }
-
- // Wait for graceful shutdown
- await new Promise(resolve => setTimeout(resolve, 3000))
-
- // Check which processes are still running and force kill only those
- const stillRunning = await this.findStillRunningProcesses(oldProcesses)
-
- if (stillRunning.length > 0) {
- console.log(`๐ก๏ธ Force killing ${stillRunning.length} stubborn processes`)
- for (const pid of stillRunning) {
- try {
- await execAsync(`kill -9 ${pid}`)
- console.log(`๐ Force killed process ${pid}`)
- } catch (error) {
- console.log(`โน๏ธ Process ${pid} already terminated`)
- }
- }
- }
-
- console.log('โ
Post-analysis cleanup completed')
-
- } catch (error) {
- console.error('Error in post-analysis cleanup:', error)
- }
- }
-
- private async findStillRunningProcesses(pids: string[]): Promise {
- const stillRunning: string[] = []
-
- for (const pid of pids) {
- try {
- await execAsync(`kill -0 ${pid}`) // Check if process exists
- stillRunning.push(pid)
- } catch (error) {
- // Process is already dead
- }
- }
-
- return stillRunning
- }
-
- // Method to get detailed process information for debugging
- async getProcessInfo(): Promise {
- try {
- console.log('๐ Current browser process information:')
-
- // Get all chromium processes with detailed info
- const { stdout } = await execAsync('ps aux | grep -E "(chromium|chrome)" | grep -v grep')
- const processes = stdout.trim().split('\n').filter(line => line.length > 0)
-
- if (processes.length === 0) {
- console.log('โ
No browser processes currently running')
- return
- }
-
- console.log(`๐ Found ${processes.length} browser processes:`)
- processes.forEach((process, index) => {
- const parts = process.split(/\s+/)
- const pid = parts[1]
- const cpu = parts[2]
- const mem = parts[3]
- const command = parts.slice(10).join(' ')
- console.log(` ${index + 1}. PID: ${pid}, CPU: ${cpu}%, MEM: ${mem}%, CMD: ${command.substring(0, 100)}...`)
- })
-
- // Get memory usage
- const { stdout: memInfo } = await execAsync('free -h')
- console.log('๐พ Memory usage:')
- console.log(memInfo)
-
- } catch (error) {
- console.error('Error getting process info:', error)
- }
+ await this.cleanupOrphanedProcesses()
}
stop(): void {
diff --git a/lib/ai-analysis.ts b/lib/ai-analysis.ts
index 6db77c8..ecb4776 100644
--- a/lib/ai-analysis.ts
+++ b/lib/ai-analysis.ts
@@ -714,34 +714,23 @@ Analyze all provided screenshots comprehensively and return only the JSON respon
if (sessionId) {
progressTracker.updateStep(sessionId, 'analysis', 'completed', 'AI analysis completed successfully!')
- }
-
- // Trigger browser cleanup immediately after analysis completes
- try {
- console.log('๐งน Triggering browser cleanup after analysis completion...')
- const { enhancedScreenshotService } = await import('./enhanced-screenshot')
- await enhancedScreenshotService.cleanup()
- console.log('โ
Browser cleanup completed')
- } catch (cleanupError) {
- console.error('Error in browser cleanup:', cleanupError)
- }
-
- // Trigger system-wide cleanup
- try {
- // Dynamic import to avoid circular dependencies
- const aggressiveCleanupModule = await import('./aggressive-cleanup')
- const aggressiveCleanup = aggressiveCleanupModule.default
- // Run cleanup in background, don't block the response
- aggressiveCleanup.runPostAnalysisCleanup().catch(console.error)
- } catch (cleanupError) {
- console.error('Error triggering post-analysis cleanup:', cleanupError)
- }
-
- if (sessionId) {
- // Mark session as complete after cleanup is initiated
+ // Mark session as complete
setTimeout(() => progressTracker.deleteSession(sessionId), 1000)
}
+ // Trigger post-analysis cleanup in development mode
+ if (process.env.NODE_ENV === 'development') {
+ try {
+ // Dynamic import to avoid circular dependencies
+ const aggressiveCleanupModule = await import('./aggressive-cleanup')
+ const aggressiveCleanup = aggressiveCleanupModule.default
+ // Run cleanup in background, don't block the response
+ aggressiveCleanup.runPostAnalysisCleanup().catch(console.error)
+ } catch (cleanupError) {
+ console.error('Error triggering post-analysis cleanup:', cleanupError)
+ }
+ }
+
return {
screenshots,
analysis
@@ -750,16 +739,6 @@ Analyze all provided screenshots comprehensively and return only the JSON respon
} catch (error) {
console.error('Automated capture and analysis with config failed:', error)
- // Trigger browser cleanup even on error
- try {
- console.log('๐งน Triggering browser cleanup after analysis error...')
- const { enhancedScreenshotService } = await import('./enhanced-screenshot')
- await enhancedScreenshotService.cleanup()
- console.log('โ
Browser cleanup completed after error')
- } catch (cleanupError) {
- console.error('Error in browser cleanup after error:', cleanupError)
- }
-
if (sessionId) {
// Find the active step and mark it as error
const progress = progressTracker.getProgress(sessionId)
diff --git a/lib/automation-service-simple.ts b/lib/automation-service-simple.ts
index 195fa09..b2fff84 100644
--- a/lib/automation-service-simple.ts
+++ b/lib/automation-service-simple.ts
@@ -568,7 +568,7 @@ ${validResults.map(r => `โข ${r.timeframe}: ${r.analysis?.recommendation} (${r.
}
// Calculate position size based on risk percentage
- const positionSize = this.calculatePositionSize(analysis)
+ const positionSize = await this.calculatePositionSize(analysis)
return {
direction: analysis.recommendation,
@@ -585,12 +585,33 @@ ${validResults.map(r => `โข ${r.timeframe}: ${r.analysis?.recommendation} (${r.
}
}
- private calculatePositionSize(analysis: any): number {
- const baseAmount = this.config!.tradingAmount
+ private async calculatePositionSize(analysis: any): Promise {
+ const baseAmount = this.config!.tradingAmount // This is the USD amount to invest
const riskAdjustment = this.config!.riskPercentage / 100
const confidenceAdjustment = analysis.confidence / 100
- return baseAmount * riskAdjustment * confidenceAdjustment
+ // Calculate the USD amount to invest
+ const usdAmount = baseAmount * riskAdjustment * confidenceAdjustment
+
+ // Get current price to convert USD to token amount
+ let currentPrice = analysis.entry?.price || analysis.currentPrice
+
+ if (!currentPrice) {
+ try {
+ const { default: PriceFetcher } = await import('./price-fetcher')
+ currentPrice = await PriceFetcher.getCurrentPrice(this.config?.symbol || 'SOLUSD')
+ console.log(`๐ Using current ${this.config?.symbol || 'SOLUSD'} price for position size: $${currentPrice}`)
+ } catch (error) {
+ console.error('Error fetching price for position size, using fallback:', error)
+ currentPrice = this.config?.symbol === 'SOLUSD' ? 189 : 100
+ }
+ }
+
+ // Calculate token amount: USD investment / token price
+ const tokenAmount = usdAmount / currentPrice
+ console.log(`๐ฐ Position calculation: $${usdAmount} รท $${currentPrice} = ${tokenAmount.toFixed(4)} tokens`)
+
+ return tokenAmount
}
private calculateStopLoss(analysis: any): number {
@@ -599,7 +620,7 @@ ${validResults.map(r => `โข ${r.timeframe}: ${r.analysis?.recommendation} (${r.
return analysis.stopLoss.price
}
- const currentPrice = analysis.entry?.price || 150 // Default SOL price
+ const currentPrice = analysis.entry?.price || 189 // Current SOL price
const stopLossPercent = this.config!.stopLossPercent / 100
if (analysis.recommendation === 'BUY') {
@@ -656,7 +677,21 @@ ${validResults.map(r => `โข ${r.timeframe}: ${r.analysis?.recommendation} (${r.
private async executeSimulationTrade(decision: any): Promise {
// Simulate trade execution with realistic parameters
- const currentPrice = decision.currentPrice || 100 // Mock price
+ let currentPrice = decision.currentPrice
+
+ // If no current price provided, fetch real price
+ if (!currentPrice) {
+ try {
+ const { default: PriceFetcher } = await import('./price-fetcher')
+ currentPrice = await PriceFetcher.getCurrentPrice(this.config?.symbol || 'SOLUSD')
+ console.log(`๐ Fetched real ${this.config?.symbol || 'SOLUSD'} price: $${currentPrice}`)
+ } catch (error) {
+ console.error('Error fetching real price, using fallback:', error)
+ // Use a more realistic fallback based on symbol
+ currentPrice = this.config?.symbol === 'SOLUSD' ? 189 : 100
+ }
+ }
+
const slippage = Math.random() * 0.005 // 0-0.5% slippage
const executionPrice = currentPrice * (1 + (Math.random() > 0.5 ? slippage : -slippage))
diff --git a/prisma/prisma/dev.db b/prisma/prisma/dev.db
index 41bd7ea..07554f2 100644
Binary files a/prisma/prisma/dev.db and b/prisma/prisma/dev.db differ
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
new file mode 100644
index 0000000..b3f76b8
--- /dev/null
+++ b/src/app/layout.tsx
@@ -0,0 +1,19 @@
+// Initialize cleanup system
+import '../../lib/startup'
+
+export const metadata = {
+ title: 'Next.js',
+ description: 'Generated by Next.js',
+}
+
+export default function RootLayout({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+ {children}
+
+ )
+}
diff --git a/status_response.json b/status_response.json
new file mode 100644
index 0000000..7d03a9d
--- /dev/null
+++ b/status_response.json
@@ -0,0 +1,279 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Open WebUI
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+

+
+
+
+
+
+
+
+
+
+