feat: implement real-time price monitoring with automatic analysis triggering
New Features: - Real-time price monitoring service with 5-minute update cycles - Automatic analysis triggering when prices approach TP/SL levels (15%/25% thresholds) - Comprehensive price monitoring UI component with live updates - Integration with automation service for smart analysis scheduling - PnL tracking and position status monitoring - EventEmitter-based real-time updates - CoinGecko API integration with rate limiting - TP/SL approach detection with configurable thresholds - Alert system for critical price movements - Database integration for trade tracking - Price monitor startup/shutdown with automation lifecycle - Event listeners for TP_APPROACH, SL_APPROACH, CRITICAL alerts - Automatic screenshot capture and AI analysis on price triggers - Enhanced progress tracking for price-based analysis - Intelligent analysis context with price movement data - RealTimePriceMonitor component with live price display - Trade monitoring cards with P&L and distance to TP/SL - Active alerts panel with price threshold notifications - Monitoring service controls (start/stop/force update) - Integration with automation page for comprehensive oversight - GET: Retrieve monitoring data, alerts, and current prices - POST: Control monitoring service and force price updates - Real-time data formatting and status management - Comprehensive price monitor integration tests - Basic functionality validation scripts - API endpoint testing capabilities This implements the user's request for real-time price monitoring with automatic analysis triggering when prices approach critical levels, providing enhanced oversight of active trading positions.
This commit is contained in:
@@ -3,9 +3,10 @@ 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 } from './progress-tracker'
|
||||
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()
|
||||
|
||||
@@ -110,6 +111,31 @@ export class AutomationService {
|
||||
// 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)
|
||||
@@ -791,6 +817,14 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r.
|
||||
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({
|
||||
@@ -951,6 +985,111 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger analysis based on price movement alerts
|
||||
*/
|
||||
private async triggerPriceBasedAnalysis(
|
||||
trigger: 'TP_APPROACH' | 'SL_APPROACH' | 'CRITICAL',
|
||||
data: any
|
||||
): Promise<void> {
|
||||
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()
|
||||
|
||||
Reference in New Issue
Block a user