/** * HNSW Vector Search Integration * * Demonstrates using Neural Trader's native HNSW implementation * (150x faster than pure JS) with RuVector's vector database * * Features: * - Native Rust HNSW indexing via NAPI * - SIMD-accelerated distance calculations * - Approximate nearest neighbor search * - Pattern matching for trading signals */ import NeuralTrader from 'neural-trader'; // HNSW configuration optimized for trading patterns const hnswConfig = { // Index construction parameters m: 32, // Max connections per node (higher = better recall, more memory) efConstruction: 200, // Build-time search depth (higher = better index, slower build) // Search parameters efSearch: 100, // Query-time search depth (higher = better recall, slower search) // Distance metric distanceMetric: 'cosine', // cosine, euclidean, dotProduct, manhattan // Performance optimizations simd: true, // Use SIMD for distance calculations quantization: { enabled: false, // Enable for 4x memory reduction bits: 8 // Quantization precision } }; // Vector dimension for trading features const VECTOR_DIM = 256; const PATTERN_LOOKBACK = 50; // Days to analyze for patterns async function main() { console.log('='.repeat(60)); console.log('HNSW Vector Search - Neural Trader Integration'); console.log('='.repeat(60)); console.log(); // 1. Initialize HNSW Index console.log('1. Initializing HNSW Index...'); console.log(` Dimensions: ${VECTOR_DIM}`); console.log(` M (connections): ${hnswConfig.m}`); console.log(` ef_construction: ${hnswConfig.efConstruction}`); console.log(` ef_search: ${hnswConfig.efSearch}`); console.log(` SIMD acceleration: ${hnswConfig.simd ? 'Enabled' : 'Disabled'}`); console.log(); // 2. Generate historical trading patterns console.log('2. Generating historical trading patterns...'); const patterns = generateHistoricalPatterns(10000); console.log(` Generated ${patterns.length} historical patterns`); console.log(); // 3. Build HNSW index console.log('3. Building HNSW index...'); const buildStart = performance.now(); // Simulate native HNSW index building const index = await buildHNSWIndex(patterns, hnswConfig); const buildTime = performance.now() - buildStart; console.log(` Index built in ${buildTime.toFixed(2)}ms`); console.log(` Throughput: ${(patterns.length / (buildTime / 1000)).toFixed(0)} vectors/sec`); console.log(); // 4. Real-time pattern matching console.log('4. Real-time pattern matching...'); const currentPattern = generateCurrentPattern(); const searchStart = performance.now(); const matches = await searchHNSW(index, currentPattern.vector, 10); const searchTime = performance.now() - searchStart; console.log(` Query time: ${searchTime.toFixed(3)}ms`); console.log(` Found ${matches.length} similar patterns:`); console.log(); // Display matches console.log(' Rank | Similarity | Symbol | Date | Next Day Return'); console.log(' ' + '-'.repeat(55)); matches.forEach((match, i) => { const date = new Date(match.metadata.timestamp).toISOString().split('T')[0]; const returnStr = (match.metadata.nextDayReturn * 100).toFixed(2) + '%'; console.log(` ${(i + 1).toString().padStart(4)} | ${match.similarity.toFixed(4).padStart(10)} | ${match.metadata.symbol.padEnd(6)} | ${date} | ${returnStr.padStart(15)}`); }); console.log(); // 5. Generate trading signal based on historical patterns console.log('5. Trading Signal Analysis...'); const signal = analyzePatterns(matches); console.log(` Expected return: ${(signal.expectedReturn * 100).toFixed(2)}%`); console.log(` Win rate: ${(signal.winRate * 100).toFixed(1)}%`); console.log(` Confidence: ${(signal.confidence * 100).toFixed(1)}%`); console.log(` Signal: ${signal.action.toUpperCase()}`); console.log(); // 6. Benchmark comparison console.log('6. Performance Benchmark...'); await runBenchmark(patterns); console.log(); console.log('='.repeat(60)); console.log('HNSW Vector Search completed!'); console.log('='.repeat(60)); } // Generate historical trading patterns with labels function generateHistoricalPatterns(count) { const symbols = ['AAPL', 'GOOGL', 'MSFT', 'AMZN', 'NVDA', 'META', 'TSLA', 'AMD']; const patterns = []; for (let i = 0; i < count; i++) { const symbol = symbols[i % symbols.length]; const vector = generatePatternVector(); const nextDayReturn = (Math.random() - 0.48) * 0.1; // Slight positive bias patterns.push({ id: `pattern_${i}`, vector, metadata: { symbol, timestamp: Date.now() - (count - i) * 86400000, nextDayReturn, volatility: Math.random() * 0.05, volume: Math.floor(Math.random() * 10000000) } }); } return patterns; } // Generate a pattern vector with technical features function generatePatternVector() { const vector = new Float32Array(VECTOR_DIM); // Price returns (0-49) for (let i = 0; i < 50; i++) { vector[i] = (Math.random() - 0.5) * 0.1; } // Volume features (50-99) for (let i = 50; i < 100; i++) { vector[i] = Math.random() * 2 - 1; } // Moving averages (100-119) for (let i = 100; i < 120; i++) { vector[i] = (Math.random() - 0.5) * 0.2; } // RSI features (120-139) for (let i = 120; i < 140; i++) { vector[i] = Math.random() * 2 - 1; // Normalized RSI } // MACD features (140-159) for (let i = 140; i < 160; i++) { vector[i] = (Math.random() - 0.5) * 0.5; } // Bollinger band features (160-179) for (let i = 160; i < 180; i++) { vector[i] = (Math.random() - 0.5) * 2; } // Additional technical indicators (180-255) for (let i = 180; i < VECTOR_DIM; i++) { vector[i] = (Math.random() - 0.5) * 0.3; } // Normalize the vector const norm = Math.sqrt(vector.reduce((sum, v) => sum + v * v, 0)); for (let i = 0; i < VECTOR_DIM; i++) { vector[i] /= norm; } return vector; } // Generate current market pattern function generateCurrentPattern() { return { vector: generatePatternVector(), metadata: { symbol: 'CURRENT', timestamp: Date.now() } }; } // Build HNSW index (simulates native binding) async function buildHNSWIndex(patterns, config) { // In production with neural-trader native bindings: // const { HNSWIndex } = require('neural-trader/native'); // const index = new HNSWIndex(VECTOR_DIM, config); // await index.addBatch(patterns); // Simulate index building const index = { size: patterns.length, patterns: patterns, config: config }; // Simulate build time based on complexity const estimatedBuildTime = patterns.length * 0.05; // ~0.05ms per vector await new Promise(resolve => setTimeout(resolve, Math.min(estimatedBuildTime, 100))); return index; } // Search HNSW index async function searchHNSW(index, queryVector, k) { // In production: // return await index.search(queryVector, k); // Simulate approximate nearest neighbor search const results = []; const queryNorm = Math.sqrt(queryVector.reduce((sum, v) => sum + v * v, 0)); // Calculate cosine similarities (simulated - in production uses SIMD) const similarities = index.patterns.map((pattern, idx) => { let dotProduct = 0; for (let i = 0; i < VECTOR_DIM; i++) { dotProduct += queryVector[i] * pattern.vector[i]; } return { index: idx, similarity: dotProduct // Already normalized }; }); // Sort by similarity (descending) and take top k similarities.sort((a, b) => b.similarity - a.similarity); for (let i = 0; i < k; i++) { const match = similarities[i]; const pattern = index.patterns[match.index]; results.push({ id: pattern.id, similarity: match.similarity, metadata: pattern.metadata }); } return results; } // Analyze matched patterns to generate trading signal function analyzePatterns(matches) { // Calculate expected return from similar patterns const returns = matches.map(m => m.metadata.nextDayReturn); const weights = matches.map(m => m.similarity); const totalWeight = weights.reduce((sum, w) => sum + w, 0); const expectedReturn = returns.reduce((sum, r, i) => sum + r * weights[i], 0) / totalWeight; const winRate = returns.filter(r => r > 0).length / returns.length; // Confidence based on similarity and consistency const avgSimilarity = matches.reduce((sum, m) => sum + m.similarity, 0) / matches.length; const returnStd = Math.sqrt( returns.reduce((sum, r) => sum + Math.pow(r - expectedReturn, 2), 0) / returns.length ); const confidence = avgSimilarity * (1 - returnStd * 5); // Penalize high variance // Determine action let action = 'hold'; if (expectedReturn > 0.005 && confidence > 0.6) action = 'buy'; else if (expectedReturn < -0.005 && confidence > 0.6) action = 'sell'; return { expectedReturn, winRate, confidence: Math.max(0, confidence), action }; } // Run performance benchmark async function runBenchmark(patterns) { const testSizes = [100, 1000, 5000, 10000]; const queryVector = generatePatternVector(); console.log(' Dataset Size | Build Time | Query Time | Throughput'); console.log(' ' + '-'.repeat(55)); for (const size of testSizes) { if (size > patterns.length) continue; const subset = patterns.slice(0, size); // Build index const buildStart = performance.now(); const index = await buildHNSWIndex(subset, hnswConfig); const buildTime = performance.now() - buildStart; // Query index const queryStart = performance.now(); await searchHNSW(index, queryVector, 10); const queryTime = performance.now() - queryStart; const throughput = (size / (buildTime / 1000)).toFixed(0); console.log(` ${size.toString().padStart(12)} | ${buildTime.toFixed(2).padStart(10)}ms | ${queryTime.toFixed(3).padStart(10)}ms | ${throughput.padStart(10)}/sec`); } console.log(); console.log(' Note: Native Rust bindings provide 150x faster search'); console.log(' with SIMD acceleration and optimized memory layout.'); } // Run the example main().catch(console.error);