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:
mindesbunister
2025-07-21 10:31:49 +02:00
parent d0cabeb911
commit 7de3eaf7b8
8 changed files with 1171 additions and 1 deletions

View File

@@ -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()