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'; import { SignalDirection } from '../src/strategies/rules/types.js'; // Mock Exchange class MockExchange implements IExchangeConnector { async fetchOHLCV(symbol: string, timeframe: string, limit?: number): Promise { // Return mostly flat/bullish data to pass other rules const candles: Candle[] = []; let price = 50000; const now = Date.now(); for (let i = 0; i < 300; i++) { price += (Math.random() - 0.4) * 100; // Slight uptrend candles.push({ timestamp: now - (300 - i) * 3600000, open: price, high: price + 50, low: price - 50, close: price + 10, volume: 1000 }); } return candles; } async placeOrder(symbol: string, side: 'buy' | 'sell', qty: number, type: 'market' | 'limit'): Promise { return { id: 'mock-order' }; } async getPosition(symbol: string): Promise { return null; } } async function runTest() { logger.info('--- STARTING AI LAYER VERIFICATION ---'); // MOCK CONFIG config.PRO_STRATEGY.ENABLED_RULES = ['ai_analysis']; // Only checking AI config.AI.API_KEY = 'test-key'; // Fake key to pass isEnabled check config.AI.CONFIDENCE_THRESHOLD = 70; const exchange = new MockExchange(); const engine = new ProStrategyEngine(exchange); // INJECT MOCK AI CLIENT const aiRule: any = engine['rules'].find((r: any) => r.name === 'AIAnalysisRule'); if (!aiRule) { logger.error('❌ AIAnalysisRule not found in engine!'); return; } // Mock the generateAnalysis method aiRule.aiClient.generateAnalysis = async (prompt: string) => { logger.info(`[MockAI] Received Prompt length: ${prompt.length}`); // Return a HIGH confidence response return JSON.stringify({ action: "BUY", confidence: 85, reasoning: "Strong uptrend confirmed by EMA alignment." }); }; logger.info('[TEST 1] High Confidence Scenario'); const resultPass = await engine.execute('BTC/USD'); if (resultPass?.passed && resultPass?.metadata?.aiReasoning) { logger.info(`✅ PASSED -> AI Confidence 85 accepted. Reasoning: ${resultPass.metadata.aiReasoning}`); } else { logger.error(`❌ FAILED -> ${resultPass?.reason}`); } // TEST LOW CONFIDENCE logger.info('\n[TEST 2] Low Confidence Scenario'); aiRule.aiClient.generateAnalysis = async (prompt: string) => { return JSON.stringify({ action: "HOLD", confidence: 40, reasoning: "Market choppy, low confidence." }); }; const resultFail = await engine.execute('BTC/USD'); if (!resultFail?.passed && resultFail?.ruleName === 'AIAnalysisRule') { logger.info(`✅ CORRECTLY FAILED -> AI Confidence 40 rejected. Reason: ${resultFail.reason}`); } else { logger.error(`❌ UNEXPECTED PASS or WRONG FAIL -> ${resultFail?.reason}`); } } runTest().catch(console.error);