/** * Technical Indicators Service * Leverages @stock-bot/utils for calculations */ import { getLogger } from '@stock-bot/logger'; import { ema, macd, rsi, sma } from '@stock-bot/utils'; const logger = getLogger('indicators-service'); export interface IndicatorRequest { symbol: string; data: number[]; indicators: string[]; parameters?: Record; } export interface IndicatorResult { symbol: string; timestamp: Date; indicators: Record; } export class IndicatorsService { async calculateIndicators(request: IndicatorRequest): Promise { logger.info('Calculating indicators', { symbol: request.symbol, indicators: request.indicators, dataPoints: request.data.length, }); const results: Record = {}; for (const indicator of request.indicators) { try { switch (indicator.toLowerCase()) { case 'sma': { const smaPeriod = request.parameters?.smaPeriod || 20; results.sma = sma(request.data, smaPeriod); break; } case 'ema': { const emaPeriod = request.parameters?.emaPeriod || 20; results.ema = ema(request.data, emaPeriod); break; } case 'rsi': { const rsiPeriod = request.parameters?.rsiPeriod || 14; results.rsi = rsi(request.data, rsiPeriod); break; } case 'macd': { const fast = request.parameters?.macdFast || 12; const slow = request.parameters?.macdSlow || 26; const signal = request.parameters?.macdSignal || 9; results.macd = macd(request.data, fast, slow, signal).macd; break; } case 'stochastic': // TODO: Implement stochastic oscillator logger.warn('Stochastic oscillator not implemented yet'); break; default: logger.warn('Unknown indicator requested', { indicator }); } } catch (error) { logger.error('Error calculating indicator', { indicator, error }); } } return { symbol: request.symbol, timestamp: new Date(), indicators: results, }; } }