FRONTEND PRESET CORRECTIONS: - Scalp Trading: 5m, 15m, 30m (was 5m, 15m) → 3 timeframes - Day Trading: 1h, 2h (was 1h, 4h) → 2 timeframes - Swing Trading: 4h, 1D (correct) → 2 timeframes UPDATED FILES: - lib/superior-screenshot-service.ts → Correct timeframe definitions - lib/auto-trading-service.ts → TRADING_CONFIGS match frontend - app/api/superior-screenshot/route.js → API presets corrected - Verification and test scripts updated PERFORMANCE ESTIMATES: - Scalp (3 timeframes): ~90s → ~30-40s parallel - Day Trading (2 timeframes): ~60s → ~20-30s parallel - Swing Trading (2 timeframes): ~60s → ~20-30s parallel - Extended (9 timeframes): ~270s → ~70-100s parallel System now matches frontend UI exactly with superior parallel capture!
317 lines
11 KiB
TypeScript
317 lines
11 KiB
TypeScript
/**
|
|
* Superior Parallel Screenshot Service
|
|
* Uses the proven scalp preset parallel API technique for maximum efficiency
|
|
*/
|
|
|
|
// Trading strategy presets matching the frontend UI
|
|
const SCALP_TIMEFRAMES = [
|
|
{ name: '5m', tv: '5', description: 'Standard scalping' },
|
|
{ name: '15m', tv: '15', description: 'Swing scalping' },
|
|
{ name: '30m', tv: '30', description: 'Extended scalping' }
|
|
]
|
|
|
|
const DAY_TRADING_TIMEFRAMES = [
|
|
{ name: '1h', tv: '60', description: 'Hourly analysis' },
|
|
{ name: '2h', tv: '120', description: 'Two-hour trend' }
|
|
]
|
|
|
|
const SWING_TRADING_TIMEFRAMES = [
|
|
{ name: '4h', tv: '240', description: 'Four-hour trend' },
|
|
{ name: '1D', tv: '1D', description: 'Daily analysis' }
|
|
]
|
|
|
|
// Additional timeframes for comprehensive analysis
|
|
const EXTENDED_TIMEFRAMES = [
|
|
{ name: '1m', tv: '1', description: 'Ultra-short scalping' },
|
|
{ name: '3m', tv: '3', description: 'Short scalping' },
|
|
{ name: '2m', tv: '2', description: 'Very short scalping' },
|
|
{ name: '10m', tv: '10', description: 'Medium scalping' },
|
|
{ name: '30m', tv: '30', description: 'Longer scalping' },
|
|
{ name: '45m', tv: '45', description: 'Extended scalping' },
|
|
{ name: '2h', tv: '120', description: 'Medium trend' },
|
|
{ name: '6h', tv: '360', description: 'Long trend' },
|
|
{ name: '12h', tv: '720', description: 'Daily trend' },
|
|
{ name: '3D', tv: '3D', description: 'Multi-day trend' },
|
|
{ name: '1W', tv: '1W', description: 'Weekly analysis' }
|
|
]
|
|
|
|
export interface SuperiorScreenshotConfig {
|
|
symbol: string
|
|
timeframes?: string[] // If not provided, uses SCALP_TIMEFRAMES
|
|
layouts?: string[] // Default: ['ai', 'diy']
|
|
preset?: 'scalp' | 'day-trading' | 'swing-trading' | 'extended' | 'all' | 'custom'
|
|
analyze?: boolean // Whether to run AI analysis
|
|
apiUrl?: string // API endpoint (default: http://localhost:9001)
|
|
}
|
|
|
|
export interface ScreenshotResult {
|
|
timeframe: string
|
|
timeframeName: string
|
|
success: boolean
|
|
screenshots?: string[]
|
|
sessionId?: string
|
|
error?: string
|
|
}
|
|
|
|
export class SuperiorScreenshotService {
|
|
private apiUrl: string
|
|
|
|
constructor(apiUrl: string = 'http://localhost:9001') {
|
|
this.apiUrl = apiUrl
|
|
}
|
|
|
|
/**
|
|
* Capture screenshots using the superior parallel API technique
|
|
* This replaces all legacy screenshot methods with proven efficiency
|
|
*/
|
|
async captureParallel(config: SuperiorScreenshotConfig): Promise<ScreenshotResult[]> {
|
|
console.log('🚀 SUPERIOR SCREENSHOT SERVICE: Parallel API Capture')
|
|
|
|
const {
|
|
symbol,
|
|
layouts = ['ai', 'diy'],
|
|
preset = 'scalp',
|
|
analyze = false
|
|
} = config
|
|
|
|
// Determine timeframes based on preset
|
|
let timeframesToCapture: typeof SCALP_TIMEFRAMES
|
|
|
|
switch (preset) {
|
|
case 'scalp':
|
|
timeframesToCapture = SCALP_TIMEFRAMES
|
|
break
|
|
case 'day-trading':
|
|
timeframesToCapture = DAY_TRADING_TIMEFRAMES
|
|
break
|
|
case 'swing-trading':
|
|
timeframesToCapture = SWING_TRADING_TIMEFRAMES
|
|
break
|
|
case 'extended':
|
|
timeframesToCapture = [...SCALP_TIMEFRAMES, ...DAY_TRADING_TIMEFRAMES, ...SWING_TRADING_TIMEFRAMES, ...EXTENDED_TIMEFRAMES]
|
|
break
|
|
case 'all':
|
|
timeframesToCapture = [...SCALP_TIMEFRAMES, ...DAY_TRADING_TIMEFRAMES, ...SWING_TRADING_TIMEFRAMES, ...EXTENDED_TIMEFRAMES]
|
|
break
|
|
case 'custom':
|
|
if (config.timeframes) {
|
|
// Convert custom timeframes to our format
|
|
timeframesToCapture = config.timeframes.map(tf => ({
|
|
name: tf,
|
|
tv: tf,
|
|
description: 'Custom timeframe'
|
|
}))
|
|
} else {
|
|
timeframesToCapture = SCALP_TIMEFRAMES
|
|
}
|
|
break
|
|
default:
|
|
timeframesToCapture = SCALP_TIMEFRAMES
|
|
}
|
|
|
|
console.log('📋 Configuration:')
|
|
console.log(` 📊 Symbol: ${symbol}`)
|
|
console.log(` 📈 Preset: ${preset}`)
|
|
console.log(` ⏱️ Timeframes: ${timeframesToCapture.length} (${timeframesToCapture.map(tf => tf.name).join(', ')})`)
|
|
console.log(` 🎨 Layouts: ${layouts.length} (${layouts.join(', ')})`)
|
|
console.log(` 📸 Total Screenshots: ${timeframesToCapture.length * layouts.length}`)
|
|
console.log(` 🤖 AI Analysis: ${analyze ? 'Yes' : 'No'}`)
|
|
|
|
const startTime = Date.now()
|
|
|
|
try {
|
|
console.log('\n🔄 Starting superior parallel capture...')
|
|
|
|
// Create parallel promises for each timeframe using proven API technique
|
|
const capturePromises = timeframesToCapture.map(async (tf, index) => {
|
|
try {
|
|
console.log(`📸 [${index + 1}/${timeframesToCapture.length}] Capturing ${tf.name} (${tf.tv})...`)
|
|
|
|
const response = await fetch(`${this.apiUrl}/api/enhanced-screenshot`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({
|
|
symbol: symbol,
|
|
timeframe: tf.tv,
|
|
layouts: layouts,
|
|
analyze: analyze
|
|
})
|
|
})
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`API request failed: ${response.status} ${response.statusText}`)
|
|
}
|
|
|
|
const result = await response.json()
|
|
|
|
if (result.success && result.screenshots) {
|
|
console.log(`✅ ${tf.name}: Captured ${result.screenshots.length}/${layouts.length} screenshots`)
|
|
return {
|
|
timeframe: tf.tv,
|
|
timeframeName: tf.name,
|
|
success: true,
|
|
screenshots: result.screenshots,
|
|
sessionId: result.sessionId
|
|
}
|
|
} else {
|
|
throw new Error(result.error || 'Unknown API error')
|
|
}
|
|
|
|
} catch (error) {
|
|
const errorMessage = error instanceof Error ? error.message : String(error)
|
|
console.error(`❌ ${tf.name}: Failed - ${errorMessage}`)
|
|
return {
|
|
timeframe: tf.tv,
|
|
timeframeName: tf.name,
|
|
success: false,
|
|
error: errorMessage
|
|
}
|
|
}
|
|
})
|
|
|
|
// Wait for all parallel captures to complete
|
|
console.log('\n⏳ Waiting for all parallel captures to complete...')
|
|
const results = await Promise.all(capturePromises)
|
|
|
|
const endTime = Date.now()
|
|
const duration = (endTime - startTime) / 1000
|
|
|
|
// Analyze results
|
|
const successful = results.filter(r => r.success)
|
|
const failed = results.filter(r => !r.success)
|
|
const totalScreenshots = successful.reduce((sum, r) => sum + (r.screenshots?.length || 0), 0)
|
|
|
|
console.log('\n✅ SUPERIOR PARALLEL CAPTURE COMPLETED!')
|
|
console.log(`⏱️ Total Duration: ${duration.toFixed(2)} seconds`)
|
|
console.log(`📸 Screenshots Captured: ${totalScreenshots}/${timeframesToCapture.length * layouts.length}`)
|
|
console.log(`🎯 Timeframes Successful: ${successful.length}/${timeframesToCapture.length}`)
|
|
console.log(`🚀 Average Speed: ${(totalScreenshots / duration).toFixed(1)} screenshots/second`)
|
|
|
|
const successRate = (successful.length / timeframesToCapture.length * 100).toFixed(1)
|
|
console.log(`📈 SUCCESS RATE: ${successRate}%`)
|
|
|
|
if (successful.length === timeframesToCapture.length) {
|
|
console.log('🎉 PERFECT SUCCESS: All timeframes captured!')
|
|
} else if (successful.length > 0) {
|
|
console.log(`⚠️ PARTIAL SUCCESS: ${successful.length}/${timeframesToCapture.length} timeframes`)
|
|
}
|
|
|
|
return results
|
|
|
|
} catch (error) {
|
|
console.error('❌ Superior screenshot service failed:', error)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Quick capture for single timeframe (backwards compatibility)
|
|
* Uses the superior parallel technique even for single captures
|
|
*/
|
|
async captureQuick(symbol: string, timeframe: string, layouts: string[] = ['ai']): Promise<string[]> {
|
|
console.log(`🚀 Quick capture using superior technique: ${symbol} ${timeframe}`)
|
|
|
|
const config: SuperiorScreenshotConfig = {
|
|
symbol,
|
|
preset: 'custom',
|
|
timeframes: [timeframe],
|
|
layouts,
|
|
analyze: false
|
|
}
|
|
|
|
const results = await this.captureParallel(config)
|
|
const successfulResult = results.find(r => r.success)
|
|
|
|
return successfulResult?.screenshots || []
|
|
}
|
|
|
|
/**
|
|
* Scalp preset - optimized for scalping strategies (5m, 15m)
|
|
*/
|
|
async captureScalpPreset(symbol: string, analyze: boolean = false): Promise<ScreenshotResult[]> {
|
|
return this.captureParallel({
|
|
symbol,
|
|
preset: 'scalp',
|
|
layouts: ['ai', 'diy'],
|
|
analyze
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Day trading preset - moderate timeframes (1h, 4h)
|
|
*/
|
|
async captureDayTradingPreset(symbol: string, analyze: boolean = false): Promise<ScreenshotResult[]> {
|
|
return this.captureParallel({
|
|
symbol,
|
|
preset: 'day-trading',
|
|
layouts: ['ai', 'diy'],
|
|
analyze
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Swing trading preset - longer timeframes (4h, 1D)
|
|
*/
|
|
async captureSwingTradingPreset(symbol: string, analyze: boolean = false): Promise<ScreenshotResult[]> {
|
|
return this.captureParallel({
|
|
symbol,
|
|
preset: 'swing-trading',
|
|
layouts: ['ai', 'diy'],
|
|
analyze
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Extended preset - comprehensive timeframe analysis
|
|
*/
|
|
async captureExtendedPreset(symbol: string, analyze: boolean = false): Promise<ScreenshotResult[]> {
|
|
return this.captureParallel({
|
|
symbol,
|
|
preset: 'extended',
|
|
layouts: ['ai', 'diy'],
|
|
analyze
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Legacy compatibility method - replaces old captureWithLogin
|
|
*/
|
|
async captureWithLogin(config: any): Promise<string[]> {
|
|
console.log('🔄 Legacy captureWithLogin called - upgrading to superior technique')
|
|
|
|
const superiorConfig: SuperiorScreenshotConfig = {
|
|
symbol: config.symbol || 'SOLUSD',
|
|
preset: 'custom',
|
|
timeframes: [config.timeframe || '240'],
|
|
layouts: config.layouts || ['ai', 'diy'],
|
|
analyze: false
|
|
}
|
|
|
|
const results = await this.captureParallel(superiorConfig)
|
|
|
|
// Return flat array of screenshot paths for compatibility
|
|
return results.reduce((paths: string[], result) => {
|
|
if (result.success && result.screenshots) {
|
|
paths.push(...result.screenshots)
|
|
}
|
|
return paths
|
|
}, [])
|
|
}
|
|
|
|
/**
|
|
* No cleanup needed - API handles all browser management
|
|
*/
|
|
async cleanup(): Promise<void> {
|
|
console.log('✅ Superior screenshot service cleanup (API-managed)')
|
|
// No action needed - API handles all cleanup
|
|
}
|
|
}
|
|
|
|
// Export singleton instance for drop-in replacement
|
|
export const superiorScreenshotService = new SuperiorScreenshotService()
|
|
|
|
// Export for legacy compatibility
|
|
export const enhancedScreenshotService = superiorScreenshotService
|