UNPKG

@infosel-sdk/funds

Version:

SDK de Fondos para la plataforma de servicios financieros Infosel

691 lines (564 loc) 18.7 kB
# @infosel-sdk/funds [![npm version](https://badge.fury.io/js/@infosel-sdk%2Ffunds.svg)](https://badge.fury.io/js/@infosel-sdk%2Ffunds) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?logo=typescript&logoColor=white)](https://www.typescriptlang.org/) SDK de Fondos para la plataforma de servicios financieros Infosel. Proporciona acceso completo a información de fondos de inversión, incluyendo prospectos, rendimientos históricos, precios y datos fundamentales. ## 🚀 Características - **📊 Información de Fondos**: Acceso a datos completos de fondos de inversión - **📈 Rendimientos**: Cálculo de rendimientos en múltiples períodos (diario, semanal, mensual, anual) - **📋 Prospectos**: Información detallada de prospectos de fondos - **📊 Precios Históricos**: Datos históricos de precios con diferentes intervalos - **🔍 Filtros Avanzados**: Búsqueda por tipo, administrador y otros criterios - **⚡ Integración Core**: Completamente integrado con @infosel-sdk/core - **🌍 Multi-Ambiente**: Soporte para QA y producción ## 📦 Instalación ```bash npm install @infosel-sdk/funds ``` ### Dependencias - **@infosel-sdk/core**: ^0.0.2 (requerido) - **dayjs**: ^1.11.10 (para manejo de fechas) - **tslib**: ^2.8.1 (para TypeScript) ## 🔧 Configuración Inicial ### Configurar el SDK Core Primero, necesitas configurar el SDK Core con autenticación: ```typescript import { InfoselSdkManager, AuthConfigurationBuilder } from '@infosel-sdk/core'; import InfoselFunds from '@infosel-sdk/funds'; // Configurar autenticación KeyCloak const authConfig = AuthConfigurationBuilder.keyCloak() .withRealm('funds-realm') .withEnvironment('qa') // o 'prod' .withCredentials({ grant_type: 'client_credentials', client_id: 'your-funds-client', client_secret: 'your-funds-secret', }) .build(); // Inicializar el SDK Core const sdkManager = InfoselSdkManager.initWithConfiguration({ authConfiguration: authConfig, }); // Inicializar el SDK de Fondos const fundsSdk = InfoselFunds.init({ sdkManager, }); ``` ## 📚 Métodos Disponibles ### 1. Obtener Lista de Fondos ```typescript // Obtener todos los fondos const allFunds = await fundsSdk.getFunds(); // Filtrar por tipo de fondo const equityFunds = await fundsSdk.getFunds({ typeId: 1, // Fondos de renta variable }); // Filtrar por administrador const specificAdminFunds = await fundsSdk.getFunds({ administratorId: 123, }); // Combinar filtros const filteredFunds = await fundsSdk.getFunds({ typeId: 2, // Fondos de renta fija administratorId: 456, }); console.log('Fondos encontrados:', allFunds.length); console.log('Primer fondo:', allFunds[0]); ``` **Respuesta esperada:** ```typescript type Funds = { readonly id: number; readonly marketTypeId: number; readonly valueTypeIds: number; readonly exchangeId: number; readonly symbol: string; readonly issuer: string; readonly series: string; readonly isTrading: number; readonly name: string; readonly instrumentKey: string; readonly exchangeValueType: string; readonly isin: string; readonly active: number; }; ``` ### 2. Obtener Prospecto de Fondo ```typescript // Obtener prospecto por emisora const prospectus = await fundsSdk.getFundProspectus({ issuer: 'BANORTE', }); console.log('Nombre del negocio:', prospectus.bussinesName); console.log('Tipo de fondo:', prospectus.fundType); console.log('Clase de activo:', prospectus.fundAssetClass); console.log('Administrador:', prospectus.administrator); console.log('Activos bajo gestión:', prospectus.assetsUnderManagement); ``` **Respuesta esperada:** ```typescript type FundProspectus = { readonly fundId: number; readonly series: string[]; readonly issuer: string; readonly bussinesName: string; readonly fundDateAuth: string; readonly fundType: string; readonly fundAssetClass: string; readonly administrator: string; readonly fundTerm: string; readonly investmentRegime: string; readonly liquidity: string; readonly lockInPeriod: string; readonly netAsset: number; readonly assetsUnderManagement: number; readonly fundHoldings: number; readonly marketRating: string; readonly creditRating: string; readonly fundManager: string; readonly active: number; readonly closeTime: string; }; ``` ### 3. Obtener Rendimientos de Fondo ```typescript // Obtener rendimientos para una fecha específica const yields = await fundsSdk.getFundYield({ issuer: 'BANORTE', series: 'A', date: new Date('2024-01-15'), }); console.log('Rendimiento anual:', yields.annual); console.log('Rendimiento diario:', yields.daily); console.log('Rendimiento mensual:', yields.monthly); console.log('Rendimiento semanal:', yields.weekly); console.log('Rendimiento año a la fecha:', yields.yearToDate); ``` **Respuesta esperada:** ```typescript type FundYield = { readonly annual: number; readonly daily: number; readonly dailyAnnualized: number; readonly monthly: number; readonly monthlyAnnualized: number; readonly weekly: number; readonly weeklyAnnualized: number; readonly yearToDate: number; readonly yearToDateAnnualized: number; }; ``` ### 4. Obtener Precios Históricos ```typescript // Obtener precios históricos diarios const dailyPrices = await fundsSdk.getFundHistoricalPrices({ issuer: 'BANORTE', series: 'A', period: 30, // 30as interval: 'D', // Diario }); // Obtener precios semanales const weeklyPrices = await fundsSdk.getFundHistoricalPrices({ issuer: 'BANORTE', series: 'A', period: 12, // 12 semanas interval: 'W', // Semanal }); // Obtener precios mensuales const monthlyPrices = await fundsSdk.getFundHistoricalPrices({ issuer: 'BANORTE', series: 'A', period: 24, // 24 meses interval: 'M', // Mensual }); // Obtener precios trimestrales const quarterlyPrices = await fundsSdk.getFundHistoricalPrices({ issuer: 'BANORTE', series: 'A', period: 8, // 8 trimestres interval: 'Q', // Trimestral }); console.log('Precios diarios:', dailyPrices.length); console.log('Último precio:', dailyPrices[dailyPrices.length - 1]); ``` **Respuesta esperada:** ```typescript type FundsHistoricalPrices = { readonly date: string; readonly high: number; readonly low: number; readonly close: number; }; ``` ## 🔍 Casos de Uso Comunes ### Dashboard de Fondos ```typescript async function createFundsDashboard() { try { // Obtener lista de fondos activos const activeFunds = await fundsSdk.getFunds(); const dashboardData = await Promise.all( activeFunds.slice(0, 10).map(async fund => { // Obtener prospecto const prospectus = await fundsSdk.getFundProspectus({ issuer: fund.issuer, }); // Obtener rendimiento actual const yield = await fundsSdk.getFundYield({ issuer: fund.issuer, series: fund.series, date: new Date(), }); // Obtener precios históricos (últimos 30as) const historicalPrices = await fundsSdk.getFundHistoricalPrices({ issuer: fund.issuer, series: fund.series, period: 30, interval: 'D', }); return { fund, prospectus, currentYield: yield.annual, priceHistory: historicalPrices, }; }), ); return dashboardData; } catch (error) { console.error('Error al crear dashboard:', error); throw error; } } ``` ### Análisis de Rendimiento ```typescript async function analyzeFundPerformance(issuer: string, series: string) { try { // Obtener rendimientos en diferentes períodos const yields = await fundsSdk.getFundYield({ issuer, series, date: new Date(), }); // Obtener precios históricos para análisis técnico const dailyPrices = await fundsSdk.getFundHistoricalPrices({ issuer, series, period: 90, // 90as interval: 'D', }); const monthlyPrices = await fundsSdk.getFundHistoricalPrices({ issuer, series, period: 36, // 36 meses interval: 'M', }); // Calcular métricas de rendimiento const performanceMetrics = { shortTerm: yields.monthly, mediumTerm: yields.annual, longTerm: yields.yearToDate, volatility: calculateVolatility(dailyPrices), trend: analyzeTrend(monthlyPrices), }; return performanceMetrics; } catch (error) { console.error('Error en análisis de rendimiento:', error); throw error; } } function calculateVolatility(prices: FundsHistoricalPrices[]): number { // Implementar cálculo de volatilidad const returns = prices .slice(1) .map((price, i) => (price.close - prices[i].close) / prices[i].close); const mean = returns.reduce((sum, ret) => sum + ret, 0) / returns.length; const variance = returns.reduce((sum, ret) => sum + Math.pow(ret - mean, 2), 0) / returns.length; return Math.sqrt(variance); } function analyzeTrend( prices: FundsHistoricalPrices[], ): 'up' | 'down' | 'sideways' { if (prices.length < 2) return 'sideways'; const firstPrice = prices[0].close; const lastPrice = prices[prices.length - 1].close; const change = (lastPrice - firstPrice) / firstPrice; if (change > 0.05) return 'up'; if (change < -0.05) return 'down'; return 'sideways'; } ``` ### Comparación de Fondos ```typescript async function compareFunds( fund1: { issuer: string; series: string }, fund2: { issuer: string; series: string }, ) { try { const [prospectus1, prospectus2, yield1, yield2] = await Promise.all([ fundsSdk.getFundProspectus({ issuer: fund1.issuer }), fundsSdk.getFundProspectus({ issuer: fund2.issuer }), fundsSdk.getFundYield({ issuer: fund1.issuer, series: fund1.series, date: new Date(), }), fundsSdk.getFundYield({ issuer: fund2.issuer, series: fund2.series, date: new Date(), }), ]); const comparison = { fund1: { name: prospectus1.bussinesName, type: prospectus1.fundType, assetClass: prospectus1.fundAssetClass, annualYield: yield1.annual, assetsUnderManagement: prospectus1.assetsUnderManagement, }, fund2: { name: prospectus2.bussinesName, type: prospectus2.fundType, assetClass: prospectus2.fundAssetClass, annualYield: yield2.annual, assetsUnderManagement: prospectus2.assetsUnderManagement, }, analysis: { higherYield: yield1.annual > yield2.annual ? 'fund1' : 'fund2', yieldDifference: Math.abs(yield1.annual - yield2.annual), largerFund: prospectus1.assetsUnderManagement > prospectus2.assetsUnderManagement ? 'fund1' : 'fund2', }, }; return comparison; } catch (error) { console.error('Error al comparar fondos:', error); throw error; } } ``` ## 🚨 Manejo de Errores ```typescript import { SdkError, SdkErrorType } from '@infosel-sdk/core'; try { const funds = await fundsSdk.getFunds(); console.log('Fondos obtenidos:', funds); } catch (error) { if (error instanceof SdkError) { switch (error.type) { case SdkErrorType.REQUEST_OBJECT_IS_REQUIRED: console.error('Request object is required for this operation'); break; case SdkErrorType.AXIOS_RESPONSE_ERROR: console.error('HTTP response error:', error.message); break; case SdkErrorType.GRAPH_QL_ERROR: console.error('GraphQL error:', error.message); break; default: console.error('SDK error:', error.message); } } else { console.error('Unexpected error:', error); } } ``` ## 🔧 Configuración Avanzada ### Personalización de URLs ```typescript import { InfoselSdkManager, AuthConfigurationBuilder } from '@infosel-sdk/core'; import InfoselFunds from '@infosel-sdk/funds'; // Configuración personalizada para diferentes ambientes const customConfig = { qa: { baseUrl: 'https://custom-qa-api.infosel.com/funds/api/v1', realm: 'qa-funds', clientId: 'qa-funds-client', clientSecret: 'qa-funds-secret', }, prod: { baseUrl: 'https://custom-prod-api.infosel.com/funds/api/v1', realm: 'prod-funds', clientId: 'prod-funds-client', clientSecret: 'prod-funds-secret', }, }; function createCustomFundsSdk(environment: 'qa' | 'prod') { const config = customConfig[environment]; const authConfig = AuthConfigurationBuilder.keyCloak() .withEnvironment(environment) .withRealm(config.realm) .withCredentials({ grant_type: 'client_credentials', client_id: config.clientId, client_secret: config.clientSecret, }) .build(); const sdkManager = InfoselSdkManager.initWithConfiguration({ authConfiguration: authConfig, }); return InfoselFunds.init({ sdkManager }); } ``` ## 🧪 Testing ```typescript import { InfoselSdkManager, AuthConfigurationBuilder } from '@infosel-sdk/core'; import InfoselFunds from '@infosel-sdk/funds'; // Mock del SDK Manager para testing const mockSdkManager = { mode: 'qa', getRealm: () => 'test-realm', } as any; // Test de inicialización describe('InfoselFunds', () => { it('should initialize with SDK manager', () => { const fundsSdk = InfoselFunds.init({ sdkManager: mockSdkManager }); expect(fundsSdk).toBeDefined(); }); }); ``` ## 📊 Estructura de Datos ### Tipos de Request ```typescript // Filtros para obtener fondos type FundsRequest = { readonly typeId?: number; // ID del tipo de fondo readonly administratorId?: number; // ID del administrador }; // Request para prospecto type FundProspectusRequest = { readonly issuer: string; // Emisora del fondo }; // Request para rendimientos type FundYieldRequest = { readonly issuer: string; // Emisora del fondo readonly series: string; // Serie del fondo readonly date: Date; // Fecha para el cálculo }; // Request para precios históricos type FundHistoricalPricesRequest = { readonly issuer: string; // Emisora del fondo readonly series: string; // Serie del fondo readonly period: number; // Período en unidades del intervalo readonly interval: 'D' | 'W' | 'M' | 'Q'; // D=Diario, W=Semanal, M=Mensual, Q=Trimestral }; ``` ## 🔗 Integración con Otros SDKs ```typescript import { InfoselSdkManager, AuthConfigurationBuilder } from '@infosel-sdk/core'; import InfoselFunds from '@infosel-sdk/funds'; import InfoselMarkets from '@infosel-sdk/markets'; // Configuración compartida const authConfig = AuthConfigurationBuilder.keyCloak() .withRealm('shared-realm') .withEnvironment('prod') .withCredentials({ grant_type: 'client_credentials', client_id: 'shared-client', client_secret: 'shared-secret', }) .build(); const sdkManager = InfoselSdkManager.initWithConfiguration({ authConfiguration: authConfig, }); // Inicializar múltiples SDKs const fundsSdk = InfoselFunds.init({ sdkManager }); const marketsSdk = InfoselMarkets.init({ sdkManager }); // Uso combinado async function getFundWithMarketData(issuer: string, series: string) { const [fundProspectus, marketInstruments] = await Promise.all([ fundsSdk.getFundProspectus({ issuer }), marketsSdk.searchInstruments({ query: issuer, limit: 10 }), ]); return { fund: fundProspectus, relatedInstruments: marketInstruments, }; } ``` ## 📈 Performance y Optimización ### Lazy Loading de Use Cases El SDK implementa lazy loading para optimizar el uso de memoria: ```typescript // Los use cases se crean solo cuando se necesitan const funds = await fundsSdk.getFunds(); // Crea GetFundsUseCase internamente // Reutiliza la instancia existente const moreFunds = await fundsSdk.getFunds(); // Usa la instancia existente ``` ### Manejo de Promesas ```typescript // Ejecutar múltiples operaciones en paralelo const [funds, prospectus, yields] = await Promise.all([ fundsSdk.getFunds(), fundsSdk.getFundProspectus({ issuer: 'BANORTE' }), fundsSdk.getFundYield({ issuer: 'BANORTE', series: 'A', date: new Date() }), ]); // Ejecutar operaciones secuenciales cuando hay dependencias const funds = await fundsSdk.getFunds(); const firstFund = funds[0]; const prospectus = await fundsSdk.getFundProspectus({ issuer: firstFund.issuer, }); ``` ## 🔍 Troubleshooting ### Problemas Comunes 1. **Error de autenticación** ```typescript // Verificar configuración del realm console.log('Realm configurado:', sdkManager.getRealm()); // Verificar ambiente console.log('Ambiente:', sdkManager.mode); ``` 2. **Fondos no encontrados** ```typescript // Verificar filtros aplicados const allFunds = await fundsSdk.getFunds(); console.log('Total de fondos:', allFunds.length); // Verificar fondos activos const activeFunds = allFunds.filter(fund => fund.active === 1); console.log('Fondos activos:', activeFunds.length); ``` 3. **Errores de fecha** ```typescript // Asegurar formato correcto de fecha const today = new Date(); console.log('Fecha utilizada:', today.toISOString()); // Para rendimientos, usar fecha válida const yields = await fundsSdk.getFundYield({ issuer: 'BANORTE', series: 'A', date: new Date('2024-01-15'), // Formato ISO }); ``` ## 📚 API Reference ### Clases Principales - `InfoselFunds`: Clase principal del SDK de fondos - `GetFundsUseCase`: Use case para obtener fondos - `GetProspectusUseCase`: Use case para obtener prospectos - `GetFundYieldUseCase`: Use case para obtener rendimientos - `GetFundHistoricalPricesUseCase`: Use case para obtener precios históricos ### Métodos Públicos - `getFunds(request?: FundsRequest): Promise<Funds[]>` - `getFundProspectus(request: FundProspectusRequest): Promise<FundProspectus>` - `getFundYield(request: FundYieldRequest): Promise<FundYield>` - `getFundHistoricalPrices(request: FundHistoricalPricesRequest): Promise<FundsHistoricalPrices[]>` ## 🤝 Contribución 1. Fork el proyecto 2. Crea una rama para tu feature (`git checkout -b feature/AmazingFeature`) 3. Commit tus cambios (`git commit -m 'Add some AmazingFeature'`) 4. Push a la rama (`git push origin feature/AmazingFeature`) 5. Abre un Pull Request ## 📄 Licencia Este proyecto está bajo la Licencia MIT. Ver el archivo `LICENSE` para más detalles. ## 📞 Soporte - **Documentación**: [SDK Core Documentation](../core/README.md) - **Issues**: [GitHub Issues](https://github.com/infosel/am-sdks/issues) - **Equipo**: Infosel Team --- **Hecho con ❤️ por el equipo de Infosel**