import { supabaseService } from '../src/services/SupabaseService.js'; import { AutoTrader } from '../src/services/AutoTrader.js'; import { TradeExecutor } from '../src/services/TradeExecutor.js'; import { AlpacaConnector } from '../src/connectors/alpaca.js'; import { ProStrategyEngine } from '../src/strategies/ProStrategyEngine.js'; import { config } from '../src/config/index.js'; import { SignalDirection, MarketContext } from '../src/strategies/rules/types.js'; import logger from '../src/utils/logger.js'; config.ENABLE_TRADING = true; config.PAPER_TRADING = true; const SLEEP_MS = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); async function runParamVerification() { logger.info('==================================================='); logger.info('๐Ÿงช STARTING PARAMETER-AWARE E2E VERIFICATION'); logger.info(' Testing contrast between High Risk and Low Risk settings.'); logger.info('==================================================='); // 1. Fetch our two distinct profiles const profiles = await supabaseService.getActiveProfiles(); const highRisk = profiles.find(p => p.name.includes('High Risk')); const lowRisk = profiles.find(p => p.name.includes('Low Risk')); if (!highRisk || !lowRisk) { logger.error('โŒ Could not find both profiles (Scalper and Swing). Run create scripts first.'); process.exit(1); } const user = highRisk.users; // Both belong to same user in our setup const exchange = new AlpacaConnector(user.ALPACA_API_KEY, user.ALPACA_SECRET_KEY); const engine = new ProStrategyEngine(exchange); // 2. Setup Traders const executorHigh = new TradeExecutor(exchange, undefined, user.user_id, highRisk.id); const traderHigh = new AutoTrader(executorHigh, exchange, highRisk, engine); const executorLow = new TradeExecutor(exchange, undefined, user.user_id, lowRisk.id); const traderLow = new AutoTrader(executorLow, exchange, lowRisk, engine); // 3. Define Market Context with RSI = 75 // Scenario: RSI is 75. // Low Risk Swing logic (default RSI 70) -> Should Trigger SELL // High Risk Scalper logic (custom RSI 80) -> Should NOT Trigger (75 < 80) const mockCandles = Array(100).fill({ close: 65000, high: 65100, low: 64900, open: 65000, volume: 100 }); const mockContext: MarketContext = { symbol: 'BTC/USD', currentPrice: 65000, candles1h: mockCandles, candles15m: mockCandles, candles4h: mockCandles, rsi_1h: 75, // THE MAGIC NUMBER ema20_1h: 64000, ema50_4h: 60000, ema200_4h: 55000, session: 'NY', isMajorSession: true, volatility: 'Med', change24h: 1, changeToday: 0.5, latestSignal: SignalDirection.NONE }; const analysis: any = { symbol: 'BTC/USD', globalSignal: SignalDirection.NONE, rules: {}, // Global results don't matter now as we re-evaluate context: mockContext }; logger.info('\n๐Ÿ“Š Scenario: RSI is 75'); logger.info(` Profile [Low Risk]: Threshold 70 -> Expected: PASS`); logger.info(` Profile [High Risk]: Threshold 80 -> Expected: FAIL`); // 4. Test Execution logger.info('\nโšก Testing [Low Risk Swing]...'); await traderLow.handleSignal('BTC/USD', analysis); logger.info('โšก Testing [High Risk Scalper]...'); await traderHigh.handleSignal('BTC/USD', analysis); // 5. Verification logger.info('\n๐Ÿ RESULTS:'); // We can't easily wait for orders in this fake test without mocking exchange, // but we can look at the logs to see where "EXECUTING" appeared. logger.info('==================================================='); logger.info('โœ… VERIFICATION COMPLETE'); logger.info(' Please check the logs above for "EXECUTING" vs "Blocked" messages.'); logger.info('==================================================='); process.exit(0); } runParamVerification().catch(err => { logger.error('Test Failed:', err); process.exit(1); });