/** * ML Controller * Handles ML Engine integration endpoints */ import { Request, Response, NextFunction } from 'express'; import { mlIntegrationService, TimeHorizon, SignalType, } from '../services/ml-integration.service'; // ============================================================================ // Types // ============================================================================ // Use Request directly - user is already declared globally in auth.middleware.ts type AuthRequest = Request; // ============================================================================ // Health & Status // ============================================================================ /** * Get ML Engine health status */ export async function getHealth(req: Request, res: Response, next: NextFunction): Promise { try { const health = await mlIntegrationService.getHealth(); res.json({ success: true, data: health, }); } catch (error) { next(error); } } /** * Check ML Engine connection */ export async function checkConnection(req: Request, res: Response, next: NextFunction): Promise { try { const isConnected = await mlIntegrationService.checkConnection(); res.json({ success: true, data: { connected: isConnected }, }); } catch (error) { next(error); } } // ============================================================================ // Signals // ============================================================================ /** * Get trading signal for a symbol */ export async function getSignal(req: Request, res: Response, next: NextFunction): Promise { try { const { symbol } = req.params; const { timeHorizon = 'intraday' } = req.query; const signal = await mlIntegrationService.getSignal( symbol, timeHorizon as TimeHorizon ); res.json({ success: true, data: signal, }); } catch (error) { next(error); } } /** * Get signals for multiple symbols */ export async function getSignals(req: Request, res: Response, next: NextFunction): Promise { try { const { symbols, timeHorizon = 'intraday' } = req.body; if (!symbols || !Array.isArray(symbols) || symbols.length === 0) { res.status(400).json({ success: false, error: { message: 'Symbols array is required', code: 'VALIDATION_ERROR' }, }); return; } const signals = await mlIntegrationService.getSignals( symbols, timeHorizon as TimeHorizon ); res.json({ success: true, data: signals, }); } catch (error) { next(error); } } /** * Get historical signals */ export async function getHistoricalSignals(req: Request, res: Response, next: NextFunction): Promise { try { const { symbol } = req.params; const { startTime, endTime, limit, signalType } = req.query; const signals = await mlIntegrationService.getHistoricalSignals(symbol, { startTime: startTime ? new Date(startTime as string) : undefined, endTime: endTime ? new Date(endTime as string) : undefined, limit: limit ? Number(limit) : undefined, signalType: signalType as SignalType | undefined, }); res.json({ success: true, data: signals, }); } catch (error) { next(error); } } // ============================================================================ // Predictions // ============================================================================ /** * Get price prediction */ export async function getPrediction(req: Request, res: Response, next: NextFunction): Promise { try { const { symbol } = req.params; const { horizonMinutes = 90 } = req.query; const prediction = await mlIntegrationService.getPrediction( symbol, Number(horizonMinutes) ); res.json({ success: true, data: prediction, }); } catch (error) { next(error); } } /** * Get AMD phase prediction */ export async function getAMDPhase(req: Request, res: Response, next: NextFunction): Promise { try { const { symbol } = req.params; const amdPhase = await mlIntegrationService.getAMDPhase(symbol); res.json({ success: true, data: amdPhase, }); } catch (error) { next(error); } } // ============================================================================ // Indicators // ============================================================================ /** * Get technical indicators */ export async function getIndicators(req: Request, res: Response, next: NextFunction): Promise { try { const { symbol } = req.params; const indicators = await mlIntegrationService.getIndicators(symbol); res.json({ success: true, data: indicators, }); } catch (error) { next(error); } } // ============================================================================ // Backtesting // ============================================================================ /** * Run backtest */ export async function runBacktest(req: AuthRequest, res: Response, next: NextFunction): Promise { try { const userId = req.user?.id; if (!userId) { res.status(401).json({ success: false, error: { message: 'Unauthorized', code: 'UNAUTHORIZED' }, }); return; } const { symbol, startDate, endDate, initialCapital, strategy, params } = req.body; if (!symbol || !startDate || !endDate) { res.status(400).json({ success: false, error: { message: 'Symbol, startDate, and endDate are required', code: 'VALIDATION_ERROR' }, }); return; } const result = await mlIntegrationService.runBacktest(symbol, { startDate: new Date(startDate), endDate: new Date(endDate), initialCapital, strategy, params, }); res.json({ success: true, data: result, }); } catch (error) { next(error); } } // ============================================================================ // Models (Admin) // ============================================================================ /** * Get available models */ export async function getModels(req: Request, res: Response, next: NextFunction): Promise { try { const models = await mlIntegrationService.getModels(); res.json({ success: true, data: models, }); } catch (error) { next(error); } } /** * Trigger model retraining */ export async function triggerRetraining(req: AuthRequest, res: Response, next: NextFunction): Promise { try { // TODO: Add admin check const { symbol } = req.body; const result = await mlIntegrationService.triggerRetraining(symbol); res.json({ success: true, data: result, }); } catch (error) { next(error); } } /** * Get retraining job status */ export async function getRetrainingStatus(req: Request, res: Response, next: NextFunction): Promise { try { const { jobId } = req.params; const status = await mlIntegrationService.getRetrainingStatus(jobId); res.json({ success: true, data: status, }); } catch (error) { next(error); } }