trading-platform/apps/backend/src/modules/ml/controllers/ml.controller.ts

302 lines
7.1 KiB
TypeScript

/**
* 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<void> {
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<void> {
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<void> {
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<void> {
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<void> {
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<void> {
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<void> {
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<void> {
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<void> {
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<void> {
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<void> {
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<void> {
try {
const { jobId } = req.params;
const status = await mlIntegrationService.getRetrainingStatus(jobId);
res.json({
success: true,
data: status,
});
} catch (error) {
next(error);
}
}