import { ProStrategyEngine } from '../src/strategies/ProStrategyEngine.js'; import { IExchangeConnector, Candle } from '../src/connectors/types.js'; import { config } from '../src/config/index.js'; import logger from '../src/utils/logger.js'; // --- MOCK LIVE EXCHANGE --- class LiveSimulationExchange implements IExchangeConnector { private currentTime = Date.now(); private price = 50000; private trend = 1; // 1 = Up, -1 = Down async fetchOHLCV(symbol: string, timeframe: string, limit?: number): Promise { // Generate a history of candles ending at 'currentTime' const candles: Candle[] = []; let tempPrice = this.price - (300 * 10); // Start back in time const count = limit || 100; for (let i = 0; i < count; i++) { // Add some "trend" bias based on our internal state const noise = (Math.random() - 0.5) * 50; const move = (this.trend * 50) + noise; // Stronger trend (was 20) tempPrice += move; candles.push({ timestamp: this.currentTime - ((count - i) * getMs(timeframe)), open: tempPrice, high: tempPrice + 50, low: tempPrice - 50, close: tempPrice, // Close is what matters for EMA typically volume: 1000 }); } return candles; } // Helper to advance the simulation public tick() { this.currentTime += 60 * 60 * 1000; // Advance 1 hour this.price += this.trend * 100 + (Math.random() - 0.5) * 200; // Move price } public setTrend(dir: 1 | -1) { this.trend = dir; } async placeOrder(symbol: string, side: 'buy' | 'sell', qty: number, type: 'market' | 'limit'): Promise { return { id: 'mock-sim-order' }; } async getPosition(symbol: string): Promise { return null; } } function getMs(tf: string): number { if (tf === '4h') return 4 * 60 * 60 * 1000; if (tf === '1h') return 1 * 60 * 60 * 1000; return 60000; } // --- MAIN RUNNER --- async function runLiveSimulation() { console.log('🚀 INITIALIZING PRO STRATEGY LIVE SIMULATION...\n'); // 1. Setup Mock Exchange const exchange = new LiveSimulationExchange(); const engine = new ProStrategyEngine(exchange); // Mock Config config.PRO_STRATEGY.PARAMETERS.SESSION_WINDOWS = [{ start: 0, end: 24 }]; config.PRO_STRATEGY.PARAMETERS.RSI_OVERBOUGHT = 99; console.log('--- PHASE 1: WARMUP (Generating Uptrend Data) ---'); exchange.setTrend(1); // Uptrend // Simulate 5 "Ticks" (Hours) of trading for (let i = 1; i <= 5; i++) { console.log(`\n⏰ HOUR ${i}: Fetching Market Data...`); exchange.tick(); // Advance time/price const result = await engine.execute('BTC/USD'); if (result?.passed) { const reason = result.reason || 'No reason'; console.log(`✅ [Trade Taken] ${result.signal} | Reason: ${reason.split('\n')[0]}...`); } else { console.log(`⏸️ [Skipped] Reason: ${result?.reason}`); } // Sleep for effect await new Promise(r => setTimeout(r, 500)); } console.log('\n--- PHASE 2: MARKET CRASH (Trend Reversal) ---'); exchange.setTrend(-1); // Downtrend for (let i = 1; i <= 10; i++) { // Need enough ticks to bend the 4H EMA // Speed up simulation exchange.tick(); exchange.tick(); exchange.tick(); } console.log(`\n⏰ HOUR 6 (After Crash): Checking Logic...`); const resultCrash = await engine.execute('BTC/USD'); if (!resultCrash?.passed) { console.log(`✅ [Correctly Skipped] Market Crash filtered! Reason: ${resultCrash?.reason}`); } else { console.log(`❌ [BAD TRADE] Strategy bought during crash? Signal: ${resultCrash?.signal}`); } console.log('\n✨ SIMULATION COMPLETE'); } runLiveSimulation();