import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; export interface TradingStrategy { id: string; name: string; description: string; status: 'ACTIVE' | 'INACTIVE' | 'PAUSED' | 'ERROR'; type: string; symbols: string[]; parameters: Record; performance: { totalTrades: number; winRate: number; totalReturn: number; sharpeRatio: number; maxDrawdown: number; }; createdAt: Date; updatedAt: Date; } export interface BacktestRequest { strategyType: string; strategyParams: Record; symbols: string[]; startDate: Date | string; endDate: Date | string; initialCapital: number; dataResolution: '1m' | '5m' | '15m' | '30m' | '1h' | '4h' | '1d'; commission: number; slippage: number; mode: 'event' | 'vector'; } export interface BacktestResult { strategyId: string; startDate: Date; endDate: Date; duration: number; initialCapital: number; finalCapital: number; totalReturn: number; annualizedReturn: number; sharpeRatio: number; maxDrawdown: number; maxDrawdownDuration: number; winRate: number; totalTrades: number; winningTrades: number; losingTrades: number; averageWinningTrade: number; averageLosingTrade: number; profitFactor: number; dailyReturns: Array<{ date: Date; return: number }>; trades: Array<{ symbol: string; entryTime: Date; entryPrice: number; exitTime: Date; exitPrice: number; quantity: number; pnl: number; pnlPercent: number; }>; // Advanced metrics sortinoRatio?: number; calmarRatio?: number; omegaRatio?: number; cagr?: number; volatility?: number; ulcerIndex?: number; } interface ApiResponse { success: boolean; data: T; error?: string; } @Injectable({ providedIn: 'root', }) export class StrategyService { private apiBaseUrl = '/api'; // Will be proxied to the correct backend endpoint constructor(private http: HttpClient) {} // Strategy Management getStrategies(): Observable> { return this.http.get>(`${this.apiBaseUrl}/strategies`); } getStrategy(id: string): Observable> { return this.http.get>(`${this.apiBaseUrl}/strategies/${id}`); } createStrategy(strategy: Partial): Observable> { return this.http.post>(`${this.apiBaseUrl}/strategies`, strategy); } updateStrategy( id: string, updates: Partial ): Observable> { return this.http.put>( `${this.apiBaseUrl}/strategies/${id}`, updates ); } startStrategy(id: string): Observable> { return this.http.post>( `${this.apiBaseUrl}/strategies/${id}/start`, {} ); } stopStrategy(id: string): Observable> { return this.http.post>( `${this.apiBaseUrl}/strategies/${id}/stop`, {} ); } pauseStrategy(id: string): Observable> { return this.http.post>( `${this.apiBaseUrl}/strategies/${id}/pause`, {} ); } // Backtest Management getStrategyTypes(): Observable> { return this.http.get>(`${this.apiBaseUrl}/strategy-types`); } getStrategyParameters(type: string): Observable>> { return this.http.get>>( `${this.apiBaseUrl}/strategy-parameters/${type}` ); } runBacktest(request: BacktestRequest): Observable> { return this.http.post>(`${this.apiBaseUrl}/backtest`, request); } getBacktestResult(id: string): Observable> { return this.http.get>(`${this.apiBaseUrl}/backtest/${id}`); } optimizeStrategy( baseRequest: BacktestRequest, parameterGrid: Record ): Observable }>>> { return this.http.post }>>>( `${this.apiBaseUrl}/backtest/optimize`, { baseRequest, parameterGrid } ); } // Strategy Signals and Trades getStrategySignals(strategyId: string): Observable< ApiResponse< Array<{ id: string; strategyId: string; symbol: string; action: string; price: number; quantity: number; timestamp: Date; confidence: number; metadata?: any; }> > > { return this.http.get>(`${this.apiBaseUrl}/strategies/${strategyId}/signals`); } getStrategyTrades(strategyId: string): Observable< ApiResponse< Array<{ id: string; strategyId: string; symbol: string; entryPrice: number; entryTime: Date; exitPrice: number; exitTime: Date; quantity: number; pnl: number; pnlPercent: number; }> > > { return this.http.get>(`${this.apiBaseUrl}/strategies/${strategyId}/trades`); } // Helper methods for common transformations formatBacktestRequest(formData: any): BacktestRequest { // Handle date formatting and parameter conversion return { ...formData, startDate: formData.startDate instanceof Date ? formData.startDate.toISOString() : formData.startDate, endDate: formData.endDate instanceof Date ? formData.endDate.toISOString() : formData.endDate, strategyParams: this.convertParameterTypes(formData.strategyType, formData.strategyParams), }; } private convertParameterTypes( strategyType: string, params: Record ): Record { // Convert string parameters to correct types based on strategy requirements const result: Record = {}; for (const [key, value] of Object.entries(params)) { if (typeof value === 'string') { // Try to convert to number if it looks like a number if (!isNaN(Number(value))) { result[key] = Number(value); } else if (value.toLowerCase() === 'true') { result[key] = true; } else if (value.toLowerCase() === 'false') { result[key] = false; } else { result[key] = value; } } else { result[key] = value; } } return result; } }