screen_opportunities
Identify investment opportunities in the Spanish stock market by filtering stocks based on criteria like P/E ratio, market cap, sectors, and governance quality.
Instructions
Screen for investment opportunities based on specific criteria (value, growth, dividend, ESG, etc.)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of opportunities to return | |
| screening_criteria | Yes |
Implementation Reference
- src/analytics.ts:559-625 (handler)Main handler function that screens IBEX 35 companies based on criteria like P/E ratio, market cap, sectors. Filters companies, scores them using helper, ranks and returns top opportunities.async screenOpportunities(criteria: any, limit: number = 10): Promise<any> { try { const companies = await this.db.getAllCompanies(); const screening = { criteria: criteria, total_companies_screened: companies.length, opportunities: [], screening_date: new Date().toISOString(), summary: {} }; // Apply screening filters let filteredCompanies = companies; if (criteria.pe_ratio_min !== undefined || criteria.pe_ratio_max !== undefined) { filteredCompanies = filteredCompanies.filter(company => { const pe = company.price_to_earnings || company.pe_ratio; if (pe === null || pe === undefined) return false; if (criteria.pe_ratio_min !== undefined && pe < criteria.pe_ratio_min) return false; if (criteria.pe_ratio_max !== undefined && pe > criteria.pe_ratio_max) return false; return true; }); } if (criteria.market_cap_min !== undefined || criteria.market_cap_max !== undefined) { filteredCompanies = filteredCompanies.filter(company => { if (!company.market_cap) return false; if (criteria.market_cap_min !== undefined && company.market_cap < criteria.market_cap_min) return false; if (criteria.market_cap_max !== undefined && company.market_cap > criteria.market_cap_max) return false; return true; }); } if (criteria.sectors && criteria.sectors.length > 0) { filteredCompanies = filteredCompanies.filter(company => criteria.sectors.some(sector => company.sector?.toLowerCase().includes(sector.toLowerCase()) ) ); } if (criteria.exclude_sectors && criteria.exclude_sectors.length > 0) { filteredCompanies = filteredCompanies.filter(company => !criteria.exclude_sectors.some(sector => company.sector?.toLowerCase().includes(sector.toLowerCase()) ) ); } // Score and rank opportunities const scoredOpportunities = await this.scoreOpportunities(filteredCompanies, criteria); screening.opportunities = scoredOpportunities.slice(0, limit); screening.summary = { companies_passed_screening: scoredOpportunities.length, top_scoring_sector: this.getTopSector(scoredOpportunities), average_score: scoredOpportunities.length > 0 ? scoredOpportunities.reduce((sum, opp) => sum + opp.score, 0) / scoredOpportunities.length : 0 }; return screening; } catch (error) { throw new Error(`Opportunity screening failed: ${error}`); } }
- src/index.ts:482-541 (registration)Tool registration in the list of tools returned by listToolsRequest, including name, description, and detailed input schema.name: 'screen_opportunities', description: 'Screen for investment opportunities based on specific criteria (value, growth, dividend, ESG, etc.)', inputSchema: { type: 'object', properties: { screening_criteria: { type: 'object', properties: { pe_ratio_max: { type: 'number', description: 'Maximum P/E ratio', }, pe_ratio_min: { type: 'number', description: 'Minimum P/E ratio', }, market_cap_min: { type: 'number', description: 'Minimum market capitalization', }, market_cap_max: { type: 'number', description: 'Maximum market capitalization', }, sectors: { type: 'array', items: { type: 'string', }, description: 'Specific sectors to include', }, exclude_sectors: { type: 'array', items: { type: 'string', }, description: 'Sectors to exclude', }, performance_period: { type: 'number', description: 'Days to look back for performance metrics', default: 30, }, governance_quality: { type: 'string', enum: ['high', 'medium', 'low', 'any'], description: 'Required governance quality level', default: 'any', }, }, }, limit: { type: 'number', description: 'Maximum number of opportunities to return', default: 10, }, }, required: ['screening_criteria'], }, },
- src/index.ts:686-688 (registration)Dispatch handler in the CallToolRequest switch statement that invokes the analytics.screenOpportunities method.case 'screen_opportunities': result = await this.analytics.screenOpportunities((args as any)?.screening_criteria, (args as any)?.limit || 10); break;
- src/analytics.ts:1001-1033 (helper)Helper method called by screenOpportunities to assign scores to filtered companies based on P/E, market cap, sector, then sorts by score.private async scoreOpportunities(companies: any[], criteria: any): Promise<any[]> { const scored = companies.map(company => { let score = 5.0; // Base score // Scoring based on P/E ratio const pe = company.price_to_earnings || company.pe_ratio; if (pe && pe < 15) score += 1.0; if (pe && pe > 25) score -= 0.5; // Scoring based on market cap if (company.market_cap > 10e9) score += 0.5; // Large cap bonus if (company.market_cap < 1e9) score -= 0.3; // Small cap penalty // Scoring based on sector if (company.sector && ['banking', 'technology', 'healthcare'].includes(company.sector.toLowerCase())) { score += 0.3; } return { company: company, symbol: company.symbol, name: company.name, sector: company.sector, score: Math.max(0, Math.min(10, score)), // Clamp between 0-10 key_metrics: { market_cap: company.market_cap, pe_ratio: pe } }; }); return scored.sort((a, b) => b.score - a.score); }
- dist/analytics.d.ts:16-16 (schema)TypeScript type definition for the screenOpportunities method.screenOpportunities(criteria: any, limit?: number): Promise<any>;