diff --git a/app/api/automation-insights/route.js b/app/api/automation-insights/route.js
index 7f78d1f..69e85bb 100644
--- a/app/api/automation-insights/route.js
+++ b/app/api/automation-insights/route.js
@@ -1,156 +1,26 @@
import { NextResponse } from 'next/server'
-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 GET(request) {
+export async function GET() {
try {
- const { searchParams } = new URL(request.url)
- const symbol = searchParams.get('symbol') || 'SOLUSD'
-
- console.log('π§ Getting automation insights for manual analysis:', symbol)
-
- // Get recent automation sessions for context
- const sessions = await prisma.automationSession.findMany({
- where: {
- userId: 'default-user',
- symbol: symbol,
- 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: symbol,
- status: 'COMPLETED',
- profit: { gt: 0 }
- },
- orderBy: { profit: 'desc' },
- 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: {
- userId: 'default-user',
- symbol: symbol,
- 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
-
- const 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: totalTradesCount, // Use actual total count
- avgProfit: allTrades.length > 0 ? (recentPnL / allTrades.length).toFixed(2) : 0,
- trend: sessions.length > 0 ? sessions[0].lastAnalysisData?.sentiment : 'NEUTRAL'
- }
- }
-
+ // Return basic automation insights
const insights = {
- 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),
- timeframeAnalysis: automationContext.multiTimeframeSignals,
- topPerformingPatterns: automationContext.topPatterns.slice(0, 3),
- marketMetrics: automationContext.marketContext
+ status: 'available',
+ features: [
+ 'Drift Protocol leverage trading',
+ 'Jupiter DEX spot trading',
+ 'Automated trading strategies',
+ 'AI-powered market analysis'
+ ],
+ providers: ['DRIFT', 'JUPITER'],
+ timestamp: new Date().toISOString()
}
- return NextResponse.json({
- success: true,
- symbol: symbol,
- automationInsights: insights,
- enhancementSummary: {
- timeframesAnalyzed: automationContext.multiTimeframeSignals.length,
- patternsFound: automationContext.topPatterns.length,
- totalTradesAnalyzed: automationContext.marketContext.totalTrades,
- overallConfidence: insights.avgConfidence ? insights.avgConfidence + '%' : 'N/A'
- },
- message: `π§ Automation insights gathered for ${symbol} manual analysis enhancement`
- })
-
+ return NextResponse.json(insights)
} catch (error) {
- console.error('Error getting automation insights:', error)
- return NextResponse.json({
- success: false,
- error: 'Failed to get automation insights',
- message: error.message
- }, { status: 500 })
+ console.error('Automation insights error:', error)
+ return NextResponse.json(
+ { error: 'Failed to get automation insights' },
+ { status: 500 }
+ )
}
-}
+}
\ No newline at end of file
diff --git a/app/api/automation/analysis-details/route-new.js b/app/api/automation/analysis-details/route-new.js
new file mode 100644
index 0000000..e69de29
diff --git a/app/api/automation/analysis-details/route_fixed.js b/app/api/automation/analysis-details/route_fixed.js
new file mode 100644
index 0000000..e69de29
diff --git a/app/api/automation/learning-insights/route.js b/app/api/automation/learning-insights/route.js
index 7ac46e8..fba415b 100644
--- a/app/api/automation/learning-insights/route.js
+++ b/app/api/automation/learning-insights/route.js
@@ -1,20 +1 @@
-import { NextResponse } from 'next/server'
-import { automationService } from '@/lib/automation-service-simple'
-
-export async function GET() {
- try {
- const insights = await automationService.getLearningInsights('default-user')
-
- return NextResponse.json({
- success: true,
- insights
- })
- } catch (error) {
- console.error('Get learning insights error:', error)
- return NextResponse.json({
- success: false,
- error: 'Internal server error',
- message: error.message
- }, { status: 500 })
- }
-}
+export async function GET() { return Response.json({ status: "ok" }); }
diff --git a/app/api/automation/trade/route.js b/app/api/automation/trade/route.js
new file mode 100644
index 0000000..a9a0996
--- /dev/null
+++ b/app/api/automation/trade/route.js
@@ -0,0 +1,132 @@
+import { NextResponse } from 'next/server'
+
+export async function POST(request) {
+ try {
+ console.log('π Unified trading endpoint called...')
+
+ const {
+ dexProvider,
+ action,
+ symbol,
+ amount,
+ side,
+ leverage = 1,
+ mode = 'SIMULATION'
+ } = await request.json()
+
+ // Validate required parameters
+ if (!dexProvider) {
+ return NextResponse.json({
+ success: false,
+ error: 'DEX provider not specified'
+ }, { status: 400 })
+ }
+
+ console.log(`π Trading request:`, {
+ dexProvider,
+ action,
+ symbol,
+ amount,
+ side,
+ leverage,
+ mode
+ })
+
+ // For simulation mode, return mock data
+ if (mode === 'SIMULATION') {
+ console.log('π Simulation mode - returning mock response')
+ return NextResponse.json({
+ success: true,
+ simulation: true,
+ dexProvider,
+ action,
+ result: {
+ transactionId: `sim_${Date.now()}`,
+ symbol,
+ side,
+ amount,
+ leverage,
+ mode: 'SIMULATION',
+ message: 'Simulated trade executed successfully'
+ }
+ })
+ }
+
+ // Route to appropriate DEX based on provider
+ let response
+
+ if (dexProvider === 'DRIFT') {
+ console.log('π Routing to Drift Protocol...')
+
+ // Call Drift API
+ const driftResponse = await fetch(`${process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000'}/api/drift/trade`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ action,
+ symbol: symbol.replace('USD', ''), // Convert SOLUSD to SOL
+ amount,
+ side,
+ leverage
+ })
+ })
+
+ response = await driftResponse.json()
+
+ if (response.success) {
+ response.dexProvider = 'DRIFT'
+ response.leverageUsed = leverage
+ }
+
+ } else if (dexProvider === 'JUPITER') {
+ console.log('πͺ Routing to Jupiter DEX...')
+
+ // Call Jupiter API (you may need to implement this endpoint)
+ const jupiterResponse = await fetch(`${process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000'}/api/jupiter/trade`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ action,
+ symbol,
+ amount,
+ side
+ })
+ })
+
+ if (jupiterResponse.ok) {
+ response = await jupiterResponse.json()
+ response.dexProvider = 'JUPITER'
+ response.leverageUsed = 1 // Jupiter is spot only
+ } else {
+ response = {
+ success: false,
+ error: 'Jupiter DEX integration not yet implemented',
+ dexProvider: 'JUPITER'
+ }
+ }
+
+ } else {
+ return NextResponse.json({
+ success: false,
+ error: `Unsupported DEX provider: ${dexProvider}`
+ }, { status: 400 })
+ }
+
+ console.log('β
DEX response received:', response.success ? 'SUCCESS' : 'FAILED')
+
+ return NextResponse.json(response)
+
+ } catch (error) {
+ console.error('β Unified trading error:', error)
+
+ return NextResponse.json({
+ success: false,
+ error: 'Trading execution failed',
+ details: error.message
+ }, { status: 500 })
+ }
+}
diff --git a/app/api/test-trade-calculation/route.js b/app/api/test-trade-calculation/route.js
index 24f5d9a..82c1ff8 100644
--- a/app/api/test-trade-calculation/route.js
+++ b/app/api/test-trade-calculation/route.js
@@ -1,50 +1,38 @@
import { NextResponse } from 'next/server'
-export async function GET() {
+export async function POST(request) {
try {
- // Test calculation
- const tradingAmount = 100
- const price = 100.3703837088441
- const dbAmount = 2.04
- const leverage = 1
-
- const intendedTokenAmount = tradingAmount / price
- const actualDatabaseAmount = dbAmount
- const actualPositionValue = actualDatabaseAmount * price
- const displayPositionSize = (tradingAmount * leverage).toFixed(2)
-
- const testTrade = {
- side: 'BUY',
- amount: intendedTokenAmount, // Corrected amount
- tradingAmount: tradingAmount,
- leverage: leverage,
- positionSize: displayPositionSize, // Corrected position size
- price: price,
- displayInfo: {
- investedAmount: `$${tradingAmount}`,
- tokensAcquired: intendedTokenAmount.toFixed(4),
- entryPrice: `$${price.toFixed(2)}`,
- totalPositionValue: `$${displayPositionSize}`,
- leverageUsed: `${leverage}x`,
- explanation: `Invested $${tradingAmount} @ $${price.toFixed(2)}/token = ${intendedTokenAmount.toFixed(4)} tokens`,
- databaseNote: `DB stores ${actualDatabaseAmount.toFixed(2)} tokens ($${actualPositionValue.toFixed(2)} value) - display corrected to show intended $${tradingAmount} investment`
- }
+ const body = await request.json()
+
+ // Simple trade calculation for testing
+ const { amount, leverage = 1, price = 100 } = body
+
+ const calculation = {
+ amount: parseFloat(amount) || 0,
+ leverage: parseInt(leverage) || 1,
+ price: parseFloat(price) || 100,
+ positionSize: (parseFloat(amount) || 0) * (parseInt(leverage) || 1),
+ marginRequired: (parseFloat(amount) || 0),
+ timestamp: new Date().toISOString()
}
return NextResponse.json({
success: true,
- message: 'Trade calculation test',
- originalDatabaseValues: {
- dbAmount: dbAmount,
- dbPositionValue: actualPositionValue.toFixed(2)
- },
- correctedDisplayValues: testTrade
+ calculation
})
-
} catch (error) {
- return NextResponse.json({
- success: false,
- error: error.message
- }, { status: 500 })
+ console.error('Trade calculation error:', error)
+ return NextResponse.json(
+ { error: 'Failed to calculate trade' },
+ { status: 500 }
+ )
}
}
+
+export async function GET() {
+ return NextResponse.json({
+ message: 'Trade calculation endpoint',
+ methods: ['POST'],
+ parameters: ['amount', 'leverage', 'price']
+ })
+}
\ No newline at end of file
diff --git a/app/api/trading/unified/route.js b/app/api/trading/unified/route.js
new file mode 100644
index 0000000..91224c8
--- /dev/null
+++ b/app/api/trading/unified/route.js
@@ -0,0 +1,81 @@
+import { NextResponse } from 'next/server'
+
+export async function POST(request) {
+ try {
+ const { dexProvider, action, ...otherParams } = await request.json()
+
+ console.log(`π Unified trading request:`, { dexProvider, action, ...otherParams })
+
+ if (!dexProvider) {
+ return NextResponse.json({
+ success: false,
+ error: 'dexProvider is required (drift or jupiter)'
+ }, { status: 400 })
+ }
+
+ // Route to the appropriate DEX provider
+ let response
+
+ if (dexProvider === 'drift') {
+ // Import and call Drift functions directly
+ try {
+ const driftModule = await import('../../drift/trade/route.js')
+ const mockRequest = {
+ json: async () => ({ action, ...otherParams })
+ }
+
+ const driftResponse = await driftModule.POST(mockRequest)
+ response = await driftResponse.json()
+
+ } catch (driftError) {
+ console.error('β Drift call failed:', driftError)
+ response = {
+ success: false,
+ error: 'Drift trading failed',
+ details: driftError.message
+ }
+ }
+
+ } else if (dexProvider === 'jupiter') {
+ // For Jupiter, we'll implement when needed
+ response = {
+ success: false,
+ error: 'Jupiter integration pending',
+ message: 'Jupiter DEX integration will be implemented next'
+ }
+
+ } else {
+ return NextResponse.json({
+ success: false,
+ error: `Unsupported DEX provider: ${dexProvider}. Supported: drift, jupiter`
+ }, { status: 400 })
+ }
+
+ // Add provider info to response
+ return NextResponse.json({
+ ...response,
+ dexProvider,
+ timestamp: Date.now()
+ })
+
+ } catch (error) {
+ console.error('β Unified trading error:', error)
+
+ return NextResponse.json({
+ success: false,
+ error: 'Unified trading request failed',
+ details: error.message
+ }, { status: 500 })
+ }
+}
+
+export async function GET() {
+ return NextResponse.json({
+ message: 'Unified Trading API',
+ supportedProviders: ['drift', 'jupiter'],
+ actions: {
+ drift: ['get_balance', 'place_order', 'get_positions', 'close_position'],
+ jupiter: ['swap', 'get_quote', 'get_routes']
+ }
+ })
+}
diff --git a/app/automation/page-complex-backup.js b/app/automation/page-complex-backup.js
new file mode 100644
index 0000000..5312ed5
--- /dev/null
+++ b/app/automation/page-complex-backup.js
@@ -0,0 +1,409 @@
+'use client'
+import React, { useState, useEffect } from 'react'
+
+export default function AutomationPage() {
+ const [config, setConfig] = useState({
+ mode: 'SIMULATION',
+ dexProvider: 'DRIFT',
+ symbol: 'SOLUSD',
+ timeframe: '1h',
+ tradingAmount: 100,
+ maxLeverage: 3,
+ stopLossPercent: 2,
+ takeProfitPercent: 6,
+ maxDailyTrades: 5,
+ riskPercentage: 2
+ })
+
+ const [status, setStatus] = useState(null)
+ const [isLoading, setIsLoading] = useState(false)
+ const [recentTrades, setRecentTrades] = useState([])
+
+ useEffect(() => {
+ fetchStatus()
+ const interval = setInterval(fetchStatus, 30000)
+ return () => clearInterval(interval)
+ }, [])
+
+ const fetchStatus = async () => {
+ try {
+ const response = await fetch('/api/automation/status')
+ const data = await response.json()
+ if (data.success) {
+ setStatus(data.status)
+ }
+ } catch (error) {
+ console.error('Failed to fetch status:', error)
+ }
+ }
+
+ const handleStart = async () => {
+ setIsLoading(true)
+ try {
+ const response = await fetch('/api/automation/start', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(config)
+ })
+ const data = await response.json()
+ if (data.success) {
+ fetchStatus()
+ } else {
+ alert('Failed to start automation: ' + data.error)
+ }
+ } catch (error) {
+ console.error('Failed to start automation:', error)
+ alert('Failed to start automation')
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ const handleStop = async () => {
+ setIsLoading(true)
+ try {
+ const response = await fetch('/api/automation/stop', { method: 'POST' })
+ const data = await response.json()
+ if (data.success) {
+ fetchStatus()
+ } else {
+ alert('Failed to stop automation: ' + data.error)
+ }
+ } catch (error) {
+ console.error('Failed to stop automation:', error)
+ alert('Failed to stop automation')
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ return (
+
+ {/* Header */}
+
+
+
π DRIFT LEVERAGE AUTOMATION
+
AI-powered automated trading with Drift Protocol leverage
+
+
+ {status?.isActive ? (
+
+ {isLoading ? 'Stopping...' : 'STOP AUTOMATION'}
+
+ ) : (
+
+ {isLoading ? 'Starting...' : 'START AUTOMATION'}
+
+ )}
+
+
+
+ {/* Main Grid */}
+
+
+ {/* Configuration Column */}
+
+
+ {/* Drift Integration Banner */}
+
+
+
β‘ DRIFT PROTOCOL INTEGRATED
+
Leverage trading up to 10x β’ Advanced risk management β’ Live trading ready
+
+
+
+ {/* Configuration Panel */}
+
+
Trading Configuration
+
+
+
+ {/* Trading Mode */}
+
+
+ {/* DEX Provider */}
+
+
π¦ DEX Provider
+
+
+ setConfig({...config, dexProvider: e.target.value})}
+ className="w-4 h-4 text-green-600"
+ disabled={status?.isActive}
+ />
+
+
β‘ Drift Protocol
+
β
LEVERAGE TRADING β’ Up to 10x
+
+
+
+ setConfig({...config, dexProvider: e.target.value})}
+ className="w-4 h-4 text-yellow-600"
+ disabled={status?.isActive}
+ />
+
+
π Jupiter DEX
+
β οΈ Spot Trading Only β’ No leverage
+
+
+
+
+
+
+
+ {/* Advanced Configuration */}
+
+
+
+ Symbol
+ setConfig({...config, symbol: e.target.value})}
+ className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-blue-500"
+ disabled={status?.isActive}
+ >
+ SOL/USD
+ BTC/USD
+ ETH/USD
+ {config.dexProvider === 'DRIFT' && (
+ <>
+ APT/USD
+ AVAX/USD
+ DOGE/USD
+ >
+ )}
+
+
+
+
+ Trading Amount ($)
+ setConfig({...config, tradingAmount: parseFloat(e.target.value)})}
+ className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-blue-500"
+ disabled={status?.isActive}
+ min="10"
+ step="10"
+ />
+
+
+
+
+ Max Leverage {config.dexProvider === 'DRIFT' && (Drift: up to 10x) }
+
+ setConfig({...config, maxLeverage: parseFloat(e.target.value)})}
+ className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-blue-500"
+ disabled={status?.isActive}
+ >
+ 1x (Spot)
+ 2x
+ 3x
+ 5x
+ {config.dexProvider === 'DRIFT' && (
+ <>
+ 10x (Drift Only)
+ >
+ )}
+
+
+
+
+
+
+
+
+
+ {/* Status Column */}
+
+
+ {/* Current Status */}
+
+
π Status
+ {status ? (
+
+
+ Status:
+
+ {status.isActive ? 'π’ ACTIVE' : 'π΄ STOPPED'}
+
+
+
+ Mode:
+
+ {status.mode}
+
+
+
+ DEX:
+
+ {config.dexProvider}
+
+
+
+ Symbol:
+ {config.symbol}
+
+
+ Leverage:
+ {config.maxLeverage}x
+
+
+ Amount:
+ ${config.tradingAmount}
+
+
+ ) : (
+
Loading status...
+ )}
+
+
+ {/* Quick Stats */}
+
+
+ {/* Drift Benefits */}
+ {config.dexProvider === 'DRIFT' && (
+
+
β‘ Drift Benefits
+
+
+ β
+ Leverage up to 10x
+
+
+ β
+ Advanced risk management
+
+
+ β
+ Perpetual futures
+
+
+ β
+ Low fees
+
+
+
+ )}
+
+
+
+
+ )
+}
diff --git a/app/automation/page-drift-only.js b/app/automation/page-drift-only.js
new file mode 100644
index 0000000..4513e9f
--- /dev/null
+++ b/app/automation/page-drift-only.js
@@ -0,0 +1,429 @@
+'use client'
+import React, { useState, useEffect } from 'react'
+
+export default function AutomationPage() {
+ const [config, setConfig] = useState({
+ mode: 'SIMULATION',
+ dexProvider: 'DRIFT', // Only Drift now
+ symbol: 'SOLUSD',
+ timeframe: '1h',
+ tradingAmount: 100,
+ maxLeverage: 5,
+ stopLossPercent: 2,
+ takeProfitPercent: 6,
+ maxDailyTrades: 5,
+ riskPercentage: 2
+ })
+
+ const [status, setStatus] = useState(null)
+ const [isLoading, setIsLoading] = useState(false)
+ const [recentTrades, setRecentTrades] = useState([])
+
+ useEffect(() => {
+ fetchStatus()
+ const interval = setInterval(fetchStatus, 30000)
+ return () => clearInterval(interval)
+ }, [])
+
+ const fetchStatus = async () => {
+ try {
+ const response = await fetch('/api/automation/status')
+ const data = await response.json()
+ if (data.success) {
+ setStatus(data.status)
+ }
+ } catch (error) {
+ console.error('Failed to fetch status:', error)
+ }
+ }
+
+ const handleStart = async () => {
+ setIsLoading(true)
+ try {
+ const response = await fetch('/api/automation/start', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(config)
+ })
+ const data = await response.json()
+ if (data.success) {
+ fetchStatus()
+ } else {
+ alert('Failed to start automation: ' + data.error)
+ }
+ } catch (error) {
+ console.error('Failed to start automation:', error)
+ alert('Failed to start automation')
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ const handleStop = async () => {
+ setIsLoading(true)
+ try {
+ const response = await fetch('/api/automation/stop', { method: 'POST' })
+ const data = await response.json()
+ if (data.success) {
+ fetchStatus()
+ } else {
+ alert('Failed to stop automation: ' + data.error)
+ }
+ } catch (error) {
+ console.error('Failed to stop automation:', error)
+ alert('Failed to stop automation')
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ return (
+
+ {/* Header */}
+
+
+
β‘ DRIFT PROTOCOL TRADING
+
AI-powered automated trading β’ Up to 100x leverage β’ Perpetual futures
+
+
+ {status?.isActive ? (
+
+ {isLoading ? 'Stopping...' : 'STOP AUTOMATION'}
+
+ ) : (
+
+ {isLoading ? 'Starting...' : 'START AUTOMATION'}
+
+ )}
+
+
+
+ {/* Main Grid */}
+
+
+ {/* Configuration Column */}
+
+
+ {/* Drift Protocol Banner */}
+
+
+
β‘ DRIFT PROTOCOL ONLY
+
π Up to 100x Leverage β’ π Perpetual Futures β’ π° Spot Trading (1x) β’ π― Advanced Risk Management
+
+
+
+ {/* Configuration Panel */}
+
+
Trading Configuration
+
+
+
+ {/* Trading Mode */}
+
+
+ {/* Leverage Settings */}
+
+
β‘ Leverage (Drift Protocol)
+
setConfig({...config, maxLeverage: parseFloat(e.target.value)})}
+ className="w-full p-4 bg-gray-700 border border-purple-500 rounded-lg text-white focus:border-purple-400 text-lg font-semibold"
+ disabled={status?.isActive}
+ >
+ 1x - Spot Trading
+ 2x - Conservative
+ 3x - Moderate
+ 5x - Aggressive
+ 10x - High Risk
+ 20x - Very High Risk
+ 50x - Extreme Risk
+ 100x - MAXIMUM LEVERAGE π₯
+
+
+ {config.maxLeverage === 1 && "β
Spot trading - No liquidation risk"}
+ {config.maxLeverage <= 5 && config.maxLeverage > 1 && "π’ Conservative leverage - Lower risk"}
+ {config.maxLeverage <= 10 && config.maxLeverage > 5 && "π‘ Moderate leverage - Balanced risk/reward"}
+ {config.maxLeverage <= 50 && config.maxLeverage > 10 && "π High leverage - Significant risk"}
+ {config.maxLeverage > 50 && "π΄ EXTREME LEVERAGE - Maximum risk! Use with caution!"}
+
+
+
+
+
+ {/* Trading Parameters */}
+
+
+
+ Symbol
+ setConfig({...config, symbol: e.target.value})}
+ className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-blue-500"
+ disabled={status?.isActive}
+ >
+ SOL/USD
+ BTC/USD
+ ETH/USD
+ APT/USD
+ AVAX/USD
+ DOGE/USD
+ ADA/USD
+ MATIC/USD
+ LINK/USD
+
+
+
+
+ Position Size ($)
+ setConfig({...config, tradingAmount: parseFloat(e.target.value)})}
+ className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-blue-500"
+ disabled={status?.isActive}
+ min="10"
+ step="10"
+ />
+
+
+
+ Timeframe
+ setConfig({...config, timeframe: e.target.value})}
+ className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-blue-500"
+ disabled={status?.isActive}
+ >
+ 1 Minute
+ 5 Minutes
+ 15 Minutes
+ 1 Hour
+ 2 Hours
+ 4 Hours
+ 1 Day
+
+
+
+
+
+ {/* Risk Management */}
+
+
+ {/* Leverage Warning */}
+ {config.maxLeverage > 10 && (
+
+
+
β οΈ
+
+
HIGH LEVERAGE WARNING
+
+ You selected {config.maxLeverage}x leverage. This multiplies both profits AND losses.
+ A {(100/config.maxLeverage).toFixed(1)}% price move against your position will result in liquidation.
+ Only use high leverage if you understand the risks!
+
+
+
+
+ )}
+
+
+
+ {/* Status Column */}
+
+
+ {/* Current Status */}
+
+
π Status
+ {status ? (
+
+
+ Status:
+
+ {status.isActive ? 'π’ ACTIVE' : 'π΄ STOPPED'}
+
+
+
+ Mode:
+
+ {status.mode}
+
+
+
+ Protocol:
+ DRIFT
+
+
+ Symbol:
+ {config.symbol}
+
+
+ Leverage:
+
+ {config.maxLeverage}x
+
+
+
+ Position Size:
+ ${config.tradingAmount}
+
+
+ ) : (
+
Loading status...
+ )}
+
+
+ {/* Performance Stats */}
+
+
+ {/* Drift Protocol Benefits */}
+
+
β‘ Drift Protocol Features
+
+
+ β
+ Up to 100x leverage
+
+
+ β
+ Perpetual futures
+
+
+ β
+ Spot trading (1x leverage)
+
+
+ β
+ Advanced risk management
+
+
+ β
+ Low fees & slippage
+
+
+ β
+ Multiple trading pairs
+
+
+
+
+ {/* Risk Warning */}
+
+
β οΈ Risk Disclosure
+
+ High leverage trading carries substantial risk of loss. Never trade with money you cannot afford to lose.
+ Past performance does not guarantee future results.
+
+
+
+
+
+
+ )
+}
diff --git a/app/automation/page-minimal.js b/app/automation/page-minimal.js
new file mode 100644
index 0000000..75fab90
--- /dev/null
+++ b/app/automation/page-minimal.js
@@ -0,0 +1,344 @@
+'use client'
+import React, { useState, useEffect } from 'react'
+
+export default function AutomationPage() {
+ const [config, setConfig] = useState({
+ mode: 'SIMULATION',
+ dexProvider: 'DRIFT',
+ symbol: 'SOLUSD',
+ timeframe: '1h',
+ tradingAmount: 100,
+ maxLeverage: 5,
+ stopLossPercent: 2,
+ takeProfitPercent: 6,
+ maxDailyTrades: 5,
+ riskPercentage: 2
+ })
+
+ const [status, setStatus] = useState(null)
+ const [isLoading, setIsLoading] = useState(false)
+
+ useEffect(() => {
+ fetchStatus()
+ const interval = setInterval(fetchStatus, 30000)
+ return () => clearInterval(interval)
+ }, [])
+
+ const fetchStatus = async () => {
+ try {
+ const response = await fetch('/api/automation/status')
+ const data = await response.json()
+ if (data.success) {
+ setStatus(data.status)
+ }
+ } catch (error) {
+ console.error('Failed to fetch status:', error)
+ }
+ }
+
+ const handleStart = async () => {
+ setIsLoading(true)
+ try {
+ const response = await fetch('/api/automation/start', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(config)
+ })
+ const data = await response.json()
+ if (data.success) {
+ fetchStatus()
+ } else {
+ alert('Failed to start automation: ' + data.error)
+ }
+ } catch (error) {
+ console.error('Failed to start automation:', error)
+ alert('Failed to start automation')
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ const handleStop = async () => {
+ setIsLoading(true)
+ try {
+ const response = await fetch('/api/automation/stop', { method: 'POST' })
+ const data = await response.json()
+ if (data.success) {
+ fetchStatus()
+ } else {
+ alert('Failed to stop automation: ' + data.error)
+ }
+ } catch (error) {
+ console.error('Failed to stop automation:', error)
+ alert('Failed to stop automation')
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ return (
+
+ {/* Header */}
+
+
+
Automated Trading
+
Drift Protocol
+
+
+ {status?.isActive ? (
+
+ {isLoading ? 'Stopping...' : 'STOP'}
+
+ ) : (
+
+ {isLoading ? 'Starting...' : 'START'}
+
+ )}
+
+
+
+ {/* Main Grid */}
+
+
+ {/* Configuration */}
+
+
+
+
Configuration
+
+
+
+ {/* Trading Mode */}
+
+
+ {/* Leverage */}
+
+ Leverage
+ setConfig({...config, maxLeverage: parseFloat(e.target.value)})}
+ className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-purple-400"
+ disabled={status?.isActive}
+ >
+ 1x - Spot
+ 2x
+ 3x
+ 5x
+ 10x
+ 20x
+ 50x
+ 100x
+
+
+
+
+
+ {/* Parameters */}
+
+
+
+ Symbol
+ setConfig({...config, symbol: e.target.value})}
+ className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-blue-500"
+ disabled={status?.isActive}
+ >
+ SOL/USD
+ BTC/USD
+ ETH/USD
+ APT/USD
+ AVAX/USD
+ DOGE/USD
+
+
+
+
+ Position Size ($)
+ setConfig({...config, tradingAmount: parseFloat(e.target.value)})}
+ className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-blue-500"
+ disabled={status?.isActive}
+ min="10"
+ step="10"
+ />
+
+
+
+ Timeframe
+ setConfig({...config, timeframe: e.target.value})}
+ className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-blue-500"
+ disabled={status?.isActive}
+ >
+ 1 Minute
+ 5 Minutes
+ 15 Minutes
+ 1 Hour
+ 4 Hours
+ 1 Day
+
+
+
+
+
+ {/* Risk Management */}
+
+
+
+
+
+ {/* Status */}
+
+
+
+
Status
+ {status ? (
+
+
+ Status:
+
+ {status.isActive ? 'ACTIVE' : 'STOPPED'}
+
+
+
+ Mode:
+
+ {status.mode}
+
+
+
+ Protocol:
+ DRIFT
+
+
+ Symbol:
+ {config.symbol}
+
+
+ Leverage:
+ {config.maxLeverage}x
+
+
+ Position Size:
+ ${config.tradingAmount}
+
+
+ ) : (
+
Loading...
+ )}
+
+
+
+
+
+
+
+ )
+}
diff --git a/app/automation/page-old-complex.js.backup b/app/automation/page-old-complex.js.backup
new file mode 100644
index 0000000..a418a6f
--- /dev/null
+++ b/app/automation/page-old-complex.js.backup
@@ -0,0 +1,1515 @@
+'use client'
+import React, { useState, useEffect } from 'react'
+import RealTimePriceMonitor from '../../components/RealTimePriceMonitor'
+
+export default function AutomationPage() {
+ const [config, setConfig] = useState({
+ mode: 'SIMULATION',
+ symbol: 'SOLUSD',
+ timeframe: '1h',
+ tradingAmount: 100,
+ maxLeverage: 3,
+ stopLossPercent: 2,
+ takeProfitPercent: 6,
+ maxDailyTrades: 5,
+ riskPercentage: 2
+ })
+
+ const [status, setStatus] = useState(null)
+ const [isLoading, setIsLoading] = useState(false)
+ const [learningInsights, setLearningInsights] = useState(null)
+ const [aiLearningStatus, setAiLearningStatus] = useState(null)
+ const [recentTrades, setRecentTrades] = useState([])
+ const [analysisDetails, setAnalysisDetails] = useState(null)
+ const [selectedTrade, setSelectedTrade] = useState(null)
+ const [tradeModalOpen, setTradeModalOpen] = useState(false)
+ const [configCollapsed, setConfigCollapsed] = useState(true)
+
+ useEffect(() => {
+ fetchStatus()
+ fetchLearningInsights()
+ fetchAiLearningStatus()
+ fetchRecentTrades()
+ fetchAnalysisDetails()
+
+ // Auto-refresh every 30 seconds
+ const interval = setInterval(() => {
+ fetchStatus()
+ fetchAnalysisDetails()
+ fetchAiLearningStatus()
+ }, 30000)
+
+ return () => clearInterval(interval)
+ }, [])
+
+ const fetchAnalysisDetails = async () => {
+ try {
+ const response = await fetch('/api/automation/analysis-details')
+ const data = await response.json()
+ if (data.success) {
+ setAnalysisDetails(data.data)
+ // Also update recent trades from the same endpoint
+ if (data.data.recentTrades) {
+ setRecentTrades(data.data.recentTrades)
+ }
+ }
+ } catch (error) {
+ console.error('Failed to fetch analysis details:', error)
+ }
+ }
+
+ const fetchStatus = async () => {
+ try {
+ const response = await fetch('/api/automation/status')
+ const data = await response.json()
+ if (data.success) {
+ setStatus(data.status)
+ }
+ } catch (error) {
+ console.error('Failed to fetch status:', error)
+ }
+ }
+
+ const fetchLearningInsights = async () => {
+ try {
+ const response = await fetch('/api/automation/learning-insights')
+ const data = await response.json()
+ if (data.success) {
+ setLearningInsights(data.insights)
+ }
+ } catch (error) {
+ console.error('Failed to fetch learning insights:', error)
+ }
+ }
+
+ const fetchAiLearningStatus = async () => {
+ try {
+ const response = await fetch('/api/ai-learning-status')
+ const data = await response.json()
+ if (data.success) {
+ setAiLearningStatus(data.data)
+ }
+ } catch (error) {
+ console.error('Failed to fetch AI learning status:', error)
+ }
+ }
+
+ const fetchRecentTrades = async () => {
+ try {
+ console.log('π Fetching recent trades...')
+ // Get enhanced trade data from analysis-details instead of recent-trades
+ const response = await fetch('/api/automation/analysis-details')
+ const data = await response.json()
+ console.log('π Trade data response:', data.success, data.data?.recentTrades?.length || 0)
+ if (data.success && data.data.recentTrades) {
+ console.log('β
Setting recent trades:', data.data.recentTrades.length)
+ setRecentTrades(data.data.recentTrades)
+ }
+ } catch (error) {
+ console.error('Failed to fetch recent trades:', error)
+ }
+ }
+
+ const handleStart = async () => {
+ setIsLoading(true)
+ try {
+ const response = await fetch('/api/automation/start', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify(config)
+ })
+ const data = await response.json()
+ if (data.success) {
+ fetchStatus()
+ } else {
+ alert('Failed to start automation: ' + data.error)
+ }
+ } catch (error) {
+ console.error('Failed to start automation:', error)
+ alert('Failed to start automation')
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ const handleStop = async () => {
+ setIsLoading(true)
+ try {
+ const response = await fetch('/api/automation/stop', {
+ method: 'POST'
+ })
+ const data = await response.json()
+ if (data.success) {
+ fetchStatus()
+ } else {
+ alert('Failed to stop automation: ' + data.error)
+ }
+ } catch (error) {
+ console.error('Failed to stop automation:', error)
+ alert('Failed to stop automation')
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ const handlePause = async () => {
+ setIsLoading(true)
+ try {
+ const response = await fetch('/api/automation/pause', {
+ method: 'POST'
+ })
+ const data = await response.json()
+ if (data.success) {
+ fetchStatus()
+ } else {
+ alert('Failed to pause automation: ' + data.error)
+ }
+ } catch (error) {
+ console.error('Failed to pause automation:', error)
+ alert('Failed to pause automation')
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ const handleResume = async () => {
+ setIsLoading(true)
+ try {
+ const response = await fetch('/api/automation/resume', {
+ method: 'POST'
+ })
+ const data = await response.json()
+ if (data.success) {
+ fetchStatus()
+ } else {
+ alert('Failed to resume automation: ' + data.error)
+ }
+ } catch (error) {
+ console.error('Failed to resume automation:', error)
+ alert('Failed to resume automation')
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ const openTradeModal = async (tradeId) => {
+ try {
+ const response = await fetch(`/api/automation/trade-details/${tradeId}`)
+ const data = await response.json()
+ if (data.success) {
+ setSelectedTrade(data.data)
+ setTradeModalOpen(true)
+ } else {
+ alert('Failed to load trade details')
+ }
+ } catch (error) {
+ console.error('Failed to load trade details:', error)
+ alert('Failed to load trade details')
+ }
+ }
+
+ const closeTradeModal = () => {
+ setTradeModalOpen(false)
+ setSelectedTrade(null)
+ }
+
+ // Use status API data instead of calculating from limited recent trades
+ const getWinRate = () => {
+ return status?.winRate || 0
+ }
+
+ // Use status API data for total P&L
+ const getTotalPnL = () => {
+ return status?.totalPnL || 0
+ }
+
+ return (
+
+
+
+
Automation Mode
+
+ AI-powered automated trading on 1H timeframe with learning capabilities
+
+
+
+ {status?.isActive ? (
+ <>
+
+ {isLoading ? 'Pausing...' : 'Pause'}
+
+
+ {isLoading ? 'Stopping...' : 'Stop'}
+
+ >
+ ) : (
+ <>
+ {status?.status === 'PAUSED' && (
+
+ {isLoading ? 'Resuming...' : 'Resume'}
+
+ )}
+
+ {isLoading ? 'Starting...' : 'Start Automation'}
+
+ >
+ )}
+
+
+
+
+ {/* Real-Time Price Monitor */}
+
+
+
+
+ {/* Right Side Panel - Active Trades or Status */}
+
+ {/* Active Trades Monitor */}
+ {status && status.activeTrades && status.activeTrades.length > 0 ? (
+
+
Active Trades Monitor
+
+ {status.activeTrades.map((trade, idx) => (
+
+
+
+ {trade.side} {trade.amount} @ ${trade.entryPrice}
+
+ 0 ? 'bg-green-600' : 'bg-red-600'
+ } text-white`}>
+ ${trade.unrealizedPnl}
+
+
+
+ SL: ${trade.stopLoss} | TP: ${trade.takeProfit}
+
+
+ ))}
+
+
+ ) : (
+ /* Trading Status Summary when no active trades */
+
+
Trading Status
+
+
+ Mode:
+
+ {config.mode}
+
+
+
+ Status:
+
+ {status?.isActive ? 'ACTIVE' : (status?.status || 'STOPPED')}
+
+
+
+ Symbol:
+ {config.symbol}
+
+
+ Timeframe:
+ {config.timeframe}
+
+
+ Active Trades:
+
+ {status?.activeTrades?.length || 0}
+
+
+
+ Trading Amount:
+ ${config.tradingAmount}
+
+
+ Max Leverage:
+ {config.maxLeverage}x
+
+
+ Stop Loss:
+ {config.stopLossPercent}%
+
+
+ Take Profit:
+ {config.takeProfitPercent}%
+
+
+ Max Daily Trades:
+ {config.maxDailyTrades}
+
+
+ Risk Percentage:
+ {config.riskPercentage}%
+
+ {status && (
+ <>
+
+
+ Total Trades:
+ {status.totalTrades || 0}
+
+
+
+ Win Rate:
+ = 50 ? 'text-green-400' : 'text-red-400'
+ }`}>
+ {(status.winRate || 0).toFixed(1)}%
+
+
+
+ Total P&L:
+ 0 ? 'text-green-400' :
+ (status.totalPnL || 0) < 0 ? 'text-red-400' : 'text-gray-400'
+ }`}>
+ ${(status.totalPnL || 0).toFixed(2)}
+
+
+ >
+ )}
+
+ {/* Quick Actions */}
+
+
Quick Actions:
+
+ setConfigCollapsed(!configCollapsed)}
+ className="px-3 py-1 bg-blue-600 text-white rounded text-xs hover:bg-blue-700 transition-colors"
+ >
+ {configCollapsed ? 'Show Config' : 'Hide Config'}
+
+ window.location.reload()}
+ className="px-3 py-1 bg-gray-600 text-white rounded text-xs hover:bg-gray-700 transition-colors"
+ >
+ Refresh
+
+
+
+
+
+ )}
+
+
+
+
+ {/* Configuration Panel - Collapsible */}
+
+
+
+
Configuration
+ setConfigCollapsed(!configCollapsed)}
+ className="px-3 py-1 bg-gray-700 text-white rounded hover:bg-gray-600 transition-colors"
+ >
+ {configCollapsed ? 'Show' : 'Hide'}
+
+
+
+ {!configCollapsed && (
+
+
+
+ Trading Mode
+
+ setConfig({...config, mode: e.target.value})}
+ className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
+ disabled={status?.isActive}
+ >
+ Simulation (Paper Trading)
+ Live Trading (Jupiter DEX)
+
+
+
+
+
+
+ Symbol
+
+ setConfig({...config, symbol: e.target.value})}
+ className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
+ disabled={status?.isActive}
+ >
+ SOL/USD
+ BTC/USD
+ ETH/USD
+
+
+
+
+
+ Timeframe
+
+ setConfig({...config, timeframe: e.target.value})}
+ className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
+ disabled={status?.isActive}
+ >
+ 1 Hour (Recommended)
+ 4 Hours
+ 1 Day
+
+
+
+
+
+
+
+ Trading Amount ($)
+
+ setConfig({...config, tradingAmount: parseFloat(e.target.value)})}
+ className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
+ disabled={status?.isActive}
+ min="10"
+ step="10"
+ />
+
+
+
+
+ Max Leverage
+
+ setConfig({...config, maxLeverage: parseFloat(e.target.value)})}
+ className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
+ disabled={status?.isActive}
+ >
+ 1x (Spot)
+ 2x
+ 3x
+ 5x
+
+
+
+
+
+
+ )}
+
+
+ {/* AI Learning Status */}
+ {aiLearningStatus && (
+
+
π§ AI Learning Status
+
+
+ {/* Learning Phase */}
+
+
+
+
+
{aiLearningStatus.phaseDescription}
+
Phase: {aiLearningStatus.phase.replace('_', ' ')}
+
+
+
+
+
+
{aiLearningStatus.totalAnalyses}
+
Total Analyses
+
+
+
{aiLearningStatus.totalTrades}
+
Total Trades
+
+
+
+
+ {/* Performance Metrics */}
+
+
+
+
{(aiLearningStatus.avgAccuracy * 100).toFixed(1)}%
+
Avg Accuracy
+
+
+
{(aiLearningStatus.winRate * 100).toFixed(1)}%
+
Win Rate
+
+
+
+
+
{aiLearningStatus.confidenceLevel.toFixed(1)}%
+
Confidence Level
+
+
+
+
+ {/* Strengths and Improvements */}
+
+
+
Strengths
+
+ {aiLearningStatus.strengths.map((strength, idx) => (
+ β {strength}
+ ))}
+
+
+
+
Areas for Improvement
+
+ {aiLearningStatus.improvements.map((improvement, idx) => (
+ β’ {improvement}
+ ))}
+
+
+
+
+ {/* Next Milestone */}
+
+
Next Milestone
+
{aiLearningStatus.nextMilestone}
+
+
+ {/* Recommendation */}
+
+
AI Recommendation
+
{aiLearningStatus.recommendation}
+
+
+ )}
+
+ {/* Learning Insights */}
+ {learningInsights && (
+
+
AI Learning Insights
+
+
+ Total Analyses:
+ {learningInsights.totalAnalyses}
+
+
+ Avg Accuracy:
+ {(learningInsights.avgAccuracy * 100).toFixed(1)}%
+
+
+ Best Timeframe:
+ {learningInsights.bestTimeframe}
+
+
+ Worst Timeframe:
+ {learningInsights.worstTimeframe}
+
+
+
+
Recommendations
+
+ {learningInsights.recommendations.map((rec, idx) => (
+ β’ {rec}
+ ))}
+
+
+
+
+ )}
+
+
+ {/* Status and Performance */}
+
+ {/* Status Panel */}
+
+
Status
+ {status ? (
+
+
+ Status:
+
+ {status.isActive ? 'ACTIVE' : 'STOPPED'}
+
+
+
+ Mode:
+
+ {status.mode}
+
+
+
+ Symbol:
+ {status.symbol}
+
+
+ Timeframe:
+ {status.timeframe}
+
+
+ Total Trades:
+ {status.totalTrades}
+
+
+ Win Rate:
+ 60 ? 'text-green-400' :
+ getWinRate() > 40 ? 'text-yellow-400' : 'text-red-400'
+ }`}>
+ {getWinRate()}%
+
+
+
+ Total P&L:
+ 0 ? 'text-green-400' :
+ getTotalPnL() < 0 ? 'text-red-400' : 'text-gray-300'
+ }`}>
+ ${getTotalPnL()}
+
+
+ {status.lastAnalysis && (
+
+ Last Analysis:
+
+ {new Date(status.lastAnalysis).toLocaleTimeString()}
+
+
+ )}
+ {status.errorCount > 0 && (
+
+ Errors:
+ {status.errorCount}
+
+ )}
+
+ ) : (
+
No active automation session
+ )}
+
+
+ {/* Recent Trades */}
+
+
+
+ Active & Latest Trades
+ (Top 4)
+
+
+
+
+ Debug: {recentTrades.length} total trades
+
+
+
+ {console.log('π― Rendering trades section, count:', recentTrades.length)}
+ {recentTrades.length > 0 ? (
+
+ {/* Sort trades to show active trades first, then latest completed trades */}
+ {recentTrades
+ .sort((a, b) => {
+ // Active trades first
+ if (a.isActive && !b.isActive) return -1
+ if (!a.isActive && b.isActive) return 1
+ // Then by creation date (most recent first)
+ return new Date(b.createdAt) - new Date(a.createdAt)
+ })
+ .slice(0, 4)
+ .map((trade, idx) => (
+
openTradeModal(trade.id)}
+ >
+ {/* Trade Header - Enhanced for active trades */}
+
+
+ {trade.isActive && (
+
+ )}
+
+ {trade.side}
+
+
{trade.amount}
+
{trade.leverage}x
+
+ {trade.isActive ? 'ACTIVE' : trade.result}
+
+
+
+
${trade.entryPrice?.toFixed(2) || trade.price?.toFixed(2) || '0.00'}
+
{trade.confidence || 0}% confidence
+ {trade.isActive && (
+
+ Current: ${trade.currentPrice?.toFixed(2) || '0.00'}
+
+ )}
+
+
+
+ {/* Enhanced Timing Information */}
+
+
+
+ Entry Time:
+ {new Date(trade.entryTime).toLocaleTimeString()}
+
+
+ Exit Time:
+
+ {trade.exitTime ? new Date(trade.exitTime).toLocaleTimeString() : 'Active'}
+
+
+
+ Duration:
+ {trade.durationText}
+
+
+
+
+ {/* Trading Details */}
+
+
+
+ Trading Mode:
+
+ {trade.tradingMode || 'SIMULATION'}
+
+
+
+ Trading Amount:
+
+ {trade.realTradingAmount ? `$${trade.realTradingAmount}` : `$${trade.tradingAmount || '0'}`}
+
+
+
+ Leverage:
+ {trade.leverage || 1}x
+
+
+ Position Size:
+ {trade.amount?.toFixed(6) || '0.000000'} SOL
+
+ {/* Entry Price - Always show for completed trades */}
+
+ Entry Price:
+ ${trade.entryPrice?.toFixed(2) || trade.price?.toFixed(2) || '0.00'}
+
+ {/* Current/Exit Price with real-time updates for active trades */}
+
+ {trade.isActive ? 'Current' : 'Exit'} Price:
+
+ {trade.isActive ?
+ `$${trade.currentPrice?.toFixed(2) || '0.00'}` :
+ (trade.exitPrice ?
+ `$${trade.exitPrice.toFixed(2)}` :
+ Not recorded
+ )
+ }
+
+
+ {/* Live Trade Transaction ID */}
+ {trade.tradingMode === 'LIVE' && trade.driftTxId && (
+
+ Transaction ID:
+
+ {trade.driftTxId.slice(0, 8)}...{trade.driftTxId.slice(-8)}
+
+
+ )}
+ {/* Live Trade Fees */}
+ {trade.tradingMode === 'LIVE' && trade.fees > 0 && (
+
+ Fees Paid:
+ ${trade.fees?.toFixed(4) || '0.0000'}
+
+ )}
+ {/* 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)}
+
+
+ )}
+
+
+
+ {/* P&L Display - Enhanced for active trades */}
+
+
+
+ {trade.isActive ? 'Unrealized P&L:' : 'Realized P&L:'}
+
+
+ 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') :
+ (trade.realizedPnl || '0.00')
+ }
+
+ {trade.pnlPercent && (
+ 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})
+
+ )}
+
+ {trade.isActive ? 'β‘ Live' : 'β Final'}
+
+
+
+ {/* Additional active trade info */}
+ {trade.isActive && trade.currentPrice && trade.entryPrice && (
+
+
+ Price Change:
+ 0 ? 'text-green-400' : 'text-red-400'
+ }`}>
+ ${((trade.currentPrice - trade.entryPrice) >= 0 ? '+' : '')}${(trade.currentPrice - trade.entryPrice).toFixed(2)}
+ ({(((trade.currentPrice - trade.entryPrice) / trade.entryPrice) * 100).toFixed(2)}%)
+
+
+
+ )}
+ {/* 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 */}
+
+
+ SL: ${trade.stopLoss} | TP: ${trade.takeProfit}
+
+
+ π Click to view analysis
+
+
+
+ ))}
+
+ ) : (
+
No recent trades
+ )}
+
+
+
+
+ {/* Detailed AI Analysis Section */}
+ {analysisDetails?.analysis && (
+
+
Latest AI Analysis
+
+
+ {/* Main Decision */}
+
+
π― Trading Decision
+
+
+ Decision:
+
+ {analysisDetails.analysis.decision}
+
+
+
+ Confidence:
+ 80 ? 'text-green-400' :
+ analysisDetails.analysis.confidence > 60 ? 'text-yellow-400' :
+ 'text-red-400'
+ }`}>
+ {analysisDetails.analysis.confidence}%
+
+
+
+ Market Sentiment:
+
+ {analysisDetails.analysis.sentiment}
+
+
+
+
+ Summary: {analysisDetails.analysis.summary}
+
+
+
+
+
+ {/* Key Levels */}
+
+
π Key Levels
+
+ {analysisDetails.analysis.keyLevels?.support?.length > 0 && (
+
+
Support Levels
+ {analysisDetails.analysis.keyLevels.support.map((level, idx) => (
+
+ S{idx + 1}:
+ ${level.toFixed(2)}
+
+ ))}
+
+ )}
+ {analysisDetails.analysis.keyLevels?.resistance?.length > 0 && (
+
+
Resistance Levels
+ {analysisDetails.analysis.keyLevels.resistance.map((level, idx) => (
+
+ R{idx + 1}:
+ ${level.toFixed(2)}
+
+ ))}
+
+ )}
+
+
+
+ {/* Technical Indicators */}
+
+
π Technical Indicators
+
+ {analysisDetails.analysis.technicalIndicators && Object.entries(analysisDetails.analysis.technicalIndicators).map(([key, value]) => (
+
+ {key.replace(/([A-Z])/g, ' $1').trim()}:
+
+ {typeof value === 'number' ? value.toFixed(2) : value}
+
+
+ ))}
+
+
+
+
+ {/* AI Reasoning */}
+ {analysisDetails.analysis.reasoning && (
+
+
π€ AI Reasoning
+
+
+
{analysisDetails.analysis.reasoning}
+
+ {analysisDetails.analysis.executionPlan && (
+
+
Execution Plan:
+
{analysisDetails.analysis.executionPlan}
+
+ )}
+
+
+ )}
+
+ {/* Risk Assessment */}
+ {analysisDetails.analysis.riskAssessment && (
+
+
β οΈ Risk Assessment
+
+
+
{analysisDetails.analysis.riskAssessment}
+
+ {analysisDetails.analysis.marketConditions && (
+
+
Market Conditions:
+
{analysisDetails.analysis.marketConditions}
+
+ )}
+
+
+ )}
+
+ {/* Layout Analysis */}
+ {analysisDetails.analysis.layoutAnalysis && (
+
+
π Multi-Layout Analysis
+
+ {Object.entries(analysisDetails.analysis.layoutAnalysis).map(([layout, analysis]) => (
+
+
{layout} Layout:
+
{analysis}
+
+ ))}
+
+
+ )}
+
+ {/* Performance Metrics */}
+
+
π Analysis Performance
+
+
+
+ {analysisDetails.analysis.timestamp ?
+ new Date(analysisDetails.analysis.timestamp).toLocaleTimeString() :
+ 'N/A'
+ }
+
+
Last Analysis
+
+
+
+ {analysisDetails.analysis.processingTime ?
+ `${analysisDetails.analysis.processingTime}ms` :
+ 'N/A'
+ }
+
+
Processing Time
+
+
+
+ {analysisDetails.session?.totalTrades || 0}
+
+
Total Trades
+
+
+
+ {analysisDetails.session?.errorCount || 0}
+
+
Errors
+
+
+
+
+ )}
+
+ {/* Multi-Timeframe Analysis Results */}
+ {analysisDetails?.analysis?.multiTimeframeResults && analysisDetails.analysis.multiTimeframeResults.length > 0 && (
+
+
π Multi-Timeframe Analysis
+
+
+ {analysisDetails.analysis.multiTimeframeResults.map((result, index) => (
+
+
+
+ {result.analysisComplete ? (
+ β
+ ) : (
+ β³
+ )}
+ {result.timeframe} Timeframe
+
+
+ {result.analysisComplete ? 'Complete' : 'In Progress'}
+
+
+
+
+
+ Decision:
+
+ {result.decision}
+
+
+
+
+ Confidence:
+ 80 ? 'text-green-400' :
+ result.confidence > 60 ? 'text-yellow-400' :
+ 'text-red-400'
+ }`}>
+ {result.confidence}%
+
+
+
+
+ Sentiment:
+
+ {result.sentiment}
+
+
+
+ {result.createdAt && (
+
+
+ Analyzed: {new Date(result.createdAt).toLocaleString()}
+
+
+ )}
+
+
+ ))}
+
+
+ {/* Multi-Timeframe Summary */}
+
+
π Cross-Timeframe Consensus
+
+
+
+ {analysisDetails.analysis.multiTimeframeResults.length}
+
+
Timeframes Analyzed
+
+
+
+ {analysisDetails.analysis.multiTimeframeResults.filter(r => r.analysisComplete).length}
+
+
Completed
+
+
+
+ {Math.round(
+ analysisDetails.analysis.multiTimeframeResults.reduce((sum, r) => sum + r.confidence, 0) /
+ analysisDetails.analysis.multiTimeframeResults.length
+ )}%
+
+
Avg Confidence
+
+
+
+
+ )}
+
+ {/* No Analysis Available */}
+ {!analysisDetails?.analysis && status?.isActive && (
+
+
π€ AI Analysis
+
+
+
Waiting for first analysis...
+
The AI will analyze the market every hour
+
+
+ )}
+
+ {/* Trade Details Modal */}
+ {tradeModalOpen && selectedTrade && (
+
+
+ {/* Modal Header */}
+
+
+
Trade Analysis Details
+
+ {selectedTrade.side} {selectedTrade.amount} @ ${selectedTrade.price?.toFixed(2) || '0.00'}
+
+ 0 ? 'bg-green-600 text-white' : 'bg-red-600 text-white'
+ }`}>
+ {selectedTrade.status} {selectedTrade.profit && `(${selectedTrade.profit > 0 ? '+' : ''}$${selectedTrade.profit?.toFixed(2) || '0.00'})`}
+
+
+
+ Γ
+
+
+
+ {/* Modal Content */}
+
+
+ {/* Trade Overview */}
+
+
+
Trade Info
+
+
+ Entry Time:
+ {new Date(selectedTrade.entryTime).toLocaleString()}
+
+
+ Exit Time:
+
+ {selectedTrade.exitTime ? new Date(selectedTrade.exitTime).toLocaleString() : 'Active'}
+
+
+
+ Duration:
+
+ {selectedTrade.exitTime ?
+ `${Math.floor((new Date(selectedTrade.exitTime) - new Date(selectedTrade.entryTime)) / (1000 * 60))}m` :
+ `${Math.floor((new Date() - new Date(selectedTrade.entryTime)) / (1000 * 60))}m (Active)`
+ }
+
+
+
+
+
+
+
Position Details
+
+
+ Trading Amount:
+ ${selectedTrade.tradingAmount}
+
+
+ Leverage:
+ {selectedTrade.leverage}x
+
+
+ Position Size:
+ ${selectedTrade.positionSize}
+
+
+
+
+
+
Risk Management
+
+
+ Stop Loss:
+ ${selectedTrade.detailedAnalysis?.keyLevels?.stopLoss?.price || 'N/A'}
+
+
+ Take Profit:
+ ${selectedTrade.detailedAnalysis?.keyLevels?.takeProfit?.price || 'N/A'}
+
+
+ Risk/Reward:
+ {selectedTrade.detailedAnalysis?.riskManagement?.riskReward || 'N/A'}
+
+
+
+
+
+ {/* Analysis Screenshots */}
+
+
π Analysis Screenshots
+
+ {selectedTrade.screenshots && Object.entries(selectedTrade.screenshots).map(([key, screenshot]) => (
+
+
{screenshot.title}
+
+
+ π· {screenshot.title}
+
+ {screenshot.description}
+
+
+
{screenshot.description}
+
+ ))}
+
+
+
+ {/* AI Analysis Details */}
+ {selectedTrade.detailedAnalysis && (
+
+
π€ AI Analysis
+
+ {/* Decision Summary */}
+
+
+
Decision Summary
+
+ {selectedTrade.detailedAnalysis.decision} ({selectedTrade.detailedAnalysis.confidence}%)
+
+
+
{selectedTrade.detailedAnalysis.aiReasoning}
+
+
+ {/* Multi-timeframe Analysis */}
+
+
Multi-timeframe Analysis
+
+ {selectedTrade.detailedAnalysis.timeframes && Object.entries(selectedTrade.detailedAnalysis.timeframes).map(([tf, data]) => (
+
+
+ {tf}
+
+ {data.decision}
+
+
+
+ Confidence: {data.confidence}%
+
+
+ {data.signals.slice(0, 2).map((signal, idx) => (
+
β’ {signal}
+ ))}
+
+
+ ))}
+
+
+
+ {/* Technical Indicators */}
+
+
Technical Indicators
+
+ {selectedTrade.detailedAnalysis.technicalIndicators && Object.entries(selectedTrade.detailedAnalysis.technicalIndicators).map(([indicator, data]) => (
+
+
{indicator}
+
{data.value}
+
{data.interpretation}
+
+ ))}
+
+
+
+ {/* Execution Plan */}
+
+
Execution Plan
+
+ {selectedTrade.detailedAnalysis.executionPlan && Object.entries(selectedTrade.detailedAnalysis.executionPlan).map(([key, value]) => (
+
+ {key}:
+ {value}
+
+ ))}
+
+
+
+ )}
+
+
+
+ )}
+
+ )
+}
diff --git a/app/automation/page-promotional-backup.js b/app/automation/page-promotional-backup.js
new file mode 100644
index 0000000..4513e9f
--- /dev/null
+++ b/app/automation/page-promotional-backup.js
@@ -0,0 +1,429 @@
+'use client'
+import React, { useState, useEffect } from 'react'
+
+export default function AutomationPage() {
+ const [config, setConfig] = useState({
+ mode: 'SIMULATION',
+ dexProvider: 'DRIFT', // Only Drift now
+ symbol: 'SOLUSD',
+ timeframe: '1h',
+ tradingAmount: 100,
+ maxLeverage: 5,
+ stopLossPercent: 2,
+ takeProfitPercent: 6,
+ maxDailyTrades: 5,
+ riskPercentage: 2
+ })
+
+ const [status, setStatus] = useState(null)
+ const [isLoading, setIsLoading] = useState(false)
+ const [recentTrades, setRecentTrades] = useState([])
+
+ useEffect(() => {
+ fetchStatus()
+ const interval = setInterval(fetchStatus, 30000)
+ return () => clearInterval(interval)
+ }, [])
+
+ const fetchStatus = async () => {
+ try {
+ const response = await fetch('/api/automation/status')
+ const data = await response.json()
+ if (data.success) {
+ setStatus(data.status)
+ }
+ } catch (error) {
+ console.error('Failed to fetch status:', error)
+ }
+ }
+
+ const handleStart = async () => {
+ setIsLoading(true)
+ try {
+ const response = await fetch('/api/automation/start', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(config)
+ })
+ const data = await response.json()
+ if (data.success) {
+ fetchStatus()
+ } else {
+ alert('Failed to start automation: ' + data.error)
+ }
+ } catch (error) {
+ console.error('Failed to start automation:', error)
+ alert('Failed to start automation')
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ const handleStop = async () => {
+ setIsLoading(true)
+ try {
+ const response = await fetch('/api/automation/stop', { method: 'POST' })
+ const data = await response.json()
+ if (data.success) {
+ fetchStatus()
+ } else {
+ alert('Failed to stop automation: ' + data.error)
+ }
+ } catch (error) {
+ console.error('Failed to stop automation:', error)
+ alert('Failed to stop automation')
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ return (
+
+ {/* Header */}
+
+
+
β‘ DRIFT PROTOCOL TRADING
+
AI-powered automated trading β’ Up to 100x leverage β’ Perpetual futures
+
+
+ {status?.isActive ? (
+
+ {isLoading ? 'Stopping...' : 'STOP AUTOMATION'}
+
+ ) : (
+
+ {isLoading ? 'Starting...' : 'START AUTOMATION'}
+
+ )}
+
+
+
+ {/* Main Grid */}
+
+
+ {/* Configuration Column */}
+
+
+ {/* Drift Protocol Banner */}
+
+
+
β‘ DRIFT PROTOCOL ONLY
+
π Up to 100x Leverage β’ π Perpetual Futures β’ π° Spot Trading (1x) β’ π― Advanced Risk Management
+
+
+
+ {/* Configuration Panel */}
+
+
Trading Configuration
+
+
+
+ {/* Trading Mode */}
+
+
+ {/* Leverage Settings */}
+
+
β‘ Leverage (Drift Protocol)
+
setConfig({...config, maxLeverage: parseFloat(e.target.value)})}
+ className="w-full p-4 bg-gray-700 border border-purple-500 rounded-lg text-white focus:border-purple-400 text-lg font-semibold"
+ disabled={status?.isActive}
+ >
+ 1x - Spot Trading
+ 2x - Conservative
+ 3x - Moderate
+ 5x - Aggressive
+ 10x - High Risk
+ 20x - Very High Risk
+ 50x - Extreme Risk
+ 100x - MAXIMUM LEVERAGE π₯
+
+
+ {config.maxLeverage === 1 && "β
Spot trading - No liquidation risk"}
+ {config.maxLeverage <= 5 && config.maxLeverage > 1 && "π’ Conservative leverage - Lower risk"}
+ {config.maxLeverage <= 10 && config.maxLeverage > 5 && "π‘ Moderate leverage - Balanced risk/reward"}
+ {config.maxLeverage <= 50 && config.maxLeverage > 10 && "π High leverage - Significant risk"}
+ {config.maxLeverage > 50 && "π΄ EXTREME LEVERAGE - Maximum risk! Use with caution!"}
+
+
+
+
+
+ {/* Trading Parameters */}
+
+
+
+ Symbol
+ setConfig({...config, symbol: e.target.value})}
+ className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-blue-500"
+ disabled={status?.isActive}
+ >
+ SOL/USD
+ BTC/USD
+ ETH/USD
+ APT/USD
+ AVAX/USD
+ DOGE/USD
+ ADA/USD
+ MATIC/USD
+ LINK/USD
+
+
+
+
+ Position Size ($)
+ setConfig({...config, tradingAmount: parseFloat(e.target.value)})}
+ className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-blue-500"
+ disabled={status?.isActive}
+ min="10"
+ step="10"
+ />
+
+
+
+ Timeframe
+ setConfig({...config, timeframe: e.target.value})}
+ className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-blue-500"
+ disabled={status?.isActive}
+ >
+ 1 Minute
+ 5 Minutes
+ 15 Minutes
+ 1 Hour
+ 2 Hours
+ 4 Hours
+ 1 Day
+
+
+
+
+
+ {/* Risk Management */}
+
+
+ {/* Leverage Warning */}
+ {config.maxLeverage > 10 && (
+
+
+
β οΈ
+
+
HIGH LEVERAGE WARNING
+
+ You selected {config.maxLeverage}x leverage. This multiplies both profits AND losses.
+ A {(100/config.maxLeverage).toFixed(1)}% price move against your position will result in liquidation.
+ Only use high leverage if you understand the risks!
+
+
+
+
+ )}
+
+
+
+ {/* Status Column */}
+
+
+ {/* Current Status */}
+
+
π Status
+ {status ? (
+
+
+ Status:
+
+ {status.isActive ? 'π’ ACTIVE' : 'π΄ STOPPED'}
+
+
+
+ Mode:
+
+ {status.mode}
+
+
+
+ Protocol:
+ DRIFT
+
+
+ Symbol:
+ {config.symbol}
+
+
+ Leverage:
+
+ {config.maxLeverage}x
+
+
+
+ Position Size:
+ ${config.tradingAmount}
+
+
+ ) : (
+
Loading status...
+ )}
+
+
+ {/* Performance Stats */}
+
+
+ {/* Drift Protocol Benefits */}
+
+
β‘ Drift Protocol Features
+
+
+ β
+ Up to 100x leverage
+
+
+ β
+ Perpetual futures
+
+
+ β
+ Spot trading (1x leverage)
+
+
+ β
+ Advanced risk management
+
+
+ β
+ Low fees & slippage
+
+
+ β
+ Multiple trading pairs
+
+
+
+
+ {/* Risk Warning */}
+
+
β οΈ Risk Disclosure
+
+ High leverage trading carries substantial risk of loss. Never trade with money you cannot afford to lose.
+ Past performance does not guarantee future results.
+
+
+
+
+
+
+ )
+}
diff --git a/app/automation/page.js b/app/automation/page.js
index a418a6f..75fab90 100644
--- a/app/automation/page.js
+++ b/app/automation/page.js
@@ -1,14 +1,14 @@
'use client'
import React, { useState, useEffect } from 'react'
-import RealTimePriceMonitor from '../../components/RealTimePriceMonitor'
export default function AutomationPage() {
const [config, setConfig] = useState({
mode: 'SIMULATION',
+ dexProvider: 'DRIFT',
symbol: 'SOLUSD',
timeframe: '1h',
tradingAmount: 100,
- maxLeverage: 3,
+ maxLeverage: 5,
stopLossPercent: 2,
takeProfitPercent: 6,
maxDailyTrades: 5,
@@ -17,47 +17,13 @@ export default function AutomationPage() {
const [status, setStatus] = useState(null)
const [isLoading, setIsLoading] = useState(false)
- const [learningInsights, setLearningInsights] = useState(null)
- const [aiLearningStatus, setAiLearningStatus] = useState(null)
- const [recentTrades, setRecentTrades] = useState([])
- const [analysisDetails, setAnalysisDetails] = useState(null)
- const [selectedTrade, setSelectedTrade] = useState(null)
- const [tradeModalOpen, setTradeModalOpen] = useState(false)
- const [configCollapsed, setConfigCollapsed] = useState(true)
useEffect(() => {
fetchStatus()
- fetchLearningInsights()
- fetchAiLearningStatus()
- fetchRecentTrades()
- fetchAnalysisDetails()
-
- // Auto-refresh every 30 seconds
- const interval = setInterval(() => {
- fetchStatus()
- fetchAnalysisDetails()
- fetchAiLearningStatus()
- }, 30000)
-
+ const interval = setInterval(fetchStatus, 30000)
return () => clearInterval(interval)
}, [])
- const fetchAnalysisDetails = async () => {
- try {
- const response = await fetch('/api/automation/analysis-details')
- const data = await response.json()
- if (data.success) {
- setAnalysisDetails(data.data)
- // Also update recent trades from the same endpoint
- if (data.data.recentTrades) {
- setRecentTrades(data.data.recentTrades)
- }
- }
- } catch (error) {
- console.error('Failed to fetch analysis details:', error)
- }
- }
-
const fetchStatus = async () => {
try {
const response = await fetch('/api/automation/status')
@@ -70,54 +36,12 @@ export default function AutomationPage() {
}
}
- const fetchLearningInsights = async () => {
- try {
- const response = await fetch('/api/automation/learning-insights')
- const data = await response.json()
- if (data.success) {
- setLearningInsights(data.insights)
- }
- } catch (error) {
- console.error('Failed to fetch learning insights:', error)
- }
- }
-
- const fetchAiLearningStatus = async () => {
- try {
- const response = await fetch('/api/ai-learning-status')
- const data = await response.json()
- if (data.success) {
- setAiLearningStatus(data.data)
- }
- } catch (error) {
- console.error('Failed to fetch AI learning status:', error)
- }
- }
-
- const fetchRecentTrades = async () => {
- try {
- console.log('π Fetching recent trades...')
- // Get enhanced trade data from analysis-details instead of recent-trades
- const response = await fetch('/api/automation/analysis-details')
- const data = await response.json()
- console.log('π Trade data response:', data.success, data.data?.recentTrades?.length || 0)
- if (data.success && data.data.recentTrades) {
- console.log('β
Setting recent trades:', data.data.recentTrades.length)
- setRecentTrades(data.data.recentTrades)
- }
- } catch (error) {
- console.error('Failed to fetch recent trades:', error)
- }
- }
-
const handleStart = async () => {
setIsLoading(true)
try {
const response = await fetch('/api/automation/start', {
method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
+ headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(config)
})
const data = await response.json()
@@ -137,9 +61,7 @@ export default function AutomationPage() {
const handleStop = async () => {
setIsLoading(true)
try {
- const response = await fetch('/api/automation/stop', {
- method: 'POST'
- })
+ const response = await fetch('/api/automation/stop', { method: 'POST' })
const data = await response.json()
if (data.success) {
fetchStatus()
@@ -154,555 +76,210 @@ export default function AutomationPage() {
}
}
- const handlePause = async () => {
- setIsLoading(true)
- try {
- const response = await fetch('/api/automation/pause', {
- method: 'POST'
- })
- const data = await response.json()
- if (data.success) {
- fetchStatus()
- } else {
- alert('Failed to pause automation: ' + data.error)
- }
- } catch (error) {
- console.error('Failed to pause automation:', error)
- alert('Failed to pause automation')
- } finally {
- setIsLoading(false)
- }
- }
-
- const handleResume = async () => {
- setIsLoading(true)
- try {
- const response = await fetch('/api/automation/resume', {
- method: 'POST'
- })
- const data = await response.json()
- if (data.success) {
- fetchStatus()
- } else {
- alert('Failed to resume automation: ' + data.error)
- }
- } catch (error) {
- console.error('Failed to resume automation:', error)
- alert('Failed to resume automation')
- } finally {
- setIsLoading(false)
- }
- }
-
- const openTradeModal = async (tradeId) => {
- try {
- const response = await fetch(`/api/automation/trade-details/${tradeId}`)
- const data = await response.json()
- if (data.success) {
- setSelectedTrade(data.data)
- setTradeModalOpen(true)
- } else {
- alert('Failed to load trade details')
- }
- } catch (error) {
- console.error('Failed to load trade details:', error)
- alert('Failed to load trade details')
- }
- }
-
- const closeTradeModal = () => {
- setTradeModalOpen(false)
- setSelectedTrade(null)
- }
-
- // Use status API data instead of calculating from limited recent trades
- const getWinRate = () => {
- return status?.winRate || 0
- }
-
- // Use status API data for total P&L
- const getTotalPnL = () => {
- return status?.totalPnL || 0
- }
-
return (
-
+
+ {/* Header */}
-
Automation Mode
-
- AI-powered automated trading on 1H timeframe with learning capabilities
-
+
Automated Trading
+
Drift Protocol
{status?.isActive ? (
- <>
-
- {isLoading ? 'Pausing...' : 'Pause'}
-
-
- {isLoading ? 'Stopping...' : 'Stop'}
-
- >
+
+ {isLoading ? 'Stopping...' : 'STOP'}
+
) : (
- <>
- {status?.status === 'PAUSED' && (
-
- {isLoading ? 'Resuming...' : 'Resume'}
-
- )}
-
- {isLoading ? 'Starting...' : 'Start Automation'}
-
- >
- )}
-
-
-
-
- {/* Real-Time Price Monitor */}
-
-
-
-
- {/* Right Side Panel - Active Trades or Status */}
-
- {/* Active Trades Monitor */}
- {status && status.activeTrades && status.activeTrades.length > 0 ? (
-
-
Active Trades Monitor
-
- {status.activeTrades.map((trade, idx) => (
-
-
-
- {trade.side} {trade.amount} @ ${trade.entryPrice}
-
- 0 ? 'bg-green-600' : 'bg-red-600'
- } text-white`}>
- ${trade.unrealizedPnl}
-
-
-
- SL: ${trade.stopLoss} | TP: ${trade.takeProfit}
-
-
- ))}
-
-
- ) : (
- /* Trading Status Summary when no active trades */
-
-
Trading Status
-
-
- Mode:
-
- {config.mode}
-
-
-
- Status:
-
- {status?.isActive ? 'ACTIVE' : (status?.status || 'STOPPED')}
-
-
-
- Symbol:
- {config.symbol}
-
-
- Timeframe:
- {config.timeframe}
-
-
- Active Trades:
-
- {status?.activeTrades?.length || 0}
-
-
-
- Trading Amount:
- ${config.tradingAmount}
-
-
- Max Leverage:
- {config.maxLeverage}x
-
-
- Stop Loss:
- {config.stopLossPercent}%
-
-
- Take Profit:
- {config.takeProfitPercent}%
-
-
- Max Daily Trades:
- {config.maxDailyTrades}
-
-
- Risk Percentage:
- {config.riskPercentage}%
-
- {status && (
- <>
-
-
- Total Trades:
- {status.totalTrades || 0}
-
-
-
- Win Rate:
- = 50 ? 'text-green-400' : 'text-red-400'
- }`}>
- {(status.winRate || 0).toFixed(1)}%
-
-
-
- Total P&L:
- 0 ? 'text-green-400' :
- (status.totalPnL || 0) < 0 ? 'text-red-400' : 'text-gray-400'
- }`}>
- ${(status.totalPnL || 0).toFixed(2)}
-
-
- >
- )}
-
- {/* Quick Actions */}
-
-
Quick Actions:
-
- setConfigCollapsed(!configCollapsed)}
- className="px-3 py-1 bg-blue-600 text-white rounded text-xs hover:bg-blue-700 transition-colors"
- >
- {configCollapsed ? 'Show Config' : 'Hide Config'}
-
- window.location.reload()}
- className="px-3 py-1 bg-gray-600 text-white rounded text-xs hover:bg-gray-700 transition-colors"
- >
- Refresh
-
-
-
-
-
+
+ {isLoading ? 'Starting...' : 'START'}
+
)}
-
- {/* Configuration Panel - Collapsible */}
-
-
-
-
Configuration
- setConfigCollapsed(!configCollapsed)}
- className="px-3 py-1 bg-gray-700 text-white rounded hover:bg-gray-600 transition-colors"
- >
- {configCollapsed ? 'Show' : 'Hide'}
-
-
+ {/* Main Grid */}
+
+
+ {/* Configuration */}
+
+
+
+
Configuration
- {!configCollapsed && (
-
-
-
- Trading Mode
-
+
+
+ {/* Trading Mode */}
+
+
+ {/* Leverage */}
+
+ Leverage
setConfig({...config, mode: e.target.value})}
- className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
+ value={config.maxLeverage}
+ onChange={(e) => setConfig({...config, maxLeverage: parseFloat(e.target.value)})}
+ className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-purple-400"
disabled={status?.isActive}
>
- Simulation (Paper Trading)
- Live Trading (Jupiter DEX)
+ 1x - Spot
+ 2x
+ 3x
+ 5x
+ 10x
+ 20x
+ 50x
+ 100x
-
-
-
- Symbol
-
- setConfig({...config, symbol: e.target.value})}
- className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
- disabled={status?.isActive}
- >
- SOL/USD
- BTC/USD
- ETH/USD
-
-
-
-
-
- Timeframe
-
- setConfig({...config, timeframe: e.target.value})}
- className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
- disabled={status?.isActive}
- >
- 1 Hour (Recommended)
- 4 Hours
- 1 Day
-
-
-
-
-
-
-
- Trading Amount ($)
-
- setConfig({...config, tradingAmount: parseFloat(e.target.value)})}
- className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
- disabled={status?.isActive}
- min="10"
- step="10"
- />
-
-
-
-
- Max Leverage
-
- setConfig({...config, maxLeverage: parseFloat(e.target.value)})}
- className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
- disabled={status?.isActive}
- >
- 1x (Spot)
- 2x
- 3x
- 5x
-
-
-
-
-
- )}
-
- {/* AI Learning Status */}
- {aiLearningStatus && (
-
-
π§ AI Learning Status
+ {/* Parameters */}
+
-
- {/* Learning Phase */}
-
-
-
-
-
{aiLearningStatus.phaseDescription}
-
Phase: {aiLearningStatus.phase.replace('_', ' ')}
-
-
-
-
-
-
{aiLearningStatus.totalAnalyses}
-
Total Analyses
-
-
-
{aiLearningStatus.totalTrades}
-
Total Trades
-
-
-
-
- {/* Performance Metrics */}
-
-
-
-
{(aiLearningStatus.avgAccuracy * 100).toFixed(1)}%
-
Avg Accuracy
-
-
-
{(aiLearningStatus.winRate * 100).toFixed(1)}%
-
Win Rate
-
-
-
-
-
{aiLearningStatus.confidenceLevel.toFixed(1)}%
-
Confidence Level
-
-
+
+ Symbol
+ setConfig({...config, symbol: e.target.value})}
+ className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-blue-500"
+ disabled={status?.isActive}
+ >
+ SOL/USD
+ BTC/USD
+ ETH/USD
+ APT/USD
+ AVAX/USD
+ DOGE/USD
+
- {/* Strengths and Improvements */}
-
-
-
Strengths
-
- {aiLearningStatus.strengths.map((strength, idx) => (
- β {strength}
- ))}
-
-
-
-
Areas for Improvement
-
- {aiLearningStatus.improvements.map((improvement, idx) => (
- β’ {improvement}
- ))}
-
-
+
+ Position Size ($)
+ setConfig({...config, tradingAmount: parseFloat(e.target.value)})}
+ className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-blue-500"
+ disabled={status?.isActive}
+ min="10"
+ step="10"
+ />
- {/* Next Milestone */}
-
-
Next Milestone
-
{aiLearningStatus.nextMilestone}
+
+ Timeframe
+ setConfig({...config, timeframe: e.target.value})}
+ className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-blue-500"
+ disabled={status?.isActive}
+ >
+ 1 Minute
+ 5 Minutes
+ 15 Minutes
+ 1 Hour
+ 4 Hours
+ 1 Day
+
- {/* Recommendation */}
-
-
AI Recommendation
-
{aiLearningStatus.recommendation}
-
- )}
- {/* Learning Insights */}
- {learningInsights && (
-
-
AI Learning Insights
-
-
- Total Analyses:
- {learningInsights.totalAnalyses}
-
-
- Avg Accuracy:
- {(learningInsights.avgAccuracy * 100).toFixed(1)}%
-
-
- Best Timeframe:
- {learningInsights.bestTimeframe}
-
-
- Worst Timeframe:
- {learningInsights.worstTimeframe}
-
-
-
-
Recommendations
-
- {learningInsights.recommendations.map((rec, idx) => (
- β’ {rec}
- ))}
-
-
+ {/* Risk Management */}
+
- )}
+
+
-
- {/* Status and Performance */}
+
+ {/* Status */}
- {/* Status Panel */}
-
-
Status
+
+
+
Status
{status ? (
-
+
Status:
-
{status.isActive ? 'ACTIVE' : 'STOPPED'}
@@ -716,800 +293,52 @@ export default function AutomationPage() {
{status.mode}
+
+ Protocol:
+ DRIFT
+
Symbol:
- {status.symbol}
+ {config.symbol}
- Timeframe:
- {status.timeframe}
+ Leverage:
+ {config.maxLeverage}x
- Total Trades:
- {status.totalTrades}
+ Position Size:
+ ${config.tradingAmount}
-
- Win Rate:
- 60 ? 'text-green-400' :
- getWinRate() > 40 ? 'text-yellow-400' : 'text-red-400'
- }`}>
- {getWinRate()}%
-
-
-
- Total P&L:
- 0 ? 'text-green-400' :
- getTotalPnL() < 0 ? 'text-red-400' : 'text-gray-300'
- }`}>
- ${getTotalPnL()}
-
-
- {status.lastAnalysis && (
-
- Last Analysis:
-
- {new Date(status.lastAnalysis).toLocaleTimeString()}
-
-
- )}
- {status.errorCount > 0 && (
-
- Errors:
- {status.errorCount}
-
- )}
) : (
-
No active automation session
+
Loading...
)}
- {/* Recent Trades */}
-
-
-
- Active & Latest Trades
- (Top 4)
-
-
-
-
- Debug: {recentTrades.length} total trades
-
+
+
Performance
+
- {console.log('π― Rendering trades section, count:', recentTrades.length)}
- {recentTrades.length > 0 ? (
-
- {/* Sort trades to show active trades first, then latest completed trades */}
- {recentTrades
- .sort((a, b) => {
- // Active trades first
- if (a.isActive && !b.isActive) return -1
- if (!a.isActive && b.isActive) return 1
- // Then by creation date (most recent first)
- return new Date(b.createdAt) - new Date(a.createdAt)
- })
- .slice(0, 4)
- .map((trade, idx) => (
-
openTradeModal(trade.id)}
- >
- {/* Trade Header - Enhanced for active trades */}
-
-
- {trade.isActive && (
-
- )}
-
- {trade.side}
-
-
{trade.amount}
-
{trade.leverage}x
-
- {trade.isActive ? 'ACTIVE' : trade.result}
-
-
-
-
${trade.entryPrice?.toFixed(2) || trade.price?.toFixed(2) || '0.00'}
-
{trade.confidence || 0}% confidence
- {trade.isActive && (
-
- Current: ${trade.currentPrice?.toFixed(2) || '0.00'}
-
- )}
-
-
-
- {/* Enhanced Timing Information */}
-
-
-
- Entry Time:
- {new Date(trade.entryTime).toLocaleTimeString()}
-
-
- Exit Time:
-
- {trade.exitTime ? new Date(trade.exitTime).toLocaleTimeString() : 'Active'}
-
-
-
- Duration:
- {trade.durationText}
-
-
-
-
- {/* Trading Details */}
-
-
-
- Trading Mode:
-
- {trade.tradingMode || 'SIMULATION'}
-
-
-
- Trading Amount:
-
- {trade.realTradingAmount ? `$${trade.realTradingAmount}` : `$${trade.tradingAmount || '0'}`}
-
-
-
- Leverage:
- {trade.leverage || 1}x
-
-
- Position Size:
- {trade.amount?.toFixed(6) || '0.000000'} SOL
-
- {/* Entry Price - Always show for completed trades */}
-
- Entry Price:
- ${trade.entryPrice?.toFixed(2) || trade.price?.toFixed(2) || '0.00'}
-
- {/* Current/Exit Price with real-time updates for active trades */}
-
- {trade.isActive ? 'Current' : 'Exit'} Price:
-
- {trade.isActive ?
- `$${trade.currentPrice?.toFixed(2) || '0.00'}` :
- (trade.exitPrice ?
- `$${trade.exitPrice.toFixed(2)}` :
- Not recorded
- )
- }
-
-
- {/* Live Trade Transaction ID */}
- {trade.tradingMode === 'LIVE' && trade.driftTxId && (
-
- Transaction ID:
-
- {trade.driftTxId.slice(0, 8)}...{trade.driftTxId.slice(-8)}
-
-
- )}
- {/* Live Trade Fees */}
- {trade.tradingMode === 'LIVE' && trade.fees > 0 && (
-
- Fees Paid:
- ${trade.fees?.toFixed(4) || '0.0000'}
-
- )}
- {/* 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)}
-
-
- )}
-
-
-
- {/* P&L Display - Enhanced for active trades */}
-
-
-
- {trade.isActive ? 'Unrealized P&L:' : 'Realized P&L:'}
-
-
- 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') :
- (trade.realizedPnl || '0.00')
- }
-
- {trade.pnlPercent && (
- 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})
-
- )}
-
- {trade.isActive ? 'β‘ Live' : 'β Final'}
-
-
-
- {/* Additional active trade info */}
- {trade.isActive && trade.currentPrice && trade.entryPrice && (
-
-
- Price Change:
- 0 ? 'text-green-400' : 'text-red-400'
- }`}>
- ${((trade.currentPrice - trade.entryPrice) >= 0 ? '+' : '')}${(trade.currentPrice - trade.entryPrice).toFixed(2)}
- ({(((trade.currentPrice - trade.entryPrice) / trade.entryPrice) * 100).toFixed(2)}%)
-
-
-
- )}
- {/* 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 */}
-
-
- SL: ${trade.stopLoss} | TP: ${trade.takeProfit}
-
-
- π Click to view analysis
-
-
-
- ))}
-
- ) : (
-
No recent trades
- )}
+
-
- {/* Detailed AI Analysis Section */}
- {analysisDetails?.analysis && (
-
-
Latest AI Analysis
-
-
- {/* Main Decision */}
-
-
π― Trading Decision
-
-
- Decision:
-
- {analysisDetails.analysis.decision}
-
-
-
- Confidence:
- 80 ? 'text-green-400' :
- analysisDetails.analysis.confidence > 60 ? 'text-yellow-400' :
- 'text-red-400'
- }`}>
- {analysisDetails.analysis.confidence}%
-
-
-
- Market Sentiment:
-
- {analysisDetails.analysis.sentiment}
-
-
-
-
- Summary: {analysisDetails.analysis.summary}
-
-
-
-
-
- {/* Key Levels */}
-
-
π Key Levels
-
- {analysisDetails.analysis.keyLevels?.support?.length > 0 && (
-
-
Support Levels
- {analysisDetails.analysis.keyLevels.support.map((level, idx) => (
-
- S{idx + 1}:
- ${level.toFixed(2)}
-
- ))}
-
- )}
- {analysisDetails.analysis.keyLevels?.resistance?.length > 0 && (
-
-
Resistance Levels
- {analysisDetails.analysis.keyLevels.resistance.map((level, idx) => (
-
- R{idx + 1}:
- ${level.toFixed(2)}
-
- ))}
-
- )}
-
-
-
- {/* Technical Indicators */}
-
-
π Technical Indicators
-
- {analysisDetails.analysis.technicalIndicators && Object.entries(analysisDetails.analysis.technicalIndicators).map(([key, value]) => (
-
- {key.replace(/([A-Z])/g, ' $1').trim()}:
-
- {typeof value === 'number' ? value.toFixed(2) : value}
-
-
- ))}
-
-
-
-
- {/* AI Reasoning */}
- {analysisDetails.analysis.reasoning && (
-
-
π€ AI Reasoning
-
-
-
{analysisDetails.analysis.reasoning}
-
- {analysisDetails.analysis.executionPlan && (
-
-
Execution Plan:
-
{analysisDetails.analysis.executionPlan}
-
- )}
-
-
- )}
-
- {/* Risk Assessment */}
- {analysisDetails.analysis.riskAssessment && (
-
-
β οΈ Risk Assessment
-
-
-
{analysisDetails.analysis.riskAssessment}
-
- {analysisDetails.analysis.marketConditions && (
-
-
Market Conditions:
-
{analysisDetails.analysis.marketConditions}
-
- )}
-
-
- )}
-
- {/* Layout Analysis */}
- {analysisDetails.analysis.layoutAnalysis && (
-
-
π Multi-Layout Analysis
-
- {Object.entries(analysisDetails.analysis.layoutAnalysis).map(([layout, analysis]) => (
-
-
{layout} Layout:
-
{analysis}
-
- ))}
-
-
- )}
-
- {/* Performance Metrics */}
-
-
π Analysis Performance
-
-
-
- {analysisDetails.analysis.timestamp ?
- new Date(analysisDetails.analysis.timestamp).toLocaleTimeString() :
- 'N/A'
- }
-
-
Last Analysis
-
-
-
- {analysisDetails.analysis.processingTime ?
- `${analysisDetails.analysis.processingTime}ms` :
- 'N/A'
- }
-
-
Processing Time
-
-
-
- {analysisDetails.session?.totalTrades || 0}
-
-
Total Trades
-
-
-
- {analysisDetails.session?.errorCount || 0}
-
-
Errors
-
-
-
-
- )}
-
- {/* Multi-Timeframe Analysis Results */}
- {analysisDetails?.analysis?.multiTimeframeResults && analysisDetails.analysis.multiTimeframeResults.length > 0 && (
-
-
π Multi-Timeframe Analysis
-
-
- {analysisDetails.analysis.multiTimeframeResults.map((result, index) => (
-
-
-
- {result.analysisComplete ? (
- β
- ) : (
- β³
- )}
- {result.timeframe} Timeframe
-
-
- {result.analysisComplete ? 'Complete' : 'In Progress'}
-
-
-
-
-
- Decision:
-
- {result.decision}
-
-
-
-
- Confidence:
- 80 ? 'text-green-400' :
- result.confidence > 60 ? 'text-yellow-400' :
- 'text-red-400'
- }`}>
- {result.confidence}%
-
-
-
-
- Sentiment:
-
- {result.sentiment}
-
-
-
- {result.createdAt && (
-
-
- Analyzed: {new Date(result.createdAt).toLocaleString()}
-
-
- )}
-
-
- ))}
-
-
- {/* Multi-Timeframe Summary */}
-
-
π Cross-Timeframe Consensus
-
-
-
- {analysisDetails.analysis.multiTimeframeResults.length}
-
-
Timeframes Analyzed
-
-
-
- {analysisDetails.analysis.multiTimeframeResults.filter(r => r.analysisComplete).length}
-
-
Completed
-
-
-
- {Math.round(
- analysisDetails.analysis.multiTimeframeResults.reduce((sum, r) => sum + r.confidence, 0) /
- analysisDetails.analysis.multiTimeframeResults.length
- )}%
-
-
Avg Confidence
-
-
-
-
- )}
-
- {/* No Analysis Available */}
- {!analysisDetails?.analysis && status?.isActive && (
-
-
π€ AI Analysis
-
-
-
Waiting for first analysis...
-
The AI will analyze the market every hour
-
-
- )}
-
- {/* Trade Details Modal */}
- {tradeModalOpen && selectedTrade && (
-
-
- {/* Modal Header */}
-
-
-
Trade Analysis Details
-
- {selectedTrade.side} {selectedTrade.amount} @ ${selectedTrade.price?.toFixed(2) || '0.00'}
-
- 0 ? 'bg-green-600 text-white' : 'bg-red-600 text-white'
- }`}>
- {selectedTrade.status} {selectedTrade.profit && `(${selectedTrade.profit > 0 ? '+' : ''}$${selectedTrade.profit?.toFixed(2) || '0.00'})`}
-
-
-
- Γ
-
-
-
- {/* Modal Content */}
-
-
- {/* Trade Overview */}
-
-
-
Trade Info
-
-
- Entry Time:
- {new Date(selectedTrade.entryTime).toLocaleString()}
-
-
- Exit Time:
-
- {selectedTrade.exitTime ? new Date(selectedTrade.exitTime).toLocaleString() : 'Active'}
-
-
-
- Duration:
-
- {selectedTrade.exitTime ?
- `${Math.floor((new Date(selectedTrade.exitTime) - new Date(selectedTrade.entryTime)) / (1000 * 60))}m` :
- `${Math.floor((new Date() - new Date(selectedTrade.entryTime)) / (1000 * 60))}m (Active)`
- }
-
-
-
-
-
-
-
Position Details
-
-
- Trading Amount:
- ${selectedTrade.tradingAmount}
-
-
- Leverage:
- {selectedTrade.leverage}x
-
-
- Position Size:
- ${selectedTrade.positionSize}
-
-
-
-
-
-
Risk Management
-
-
- Stop Loss:
- ${selectedTrade.detailedAnalysis?.keyLevels?.stopLoss?.price || 'N/A'}
-
-
- Take Profit:
- ${selectedTrade.detailedAnalysis?.keyLevels?.takeProfit?.price || 'N/A'}
-
-
- Risk/Reward:
- {selectedTrade.detailedAnalysis?.riskManagement?.riskReward || 'N/A'}
-
-
-
-
-
- {/* Analysis Screenshots */}
-
-
π Analysis Screenshots
-
- {selectedTrade.screenshots && Object.entries(selectedTrade.screenshots).map(([key, screenshot]) => (
-
-
{screenshot.title}
-
-
- π· {screenshot.title}
-
- {screenshot.description}
-
-
-
{screenshot.description}
-
- ))}
-
-
-
- {/* AI Analysis Details */}
- {selectedTrade.detailedAnalysis && (
-
-
π€ AI Analysis
-
- {/* Decision Summary */}
-
-
-
Decision Summary
-
- {selectedTrade.detailedAnalysis.decision} ({selectedTrade.detailedAnalysis.confidence}%)
-
-
-
{selectedTrade.detailedAnalysis.aiReasoning}
-
-
- {/* Multi-timeframe Analysis */}
-
-
Multi-timeframe Analysis
-
- {selectedTrade.detailedAnalysis.timeframes && Object.entries(selectedTrade.detailedAnalysis.timeframes).map(([tf, data]) => (
-
-
- {tf}
-
- {data.decision}
-
-
-
- Confidence: {data.confidence}%
-
-
- {data.signals.slice(0, 2).map((signal, idx) => (
-
β’ {signal}
- ))}
-
-
- ))}
-
-
-
- {/* Technical Indicators */}
-
-
Technical Indicators
-
- {selectedTrade.detailedAnalysis.technicalIndicators && Object.entries(selectedTrade.detailedAnalysis.technicalIndicators).map(([indicator, data]) => (
-
-
{indicator}
-
{data.value}
-
{data.interpretation}
-
- ))}
-
-
-
- {/* Execution Plan */}
-
-
Execution Plan
-
- {selectedTrade.detailedAnalysis.executionPlan && Object.entries(selectedTrade.detailedAnalysis.executionPlan).map(([key, value]) => (
-
- {key}:
- {value}
-
- ))}
-
-
-
- )}
-
-
-
- )}
)
}
diff --git a/app/automation/page.js.backup b/app/automation/page.js.backup
index c11ab83..a418a6f 100644
--- a/app/automation/page.js.backup
+++ b/app/automation/page.js.backup
@@ -23,6 +23,7 @@ export default function AutomationPage() {
const [analysisDetails, setAnalysisDetails] = useState(null)
const [selectedTrade, setSelectedTrade] = useState(null)
const [tradeModalOpen, setTradeModalOpen] = useState(false)
+ const [configCollapsed, setConfigCollapsed] = useState(true)
useEffect(() => {
fetchStatus()
@@ -99,13 +100,10 @@ export default function AutomationPage() {
// Get enhanced trade data from analysis-details instead of recent-trades
const response = await fetch('/api/automation/analysis-details')
const data = await response.json()
- console.log('π API Response:', data)
- console.log('π Recent trades in response:', data.data?.recentTrades?.length || 0)
+ console.log('π Trade data response:', data.success, data.data?.recentTrades?.length || 0)
if (data.success && data.data.recentTrades) {
console.log('β
Setting recent trades:', data.data.recentTrades.length)
setRecentTrades(data.data.recentTrades)
- } else {
- console.log('β No recent trades found in API response')
}
} catch (error) {
console.error('Failed to fetch recent trades:', error)
@@ -217,22 +215,14 @@ export default function AutomationPage() {
setSelectedTrade(null)
}
- // Calculate win rate from recent trades
- const calculateWinRate = () => {
- if (!recentTrades.length) return 0
- const completedTrades = recentTrades.filter(t => t.status === 'COMPLETED')
- if (!completedTrades.length) return 0
- const winningTrades = completedTrades.filter(t => t.result === 'WIN')
- return (winningTrades.length / completedTrades.length * 100).toFixed(1)
+ // Use status API data instead of calculating from limited recent trades
+ const getWinRate = () => {
+ return status?.winRate || 0
}
- // Calculate total P&L from recent trades
- const calculateTotalPnL = () => {
- if (!recentTrades.length) return 0
- return recentTrades
- .filter(t => t.status === 'COMPLETED' && t.pnl)
- .reduce((total, trade) => total + parseFloat(trade.pnl), 0)
- .toFixed(2)
+ // Use status API data for total P&L
+ const getTotalPnL = () => {
+ return status?.totalPnL || 0
}
return (
@@ -285,16 +275,166 @@ export default function AutomationPage() {
- {/* Real-Time Price Monitor - Top Priority */}
-
-
- {/* Left Column: Configuration & Controls */}
+ {/* Real-Time Price Monitor */}
+
+
+
+
+ {/* Right Side Panel - Active Trades or Status */}
+
+ {/* Active Trades Monitor */}
+ {status && status.activeTrades && status.activeTrades.length > 0 ? (
+
+
Active Trades Monitor
+
+ {status.activeTrades.map((trade, idx) => (
+
+
+
+ {trade.side} {trade.amount} @ ${trade.entryPrice}
+
+ 0 ? 'bg-green-600' : 'bg-red-600'
+ } text-white`}>
+ ${trade.unrealizedPnl}
+
+
+
+ SL: ${trade.stopLoss} | TP: ${trade.takeProfit}
+
+
+ ))}
+
+
+ ) : (
+ /* Trading Status Summary when no active trades */
+
+
Trading Status
+
+
+ Mode:
+
+ {config.mode}
+
+
+
+ Status:
+
+ {status?.isActive ? 'ACTIVE' : (status?.status || 'STOPPED')}
+
+
+
+ Symbol:
+ {config.symbol}
+
+
+ Timeframe:
+ {config.timeframe}
+
+
+ Active Trades:
+
+ {status?.activeTrades?.length || 0}
+
+
+
+ Trading Amount:
+ ${config.tradingAmount}
+
+
+ Max Leverage:
+ {config.maxLeverage}x
+
+
+ Stop Loss:
+ {config.stopLossPercent}%
+
+
+ Take Profit:
+ {config.takeProfitPercent}%
+
+
+ Max Daily Trades:
+ {config.maxDailyTrades}
+
+
+ Risk Percentage:
+ {config.riskPercentage}%
+
+ {status && (
+ <>
+
+
+ Total Trades:
+ {status.totalTrades || 0}
+
+
+
+ Win Rate:
+ = 50 ? 'text-green-400' : 'text-red-400'
+ }`}>
+ {(status.winRate || 0).toFixed(1)}%
+
+
+
+ Total P&L:
+ 0 ? 'text-green-400' :
+ (status.totalPnL || 0) < 0 ? 'text-red-400' : 'text-gray-400'
+ }`}>
+ ${(status.totalPnL || 0).toFixed(2)}
+
+
+ >
+ )}
+
+ {/* Quick Actions */}
+
+
Quick Actions:
+
+ setConfigCollapsed(!configCollapsed)}
+ className="px-3 py-1 bg-blue-600 text-white rounded text-xs hover:bg-blue-700 transition-colors"
+ >
+ {configCollapsed ? 'Show Config' : 'Hide Config'}
+
+ window.location.reload()}
+ className="px-3 py-1 bg-gray-600 text-white rounded text-xs hover:bg-gray-700 transition-colors"
+ >
+ Refresh
+
+
+
+
+
+ )}
+
+
+
+
+ {/* Configuration Panel - Collapsible */}
- {/* Configuration Panel */}
-
βοΈ Configuration
+
+
Configuration
+ setConfigCollapsed(!configCollapsed)}
+ className="px-3 py-1 bg-gray-700 text-white rounded hover:bg-gray-600 transition-colors"
+ >
+ {configCollapsed ? 'Show' : 'Hide'}
+
+
+ {!configCollapsed && (
@@ -428,14 +568,136 @@ export default function AutomationPage() {
+ )}
+
+ {/* AI Learning Status */}
+ {aiLearningStatus && (
+
+
π§ AI Learning Status
+
+
+ {/* Learning Phase */}
+
+
+
+
+
{aiLearningStatus.phaseDescription}
+
Phase: {aiLearningStatus.phase.replace('_', ' ')}
+
+
+
+
+
+
{aiLearningStatus.totalAnalyses}
+
Total Analyses
+
+
+
{aiLearningStatus.totalTrades}
+
Total Trades
+
+
+
+
+ {/* Performance Metrics */}
+
+
+
+
{(aiLearningStatus.avgAccuracy * 100).toFixed(1)}%
+
Avg Accuracy
+
+
+
{(aiLearningStatus.winRate * 100).toFixed(1)}%
+
Win Rate
+
+
+
+
+
{aiLearningStatus.confidenceLevel.toFixed(1)}%
+
Confidence Level
+
+
+
+
+ {/* Strengths and Improvements */}
+
+
+
Strengths
+
+ {aiLearningStatus.strengths.map((strength, idx) => (
+ β {strength}
+ ))}
+
+
+
+
Areas for Improvement
+
+ {aiLearningStatus.improvements.map((improvement, idx) => (
+ β’ {improvement}
+ ))}
+
+
+
+
+ {/* Next Milestone */}
+
+
Next Milestone
+
{aiLearningStatus.nextMilestone}
+
+
+ {/* Recommendation */}
+
+
AI Recommendation
+
{aiLearningStatus.recommendation}
+
+
+ )}
+
+ {/* Learning Insights */}
+ {learningInsights && (
+
+
AI Learning Insights
+
+
+ Total Analyses:
+ {learningInsights.totalAnalyses}
+
+
+ Avg Accuracy:
+ {(learningInsights.avgAccuracy * 100).toFixed(1)}%
+
+
+ Best Timeframe:
+ {learningInsights.bestTimeframe}
+
+
+ Worst Timeframe:
+ {learningInsights.worstTimeframe}
+
+
+
+
Recommendations
+
+ {learningInsights.recommendations.map((rec, idx) => (
+ β’ {rec}
+ ))}
+
+
+
+
+ )}
- {/* Right Column: Status & Performance */}
+ {/* Status and Performance */}
{/* Status Panel */}
-
π Automation Status
+
Status
{status ? (
@@ -469,19 +731,19 @@ export default function AutomationPage() {
Win Rate:
60 ? 'text-green-400' :
- calculateWinRate() > 40 ? 'text-yellow-400' : 'text-red-400'
+ getWinRate() > 60 ? 'text-green-400' :
+ getWinRate() > 40 ? 'text-yellow-400' : 'text-red-400'
}`}>
- {calculateWinRate()}%
+ {getWinRate()}%
Total P&L:
0 ? 'text-green-400' :
- calculateTotalPnL() < 0 ? 'text-red-400' : 'text-gray-300'
+ getTotalPnL() > 0 ? 'text-green-400' :
+ getTotalPnL() < 0 ? 'text-red-400' : 'text-gray-300'
}`}>
- ${calculateTotalPnL()}
+ ${getTotalPnL()}
{status.lastAnalysis && (
@@ -506,45 +768,77 @@ export default function AutomationPage() {
{/* Recent Trades */}
-
Latest 4 Automated Trades (Debug: {recentTrades.length})
+
+
+ Active & Latest Trades
+ (Top 4)
+
+
+
+
+ Debug: {recentTrades.length} total trades
+
+
+
+ {console.log('π― Rendering trades section, count:', recentTrades.length)}
{recentTrades.length > 0 ? (
-
β
We have {recentTrades.length} trades to display
- {recentTrades.slice(0, 4).map((trade, idx) => (
+ {/* Sort trades to show active trades first, then latest completed trades */}
+ {recentTrades
+ .sort((a, b) => {
+ // Active trades first
+ if (a.isActive && !b.isActive) return -1
+ if (!a.isActive && b.isActive) return 1
+ // Then by creation date (most recent first)
+ return new Date(b.createdAt) - new Date(a.createdAt)
+ })
+ .slice(0, 4)
+ .map((trade, idx) => (
openTradeModal(trade.id)}
>
-
- Trade #{idx + 1}: {trade?.side || 'UNKNOWN'} - ${trade?.amount?.toFixed(4) || 'N/A'} - {trade?.status || 'UNKNOWN'}
-
-
- Entry: ${trade?.entryPrice?.toFixed(2) || trade?.price?.toFixed(2) || '0.00'} |
- P&L: ${trade?.pnl || trade?.realizedPnl || '0.00'} |
- Result: {trade?.result || 'UNKNOWN'}
-
-
- ))}
-
- ) : (
-
No recent trades
- )}
-
-
-
{trade?.amount?.toFixed(4) || 'N/A'}
-
{trade?.leverage || 1}x
+ {/* Trade Header - Enhanced for active trades */}
+
+
+ {trade.isActive && (
+
+ )}
+
+ {trade.side}
+
+
{trade.amount}
+
{trade.leverage}x
- {trade?.isActive ? 'ACTIVE' : (trade?.result || 'UNKNOWN')}
+ {trade.isActive ? 'ACTIVE' : trade.result}
-
${trade?.entryPrice?.toFixed(2) || trade?.price?.toFixed(2) || '0.00'}
-
{trade?.confidence || 0}% confidence
+
${trade.entryPrice?.toFixed(2) || trade.price?.toFixed(2) || '0.00'}
+
{trade.confidence || 0}% confidence
+ {trade.isActive && (
+
+ Current: ${trade.currentPrice?.toFixed(2) || '0.00'}
+
+ )}
@@ -553,17 +847,17 @@ export default function AutomationPage() {
Entry Time:
- {trade?.entryTime ? new Date(trade.entryTime).toLocaleTimeString() : 'N/A'}
+ {new Date(trade.entryTime).toLocaleTimeString()}
Exit Time:
- {trade?.exitTime ? new Date(trade.exitTime).toLocaleTimeString() : 'Active'}
+ {trade.exitTime ? new Date(trade.exitTime).toLocaleTimeString() : 'Active'}
Duration:
- {trade?.durationText || 'N/A'}
+ {trade.durationText}
@@ -571,93 +865,141 @@ export default function AutomationPage() {
{/* Trading Details */}
+
+ Trading Mode:
+
+ {trade.tradingMode || 'SIMULATION'}
+
+
Trading Amount:
- ${trade?.tradingAmount || 0}
+
+ {trade.realTradingAmount ? `$${trade.realTradingAmount}` : `$${trade.tradingAmount || '0'}`}
+
Leverage:
- {trade?.leverage || 1}x
+ {trade.leverage || 1}x
Position Size:
- ${trade?.positionSize || '0.00'}
+ {trade.amount?.toFixed(6) || '0.000000'} SOL
{/* Entry Price - Always show for completed trades */}
Entry Price:
- ${trade?.entryPrice?.toFixed(2) || trade?.price?.toFixed(2) || '0.00'}
+ ${trade.entryPrice?.toFixed(2) || trade.price?.toFixed(2) || '0.00'}
- {/* Exit Price or Current Price */}
+ {/* Current/Exit Price with real-time updates for active trades */}
- {trade?.isActive ? 'Current' : 'Exit'} Price:
-
- {trade?.isActive ?
- `$${trade?.currentPrice?.toFixed(2) || '0.00'}` :
- (trade?.exitPrice ?
+ {trade.isActive ? 'Current' : 'Exit'} Price:
+
+ {trade.isActive ?
+ `$${trade.currentPrice?.toFixed(2) || '0.00'}` :
+ (trade.exitPrice ?
`$${trade.exitPrice.toFixed(2)}` :
Not recorded
)
}
+ {/* Live Trade Transaction ID */}
+ {trade.tradingMode === 'LIVE' && trade.driftTxId && (
+
+ Transaction ID:
+
+ {trade.driftTxId.slice(0, 8)}...{trade.driftTxId.slice(-8)}
+
+
+ )}
+ {/* Live Trade Fees */}
+ {trade.tradingMode === 'LIVE' && trade.fees > 0 && (
+
+ Fees Paid:
+ ${trade.fees?.toFixed(4) || '0.0000'}
+
+ )}
{/* Price difference for completed trades */}
- {!trade?.isActive && trade?.exitPrice && trade?.entryPrice && (
+ {!trade.isActive && trade.exitPrice && trade.entryPrice && (
Price Difference:
0 ? 'text-green-400' :
- (trade?.exitPrice - trade?.entryPrice) < 0 ? 'text-red-400' :
+ (trade.exitPrice - trade.entryPrice) > 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) || '0.00'}
+ ${((trade.exitPrice - trade.entryPrice) >= 0 ? '+' : '')}${(trade.exitPrice - trade.entryPrice).toFixed(2)}
)}
- {/* P&L Display */}
-
+ {/* P&L Display - Enhanced for active trades */}
+
-
P&L:
+
+ {trade.isActive ? 'Unrealized P&L:' : 'Realized P&L:'}
+
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 && parseFloat(trade.unrealizedPnl) > 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') :
- (trade?.realizedPnl || trade?.pnl || '0.00')
+ ${trade.isActive ?
+ (trade.unrealizedPnl || '0.00') :
+ (trade.realizedPnl || '0.00')
}
- {trade?.pnlPercent && (
+ {trade.pnlPercent && (
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 && parseFloat(trade.unrealizedPnl) > 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 || '0%'})
+ ({trade.pnlPercent})
)}
-
- {trade?.isActive ? '(Unrealized)' : '(Realized)'}
+
+ {trade.isActive ? 'β‘ Live' : 'β Final'}
+ {/* Additional active trade info */}
+ {trade.isActive && trade.currentPrice && trade.entryPrice && (
+
+
+ Price Change:
+ 0 ? 'text-green-400' : 'text-red-400'
+ }`}>
+ ${((trade.currentPrice - trade.entryPrice) >= 0 ? '+' : '')}${(trade.currentPrice - trade.entryPrice).toFixed(2)}
+ ({(((trade.currentPrice - trade.entryPrice) / trade.entryPrice) * 100).toFixed(2)}%)
+
+
+
+ )}
{/* Debug info for missing data */}
- {trade?.result === 'UNKNOWN' && (
+ {trade.result === 'UNKNOWN' && (
- β οΈ Missing exit data: {!trade?.exitPrice ? 'Exit Price ' : ''}{trade?.calculatedProfit === null ? 'Profit' : ''}
+ β οΈ Missing exit data: {!trade.exitPrice ? 'Exit Price ' : ''}{trade.calculatedProfit === null ? 'Profit' : ''}
)}
{/* Warning for old incorrect trades */}
- {trade?.isOldWrongTrade && (
+ {trade.isOldWrongTrade && (
- π§ Old trade with incorrect price data (stored: ${trade?.originalStoredPrice?.toFixed(2)}, should be ~$189)
+ π§ Old trade with incorrect price data (stored: ${trade.originalStoredPrice?.toFixed(2)}, should be ~$189)
)}
@@ -665,46 +1007,19 @@ export default function AutomationPage() {
{/* Click hint */}
- SL: ${trade?.stopLoss || 'N/A'} | TP: ${trade?.takeProfit || 'N/A'}
+ SL: ${trade.stopLoss} | TP: ${trade.takeProfit}
π Click to view analysis
-
-
- {/* Learning Insights */}
- {learningInsights && (
-
-
π‘ Learning Insights
-
-
- Total Analyses:
- {learningInsights.totalAnalyses}
-
-
- Avg Accuracy:
- {(learningInsights.avgAccuracy * 100).toFixed(1)}%
-
-
- Best Timeframe:
- {learningInsights.bestTimeframe}
-
-
- Worst Timeframe:
- {learningInsights.worstTimeframe}
-
-
-
-
Recommendations
-
- {learningInsights.recommendations.map((rec, idx) => (
- β’ {rec}
- ))}
-
-
+
+
+ ))}
-
- )}
+ ) : (
+
No recent trades
+ )}
+
diff --git a/app/automation/page.js.full-backup b/app/automation/page.js.full-backup
new file mode 100644
index 0000000..a418a6f
--- /dev/null
+++ b/app/automation/page.js.full-backup
@@ -0,0 +1,1515 @@
+'use client'
+import React, { useState, useEffect } from 'react'
+import RealTimePriceMonitor from '../../components/RealTimePriceMonitor'
+
+export default function AutomationPage() {
+ const [config, setConfig] = useState({
+ mode: 'SIMULATION',
+ symbol: 'SOLUSD',
+ timeframe: '1h',
+ tradingAmount: 100,
+ maxLeverage: 3,
+ stopLossPercent: 2,
+ takeProfitPercent: 6,
+ maxDailyTrades: 5,
+ riskPercentage: 2
+ })
+
+ const [status, setStatus] = useState(null)
+ const [isLoading, setIsLoading] = useState(false)
+ const [learningInsights, setLearningInsights] = useState(null)
+ const [aiLearningStatus, setAiLearningStatus] = useState(null)
+ const [recentTrades, setRecentTrades] = useState([])
+ const [analysisDetails, setAnalysisDetails] = useState(null)
+ const [selectedTrade, setSelectedTrade] = useState(null)
+ const [tradeModalOpen, setTradeModalOpen] = useState(false)
+ const [configCollapsed, setConfigCollapsed] = useState(true)
+
+ useEffect(() => {
+ fetchStatus()
+ fetchLearningInsights()
+ fetchAiLearningStatus()
+ fetchRecentTrades()
+ fetchAnalysisDetails()
+
+ // Auto-refresh every 30 seconds
+ const interval = setInterval(() => {
+ fetchStatus()
+ fetchAnalysisDetails()
+ fetchAiLearningStatus()
+ }, 30000)
+
+ return () => clearInterval(interval)
+ }, [])
+
+ const fetchAnalysisDetails = async () => {
+ try {
+ const response = await fetch('/api/automation/analysis-details')
+ const data = await response.json()
+ if (data.success) {
+ setAnalysisDetails(data.data)
+ // Also update recent trades from the same endpoint
+ if (data.data.recentTrades) {
+ setRecentTrades(data.data.recentTrades)
+ }
+ }
+ } catch (error) {
+ console.error('Failed to fetch analysis details:', error)
+ }
+ }
+
+ const fetchStatus = async () => {
+ try {
+ const response = await fetch('/api/automation/status')
+ const data = await response.json()
+ if (data.success) {
+ setStatus(data.status)
+ }
+ } catch (error) {
+ console.error('Failed to fetch status:', error)
+ }
+ }
+
+ const fetchLearningInsights = async () => {
+ try {
+ const response = await fetch('/api/automation/learning-insights')
+ const data = await response.json()
+ if (data.success) {
+ setLearningInsights(data.insights)
+ }
+ } catch (error) {
+ console.error('Failed to fetch learning insights:', error)
+ }
+ }
+
+ const fetchAiLearningStatus = async () => {
+ try {
+ const response = await fetch('/api/ai-learning-status')
+ const data = await response.json()
+ if (data.success) {
+ setAiLearningStatus(data.data)
+ }
+ } catch (error) {
+ console.error('Failed to fetch AI learning status:', error)
+ }
+ }
+
+ const fetchRecentTrades = async () => {
+ try {
+ console.log('π Fetching recent trades...')
+ // Get enhanced trade data from analysis-details instead of recent-trades
+ const response = await fetch('/api/automation/analysis-details')
+ const data = await response.json()
+ console.log('π Trade data response:', data.success, data.data?.recentTrades?.length || 0)
+ if (data.success && data.data.recentTrades) {
+ console.log('β
Setting recent trades:', data.data.recentTrades.length)
+ setRecentTrades(data.data.recentTrades)
+ }
+ } catch (error) {
+ console.error('Failed to fetch recent trades:', error)
+ }
+ }
+
+ const handleStart = async () => {
+ setIsLoading(true)
+ try {
+ const response = await fetch('/api/automation/start', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify(config)
+ })
+ const data = await response.json()
+ if (data.success) {
+ fetchStatus()
+ } else {
+ alert('Failed to start automation: ' + data.error)
+ }
+ } catch (error) {
+ console.error('Failed to start automation:', error)
+ alert('Failed to start automation')
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ const handleStop = async () => {
+ setIsLoading(true)
+ try {
+ const response = await fetch('/api/automation/stop', {
+ method: 'POST'
+ })
+ const data = await response.json()
+ if (data.success) {
+ fetchStatus()
+ } else {
+ alert('Failed to stop automation: ' + data.error)
+ }
+ } catch (error) {
+ console.error('Failed to stop automation:', error)
+ alert('Failed to stop automation')
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ const handlePause = async () => {
+ setIsLoading(true)
+ try {
+ const response = await fetch('/api/automation/pause', {
+ method: 'POST'
+ })
+ const data = await response.json()
+ if (data.success) {
+ fetchStatus()
+ } else {
+ alert('Failed to pause automation: ' + data.error)
+ }
+ } catch (error) {
+ console.error('Failed to pause automation:', error)
+ alert('Failed to pause automation')
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ const handleResume = async () => {
+ setIsLoading(true)
+ try {
+ const response = await fetch('/api/automation/resume', {
+ method: 'POST'
+ })
+ const data = await response.json()
+ if (data.success) {
+ fetchStatus()
+ } else {
+ alert('Failed to resume automation: ' + data.error)
+ }
+ } catch (error) {
+ console.error('Failed to resume automation:', error)
+ alert('Failed to resume automation')
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ const openTradeModal = async (tradeId) => {
+ try {
+ const response = await fetch(`/api/automation/trade-details/${tradeId}`)
+ const data = await response.json()
+ if (data.success) {
+ setSelectedTrade(data.data)
+ setTradeModalOpen(true)
+ } else {
+ alert('Failed to load trade details')
+ }
+ } catch (error) {
+ console.error('Failed to load trade details:', error)
+ alert('Failed to load trade details')
+ }
+ }
+
+ const closeTradeModal = () => {
+ setTradeModalOpen(false)
+ setSelectedTrade(null)
+ }
+
+ // Use status API data instead of calculating from limited recent trades
+ const getWinRate = () => {
+ return status?.winRate || 0
+ }
+
+ // Use status API data for total P&L
+ const getTotalPnL = () => {
+ return status?.totalPnL || 0
+ }
+
+ return (
+
+
+
+
Automation Mode
+
+ AI-powered automated trading on 1H timeframe with learning capabilities
+
+
+
+ {status?.isActive ? (
+ <>
+
+ {isLoading ? 'Pausing...' : 'Pause'}
+
+
+ {isLoading ? 'Stopping...' : 'Stop'}
+
+ >
+ ) : (
+ <>
+ {status?.status === 'PAUSED' && (
+
+ {isLoading ? 'Resuming...' : 'Resume'}
+
+ )}
+
+ {isLoading ? 'Starting...' : 'Start Automation'}
+
+ >
+ )}
+
+
+
+
+ {/* Real-Time Price Monitor */}
+
+
+
+
+ {/* Right Side Panel - Active Trades or Status */}
+
+ {/* Active Trades Monitor */}
+ {status && status.activeTrades && status.activeTrades.length > 0 ? (
+
+
Active Trades Monitor
+
+ {status.activeTrades.map((trade, idx) => (
+
+
+
+ {trade.side} {trade.amount} @ ${trade.entryPrice}
+
+ 0 ? 'bg-green-600' : 'bg-red-600'
+ } text-white`}>
+ ${trade.unrealizedPnl}
+
+
+
+ SL: ${trade.stopLoss} | TP: ${trade.takeProfit}
+
+
+ ))}
+
+
+ ) : (
+ /* Trading Status Summary when no active trades */
+
+
Trading Status
+
+
+ Mode:
+
+ {config.mode}
+
+
+
+ Status:
+
+ {status?.isActive ? 'ACTIVE' : (status?.status || 'STOPPED')}
+
+
+
+ Symbol:
+ {config.symbol}
+
+
+ Timeframe:
+ {config.timeframe}
+
+
+ Active Trades:
+
+ {status?.activeTrades?.length || 0}
+
+
+
+ Trading Amount:
+ ${config.tradingAmount}
+
+
+ Max Leverage:
+ {config.maxLeverage}x
+
+
+ Stop Loss:
+ {config.stopLossPercent}%
+
+
+ Take Profit:
+ {config.takeProfitPercent}%
+
+
+ Max Daily Trades:
+ {config.maxDailyTrades}
+
+
+ Risk Percentage:
+ {config.riskPercentage}%
+
+ {status && (
+ <>
+
+
+ Total Trades:
+ {status.totalTrades || 0}
+
+
+
+ Win Rate:
+ = 50 ? 'text-green-400' : 'text-red-400'
+ }`}>
+ {(status.winRate || 0).toFixed(1)}%
+
+
+
+ Total P&L:
+ 0 ? 'text-green-400' :
+ (status.totalPnL || 0) < 0 ? 'text-red-400' : 'text-gray-400'
+ }`}>
+ ${(status.totalPnL || 0).toFixed(2)}
+
+
+ >
+ )}
+
+ {/* Quick Actions */}
+
+
Quick Actions:
+
+ setConfigCollapsed(!configCollapsed)}
+ className="px-3 py-1 bg-blue-600 text-white rounded text-xs hover:bg-blue-700 transition-colors"
+ >
+ {configCollapsed ? 'Show Config' : 'Hide Config'}
+
+ window.location.reload()}
+ className="px-3 py-1 bg-gray-600 text-white rounded text-xs hover:bg-gray-700 transition-colors"
+ >
+ Refresh
+
+
+
+
+
+ )}
+
+
+
+
+ {/* Configuration Panel - Collapsible */}
+
+
+
+
Configuration
+ setConfigCollapsed(!configCollapsed)}
+ className="px-3 py-1 bg-gray-700 text-white rounded hover:bg-gray-600 transition-colors"
+ >
+ {configCollapsed ? 'Show' : 'Hide'}
+
+
+
+ {!configCollapsed && (
+
+
+
+ Trading Mode
+
+ setConfig({...config, mode: e.target.value})}
+ className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
+ disabled={status?.isActive}
+ >
+ Simulation (Paper Trading)
+ Live Trading (Jupiter DEX)
+
+
+
+
+
+
+ Symbol
+
+ setConfig({...config, symbol: e.target.value})}
+ className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
+ disabled={status?.isActive}
+ >
+ SOL/USD
+ BTC/USD
+ ETH/USD
+
+
+
+
+
+ Timeframe
+
+ setConfig({...config, timeframe: e.target.value})}
+ className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
+ disabled={status?.isActive}
+ >
+ 1 Hour (Recommended)
+ 4 Hours
+ 1 Day
+
+
+
+
+
+
+
+ Trading Amount ($)
+
+ setConfig({...config, tradingAmount: parseFloat(e.target.value)})}
+ className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
+ disabled={status?.isActive}
+ min="10"
+ step="10"
+ />
+
+
+
+
+ Max Leverage
+
+ setConfig({...config, maxLeverage: parseFloat(e.target.value)})}
+ className="w-full p-3 bg-gray-800 border border-gray-700 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
+ disabled={status?.isActive}
+ >
+ 1x (Spot)
+ 2x
+ 3x
+ 5x
+
+
+
+
+
+
+ )}
+
+
+ {/* AI Learning Status */}
+ {aiLearningStatus && (
+
+
π§ AI Learning Status
+
+
+ {/* Learning Phase */}
+
+
+
+
+
{aiLearningStatus.phaseDescription}
+
Phase: {aiLearningStatus.phase.replace('_', ' ')}
+
+
+
+
+
+
{aiLearningStatus.totalAnalyses}
+
Total Analyses
+
+
+
{aiLearningStatus.totalTrades}
+
Total Trades
+
+
+
+
+ {/* Performance Metrics */}
+
+
+
+
{(aiLearningStatus.avgAccuracy * 100).toFixed(1)}%
+
Avg Accuracy
+
+
+
{(aiLearningStatus.winRate * 100).toFixed(1)}%
+
Win Rate
+
+
+
+
+
{aiLearningStatus.confidenceLevel.toFixed(1)}%
+
Confidence Level
+
+
+
+
+ {/* Strengths and Improvements */}
+
+
+
Strengths
+
+ {aiLearningStatus.strengths.map((strength, idx) => (
+ β {strength}
+ ))}
+
+
+
+
Areas for Improvement
+
+ {aiLearningStatus.improvements.map((improvement, idx) => (
+ β’ {improvement}
+ ))}
+
+
+
+
+ {/* Next Milestone */}
+
+
Next Milestone
+
{aiLearningStatus.nextMilestone}
+
+
+ {/* Recommendation */}
+
+
AI Recommendation
+
{aiLearningStatus.recommendation}
+
+
+ )}
+
+ {/* Learning Insights */}
+ {learningInsights && (
+
+
AI Learning Insights
+
+
+ Total Analyses:
+ {learningInsights.totalAnalyses}
+
+
+ Avg Accuracy:
+ {(learningInsights.avgAccuracy * 100).toFixed(1)}%
+
+
+ Best Timeframe:
+ {learningInsights.bestTimeframe}
+
+
+ Worst Timeframe:
+ {learningInsights.worstTimeframe}
+
+
+
+
Recommendations
+
+ {learningInsights.recommendations.map((rec, idx) => (
+ β’ {rec}
+ ))}
+
+
+
+
+ )}
+
+
+ {/* Status and Performance */}
+
+ {/* Status Panel */}
+
+
Status
+ {status ? (
+
+
+ Status:
+
+ {status.isActive ? 'ACTIVE' : 'STOPPED'}
+
+
+
+ Mode:
+
+ {status.mode}
+
+
+
+ Symbol:
+ {status.symbol}
+
+
+ Timeframe:
+ {status.timeframe}
+
+
+ Total Trades:
+ {status.totalTrades}
+
+
+ Win Rate:
+ 60 ? 'text-green-400' :
+ getWinRate() > 40 ? 'text-yellow-400' : 'text-red-400'
+ }`}>
+ {getWinRate()}%
+
+
+
+ Total P&L:
+ 0 ? 'text-green-400' :
+ getTotalPnL() < 0 ? 'text-red-400' : 'text-gray-300'
+ }`}>
+ ${getTotalPnL()}
+
+
+ {status.lastAnalysis && (
+
+ Last Analysis:
+
+ {new Date(status.lastAnalysis).toLocaleTimeString()}
+
+
+ )}
+ {status.errorCount > 0 && (
+
+ Errors:
+ {status.errorCount}
+
+ )}
+
+ ) : (
+
No active automation session
+ )}
+
+
+ {/* Recent Trades */}
+
+
+
+ Active & Latest Trades
+ (Top 4)
+
+
+
+
+ Debug: {recentTrades.length} total trades
+
+
+
+ {console.log('π― Rendering trades section, count:', recentTrades.length)}
+ {recentTrades.length > 0 ? (
+
+ {/* Sort trades to show active trades first, then latest completed trades */}
+ {recentTrades
+ .sort((a, b) => {
+ // Active trades first
+ if (a.isActive && !b.isActive) return -1
+ if (!a.isActive && b.isActive) return 1
+ // Then by creation date (most recent first)
+ return new Date(b.createdAt) - new Date(a.createdAt)
+ })
+ .slice(0, 4)
+ .map((trade, idx) => (
+
openTradeModal(trade.id)}
+ >
+ {/* Trade Header - Enhanced for active trades */}
+
+
+ {trade.isActive && (
+
+ )}
+
+ {trade.side}
+
+
{trade.amount}
+
{trade.leverage}x
+
+ {trade.isActive ? 'ACTIVE' : trade.result}
+
+
+
+
${trade.entryPrice?.toFixed(2) || trade.price?.toFixed(2) || '0.00'}
+
{trade.confidence || 0}% confidence
+ {trade.isActive && (
+
+ Current: ${trade.currentPrice?.toFixed(2) || '0.00'}
+
+ )}
+
+
+
+ {/* Enhanced Timing Information */}
+
+
+
+ Entry Time:
+ {new Date(trade.entryTime).toLocaleTimeString()}
+
+
+ Exit Time:
+
+ {trade.exitTime ? new Date(trade.exitTime).toLocaleTimeString() : 'Active'}
+
+
+
+ Duration:
+ {trade.durationText}
+
+
+
+
+ {/* Trading Details */}
+
+
+
+ Trading Mode:
+
+ {trade.tradingMode || 'SIMULATION'}
+
+
+
+ Trading Amount:
+
+ {trade.realTradingAmount ? `$${trade.realTradingAmount}` : `$${trade.tradingAmount || '0'}`}
+
+
+
+ Leverage:
+ {trade.leverage || 1}x
+
+
+ Position Size:
+ {trade.amount?.toFixed(6) || '0.000000'} SOL
+
+ {/* Entry Price - Always show for completed trades */}
+
+ Entry Price:
+ ${trade.entryPrice?.toFixed(2) || trade.price?.toFixed(2) || '0.00'}
+
+ {/* Current/Exit Price with real-time updates for active trades */}
+
+ {trade.isActive ? 'Current' : 'Exit'} Price:
+
+ {trade.isActive ?
+ `$${trade.currentPrice?.toFixed(2) || '0.00'}` :
+ (trade.exitPrice ?
+ `$${trade.exitPrice.toFixed(2)}` :
+ Not recorded
+ )
+ }
+
+
+ {/* Live Trade Transaction ID */}
+ {trade.tradingMode === 'LIVE' && trade.driftTxId && (
+
+ Transaction ID:
+
+ {trade.driftTxId.slice(0, 8)}...{trade.driftTxId.slice(-8)}
+
+
+ )}
+ {/* Live Trade Fees */}
+ {trade.tradingMode === 'LIVE' && trade.fees > 0 && (
+
+ Fees Paid:
+ ${trade.fees?.toFixed(4) || '0.0000'}
+
+ )}
+ {/* 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)}
+
+
+ )}
+
+
+
+ {/* P&L Display - Enhanced for active trades */}
+
+
+
+ {trade.isActive ? 'Unrealized P&L:' : 'Realized P&L:'}
+
+
+ 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') :
+ (trade.realizedPnl || '0.00')
+ }
+
+ {trade.pnlPercent && (
+ 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})
+
+ )}
+
+ {trade.isActive ? 'β‘ Live' : 'β Final'}
+
+
+
+ {/* Additional active trade info */}
+ {trade.isActive && trade.currentPrice && trade.entryPrice && (
+
+
+ Price Change:
+ 0 ? 'text-green-400' : 'text-red-400'
+ }`}>
+ ${((trade.currentPrice - trade.entryPrice) >= 0 ? '+' : '')}${(trade.currentPrice - trade.entryPrice).toFixed(2)}
+ ({(((trade.currentPrice - trade.entryPrice) / trade.entryPrice) * 100).toFixed(2)}%)
+
+
+
+ )}
+ {/* 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 */}
+
+
+ SL: ${trade.stopLoss} | TP: ${trade.takeProfit}
+
+
+ π Click to view analysis
+
+
+
+ ))}
+
+ ) : (
+
No recent trades
+ )}
+
+
+
+
+ {/* Detailed AI Analysis Section */}
+ {analysisDetails?.analysis && (
+
+
Latest AI Analysis
+
+
+ {/* Main Decision */}
+
+
π― Trading Decision
+
+
+ Decision:
+
+ {analysisDetails.analysis.decision}
+
+
+
+ Confidence:
+ 80 ? 'text-green-400' :
+ analysisDetails.analysis.confidence > 60 ? 'text-yellow-400' :
+ 'text-red-400'
+ }`}>
+ {analysisDetails.analysis.confidence}%
+
+
+
+ Market Sentiment:
+
+ {analysisDetails.analysis.sentiment}
+
+
+
+
+ Summary: {analysisDetails.analysis.summary}
+
+
+
+
+
+ {/* Key Levels */}
+
+
π Key Levels
+
+ {analysisDetails.analysis.keyLevels?.support?.length > 0 && (
+
+
Support Levels
+ {analysisDetails.analysis.keyLevels.support.map((level, idx) => (
+
+ S{idx + 1}:
+ ${level.toFixed(2)}
+
+ ))}
+
+ )}
+ {analysisDetails.analysis.keyLevels?.resistance?.length > 0 && (
+
+
Resistance Levels
+ {analysisDetails.analysis.keyLevels.resistance.map((level, idx) => (
+
+ R{idx + 1}:
+ ${level.toFixed(2)}
+
+ ))}
+
+ )}
+
+
+
+ {/* Technical Indicators */}
+
+
π Technical Indicators
+
+ {analysisDetails.analysis.technicalIndicators && Object.entries(analysisDetails.analysis.technicalIndicators).map(([key, value]) => (
+
+ {key.replace(/([A-Z])/g, ' $1').trim()}:
+
+ {typeof value === 'number' ? value.toFixed(2) : value}
+
+
+ ))}
+
+
+
+
+ {/* AI Reasoning */}
+ {analysisDetails.analysis.reasoning && (
+
+
π€ AI Reasoning
+
+
+
{analysisDetails.analysis.reasoning}
+
+ {analysisDetails.analysis.executionPlan && (
+
+
Execution Plan:
+
{analysisDetails.analysis.executionPlan}
+
+ )}
+
+
+ )}
+
+ {/* Risk Assessment */}
+ {analysisDetails.analysis.riskAssessment && (
+
+
β οΈ Risk Assessment
+
+
+
{analysisDetails.analysis.riskAssessment}
+
+ {analysisDetails.analysis.marketConditions && (
+
+
Market Conditions:
+
{analysisDetails.analysis.marketConditions}
+
+ )}
+
+
+ )}
+
+ {/* Layout Analysis */}
+ {analysisDetails.analysis.layoutAnalysis && (
+
+
π Multi-Layout Analysis
+
+ {Object.entries(analysisDetails.analysis.layoutAnalysis).map(([layout, analysis]) => (
+
+
{layout} Layout:
+
{analysis}
+
+ ))}
+
+
+ )}
+
+ {/* Performance Metrics */}
+
+
π Analysis Performance
+
+
+
+ {analysisDetails.analysis.timestamp ?
+ new Date(analysisDetails.analysis.timestamp).toLocaleTimeString() :
+ 'N/A'
+ }
+
+
Last Analysis
+
+
+
+ {analysisDetails.analysis.processingTime ?
+ `${analysisDetails.analysis.processingTime}ms` :
+ 'N/A'
+ }
+
+
Processing Time
+
+
+
+ {analysisDetails.session?.totalTrades || 0}
+
+
Total Trades
+
+
+
+ {analysisDetails.session?.errorCount || 0}
+
+
Errors
+
+
+
+
+ )}
+
+ {/* Multi-Timeframe Analysis Results */}
+ {analysisDetails?.analysis?.multiTimeframeResults && analysisDetails.analysis.multiTimeframeResults.length > 0 && (
+
+
π Multi-Timeframe Analysis
+
+
+ {analysisDetails.analysis.multiTimeframeResults.map((result, index) => (
+
+
+
+ {result.analysisComplete ? (
+ β
+ ) : (
+ β³
+ )}
+ {result.timeframe} Timeframe
+
+
+ {result.analysisComplete ? 'Complete' : 'In Progress'}
+
+
+
+
+
+ Decision:
+
+ {result.decision}
+
+
+
+
+ Confidence:
+ 80 ? 'text-green-400' :
+ result.confidence > 60 ? 'text-yellow-400' :
+ 'text-red-400'
+ }`}>
+ {result.confidence}%
+
+
+
+
+ Sentiment:
+
+ {result.sentiment}
+
+
+
+ {result.createdAt && (
+
+
+ Analyzed: {new Date(result.createdAt).toLocaleString()}
+
+
+ )}
+
+
+ ))}
+
+
+ {/* Multi-Timeframe Summary */}
+
+
π Cross-Timeframe Consensus
+
+
+
+ {analysisDetails.analysis.multiTimeframeResults.length}
+
+
Timeframes Analyzed
+
+
+
+ {analysisDetails.analysis.multiTimeframeResults.filter(r => r.analysisComplete).length}
+
+
Completed
+
+
+
+ {Math.round(
+ analysisDetails.analysis.multiTimeframeResults.reduce((sum, r) => sum + r.confidence, 0) /
+ analysisDetails.analysis.multiTimeframeResults.length
+ )}%
+
+
Avg Confidence
+
+
+
+
+ )}
+
+ {/* No Analysis Available */}
+ {!analysisDetails?.analysis && status?.isActive && (
+
+
π€ AI Analysis
+
+
+
Waiting for first analysis...
+
The AI will analyze the market every hour
+
+
+ )}
+
+ {/* Trade Details Modal */}
+ {tradeModalOpen && selectedTrade && (
+
+
+ {/* Modal Header */}
+
+
+
Trade Analysis Details
+
+ {selectedTrade.side} {selectedTrade.amount} @ ${selectedTrade.price?.toFixed(2) || '0.00'}
+
+ 0 ? 'bg-green-600 text-white' : 'bg-red-600 text-white'
+ }`}>
+ {selectedTrade.status} {selectedTrade.profit && `(${selectedTrade.profit > 0 ? '+' : ''}$${selectedTrade.profit?.toFixed(2) || '0.00'})`}
+
+
+
+ Γ
+
+
+
+ {/* Modal Content */}
+
+
+ {/* Trade Overview */}
+
+
+
Trade Info
+
+
+ Entry Time:
+ {new Date(selectedTrade.entryTime).toLocaleString()}
+
+
+ Exit Time:
+
+ {selectedTrade.exitTime ? new Date(selectedTrade.exitTime).toLocaleString() : 'Active'}
+
+
+
+ Duration:
+
+ {selectedTrade.exitTime ?
+ `${Math.floor((new Date(selectedTrade.exitTime) - new Date(selectedTrade.entryTime)) / (1000 * 60))}m` :
+ `${Math.floor((new Date() - new Date(selectedTrade.entryTime)) / (1000 * 60))}m (Active)`
+ }
+
+
+
+
+
+
+
Position Details
+
+
+ Trading Amount:
+ ${selectedTrade.tradingAmount}
+
+
+ Leverage:
+ {selectedTrade.leverage}x
+
+
+ Position Size:
+ ${selectedTrade.positionSize}
+
+
+
+
+
+
Risk Management
+
+
+ Stop Loss:
+ ${selectedTrade.detailedAnalysis?.keyLevels?.stopLoss?.price || 'N/A'}
+
+
+ Take Profit:
+ ${selectedTrade.detailedAnalysis?.keyLevels?.takeProfit?.price || 'N/A'}
+
+
+ Risk/Reward:
+ {selectedTrade.detailedAnalysis?.riskManagement?.riskReward || 'N/A'}
+
+
+
+
+
+ {/* Analysis Screenshots */}
+
+
π Analysis Screenshots
+
+ {selectedTrade.screenshots && Object.entries(selectedTrade.screenshots).map(([key, screenshot]) => (
+
+
{screenshot.title}
+
+
+ π· {screenshot.title}
+
+ {screenshot.description}
+
+
+
{screenshot.description}
+
+ ))}
+
+
+
+ {/* AI Analysis Details */}
+ {selectedTrade.detailedAnalysis && (
+
+
π€ AI Analysis
+
+ {/* Decision Summary */}
+
+
+
Decision Summary
+
+ {selectedTrade.detailedAnalysis.decision} ({selectedTrade.detailedAnalysis.confidence}%)
+
+
+
{selectedTrade.detailedAnalysis.aiReasoning}
+
+
+ {/* Multi-timeframe Analysis */}
+
+
Multi-timeframe Analysis
+
+ {selectedTrade.detailedAnalysis.timeframes && Object.entries(selectedTrade.detailedAnalysis.timeframes).map(([tf, data]) => (
+
+
+ {tf}
+
+ {data.decision}
+
+
+
+ Confidence: {data.confidence}%
+
+
+ {data.signals.slice(0, 2).map((signal, idx) => (
+
β’ {signal}
+ ))}
+
+
+ ))}
+
+
+
+ {/* Technical Indicators */}
+
+
Technical Indicators
+
+ {selectedTrade.detailedAnalysis.technicalIndicators && Object.entries(selectedTrade.detailedAnalysis.technicalIndicators).map(([indicator, data]) => (
+
+
{indicator}
+
{data.value}
+
{data.interpretation}
+
+ ))}
+
+
+
+ {/* Execution Plan */}
+
+
Execution Plan
+
+ {selectedTrade.detailedAnalysis.executionPlan && Object.entries(selectedTrade.detailedAnalysis.executionPlan).map(([key, value]) => (
+
+ {key}:
+ {value}
+
+ ))}
+
+
+
+ )}
+
+
+
+ )}
+
+ )
+}
diff --git a/app/chart-trading/page.tsx b/app/chart-trading/page.tsx
index 8c91d17..ecc20bb 100644
--- a/app/chart-trading/page.tsx
+++ b/app/chart-trading/page.tsx
@@ -103,7 +103,6 @@ export default function ChartTradingPage() {
diff --git a/check-trade-counts.js b/check-trade-counts.js
index cf7c033..e69de29 100644
--- a/check-trade-counts.js
+++ b/check-trade-counts.js
@@ -1,91 +0,0 @@
-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/components/Navigation.tsx b/components/Navigation.tsx
index 9fe8404..bc61cc4 100644
--- a/components/Navigation.tsx
+++ b/components/Navigation.tsx
@@ -1,5 +1,5 @@
"use client"
-import React from 'react'
+import React, { useState, useEffect } from 'react'
import Link from 'next/link'
import { usePathname } from 'next/navigation'
@@ -44,6 +44,11 @@ const navItems = [
export default function Navigation() {
const pathname = usePathname()
+ const [mounted, setMounted] = useState(false)
+
+ useEffect(() => {
+ setMounted(true)
+ }, [])
return (
@@ -51,7 +56,8 @@ export default function Navigation() {
{navItems.map((item) => {
- const isActive = pathname === item.href
+ // Only apply active styles after component has mounted to prevent hydration mismatch
+ const isActive = mounted && pathname === item.href
return (
void
}
-export default function TradingChart({ symbol = 'SOL/USDC', positions = [], onPriceUpdate }: TradingChartProps) {
+export default function TradingChart({ symbol = 'SOL/USDC', positions = [] }: TradingChartProps) {
const chartContainerRef = useRef
(null)
const chart = useRef(null)
const candlestickSeries = useRef(null)
@@ -77,12 +76,6 @@ export default function TradingChart({ symbol = 'SOL/USDC', positions = [], onPr
console.log('Setting chart data...')
candlestickSeries.current.setData(data)
console.log('Chart data set successfully')
-
- // Call onPriceUpdate with the latest price if provided
- if (onPriceUpdate && data.length > 0) {
- const latestPrice = data[data.length - 1].close
- onPriceUpdate(latestPrice)
- }
// Add position overlays
console.log('Adding position overlays...')
diff --git a/debug-pnl.js b/debug-pnl.js
index 9c481f2..e69de29 100644
--- a/debug-pnl.js
+++ b/debug-pnl.js
@@ -1,25 +0,0 @@
-// Debug P&L calculation
-const currentPrice = 175.82
-
-// Example trade from database
-const trade = {
- side: 'BUY',
- amount: 2.04,
- price: 100.3703837088441,
- status: 'COMPLETED'
-}
-
-console.log('=== P&L CALCULATION DEBUG ===')
-console.log(`Trade: ${trade.side} ${trade.amount} @ $${trade.price}`)
-console.log(`Current Price: $${currentPrice}`)
-console.log(`Price Difference: $${currentPrice - trade.price}`)
-console.log(`Expected P&L: $${(currentPrice - trade.price) * trade.amount}`)
-
-// Check if logic is working
-const priceChange = trade.side === 'BUY' ?
- (currentPrice - trade.price) :
- (trade.price - currentPrice)
-const realizedPnL = trade.status === 'COMPLETED' ? priceChange * trade.amount : null
-
-console.log(`Calculated P&L: $${realizedPnL}`)
-console.log(`Should be profitable: ${realizedPnL > 0 ? 'YES' : 'NO'}`)
diff --git a/drift_executeLiveTrade.txt b/drift_executeLiveTrade.txt
new file mode 100644
index 0000000..4eec0de
--- /dev/null
+++ b/drift_executeLiveTrade.txt
@@ -0,0 +1,50 @@
+ private async executeLiveTrade(decision: any): Promise {
+ try {
+ console.log(`π Executing DRIFT trade: ${decision.direction} ${decision.positionSize} ${this.config!.symbol} with ${this.config!.maxLeverage}x leverage`)
+
+ const response = await fetch('http://localhost:3000/api/automation/trade', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ dexProvider: 'DRIFT',
+ action: decision.direction.toLowerCase() === 'buy' ? 'open_long' : 'open_short',
+ symbol: this.config!.symbol.replace('USD', ''), // Convert SOLUSD to SOL
+ amount: this.config!.tradingAmount,
+ side: decision.direction,
+ leverage: this.config!.maxLeverage,
+ stopLoss: decision.stopLoss,
+ takeProfit: decision.takeProfit,
+ mode: 'LIVE'
+ })
+ })
+
+ if (!response.ok) {
+ throw new Error(`Drift trade request failed: ${response.statusText}`)
+ }
+
+ const result = await response.json()
+
+ if (result.success) {
+ return {
+ transactionId: result.result?.transactionId || result.txId,
+ executionPrice: result.result?.executionPrice || decision.currentPrice,
+ amount: result.result?.amount || decision.positionSize,
+ direction: decision.direction,
+ status: 'COMPLETED',
+ timestamp: new Date(),
+ fees: result.result?.fees || 0,
+ slippage: result.result?.slippage || 0,
+ leverage: this.config!.maxLeverage,
+ dexProvider: 'DRIFT',
+ tradingAmount: this.config!.tradingAmount
+ }
+ } else {
+ throw new Error(result.error || 'Drift trade execution failed')
+ }
+ } catch (error) {
+ console.error('Live trade execution error:', error)
+ throw error
+ }
+ }
diff --git a/fix-trade-data.js b/fix-trade-data.js
index 92258eb..e69de29 100644
--- a/fix-trade-data.js
+++ b/fix-trade-data.js
@@ -1,68 +0,0 @@
-const { PrismaClient } = require('@prisma/client')
-
-const prisma = new PrismaClient()
-
-async function fixTradeData() {
- console.log('π§ Fixing trade P&L data...')
-
- try {
- const trades = await prisma.trade.findMany({
- orderBy: { createdAt: 'desc' }
- })
-
- console.log(`π Found ${trades.length} trades to fix`)
-
- for (const trade of trades) {
- // Generate realistic exit prices and profits
- const entryPrice = trade.price
-
- // Create realistic price movements (70% wins, 30% losses)
- const isWin = Math.random() < 0.7
- const priceMovement = isWin ?
- (Math.random() * 3 + 0.5) : // 0.5% to 3.5% gain
- -(Math.random() * 2 + 0.3) // 0.3% to 2.3% loss
-
- const exitPrice = trade.side === 'BUY' ?
- entryPrice * (1 + priceMovement / 100) :
- entryPrice * (1 - priceMovement / 100)
-
- // Calculate profit in USD
- const profit = trade.side === 'BUY' ?
- (exitPrice - entryPrice) * trade.amount :
- (entryPrice - exitPrice) * trade.amount
-
- // Add realistic exit times (15-60 minutes after entry)
- const entryTime = new Date(trade.createdAt)
- const exitTime = new Date(entryTime.getTime() + (Math.random() * 45 + 15) * 60 * 1000)
-
- await prisma.trade.update({
- where: { id: trade.id },
- data: {
- exitPrice: exitPrice,
- profit: profit,
- closedAt: exitTime,
- status: 'COMPLETED'
- }
- })
-
- console.log(`β
Updated trade ${trade.id}: ${trade.side} $${profit.toFixed(2)} (${isWin ? 'WIN' : 'LOSS'})`)
- }
-
- console.log('π All trades updated successfully!')
-
- // Show summary
- const updatedTrades = await prisma.trade.findMany()
- const totalProfit = updatedTrades.reduce((sum, t) => sum + (t.profit || 0), 0)
- const wins = updatedTrades.filter(t => (t.profit || 0) > 0).length
- const winRate = (wins / updatedTrades.length * 100).toFixed(1)
-
- console.log(`π Summary: ${wins}/${updatedTrades.length} wins (${winRate}% win rate), Total P&L: $${totalProfit.toFixed(2)}`)
-
- } catch (error) {
- console.error('β Error:', error)
- } finally {
- await prisma.$disconnect()
- }
-}
-
-fixTradeData()
diff --git a/lib/analysis-completion-flag.ts b/lib/analysis-completion-flag.ts
index 16977e0..4a8901a 100644
--- a/lib/analysis-completion-flag.ts
+++ b/lib/analysis-completion-flag.ts
@@ -1,56 +1,29 @@
-// Analysis completion flag manager
-// This ensures cleanup only happens after the entire analysis cycle is complete
-
-class AnalysisCompletionFlag {
- private static instance: AnalysisCompletionFlag
- private isAnalysisComplete = false
- private currentSessionId: string | null = null
-
- private constructor() {}
-
- static getInstance(): AnalysisCompletionFlag {
- if (!AnalysisCompletionFlag.instance) {
- AnalysisCompletionFlag.instance = new AnalysisCompletionFlag()
+// Analysis completion flag utility
+export const analysisCompletionFlag = {
+ isComplete: false,
+ currentSession: null as string | null,
+
+ setComplete: (value: boolean) => {
+ analysisCompletionFlag.isComplete = value
+ },
+
+ getComplete: () => analysisCompletionFlag.isComplete,
+
+ startAnalysisCycle: (sessionId: string) => {
+ analysisCompletionFlag.currentSession = sessionId
+ analysisCompletionFlag.isComplete = false
+ },
+
+ endAnalysisCycle: () => {
+ analysisCompletionFlag.isComplete = true
+ analysisCompletionFlag.currentSession = null
+ },
+
+ markAnalysisComplete: (sessionId: string) => {
+ if (analysisCompletionFlag.currentSession === sessionId) {
+ analysisCompletionFlag.isComplete = true
}
- return AnalysisCompletionFlag.instance
- }
-
- // Called at the start of each analysis cycle
- startAnalysisCycle(sessionId: string) {
- console.log(`π Starting analysis cycle: ${sessionId}`)
- this.isAnalysisComplete = false
- this.currentSessionId = sessionId
- }
-
- // Called at the end of each analysis cycle
- markAnalysisComplete(sessionId: string) {
- if (sessionId === this.currentSessionId) {
- console.log(`β
Analysis cycle complete: ${sessionId}`)
- this.isAnalysisComplete = true
- } else {
- console.log(`β οΈ Session ID mismatch: expected ${this.currentSessionId}, got ${sessionId}`)
- }
- }
-
- // Check if analysis is complete and cleanup can proceed
- canCleanup(): boolean {
- return this.isAnalysisComplete
- }
-
- // Get current session info
- getCurrentSession(): { sessionId: string | null; isComplete: boolean } {
- return {
- sessionId: this.currentSessionId,
- isComplete: this.isAnalysisComplete
- }
- }
-
- // Reset flag (for manual cleanup or new cycles)
- reset() {
- console.log(`π Resetting analysis completion flag`)
- this.isAnalysisComplete = false
- this.currentSessionId = null
}
}
-export const analysisCompletionFlag = AnalysisCompletionFlag.getInstance()
+export default analysisCompletionFlag
\ No newline at end of file
diff --git a/lib/automation-service-simple.ts b/lib/automation-service-simple.ts
index 410c88e..3a148f1 100644
--- a/lib/automation-service-simple.ts
+++ b/lib/automation-service-simple.ts
@@ -805,7 +805,7 @@ ${validResults.map(r => `β’ ${r.timeframe}: ${r.analysis?.recommendation} (${r.
if (tradeResult.status !== 'FAILED') {
setTimeout(async () => {
try {
- await aggressiveCleanup.forceCleanupAfterTrade()
+ await aggressiveCleanup.runPostAnalysisCleanup()
} catch (error) {
console.error('Error in post-trade cleanup:', error)
}
@@ -852,52 +852,53 @@ ${validResults.map(r => `β’ ${r.timeframe}: ${r.analysis?.recommendation} (${r.
}
private async executeLiveTrade(decision: any): Promise {
- // Execute real trade via Jupiter DEX
- const inputToken = decision.direction === 'BUY' ? 'USDC' : 'SOL'
- const outputToken = decision.direction === 'BUY' ? 'SOL' : 'USDC'
-
- const tokens = {
- SOL: 'So11111111111111111111111111111111111111112',
- USDC: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
- }
+ try {
+ console.log(`π Executing DRIFT trade: ${decision.direction} ${decision.positionSize} ${this.config!.symbol} with ${this.config!.maxLeverage}x leverage`)
+
+ const response = await fetch("http://localhost:3000/api/automation/trade", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ dexProvider: "DRIFT",
+ action: decision.direction.toLowerCase() === "buy" ? "open_long" : "open_short",
+ symbol: this.config!.symbol.replace("USD", ""), // Convert SOLUSD to SOL
+ amount: this.config!.tradingAmount,
+ side: decision.direction,
+ leverage: this.config!.maxLeverage,
+ stopLoss: decision.stopLoss,
+ takeProfit: decision.takeProfit,
+ mode: "LIVE"
+ })
+ })
- // Calculate proper amount for Jupiter API
- let swapAmount
- if (decision.direction === 'BUY') {
- // BUY: Use trading amount in USDC (convert to 6 decimals)
- swapAmount = Math.floor(this.config!.tradingAmount * 1e6) // USDC has 6 decimals
- console.log(`π± BUY: Converting $${this.config!.tradingAmount} USDC to ${swapAmount} USDC tokens`)
- } else {
- // SELL: Use SOL amount (convert to 9 decimals)
- swapAmount = Math.floor(decision.positionSize * 1e9) // SOL has 9 decimals
- console.log(`π± SELL: Converting ${decision.positionSize} SOL to ${swapAmount} SOL tokens`)
- }
-
- console.log(`π Executing Jupiter swap with corrected amount: ${swapAmount}`)
-
- const swapResult = await jupiterDEXService.executeSwap(
- tokens[inputToken as keyof typeof tokens],
- tokens[outputToken as keyof typeof tokens],
- swapAmount,
- 50 // 0.5% slippage
- )
-
- // Convert Jupiter result to standard trade result format
- if (swapResult.success) {
- return {
- transactionId: swapResult.txId,
- executionPrice: swapResult.executionPrice,
- amount: swapResult.outputAmount, // Amount of tokens received
- direction: decision.direction,
- status: 'COMPLETED',
- timestamp: new Date(),
- fees: swapResult.fees || 0,
- slippage: swapResult.slippage || 0,
- inputAmount: swapResult.inputAmount, // Amount of tokens spent
- tradingAmount: this.config!.tradingAmount // Original USD amount
+ if (!response.ok) {
+ throw new Error(`Drift trade request failed: ${response.statusText}`)
}
- } else {
- throw new Error(swapResult.error || 'Jupiter swap failed')
+
+ const result = await response.json()
+
+ if (result.success) {
+ return {
+ transactionId: result.result?.transactionId || result.txId,
+ executionPrice: result.result?.executionPrice || decision.currentPrice,
+ amount: result.result?.amount || decision.positionSize,
+ direction: decision.direction,
+ status: "COMPLETED",
+ timestamp: new Date(),
+ fees: result.result?.fees || 0,
+ slippage: result.result?.slippage || 0,
+ leverage: this.config!.maxLeverage,
+ dexProvider: "DRIFT",
+ tradingAmount: this.config!.tradingAmount
+ }
+ } else {
+ throw new Error(result.error || "Drift trade execution failed")
+ }
+ } catch (error) {
+ console.error("Live trade execution error:", error)
+ throw error
}
}
diff --git a/lib/automation-service-simple.ts.backup b/lib/automation-service-simple.ts.backup
new file mode 100644
index 0000000..eda5af4
--- /dev/null
+++ b/lib/automation-service-simple.ts.backup
@@ -0,0 +1,1268 @@
+import { PrismaClient } from '@prisma/client'
+import { aiAnalysisService, AnalysisResult } from './ai-analysis'
+import { jupiterDEXService } from './jupiter-dex-service'
+import { enhancedScreenshotService } from './enhanced-screenshot-simple'
+import { TradingViewCredentials } from './tradingview-automation'
+import { progressTracker, ProgressStatus } from './progress-tracker'
+import aggressiveCleanup from './aggressive-cleanup'
+import { analysisCompletionFlag } from './analysis-completion-flag'
+import priceMonitorService from './price-monitor'
+
+const prisma = new PrismaClient()
+
+export interface AutomationConfig {
+ userId: string
+ mode: 'SIMULATION' | 'LIVE'
+ symbol: string
+ timeframe: string
+ tradingAmount: number
+ maxLeverage: number
+ stopLossPercent: number
+ takeProfitPercent: number
+ maxDailyTrades: number
+ riskPercentage: number
+}
+
+export interface AutomationStatus {
+ isActive: boolean
+ mode: 'SIMULATION' | 'LIVE'
+ symbol: string
+ timeframe: string
+ totalTrades: number
+ successfulTrades: number
+ winRate: number
+ totalPnL: number
+ lastAnalysis?: Date
+ lastTrade?: Date
+ nextScheduled?: Date
+ errorCount: number
+ lastError?: string
+}
+
+export class AutomationService {
+ private isRunning = false
+ private config: AutomationConfig | null = null
+ private intervalId: NodeJS.Timeout | null = null
+ private stats = {
+ totalTrades: 0,
+ successfulTrades: 0,
+ winRate: 0,
+ totalPnL: 0,
+ errorCount: 0,
+ lastError: null as string | null
+ }
+
+ async startAutomation(config: AutomationConfig): Promise {
+ try {
+ if (this.isRunning) {
+ throw new Error('Automation is already running')
+ }
+
+ this.config = config
+ this.isRunning = true
+
+ console.log(`π€ Starting automation for ${config.symbol} ${config.timeframe} in ${config.mode} mode`)
+
+ // Ensure user exists in database
+ await prisma.user.upsert({
+ where: { id: config.userId },
+ update: {},
+ create: {
+ id: config.userId,
+ email: `${config.userId}@example.com`,
+ name: config.userId,
+ createdAt: new Date(),
+ updatedAt: new Date()
+ }
+ })
+
+ // Delete any existing automation session for this user/symbol/timeframe
+ await prisma.automationSession.deleteMany({
+ where: {
+ userId: config.userId,
+ symbol: config.symbol,
+ timeframe: config.timeframe
+ }
+ })
+
+ // Create new automation session in database
+ await prisma.automationSession.create({
+ data: {
+ userId: config.userId,
+ status: 'ACTIVE',
+ mode: config.mode,
+ symbol: config.symbol,
+ timeframe: config.timeframe,
+ settings: {
+ tradingAmount: config.tradingAmount,
+ maxLeverage: config.maxLeverage,
+ stopLossPercent: config.stopLossPercent,
+ takeProfitPercent: config.takeProfitPercent,
+ maxDailyTrades: config.maxDailyTrades,
+ riskPercentage: config.riskPercentage
+ },
+ startBalance: config.tradingAmount,
+ currentBalance: config.tradingAmount,
+ createdAt: new Date(),
+ updatedAt: new Date()
+ }
+ })
+
+ // Start automation cycle
+ this.startAutomationCycle()
+
+ // Start price monitoring
+ await priceMonitorService.startMonitoring()
+
+ // Set up price monitor event listeners for automatic analysis triggering
+ priceMonitorService.on('tp_approach', async (data) => {
+ if (data.symbol === this.config?.symbol) {
+ console.log(`π― TP approach detected for ${data.symbol}, triggering analysis...`)
+ await this.triggerPriceBasedAnalysis('TP_APPROACH', data)
+ }
+ })
+
+ priceMonitorService.on('sl_approach', async (data) => {
+ if (data.symbol === this.config?.symbol) {
+ console.log(`β οΈ SL approach detected for ${data.symbol}, triggering analysis...`)
+ await this.triggerPriceBasedAnalysis('SL_APPROACH', data)
+ }
+ })
+
+ priceMonitorService.on('critical_level', async (data) => {
+ if (data.symbol === this.config?.symbol) {
+ console.log(`π¨ Critical level reached for ${data.symbol}, triggering urgent analysis...`)
+ await this.triggerPriceBasedAnalysis('CRITICAL', data)
+ }
+ })
+
+ return true
+ } catch (error) {
+ console.error('Failed to start automation:', error)
+ this.stats.errorCount++
+ this.stats.lastError = error instanceof Error ? error.message : 'Unknown error'
+ return false
+ }
+ }
+
+ private startAutomationCycle(): void {
+ if (!this.config) return
+
+ // Get interval in milliseconds based on timeframe
+ const intervalMs = this.getIntervalFromTimeframe(this.config.timeframe)
+
+ console.log(`π Starting automation cycle every ${intervalMs/1000} seconds`)
+
+ this.intervalId = setInterval(async () => {
+ if (this.isRunning && this.config) {
+ await this.runAutomationCycle()
+ }
+ }, intervalMs)
+
+ // Run first cycle immediately
+ this.runAutomationCycle()
+ }
+
+ private getIntervalFromTimeframe(timeframe: string): number {
+ const intervals: { [key: string]: number } = {
+ '1m': 60 * 1000,
+ '3m': 3 * 60 * 1000,
+ '5m': 5 * 60 * 1000,
+ '15m': 15 * 60 * 1000,
+ '30m': 30 * 60 * 1000,
+ '1h': 60 * 60 * 1000,
+ '2h': 2 * 60 * 60 * 1000,
+ '4h': 4 * 60 * 60 * 1000,
+ '1d': 24 * 60 * 60 * 1000
+ }
+
+ return intervals[timeframe] || intervals['1h'] // Default to 1 hour
+ }
+
+ private async runAutomationCycle(): Promise {
+ if (!this.config) return
+
+ try {
+ console.log(`π Running automation cycle for ${this.config.symbol} ${this.config.timeframe}`)
+
+ // Step 1: Check daily trade limit
+ const todayTrades = await this.getTodayTradeCount(this.config.userId)
+ if (todayTrades >= this.config.maxDailyTrades) {
+ console.log(`π Daily trade limit reached (${todayTrades}/${this.config.maxDailyTrades})`)
+ // Run cleanup even when trade limit is reached
+ await this.runPostCycleCleanup('trade_limit_reached')
+ return
+ }
+
+ // Step 2: Take screenshot and analyze
+ const analysisResult = await this.performAnalysis()
+ if (!analysisResult) {
+ console.log('β Analysis failed, skipping cycle')
+ // Run cleanup when analysis fails
+ await this.runPostCycleCleanup('analysis_failed')
+ return
+ }
+
+ // Step 3: Store analysis for learning
+ await this.storeAnalysisForLearning(analysisResult)
+
+ // Step 4: Update session with latest analysis
+ await this.updateSessionWithAnalysis(analysisResult)
+
+ // Step 5: Make trading decision
+ const tradeDecision = await this.makeTradeDecision(analysisResult)
+ if (!tradeDecision) {
+ console.log('π No trading opportunity found')
+ // Run cleanup when no trading opportunity
+ await this.runPostCycleCleanup('no_opportunity')
+ return
+ }
+
+ // Step 6: Execute trade
+ await this.executeTrade(tradeDecision)
+
+ // Run cleanup after successful trade execution
+ await this.runPostCycleCleanup('trade_executed')
+
+ } catch (error) {
+ console.error('Error in automation cycle:', error)
+ this.stats.errorCount++
+ this.stats.lastError = error instanceof Error ? error.message : 'Unknown error'
+
+ // Run cleanup on error
+ await this.runPostCycleCleanup('error')
+ }
+ }
+
+ private async runPostCycleCleanup(reason: string): Promise {
+ console.log(`π§Ή Running post-cycle cleanup (reason: ${reason})`)
+
+ // Longer delay to ensure all analysis processes AND trading decision have finished
+ await new Promise(resolve => setTimeout(resolve, 10000)) // 10 seconds
+
+ try {
+ // Use the new post-analysis cleanup that respects completion flags
+ await aggressiveCleanup.runPostAnalysisCleanup()
+ console.log(`β
Post-cycle cleanup completed for: ${reason}`)
+ } catch (error) {
+ console.error('Error in post-cycle cleanup:', error)
+ }
+ }
+
+ private async performAnalysis(): Promise<{
+ screenshots: string[]
+ analysis: AnalysisResult | null
+ } | null> {
+ // Generate unique session ID for this analysis
+ const sessionId = `automation-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
+
+ // Mark the start of analysis cycle to prevent cleanup interruption
+ analysisCompletionFlag.startAnalysisCycle(sessionId)
+
+ try {
+ console.log(`πΈ Starting multi-timeframe analysis with dual layouts... (Session: ${sessionId})`)
+
+ // Create progress tracking session
+ const progressSteps = [
+ { id: 'init', title: 'Initialize', description: 'Starting multi-timeframe analysis', status: 'pending' as const },
+ { id: 'capture', title: 'Capture', description: 'Capturing screenshots for all timeframes', status: 'pending' as const },
+ { id: 'analysis', title: 'Analysis', description: 'Running AI analysis on screenshots', status: 'pending' as const },
+ { id: 'complete', title: 'Complete', description: 'Analysis complete', status: 'pending' as const }
+ ]
+
+ progressTracker.createSession(sessionId, progressSteps)
+ progressTracker.updateStep(sessionId, 'init', 'active', 'Starting multi-timeframe analysis...')
+
+ // Multi-timeframe analysis: 15m, 1h, 2h, 4h
+ const timeframes = ['15', '1h', '2h', '4h']
+ const symbol = this.config!.symbol
+
+ console.log(`π Analyzing ${symbol} across timeframes: ${timeframes.join(', ')} with AI + DIY layouts`)
+
+ progressTracker.updateStep(sessionId, 'init', 'completed', `Starting analysis for ${timeframes.length} timeframes`)
+ progressTracker.updateStep(sessionId, 'capture', 'active', 'Capturing screenshots...')
+
+ // Analyze each timeframe with both AI and DIY layouts
+ const multiTimeframeResults = await this.analyzeMultiTimeframeWithDualLayouts(symbol, timeframes, sessionId)
+
+ if (multiTimeframeResults.length === 0) {
+ console.log('β No multi-timeframe analysis results')
+ progressTracker.updateStep(sessionId, 'capture', 'error', 'No analysis results captured')
+ progressTracker.deleteSession(sessionId)
+ // Mark analysis as complete to allow cleanup
+ analysisCompletionFlag.markAnalysisComplete(sessionId)
+ return null
+ }
+
+ progressTracker.updateStep(sessionId, 'capture', 'completed', `Captured ${multiTimeframeResults.length} timeframe analyses`)
+ progressTracker.updateStep(sessionId, 'analysis', 'active', 'Processing multi-timeframe results...')
+
+ // Process and combine multi-timeframe results
+ const combinedResult = this.combineMultiTimeframeAnalysis(multiTimeframeResults)
+
+ if (!combinedResult.analysis) {
+ console.log('β Failed to combine multi-timeframe analysis')
+ progressTracker.updateStep(sessionId, 'analysis', 'error', 'Failed to combine analysis results')
+ progressTracker.deleteSession(sessionId)
+ // Mark analysis as complete to allow cleanup
+ analysisCompletionFlag.markAnalysisComplete(sessionId)
+ return null
+ }
+
+ console.log(`β
Multi-timeframe analysis completed: ${combinedResult.analysis.recommendation} with ${combinedResult.analysis.confidence}% confidence`)
+ console.log(`π Timeframe alignment: ${this.analyzeTimeframeAlignment(multiTimeframeResults)}`)
+
+ progressTracker.updateStep(sessionId, 'analysis', 'completed', `Analysis complete: ${combinedResult.analysis.recommendation}`)
+ progressTracker.updateStep(sessionId, 'complete', 'completed', 'Multi-timeframe analysis finished')
+
+ // Clean up session after successful completion
+ setTimeout(() => {
+ progressTracker.deleteSession(sessionId)
+ }, 2000)
+
+ // Mark analysis as complete to allow cleanup
+ analysisCompletionFlag.markAnalysisComplete(sessionId)
+
+ return combinedResult
+
+ } catch (error) {
+ console.error('Error performing multi-timeframe analysis:', error)
+ progressTracker.updateStep(sessionId, 'analysis', 'error', error instanceof Error ? error.message : 'Unknown error')
+ setTimeout(() => {
+ progressTracker.deleteSession(sessionId)
+ }, 5000)
+
+ // Mark analysis as complete even on error to allow cleanup
+ analysisCompletionFlag.markAnalysisComplete(sessionId)
+
+ return null
+ }
+ }
+
+ private async analyzeMultiTimeframeWithDualLayouts(
+ symbol: string,
+ timeframes: string[],
+ sessionId: string
+ ): Promise> {
+ const results: Array<{ symbol: string; timeframe: string; analysis: AnalysisResult | null }> = []
+
+ for (let i = 0; i < timeframes.length; i++) {
+ const timeframe = timeframes[i]
+ try {
+ console.log(`π Analyzing ${symbol} ${timeframe} with AI + DIY layouts... (${i + 1}/${timeframes.length})`)
+
+ // Update progress for timeframe
+ progressTracker.updateTimeframeProgress(sessionId, i + 1, timeframes.length, timeframe)
+
+ // Use the dual-layout configuration for each timeframe
+ const screenshotConfig = {
+ symbol: symbol,
+ timeframe: timeframe,
+ layouts: ['ai', 'diy'],
+ sessionId: sessionId
+ }
+
+ const result = await aiAnalysisService.captureAndAnalyzeWithConfig(screenshotConfig)
+
+ if (result.analysis) {
+ console.log(`β
${timeframe} analysis: ${result.analysis.recommendation} (${result.analysis.confidence}% confidence)`)
+ results.push({
+ symbol,
+ timeframe,
+ analysis: result.analysis
+ })
+ } else {
+ console.log(`β ${timeframe} analysis failed`)
+ results.push({
+ symbol,
+ timeframe,
+ analysis: null
+ })
+ }
+
+ // Small delay between captures to avoid overwhelming the system
+ await new Promise(resolve => setTimeout(resolve, 3000))
+
+ } catch (error) {
+ console.error(`Failed to analyze ${symbol} ${timeframe}:`, error)
+ results.push({
+ symbol,
+ timeframe,
+ analysis: null
+ })
+ }
+ }
+
+ return results
+ }
+
+ private combineMultiTimeframeAnalysis(results: Array<{ symbol: string; timeframe: string; analysis: AnalysisResult | null }>): {
+ screenshots: string[]
+ analysis: AnalysisResult | null
+ } {
+ const validResults = results.filter(r => r.analysis !== null)
+
+ if (validResults.length === 0) {
+ return { screenshots: [], analysis: null }
+ }
+
+ // Get the primary timeframe (1h) as base
+ const primaryResult = validResults.find(r => r.timeframe === '1h') || validResults[0]
+ const screenshots = validResults.length > 0 ? [primaryResult.timeframe] : []
+
+ // Calculate weighted confidence based on timeframe alignment
+ const alignment = this.calculateTimeframeAlignment(validResults)
+ const baseAnalysis = primaryResult.analysis!
+
+ // Adjust confidence based on timeframe alignment
+ const adjustedConfidence = Math.round(baseAnalysis.confidence * alignment.score)
+
+ // Create combined analysis with multi-timeframe reasoning
+ const combinedAnalysis: AnalysisResult = {
+ ...baseAnalysis,
+ confidence: adjustedConfidence,
+ reasoning: `Multi-timeframe Dual-Layout Analysis (${results.map(r => r.timeframe).join(', ')}): ${baseAnalysis.reasoning}
+
+π Each timeframe analyzed with BOTH AI layout (RSI, MACD, EMAs) and DIY layout (Stochastic RSI, VWAP, OBV)
+β±οΈ Timeframe Alignment: ${alignment.description}
+οΏ½ Signal Strength: ${alignment.strength}
+π― Confidence Adjustment: ${baseAnalysis.confidence}% β ${adjustedConfidence}% (${alignment.score >= 1 ? 'Enhanced' : 'Reduced'} due to timeframe ${alignment.score >= 1 ? 'alignment' : 'divergence'})
+
+π¬ Analysis Details:
+${validResults.map(r => `β’ ${r.timeframe}: ${r.analysis?.recommendation} (${r.analysis?.confidence}% confidence)`).join('\n')}`,
+
+ keyLevels: this.consolidateKeyLevels(validResults),
+ marketSentiment: this.consolidateMarketSentiment(validResults)
+ }
+
+ return {
+ screenshots,
+ analysis: combinedAnalysis
+ }
+ }
+
+ private calculateTimeframeAlignment(results: Array<{ symbol: string; timeframe: string; analysis: AnalysisResult | null }>): {
+ score: number
+ description: string
+ strength: string
+ } {
+ const recommendations = results.map(r => r.analysis?.recommendation).filter(Boolean)
+ const buySignals = recommendations.filter(r => r === 'BUY').length
+ const sellSignals = recommendations.filter(r => r === 'SELL').length
+ const holdSignals = recommendations.filter(r => r === 'HOLD').length
+
+ const total = recommendations.length
+ const maxSignals = Math.max(buySignals, sellSignals, holdSignals)
+ const alignmentRatio = maxSignals / total
+
+ let score = 1.0
+ let description = ''
+ let strength = ''
+
+ if (alignmentRatio >= 0.75) {
+ score = 1.2 // Boost confidence
+ description = `Strong alignment (${maxSignals}/${total} timeframes agree)`
+ strength = 'Strong'
+ } else if (alignmentRatio >= 0.5) {
+ score = 1.0 // Neutral
+ description = `Moderate alignment (${maxSignals}/${total} timeframes agree)`
+ strength = 'Moderate'
+ } else {
+ score = 0.8 // Reduce confidence
+ description = `Weak alignment (${maxSignals}/${total} timeframes agree)`
+ strength = 'Weak'
+ }
+
+ return { score, description, strength }
+ }
+
+ private consolidateKeyLevels(results: Array<{ symbol: string; timeframe: string; analysis: AnalysisResult | null }>): any {
+ const allLevels = results.map(r => r.analysis?.keyLevels).filter(Boolean)
+ if (allLevels.length === 0) return {}
+
+ // Use the 1h timeframe levels as primary, or first available
+ const primaryLevels = results.find(r => r.timeframe === '1h')?.analysis?.keyLevels || allLevels[0]
+
+ return {
+ ...primaryLevels,
+ note: `Consolidated from ${allLevels.length} timeframes`
+ }
+ }
+
+ private consolidateMarketSentiment(results: Array<{ symbol: string; timeframe: string; analysis: AnalysisResult | null }>): 'BULLISH' | 'BEARISH' | 'NEUTRAL' {
+ const sentiments = results.map(r => r.analysis?.marketSentiment).filter(Boolean)
+ if (sentiments.length === 0) return 'NEUTRAL'
+
+ // Use the 1h timeframe sentiment as primary, or first available
+ const primarySentiment = results.find(r => r.timeframe === '1h')?.analysis?.marketSentiment || sentiments[0]
+
+ return primarySentiment || 'NEUTRAL'
+ }
+
+ private analyzeTimeframeAlignment(results: Array<{ symbol: string; timeframe: string; analysis: AnalysisResult | null }>): string {
+ const recommendations = results.map(r => ({
+ timeframe: r.timeframe,
+ recommendation: r.analysis?.recommendation,
+ confidence: r.analysis?.confidence || 0
+ }))
+
+ const summary = recommendations.map(r => `${r.timeframe}: ${r.recommendation} (${r.confidence}%)`).join(', ')
+ return summary
+ }
+
+ private async storeAnalysisForLearning(result: {
+ screenshots: string[]
+ analysis: AnalysisResult | null
+ }): Promise {
+ try {
+ if (!result.analysis) return
+
+ await prisma.aILearningData.create({
+ data: {
+ userId: this.config!.userId,
+ symbol: this.config!.symbol,
+ timeframe: this.config!.timeframe,
+ screenshot: result.screenshots[0] || '',
+ analysisData: JSON.stringify(result.analysis),
+ marketConditions: JSON.stringify({
+ marketSentiment: result.analysis.marketSentiment,
+ keyLevels: result.analysis.keyLevels,
+ timestamp: new Date().toISOString()
+ }),
+ confidenceScore: result.analysis.confidence,
+ createdAt: new Date()
+ }
+ })
+ } catch (error) {
+ console.error('Error storing analysis for learning:', error)
+ }
+ }
+
+ private async updateSessionWithAnalysis(result: {
+ screenshots: string[]
+ analysis: AnalysisResult | null
+ }): Promise {
+ try {
+ if (!result.analysis) return
+
+ // Store the analysis decision in a field that works for now
+ const analysisDecision = `${result.analysis.recommendation} with ${result.analysis.confidence}% confidence - ${result.analysis.summary}`
+
+ // Update the current session with the latest analysis
+ await prisma.automationSession.updateMany({
+ where: {
+ userId: this.config!.userId,
+ symbol: this.config!.symbol,
+ timeframe: this.config!.timeframe,
+ status: 'ACTIVE'
+ },
+ data: {
+ lastAnalysis: new Date(),
+ lastError: analysisDecision // Temporarily store analysis here
+ }
+ })
+
+ // Also log the analysis for debugging
+ console.log('π Analysis stored in database:', {
+ recommendation: result.analysis.recommendation,
+ confidence: result.analysis.confidence,
+ summary: result.analysis.summary
+ })
+ } catch (error) {
+ console.error('Failed to update session with analysis:', error)
+ }
+ }
+
+ private async makeTradeDecision(result: {
+ screenshots: string[]
+ analysis: AnalysisResult | null
+ }): Promise {
+ try {
+ const analysis = result.analysis
+ if (!analysis) return null
+
+ // Only trade if confidence is high enough
+ if (analysis.confidence < 70) {
+ console.log(`π Confidence too low: ${analysis.confidence}%`)
+ return null
+ }
+
+ // Only trade if direction is clear
+ if (analysis.recommendation === 'HOLD') {
+ console.log('π No clear direction signal')
+ return null
+ }
+
+ // β
ENHANCED: Support both BUY and SELL signals
+ if (analysis.recommendation === 'SELL') {
+ // Check if we have SOL position to sell
+ const hasPosition = await this.checkCurrentPosition()
+ if (!hasPosition) {
+ console.log('π SELL signal but no SOL position to sell - skipping')
+ return null
+ }
+ console.log('π SELL signal detected with existing SOL position')
+ } else if (analysis.recommendation === 'BUY') {
+ console.log('π BUY signal detected')
+ }
+
+ // Calculate position size based on risk percentage
+ const positionSize = await this.calculatePositionSize(analysis)
+
+ return {
+ direction: analysis.recommendation,
+ confidence: analysis.confidence,
+ positionSize,
+ stopLoss: this.calculateStopLoss(analysis),
+ takeProfit: this.calculateTakeProfit(analysis),
+ marketSentiment: analysis.marketSentiment,
+ currentPrice: analysis.entry?.price || 190 // Store current price for calculations
+ }
+
+ } catch (error) {
+ console.error('Error making trade decision:', error)
+ return null
+ }
+ }
+
+ // β
NEW: Check if we have SOL position available to sell
+ private async checkCurrentPosition(): Promise {
+ try {
+ // Check recent trades to see current position
+ const recentTrades = await prisma.trade.findMany({
+ where: {
+ userId: this.config!.userId,
+ symbol: this.config!.symbol,
+ status: 'OPEN'
+ },
+ orderBy: { createdAt: 'desc' },
+ take: 5
+ })
+
+ // Count open positions
+ let netPosition = 0
+ for (const trade of recentTrades) {
+ if (trade.side === 'BUY') {
+ netPosition += trade.amount
+ } else if (trade.side === 'SELL') {
+ netPosition -= trade.amount
+ }
+ }
+
+ console.log(`π Current SOL position: ${netPosition.toFixed(4)} SOL`)
+ return netPosition > 0.001 // Have at least 0.001 SOL to sell
+
+ } catch (error) {
+ console.error('β Error checking current position:', error)
+ // If we can't check, default to allowing the trade (fail-safe)
+ return true
+ }
+ }
+
+ 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
+
+ // β
ENHANCED: Handle both BUY and SELL position sizing
+ if (analysis.recommendation === 'SELL') {
+ // For SELL orders, calculate how much SOL to sell based on current holdings
+ return await this.calculateSellAmount(analysis)
+ }
+
+ // For BUY orders, calculate 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(`π° BUY Position calculation: $${usdAmount} Γ· $${currentPrice} = ${tokenAmount.toFixed(4)} tokens`)
+
+ return tokenAmount
+ }
+
+ // β
NEW: Calculate SOL amount to sell for SELL orders
+ private async calculateSellAmount(analysis: any): Promise {
+ try {
+ // Get current SOL holdings from recent open trades
+ const openTrades = await prisma.trade.findMany({
+ where: {
+ userId: this.config!.userId,
+ symbol: this.config!.symbol,
+ status: 'OPEN',
+ side: 'BUY' // Only BUY trades represent SOL holdings
+ },
+ orderBy: { createdAt: 'desc' }
+ })
+
+ let totalSOLHoldings = 0
+ for (const trade of openTrades) {
+ totalSOLHoldings += trade.amount
+ }
+
+ // Risk-adjusted sell amount (don't sell everything at once)
+ const riskAdjustment = this.config!.riskPercentage / 100
+ const confidenceAdjustment = analysis.confidence / 100
+ const sellAmount = totalSOLHoldings * riskAdjustment * confidenceAdjustment
+
+ console.log(`π° SELL Position calculation: ${totalSOLHoldings.toFixed(4)} SOL holdings Γ ${(riskAdjustment * confidenceAdjustment * 100).toFixed(1)}% = ${sellAmount.toFixed(4)} SOL to sell`)
+
+ return Math.max(sellAmount, 0.001) // Minimum 0.001 SOL
+
+ } catch (error) {
+ console.error('β Error calculating sell amount:', error)
+ return 0.01 // Fallback: sell 0.01 SOL
+ }
+ }
+
+ private calculateStopLoss(analysis: any): number {
+ // Use AI analysis stopLoss if available, otherwise calculate from entry price
+ if (analysis.stopLoss?.price) {
+ return analysis.stopLoss.price
+ }
+
+ const currentPrice = analysis.entry?.price || 189 // Current SOL price
+ const stopLossPercent = this.config!.stopLossPercent / 100
+
+ // β
ENHANCED: Proper stop loss for both BUY and SELL
+ if (analysis.recommendation === 'BUY') {
+ // BUY: Stop loss below entry (price goes down)
+ return currentPrice * (1 - stopLossPercent)
+ } else if (analysis.recommendation === 'SELL') {
+ // SELL: Stop loss above entry (price goes up)
+ return currentPrice * (1 + stopLossPercent)
+ } else {
+ return currentPrice * (1 - stopLossPercent)
+ }
+ }
+
+ private calculateTakeProfit(analysis: any): number {
+ // Use AI analysis takeProfit if available, otherwise calculate from entry price
+ if (analysis.takeProfits?.tp1?.price) {
+ return analysis.takeProfits.tp1.price
+ }
+
+ const currentPrice = analysis.entry?.price || 150 // Default SOL price
+ const takeProfitPercent = this.config!.takeProfitPercent / 100
+
+ // β
ENHANCED: Proper take profit for both BUY and SELL
+ if (analysis.recommendation === 'BUY') {
+ // BUY: Take profit above entry (price goes up)
+ return currentPrice * (1 + takeProfitPercent)
+ } else if (analysis.recommendation === 'SELL') {
+ // SELL: Take profit below entry (price goes down)
+ return currentPrice * (1 - takeProfitPercent)
+ } else {
+ return currentPrice * (1 + takeProfitPercent)
+ }
+ }
+
+ private async executeTrade(decision: any): Promise {
+ try {
+ console.log(`π― Executing ${this.config!.mode} trade: ${decision.direction} ${decision.positionSize} ${this.config!.symbol}`)
+
+ let tradeResult: any
+
+ if (this.config!.mode === 'SIMULATION') {
+ // Execute simulation trade
+ tradeResult = await this.executeSimulationTrade(decision)
+ } else {
+ // Execute live trade via Jupiter
+ console.log(`π° LIVE TRADE: $${this.config!.tradingAmount} trading amount configured`)
+ tradeResult = await this.executeLiveTrade(decision)
+
+ // If live trade failed, fall back to simulation for data consistency
+ if (!tradeResult || !tradeResult.success) {
+ console.log('β οΈ Live trade failed, falling back to simulation for record keeping')
+ tradeResult = await this.executeSimulationTrade(decision)
+ tradeResult.status = 'FAILED'
+ tradeResult.error = 'Jupiter DEX execution failed'
+ }
+ }
+
+ // Store trade in database
+ await this.storeTrade(decision, tradeResult)
+
+ // Update stats
+ this.updateStats(tradeResult)
+
+ console.log(`β
Trade executed successfully: ${tradeResult.transactionId || 'SIMULATION'}`)
+
+ // Force cleanup after successful trade execution
+ if (tradeResult.status !== 'FAILED') {
+ setTimeout(async () => {
+ try {
+ await aggressiveCleanup.runPostAnalysisCleanup()
+ } catch (error) {
+ console.error('Error in post-trade cleanup:', error)
+ }
+ }, 2000) // 2 second delay
+ }
+
+ } catch (error) {
+ console.error('Error executing trade:', error)
+ this.stats.errorCount++
+ this.stats.lastError = error instanceof Error ? error.message : 'Trade execution failed'
+ }
+ }
+
+ private async executeSimulationTrade(decision: any): Promise {
+ // Simulate trade execution with realistic parameters
+ 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))
+
+ return {
+ transactionId: `SIM_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
+ executionPrice,
+ amount: decision.positionSize,
+ direction: decision.direction,
+ status: 'OPEN', // Trades start as OPEN, not COMPLETED
+ timestamp: new Date(),
+ fees: decision.positionSize * 0.001, // 0.1% fee
+ slippage: slippage * 100
+ }
+ }
+
+ private async executeLiveTrade(decision: any): Promise {
+ // Execute real trade via Jupiter DEX
+ const inputToken = decision.direction === 'BUY' ? 'USDC' : 'SOL'
+ const outputToken = decision.direction === 'BUY' ? 'SOL' : 'USDC'
+
+ const tokens = {
+ SOL: 'So11111111111111111111111111111111111111112',
+ USDC: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
+ }
+
+ // Calculate proper amount for Jupiter API
+ let swapAmount
+ if (decision.direction === 'BUY') {
+ // BUY: Use trading amount in USDC (convert to 6 decimals)
+ swapAmount = Math.floor(this.config!.tradingAmount * 1e6) // USDC has 6 decimals
+ console.log(`π± BUY: Converting $${this.config!.tradingAmount} USDC to ${swapAmount} USDC tokens`)
+ } else {
+ // SELL: Use SOL amount (convert to 9 decimals)
+ swapAmount = Math.floor(decision.positionSize * 1e9) // SOL has 9 decimals
+ console.log(`π± SELL: Converting ${decision.positionSize} SOL to ${swapAmount} SOL tokens`)
+ }
+
+ console.log(`π Executing Jupiter swap with corrected amount: ${swapAmount}`)
+
+ const swapResult = await jupiterDEXService.executeSwap(
+ tokens[inputToken as keyof typeof tokens],
+ tokens[outputToken as keyof typeof tokens],
+ swapAmount,
+ 50 // 0.5% slippage
+ )
+
+ // Convert Jupiter result to standard trade result format
+ if (swapResult.success) {
+ return {
+ transactionId: swapResult.txId,
+ executionPrice: swapResult.executionPrice,
+ amount: swapResult.outputAmount, // Amount of tokens received
+ direction: decision.direction,
+ status: 'COMPLETED',
+ timestamp: new Date(),
+ fees: swapResult.fees || 0,
+ slippage: swapResult.slippage || 0,
+ inputAmount: swapResult.inputAmount, // Amount of tokens spent
+ tradingAmount: this.config!.tradingAmount // Original USD amount
+ }
+ } else {
+ throw new Error(swapResult.error || 'Jupiter swap failed')
+ }
+ }
+
+ private async storeTrade(decision: any, result: any): Promise {
+ try {
+ // Ensure we have a valid price for database storage
+ const executionPrice = result.executionPrice || decision.currentPrice || decision.entryPrice
+
+ if (!executionPrice) {
+ console.error('β No valid price available for trade storage. Result:', result)
+ console.error('β Decision data:', { currentPrice: decision.currentPrice, entryPrice: decision.entryPrice })
+ return
+ }
+
+ // For live trades, use the actual amounts from Jupiter
+ const tradeAmount = result.tradingAmount ? this.config!.tradingAmount : decision.positionSize
+ const actualAmount = result.amount || decision.positionSize
+
+ console.log(`πΎ Storing trade: ${decision.direction} ${actualAmount} ${this.config!.symbol} at $${executionPrice}`)
+
+ await prisma.trade.create({
+ data: {
+ userId: this.config!.userId,
+ symbol: this.config!.symbol,
+ side: decision.direction,
+ amount: actualAmount,
+ price: executionPrice,
+ status: result.status || 'COMPLETED',
+ driftTxId: result.transactionId || result.txId,
+ fees: result.fees || 0,
+ stopLoss: decision.stopLoss,
+ takeProfit: decision.takeProfit,
+ isAutomated: true,
+ tradingMode: this.config!.mode,
+ confidence: decision.confidence,
+ marketSentiment: decision.marketSentiment,
+ createdAt: new Date(),
+ // Add Jupiter-specific fields for live trades
+ ...(this.config!.mode === 'LIVE' && result.tradingAmount && {
+ realTradingAmount: this.config!.tradingAmount,
+ inputAmount: result.inputAmount,
+ slippage: result.slippage
+ })
+ }
+ })
+
+ console.log('β
Trade stored in database successfully')
+ } catch (error) {
+ console.error('β Error storing trade:', error)
+ }
+ }
+
+ private updateStats(result: any): void {
+ this.stats.totalTrades++
+
+ if (result.status === 'COMPLETED') {
+ this.stats.successfulTrades++
+ this.stats.winRate = (this.stats.successfulTrades / this.stats.totalTrades) * 100
+
+ // Update PnL (simplified calculation)
+ const pnl = result.amount * 0.01 * (Math.random() > 0.5 ? 1 : -1) // Random PnL for demo
+ this.stats.totalPnL += pnl
+ }
+ }
+
+ private async getTodayTradeCount(userId: string): Promise {
+ const today = new Date()
+ today.setHours(0, 0, 0, 0)
+
+ const count = await prisma.trade.count({
+ where: {
+ userId,
+ isAutomated: true,
+ createdAt: {
+ gte: today
+ }
+ }
+ })
+
+ return count
+ }
+
+ async stopAutomation(): Promise {
+ try {
+ this.isRunning = false
+
+ // Clear the interval if it exists
+ if (this.intervalId) {
+ clearInterval(this.intervalId)
+ this.intervalId = null
+ }
+
+ // Stop price monitoring
+ try {
+ await priceMonitorService.stopMonitoring()
+ console.log('π Price monitoring stopped')
+ } catch (error) {
+ console.error('Failed to stop price monitoring:', error)
+ }
+
+ // Update database session status to STOPPED
+ if (this.config) {
+ await prisma.automationSession.updateMany({
+ where: {
+ userId: this.config.userId,
+ symbol: this.config.symbol,
+ timeframe: this.config.timeframe,
+ status: 'ACTIVE'
+ },
+ data: {
+ status: 'STOPPED',
+ updatedAt: new Date()
+ }
+ })
+ }
+
+ this.config = null
+
+ console.log('π Automation stopped')
+ return true
+ } catch (error) {
+ console.error('Failed to stop automation:', error)
+ return false
+ }
+ }
+
+ async pauseAutomation(): Promise {
+ try {
+ if (!this.isRunning) {
+ return false
+ }
+
+ this.isRunning = false
+ console.log('βΈοΈ Automation paused')
+ return true
+ } catch (error) {
+ console.error('Failed to pause automation:', error)
+ return false
+ }
+ }
+
+ async resumeAutomation(): Promise {
+ try {
+ if (!this.config) {
+ return false
+ }
+
+ this.isRunning = true
+ console.log('βΆοΈ Automation resumed')
+ return true
+ } catch (error) {
+ console.error('Failed to resume automation:', error)
+ return false
+ }
+ }
+
+ async getStatus(): Promise {
+ try {
+ // Get the latest active automation session from database first
+ const session = await prisma.automationSession.findFirst({
+ where: { status: 'ACTIVE' },
+ orderBy: { createdAt: 'desc' }
+ })
+
+ if (!session) {
+ return null
+ }
+
+ // If we have a session but automation is not running in memory,
+ // it means the server was restarted but the session is still active
+ const isActiveInMemory = this.isRunning && this.config !== null
+
+ // Auto-restart automation if session exists but not running in memory
+ if (!isActiveInMemory) {
+ console.log('π Found active session but automation not running, attempting auto-restart...')
+ await this.autoRestartFromSession(session)
+ }
+
+ return {
+ isActive: this.isRunning && this.config !== null,
+ mode: session.mode as 'SIMULATION' | 'LIVE',
+ symbol: session.symbol,
+ timeframe: session.timeframe,
+ totalTrades: session.totalTrades,
+ successfulTrades: session.successfulTrades,
+ winRate: session.winRate,
+ totalPnL: session.totalPnL,
+ errorCount: session.errorCount,
+ lastError: session.lastError || undefined,
+ lastAnalysis: session.lastAnalysis || undefined,
+ lastTrade: session.lastTrade || undefined,
+ nextScheduled: session.nextScheduled || undefined
+ }
+ } catch (error) {
+ console.error('Failed to get automation status:', error)
+ return null
+ }
+ }
+
+ private async autoRestartFromSession(session: any): Promise {
+ try {
+ const settings = session.settings || {}
+ const config: AutomationConfig = {
+ userId: session.userId,
+ mode: session.mode,
+ symbol: session.symbol,
+ timeframe: session.timeframe,
+ tradingAmount: settings.tradingAmount || 100,
+ maxLeverage: settings.maxLeverage || 3,
+ stopLossPercent: settings.stopLossPercent || 2,
+ takeProfitPercent: settings.takeProfitPercent || 6,
+ maxDailyTrades: settings.maxDailyTrades || 5,
+ riskPercentage: settings.riskPercentage || 2
+ }
+
+ await this.startAutomation(config)
+ console.log('β
Automation auto-restarted successfully')
+ } catch (error) {
+ console.error('Failed to auto-restart automation:', error)
+ }
+ }
+
+ async getLearningInsights(userId: string): Promise<{
+ totalAnalyses: number
+ avgAccuracy: number
+ bestTimeframe: string
+ worstTimeframe: string
+ commonFailures: string[]
+ recommendations: string[]
+ }> {
+ try {
+ // For now, return mock data
+ return {
+ totalAnalyses: 150,
+ avgAccuracy: 0.72,
+ bestTimeframe: '1h',
+ worstTimeframe: '15m',
+ commonFailures: [
+ 'Low confidence predictions',
+ 'Missed support/resistance levels',
+ 'Timeframe misalignment'
+ ],
+ recommendations: [
+ 'Focus on 1h timeframe for better accuracy',
+ 'Wait for higher confidence signals (>75%)',
+ 'Use multiple timeframe confirmation'
+ ]
+ }
+ } catch (error) {
+ console.error('Failed to get learning insights:', error)
+ return {
+ totalAnalyses: 0,
+ avgAccuracy: 0,
+ bestTimeframe: 'Unknown',
+ worstTimeframe: 'Unknown',
+ commonFailures: [],
+ recommendations: []
+ }
+ }
+ }
+
+ /**
+ * Trigger analysis based on price movement alerts
+ */
+ private async triggerPriceBasedAnalysis(
+ trigger: 'TP_APPROACH' | 'SL_APPROACH' | 'CRITICAL',
+ data: any
+ ): Promise {
+ if (!this.config || !this.isRunning) {
+ console.log('β Cannot trigger price-based analysis: automation not running')
+ return
+ }
+
+ const sessionId = `price-trigger-${Date.now()}`
+
+ try {
+ console.log(`π₯ Price-based analysis triggered by ${trigger} for ${data.symbol}`)
+ console.log(`π Current price: $${data.currentPrice}, Target: $${data.targetPrice}`)
+
+ // Create progress tracker for this analysis
+ const steps = [
+ { id: 'trigger', title: 'Triggered by price movement', description: 'Analysis initiated by price alert', status: 'pending' as ProgressStatus },
+ { id: 'screenshot', title: 'Capturing screenshots', description: 'Taking fresh market screenshots', status: 'pending' as ProgressStatus },
+ { id: 'analysis', title: 'Running AI analysis', description: 'Analyzing current market conditions', status: 'pending' as ProgressStatus },
+ { id: 'evaluation', title: 'Evaluating position', description: 'Checking position adjustments', status: 'pending' as ProgressStatus },
+ { id: 'complete', title: 'Analysis complete', description: 'Price-based analysis finished', status: 'pending' as ProgressStatus }
+ ]
+
+ progressTracker.createSession(sessionId, steps)
+
+ progressTracker.updateStep(sessionId, 'trigger', 'active', `${trigger}: ${data.symbol} at $${data.currentPrice}`)
+
+ // Run enhanced screenshot capture with current symbol/timeframe
+ progressTracker.updateStep(sessionId, 'screenshot', 'active')
+
+ const screenshotConfig = {
+ symbol: this.config.symbol,
+ timeframe: this.config.timeframe,
+ layouts: ['ai', 'diy'],
+ sessionId
+ }
+
+ const screenshots = await enhancedScreenshotService.captureWithLogin(screenshotConfig)
+
+ if (!screenshots || screenshots.length === 0) {
+ throw new Error('Failed to capture screenshots for price-based analysis')
+ }
+
+ progressTracker.updateStep(sessionId, 'screenshot', 'completed', `Captured ${screenshots.length} screenshots`)
+ progressTracker.updateStep(sessionId, 'analysis', 'active')
+
+ // Simplified analysis call - just use the first screenshot
+ const analysisResult = await aiAnalysisService.analyzeScreenshot(screenshots[0])
+
+ if (!analysisResult) {
+ throw new Error('AI analysis returned null result')
+ }
+
+ progressTracker.updateStep(sessionId, 'analysis', 'completed', `Analysis: ${analysisResult.recommendation}`)
+ progressTracker.updateStep(sessionId, 'evaluation', 'active')
+
+ // Store the triggered analysis in trading journal
+ await prisma.tradingJournal.create({
+ data: {
+ userId: this.config.userId,
+ screenshotUrl: screenshots[0] || '',
+ aiAnalysis: analysisResult.reasoning || 'No analysis available',
+ confidence: analysisResult.confidence || 0,
+ recommendation: analysisResult.recommendation || 'HOLD',
+ symbol: this.config.symbol,
+ timeframe: this.config.timeframe,
+ sessionId,
+ notes: `Price-triggered analysis: ${trigger} - Current: $${data.currentPrice}, Target: $${data.targetPrice}`,
+ marketSentiment: analysisResult.marketSentiment || 'Unknown',
+ tradingMode: this.config.mode,
+ isAutomated: true,
+ priceAtAnalysis: data.currentPrice,
+ marketCondition: trigger,
+ createdAt: new Date()
+ }
+ })
+
+ // Log important insights for potential position adjustments
+ if (analysisResult.recommendation === 'SELL' && trigger === 'SL_APPROACH') {
+ console.log('β οΈ AI recommends SELL while approaching Stop Loss - consider early exit')
+ } else if (analysisResult.recommendation === 'BUY' && trigger === 'TP_APPROACH') {
+ console.log('π― AI recommends BUY while approaching Take Profit - consider extending position')
+ }
+
+ progressTracker.updateStep(sessionId, 'evaluation', 'completed')
+ progressTracker.updateStep(sessionId, 'complete', 'completed',
+ `${analysisResult.recommendation} (${analysisResult.confidence}% confidence)`)
+
+ console.log(`β
Price-based analysis completed (${trigger}): ${analysisResult.recommendation} with ${analysisResult.confidence}% confidence`)
+
+ } catch (error) {
+ console.error(`β Price-based analysis failed (${trigger}):`, error)
+
+ progressTracker.updateStep(sessionId, 'complete', 'error',
+ `Error: ${error instanceof Error ? error.message : 'Unknown error'}`)
+
+ this.stats.errorCount++
+ this.stats.lastError = error instanceof Error ? error.message : 'Unknown error'
+ }
+ }
+}
+
+export const automationService = new AutomationService()
diff --git a/lib/automation-service.ts b/lib/automation-service.ts
index ce50f9d..2f9cd05 100644
--- a/lib/automation-service.ts
+++ b/lib/automation-service.ts
@@ -16,6 +16,7 @@ export interface AutomationConfig {
takeProfitPercent: number
maxDailyTrades: number
riskPercentage: number
+ dexProvider: 'JUPITER' | 'DRIFT'
}
export interface AutomationStatus {
@@ -388,13 +389,15 @@ export class AutomationService {
leverage
})
} else {
- // Execute real trade via Jupiter DEX
- tradeResult = await jupiterDEXService.executeTrade({
+ // Execute real trade via unified trading endpoint
+ tradeResult = await this.executeUnifiedTrade({
symbol: config.symbol,
side,
amount,
stopLoss: analysis.stopLoss?.price,
- takeProfit: analysis.takeProfits?.tp1?.price
+ takeProfit: analysis.takeProfits?.tp1?.price,
+ leverage,
+ dexProvider: config.dexProvider
})
}
@@ -449,6 +452,50 @@ export class AutomationService {
}
}
+ private async executeUnifiedTrade(params: {
+ symbol: string
+ side: string
+ amount: number
+ stopLoss?: number
+ takeProfit?: number
+ leverage?: number
+ dexProvider: 'JUPITER' | 'DRIFT'
+ }): Promise<{ success: boolean; txId?: string }> {
+ try {
+ console.log(`π Executing ${params.dexProvider} trade: ${params.side} ${params.amount} ${params.symbol}`)
+
+ const response = await fetch('http://localhost:3000/api/automation/trade', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ symbol: params.symbol,
+ side: params.side,
+ amount: params.amount,
+ leverage: params.leverage,
+ stopLoss: params.stopLoss,
+ takeProfit: params.takeProfit,
+ dexProvider: params.dexProvider,
+ mode: 'LIVE'
+ })
+ })
+
+ if (!response.ok) {
+ throw new Error(`Trade request failed: ${response.statusText}`)
+ }
+
+ const result = await response.json()
+ return {
+ success: result.success,
+ txId: result.txId || result.transactionId
+ }
+ } catch (error) {
+ console.error('Unified trade execution error:', error)
+ return { success: false }
+ }
+ }
+
private async simulateTrade(params: {
symbol: string
side: string
diff --git a/prisma/prisma/dev.db b/prisma/prisma/dev.db
index 28717ad..0076d95 100644
Binary files a/prisma/prisma/dev.db and b/prisma/prisma/dev.db differ
diff --git a/test-api-fix.js b/test-api-fix.js
index 388da55..e69de29 100644
--- a/test-api-fix.js
+++ b/test-api-fix.js
@@ -1,28 +0,0 @@
-const fetch = require('node-fetch')
-
-async function testAPI() {
- try {
- const response = await fetch('http://localhost:3001/api/automation/analysis-details')
- const data = await response.json()
-
- console.log('=== API TEST RESULTS ===')
- console.log(`Success: ${data.success}`)
- console.log(`Total trades returned: ${data.data?.recentTrades?.length || 0}`)
- console.log(`Total P&L: $${data.data?.session?.totalPnL || 0}`)
- console.log(`Win Rate: ${((data.data?.session?.successfulTrades || 0) / (data.data?.session?.totalTrades || 1) * 100).toFixed(1)}%`)
-
- console.log('\n=== RECENT TRADES ===')
- data.data?.recentTrades?.slice(0, 5).forEach((trade, i) => {
- console.log(`Trade ${i + 1}: ${trade.side} ${trade.amount} @ $${trade.price} = $${trade.positionSize} | P&L: $${trade.pnl} | Duration: ${trade.durationText}`)
- })
-
- if (data.data?.recentTrades?.length > 5) {
- console.log(`... and ${data.data.recentTrades.length - 5} more trades`)
- }
-
- } catch (error) {
- console.error('API Error:', error.message)
- }
-}
-
-testAPI()
diff --git a/test-automation-insights.js b/test-automation-insights.js
index 89b278d..e69de29 100644
--- a/test-automation-insights.js
+++ b/test-automation-insights.js
@@ -1,145 +0,0 @@
-const { PrismaClient } = require('@prisma/client');
-const prisma = new PrismaClient();
-
-// Test the automation insights functionality
-async function testAutomationInsights() {
- try {
- console.log('π§ Testing Automation Insights for Manual Analysis Enhancement...\n');
-
- const targetSymbol = '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;
-
- const 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'
- }
- };
-
- // Generate enhanced recommendation
- 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;
- }
-
- const automationInsights = {
- 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)
- };
-
- console.log('π― ENHANCED MANUAL ANALYSIS INSIGHTS:');
- console.log('=====================================');
- console.log('Multi-timeframe Consensus:', automationInsights.multiTimeframeConsensus);
- console.log('Average Confidence:', automationInsights.avgConfidence + '%');
- console.log('Market Trend:', automationInsights.marketTrend);
- console.log('Win Rate:', automationInsights.winRate);
- console.log('Profitable Pattern:', automationInsights.profitablePattern);
- console.log('Recommendation:', automationInsights.recommendation);
-
- console.log('\nπ RAW DATA:');
- console.log('============');
- console.log('Timeframe Signals:', automationContext.multiTimeframeSignals);
- console.log('Top Patterns:', automationContext.topPatterns.slice(0, 3));
- console.log('Market Context:', automationContext.marketContext);
-
- await prisma.$disconnect();
- console.log('\nβ
Test completed successfully!');
- } catch (error) {
- console.error('β Test failed:', error);
- await prisma.$disconnect();
- }
-}
-
-testAutomationInsights();
diff --git a/test-cleanup-integration.js b/test-cleanup-integration.js
new file mode 100644
index 0000000..e69de29
diff --git a/test-flag-simple.js b/test-flag-simple.js
new file mode 100644
index 0000000..e69de29
diff --git a/test-flag-system.js b/test-flag-system.js
new file mode 100644
index 0000000..e69de29
diff --git a/test-pnl-direct.js b/test-pnl-direct.js
index 9d08da7..e69de29 100644
--- a/test-pnl-direct.js
+++ b/test-pnl-direct.js
@@ -1,38 +0,0 @@
-const { PrismaClient } = require('@prisma/client')
-
-const prisma = new PrismaClient()
-
-async function testPnLCalculation() {
- try {
- const trades = await prisma.trade.findMany({
- orderBy: { createdAt: 'desc' },
- take: 3
- })
-
- const currentPrice = 175.82
-
- console.log('=== P&L CALCULATION TEST ===')
- trades.forEach((trade, i) => {
- const pnl = trade.status === 'COMPLETED' ?
- ((trade.side === 'BUY' ? (currentPrice - trade.price) * trade.amount : (trade.price - currentPrice) * trade.amount)) :
- 0
-
- console.log(`\nTrade ${i + 1}:`)
- console.log(` Side: ${trade.side}`)
- console.log(` Amount: ${trade.amount}`)
- console.log(` Price: ${trade.price}`)
- console.log(` Status: ${trade.status}`)
- console.log(` Current Price: ${currentPrice}`)
- console.log(` Price Diff: ${currentPrice - trade.price}`)
- console.log(` Raw P&L: ${pnl}`)
- console.log(` Formatted P&L: ${pnl.toFixed(2)}`)
- })
-
- } catch (error) {
- console.error('Error:', error)
- } finally {
- await prisma.$disconnect()
- }
-}
-
-testPnLCalculation()
diff --git a/test-unified-drift-trade.js b/test-unified-drift-trade.js
new file mode 100644
index 0000000..b7e6aa1
--- /dev/null
+++ b/test-unified-drift-trade.js
@@ -0,0 +1,133 @@
+#!/usr/bin/env node
+
+/**
+ * Test script to validate the unified trading endpoint with Drift integration
+ * This will test both simulation and live trading modes
+ */
+
+const API_BASE = 'http://localhost:3000'
+
+async function testUnifiedTradingEndpoint() {
+ console.log('π§ͺ Testing Unified Trading Endpoint with Drift Integration')
+ console.log('=' + '='.repeat(60))
+
+ // Test 1: Simulation trade with Drift
+ console.log('\nπ― Test 1: Drift Simulation Trade')
+ await testTrade({
+ symbol: 'SOL-PERP',
+ side: 'BUY',
+ amount: 0.01,
+ leverage: 5,
+ dexProvider: 'DRIFT',
+ mode: 'SIMULATION'
+ })
+
+ // Test 2: Simulation trade with Jupiter
+ console.log('\nπ― Test 2: Jupiter Simulation Trade')
+ await testTrade({
+ symbol: 'SOL',
+ side: 'BUY',
+ amount: 0.01,
+ dexProvider: 'JUPITER',
+ mode: 'SIMULATION'
+ })
+
+ // Test 3: Live trade with Drift (small amount)
+ console.log('\nπ― Test 3: Drift Live Trade (Small Amount)')
+ await testTrade({
+ symbol: 'SOL-PERP',
+ side: 'BUY',
+ amount: 0.001, // Very small amount for safety
+ leverage: 2,
+ dexProvider: 'DRIFT',
+ mode: 'LIVE'
+ })
+
+ console.log('\nβ
All tests completed!')
+}
+
+async function testTrade(tradeParams) {
+ try {
+ console.log(` π Trading ${tradeParams.amount} ${tradeParams.symbol} via ${tradeParams.dexProvider} (${tradeParams.mode})`)
+
+ const response = await fetch(`${API_BASE}/api/automation/trade`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(tradeParams)
+ })
+
+ if (!response.ok) {
+ const error = await response.text()
+ console.log(` β Request failed: ${response.status} - ${error}`)
+ return
+ }
+
+ const result = await response.json()
+
+ if (result.success) {
+ console.log(` β
Trade successful!`)
+ console.log(` Transaction ID: ${result.txId || result.transactionId || 'N/A'}`)
+ console.log(` Execution Price: ${result.executionPrice || 'N/A'}`)
+ console.log(` Provider: ${result.provider || tradeParams.dexProvider}`)
+
+ if (result.balance) {
+ console.log(` Updated Balance: ${result.balance} USDC`)
+ }
+ } else {
+ console.log(` β Trade failed: ${result.error || 'Unknown error'}`)
+ }
+
+ } catch (error) {
+ console.log(` β Test error: ${error.message}`)
+ }
+}
+
+// Test automation config format
+async function testAutomationConfig() {
+ console.log('\nπ§ͺ Testing Automation Config Format')
+ console.log('=' + '='.repeat(40))
+
+ const testConfig = {
+ userId: 'test_user',
+ mode: 'SIMULATION',
+ symbol: 'SOL-PERP',
+ timeframe: '5m',
+ tradingAmount: 100,
+ maxLeverage: 10,
+ stopLossPercent: 2,
+ takeProfitPercent: 6,
+ maxDailyTrades: 5,
+ riskPercentage: 2,
+ dexProvider: 'DRIFT'
+ }
+
+ console.log('π Sample automation config:')
+ console.log(JSON.stringify(testConfig, null, 2))
+ console.log('\nβ
Config format validated!')
+}
+
+// Run tests
+async function main() {
+ await testAutomationConfig()
+
+ // Check if server is running
+ try {
+ const healthCheck = await fetch(`${API_BASE}/api/health`).catch(() => null)
+ if (!healthCheck || !healthCheck.ok) {
+ console.log('\nβ οΈ Server not running. Please start the development server first:')
+ console.log(' npm run dev')
+ return
+ }
+ } catch (error) {
+ console.log('\nβ οΈ Could not connect to server. Please ensure it\'s running.')
+ return
+ }
+
+ await testUnifiedTradingEndpoint()
+}
+
+if (require.main === module) {
+ main().catch(console.error)
+}