/** * LLM Agent Service * Client for connecting to the LLM Agent API (Predictions & Backtesting) * * @version 1.0.0 */ const LLM_AGENT_URL = import.meta.env.VITE_LLM_AGENT_URL || 'http://localhost:3085'; // ============================================================================ // Types - Predictions // ============================================================================ export interface PredictionRequest { symbol: string; timeframe?: string; } export interface AMDPhaseInfo { phase: string; confidence: number; support: number; resistance: number; } export interface SignalInfo { direction: 'LONG' | 'SHORT' | 'HOLD'; confidence: number; entry_price: number; stop_loss: number; take_profit: number; } export interface RangePredictionInfo { predicted_high: number; predicted_low: number; expected_range_pct: number; } export interface ICTContextInfo { market_bias: string; order_blocks: Array<{ type: string; price: number }>; fair_value_gaps: Array<{ type: string; high: number; low: number }>; } export interface PredictionResponse { symbol: string; timeframe: string; timestamp: string; current_price: number; amd_phase: AMDPhaseInfo; signal: SignalInfo; range_prediction: RangePredictionInfo; ict_context: ICTContextInfo; confluence_score: number; explanation: string; risk_assessment?: { allowed: boolean; recommended_size: number; position_risk_pct: number; checks: Record; }; } export interface ActiveSignal { symbol: string; direction: string; confidence: number; confluence_score: number; entry_price: number; stop_loss: number; take_profit: number; timestamp: string; } export interface RiskSummary { level: string; limits: { max_position_size_pct: number; max_daily_drawdown_pct: number; max_total_exposure_pct: number; }; current_state: { daily_pnl: number; total_exposure_pct: number; open_trades: number; }; circuit_breaker_active: boolean; } // ============================================================================ // Types - Backtesting // ============================================================================ export interface BacktestRequest { initial_balance: number; risk_per_trade_pct: number; max_open_trades: number; min_confluence_score: number; min_confidence: number; symbols: string[]; timeframe: string; days_back: number; use_amd_filter: boolean; use_killzone_filter: boolean; } export interface BacktestStatus { id: string; status: 'pending' | 'running' | 'completed' | 'failed'; progress: number; started_at?: string; completed_at?: string; error?: string; } export interface BacktestSummary { id: string; initial_balance: number; final_balance: number; total_return: number; total_return_pct: number; total_trades: number; win_rate: number; profit_factor: number; max_drawdown_pct: number; sharpe_ratio: number; duration_days: number; } export interface BacktestTrade { id: string; symbol: string; direction: string; entry_price: number; exit_price: number; entry_time: string; exit_time: string; pnl: number; pnl_pips: number; status: string; confidence: number; amd_phase: string; confluence_score: number; } export interface EquityCurvePoint { timestamp: string; equity: number; balance: number; drawdown_pct: number; } export interface BacktestResult { summary: { initial_balance: number; final_balance: number; total_return: number; total_return_pct: number; duration_days: number; }; performance: { total_trades: number; winning_trades: number; losing_trades: number; win_rate: number; profit_factor: number; sharpe_ratio: number; sortino_ratio: number; }; risk: { max_drawdown: number; max_drawdown_pct: number; avg_winner: number; avg_loser: number; largest_winner: number; largest_loser: number; }; activity: { avg_trade_pnl: number; avg_trade_duration_hours: number; trades_per_day: number; }; monthly_returns: Record; trades_by_phase: Record; trades_by_symbol: Record; equity_curve: EquityCurvePoint[]; trades: BacktestTrade[]; } // ============================================================================ // Predictions API // ============================================================================ /** * Analyze a symbol with all ML models */ export async function analyzeSymbol( symbol: string, timeframe: string = '5m' ): Promise { try { const response = await fetch(`${LLM_AGENT_URL}/api/v1/predictions/analyze`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ symbol, timeframe }), }); if (!response.ok) { throw new Error(`API error: ${response.status}`); } return await response.json(); } catch (error) { console.error('Error analyzing symbol:', error); return null; } } /** * Get active signals above minimum confluence */ export async function getActiveSignals( minConfluence: number = 0.6 ): Promise { try { const response = await fetch( `${LLM_AGENT_URL}/api/v1/predictions/active-signals?min_confluence=${minConfluence}` ); if (!response.ok) { throw new Error(`API error: ${response.status}`); } return await response.json(); } catch (error) { console.error('Error fetching active signals:', error); return []; } } /** * Get current risk summary */ export async function getRiskSummary(): Promise { try { const response = await fetch(`${LLM_AGENT_URL}/api/v1/predictions/risk-summary`); if (!response.ok) { throw new Error(`API error: ${response.status}`); } return await response.json(); } catch (error) { console.error('Error fetching risk summary:', error); return null; } } /** * Set risk level */ export async function setRiskLevel( level: 'minimal' | 'conservative' | 'moderate' | 'aggressive' ): Promise { try { const response = await fetch( `${LLM_AGENT_URL}/api/v1/predictions/risk-level?level=${level}`, { method: 'POST' } ); return response.ok; } catch (error) { console.error('Error setting risk level:', error); return false; } } /** * Validate a trade against risk rules */ export async function validateTrade(params: { symbol: string; side: 'BUY' | 'SELL'; size: number; entry_price: number; stop_loss: number; pip_value?: number; }): Promise<{ allowed: boolean; recommended_size: number; position_risk_pct: number; checks: Record; formatted_message: string; } | null> { try { const response = await fetch(`${LLM_AGENT_URL}/api/v1/predictions/validate-trade`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(params), }); if (!response.ok) { throw new Error(`API error: ${response.status}`); } return await response.json(); } catch (error) { console.error('Error validating trade:', error); return null; } } // ============================================================================ // Backtesting API // ============================================================================ /** * Start a new backtest (background) */ export async function startBacktest( params: Partial ): Promise { try { const request: BacktestRequest = { initial_balance: params.initial_balance || 1000, risk_per_trade_pct: params.risk_per_trade_pct || 1.0, max_open_trades: params.max_open_trades || 3, min_confluence_score: params.min_confluence_score || 0.65, min_confidence: params.min_confidence || 0.60, symbols: params.symbols || ['XAUUSD', 'EURUSD', 'GBPUSD'], timeframe: params.timeframe || '1H', days_back: params.days_back || 365, use_amd_filter: params.use_amd_filter ?? true, use_killzone_filter: params.use_killzone_filter ?? true, }; const response = await fetch(`${LLM_AGENT_URL}/api/v1/backtesting/run`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(request), }); if (!response.ok) { throw new Error(`API error: ${response.status}`); } return await response.json(); } catch (error) { console.error('Error starting backtest:', error); return null; } } /** * Run a quick synchronous backtest (< 90 days) */ export async function runQuickBacktest(params: { initial_balance?: number; days?: number; symbol?: string; }): Promise { try { const queryParams = new URLSearchParams({ initial_balance: String(params.initial_balance || 1000), days: String(params.days || 30), symbol: params.symbol || 'XAUUSD', }); const response = await fetch( `${LLM_AGENT_URL}/api/v1/backtesting/quick-test?${queryParams}` ); if (!response.ok) { throw new Error(`API error: ${response.status}`); } return await response.json(); } catch (error) { console.error('Error running quick backtest:', error); return null; } } /** * Get backtest status */ export async function getBacktestStatus(id: string): Promise { try { const response = await fetch(`${LLM_AGENT_URL}/api/v1/backtesting/status/${id}`); if (!response.ok) { if (response.status === 404) return null; throw new Error(`API error: ${response.status}`); } return await response.json(); } catch (error) { console.error('Error fetching backtest status:', error); return null; } } /** * Get backtest results */ export async function getBacktestResults(id: string): Promise { try { const response = await fetch(`${LLM_AGENT_URL}/api/v1/backtesting/results/${id}`); if (!response.ok) { if (response.status === 404) return null; throw new Error(`API error: ${response.status}`); } return await response.json(); } catch (error) { console.error('Error fetching backtest results:', error); return null; } } /** * List recent backtests */ export async function listBacktests(limit: number = 10): Promise { try { const response = await fetch( `${LLM_AGENT_URL}/api/v1/backtesting/list?limit=${limit}` ); if (!response.ok) { throw new Error(`API error: ${response.status}`); } return await response.json(); } catch (error) { console.error('Error listing backtests:', error); return []; } } /** * Delete a backtest */ export async function deleteBacktest(id: string): Promise { try { const response = await fetch(`${LLM_AGENT_URL}/api/v1/backtesting/${id}`, { method: 'DELETE', }); return response.ok; } catch (error) { console.error('Error deleting backtest:', error); return false; } } // ============================================================================ // Health Check // ============================================================================ /** * Check LLM Agent health */ export async function checkHealth(): Promise<{ llmAgent: boolean; predictions: boolean; backtesting: boolean; }> { const results = { llmAgent: false, predictions: false, backtesting: false, }; try { const [rootRes, predictionsRes, backtestingRes] = await Promise.allSettled([ fetch(`${LLM_AGENT_URL}/`), fetch(`${LLM_AGENT_URL}/api/v1/predictions/health`), fetch(`${LLM_AGENT_URL}/api/v1/backtesting/health`), ]); results.llmAgent = rootRes.status === 'fulfilled' && rootRes.value.ok; results.predictions = predictionsRes.status === 'fulfilled' && predictionsRes.value.ok; results.backtesting = backtestingRes.status === 'fulfilled' && backtestingRes.value.ok; } catch (error) { console.error('Error checking LLM Agent health:', error); } return results; } // ============================================================================ // Polling utilities // ============================================================================ /** * Poll for backtest completion */ export async function waitForBacktest( id: string, onProgress?: (progress: number) => void, pollInterval: number = 2000, timeout: number = 600000 // 10 minutes ): Promise { const startTime = Date.now(); while (Date.now() - startTime < timeout) { const status = await getBacktestStatus(id); if (!status) { throw new Error('Backtest not found'); } if (onProgress) { onProgress(status.progress); } if (status.status === 'completed') { return await getBacktestResults(id); } if (status.status === 'failed') { throw new Error(status.error || 'Backtest failed'); } await new Promise(resolve => setTimeout(resolve, pollInterval)); } throw new Error('Backtest timed out'); }