""" Report Service - 财务报告数据服务 集成 EasyFinancialAgent 的 MCP 工具,提供完整的数据查询方法 """ from EasyFinancialAgent.chat_direct import ( analyze_company_with_llm, chatbot_response, search_company_direct, get_company_info_direct, extract_financial_metrics_direct, get_company_filings_direct, get_latest_financial_data_direct, query_company_direct ) from datetime import datetime from typing import Optional def get_report_data(symbol_or_name: str, years: int = 5): """ 获取公司完整财务报告数据 Args: symbol_or_name: 公司代码或名称 (e.g., "Apple", "AAPL", "0000320193") years: 财务年限 (默认 5 年) Returns: 完整的报告数据字典,包含公司信息、财务指标、最新数据等 Example: report = get_report_data("Apple", years=5) """ result = { "timestamp": datetime.now().isoformat(), "query_input": symbol_or_name, "status": "success", "data": { "company_search": None, "company_info": None, "latest_financial": None, "financial_metrics": None, "filings": None }, "errors": [] } try: # 1. 搜索公司 print(f"[Report Service] 搜索公司: {symbol_or_name}") search_result = search_company_direct(symbol_or_name) print(f"[Report Service] 搜索结果: {search_result}") if "error" in search_result: result["errors"].append(f"Search failed: {search_result['error']}") result["status"] = "error" return result result["data"]["company_search"] = search_result # 从搜索结果提取 CIK cik = None if isinstance(search_result, dict): cik = search_result.get("cik") elif isinstance(search_result, (list, tuple)) and len(search_result) > 0: try: first = search_result[0] if isinstance(search_result, (list, tuple)) else None if isinstance(first, dict): cik = first.get("cik") except (IndexError, TypeError): pass if not cik: result["errors"].append("Could not extract CIK from search result") result["status"] = "error" return result print(f"[Report Service] 找到公司 CIK: {cik}") # 2. 获取公司详细信息 # print(f"[Report Service] 获取公司详细信息") # company_info = get_company_info_direct(cik) # if "error" not in company_info: # result["data"]["company_info"] = company_info # else: # result["errors"].append(f"Failed to get company info: {company_info.get('error')}") # 3. 获取最新财务数据 # print(f"[Report Service] 获取最新财务数据") # latest_data = get_latest_financial_data_direct(cik) # if "error" not in latest_data: # result["data"]["latest_financial"] = latest_data # else: # result["errors"].append(f"Failed to get latest financial data: {latest_data.get('error')}") # 4. 获取多年财务指标 print(f"[Report Service] 获取 {years} 年财务指标") metrics = extract_financial_metrics_direct(cik, years=years) if "error" not in metrics: result["data"]["financial_metrics"] = metrics else: result["errors"].append(f"Failed to get financial metrics: {metrics.get('error')}") # 5. 获取公司文件列表 # print(f"[Report Service] 获取公司 SEC 文件列表") # filings = get_company_filings_direct(cik) # if "error" not in filings: # result["data"]["filings"] = filings # else: # result["errors"].append(f"Failed to get filings: {filings.get('error')}") print(f"[Report Service] 报告数据获取完成") except Exception as e: result["status"] = "error" result["errors"].append(f"Exception: {str(e)}") import traceback result["errors"].append(traceback.format_exc()) return result def get_company_summary(symbol_or_name: str): """ 获取公司摘要信息(轻量级查询) Args: symbol_or_name: 公司代码或名称 Returns: 公司摘要数据字典 Example: summary = get_company_summary("Tesla") """ result = { "timestamp": datetime.now().isoformat(), "query_input": symbol_or_name, "status": "success", "data": { "company_search": None, "company_info": None, "latest_financial": None }, "errors": [] } try: # 搜索公司 search_result = search_company_direct(symbol_or_name) if "error" in search_result: result["errors"].append(f"Search failed: {search_result['error']}") result["status"] = "error" return result result["data"]["company_search"] = search_result # 提取 CIK cik = None if isinstance(search_result, dict): cik = search_result.get("cik") elif isinstance(search_result, (list, tuple)) and len(search_result) > 0: try: first = search_result[0] if isinstance(search_result, (list, tuple)) else None if isinstance(first, dict): cik = first.get("cik") except (IndexError, TypeError): pass if not cik: result["errors"].append("Could not extract CIK") result["status"] = "error" return result # 获取公司信息 company_info = get_company_info_direct(cik) if "error" not in company_info: result["data"]["company_info"] = company_info # 获取最新财务数据 latest_data = get_latest_financial_data_direct(cik) if "error" not in latest_data: result["data"]["latest_financial"] = latest_data except Exception as e: result["status"] = "error" result["errors"].append(str(e)) return result def get_financial_metrics(symbol_or_name: str, years: int = 5): """ 获取财务指标趋势数据 Args: symbol_or_name: 公司代码或名称 years: 年数(默认 5 年) Returns: 财务指标数据字典 Example: metrics = get_financial_metrics("Microsoft", years=10) """ result = { "timestamp": datetime.now().isoformat(), "query_input": symbol_or_name, "years": years, "status": "success", "data": None, "errors": [] } try: # 搜索公司 search_result = search_company_direct(symbol_or_name) if "error" in search_result: result["errors"].append(f"Search failed: {search_result['error']}") result["status"] = "error" return result # 提取 CIK cik = None if isinstance(search_result, dict): cik = search_result.get("cik") elif isinstance(search_result, (list, tuple)) and len(search_result) > 0: try: first = search_result[0] if isinstance(search_result, (list, tuple)) else None if isinstance(first, dict): cik = first.get("cik") except (IndexError, TypeError): pass if not cik: result["errors"].append("Could not extract CIK") result["status"] = "error" return result # 获取财务指标 metrics = extract_financial_metrics_direct(cik, years=years) if "error" in metrics: result["errors"].append(f"Failed to get metrics: {metrics['error']}") result["status"] = "error" else: result["data"] = metrics except Exception as e: result["status"] = "error" result["errors"].append(str(e)) return result def get_service_health(): """ 检查财务数据服务健康状态 Returns: 服务状态字典 Example: health = get_service_health() """ return { "status": "ok", "message": "Using direct MCP functions (no HTTP service required)" } def query_company_advanced(company_input: str, type: str): """ 综合查询公司信息 (直接调用 chat_direct 的高级方法) 包括搜索、基本信息、文件列表和财务指标 Args: company_input: 公司名称或代码 get_filings: 是否获取文件列表 get_metrics: 是否获取财务指标 Returns: 综合结果字典,包含 company_search, company_info, filings, metrics Example: result = query_company_advanced("Apple", get_filings=True, get_metrics=True) """ prompt_suggestion = f""" Role: You are an expert investment advisor who provides data-driven recommendations based on a company’s financials, news, and market data. Task: Analyze the following for {company_input}: Financial metrics – revenue, profit, debt, cash flow, etc. Recent news – assess risks and opportunities. Stock data – price trend, volume, etc. Output Restriction: Your response must contain only the following two elements and nothing else: The exact block titled "Investment Recommendation:" with the four specified fields filled in. A single concluding sentence summarizing how the recommendation integrates financial, news, and market data. Final Output Format: Investment Recommendation: Recommendation: [Buy / Hold / Avoid] Entry & Exit Price: [Specify] Stop-Loss & Take-Profit Levels: [Specify] Holding Horizon: Short-term (<1 month) or Long-term (>1 month) This recommendation is based on an objective synthesis of the company’s latest financial performance, material news developments, and current market price action. Rules: Base all advice strictly on factual, verifiable data—no speculation or opinion. Be concise, professional, and actionable. Always ground entry/exit and stop/take-profit levels in recent price behavior (e.g., support/resistance, volatility). If insufficient reliable data exists, default to "Avoid". Output must be in English only. """ prompt_report = f""" Analyze the following for {company_input}: 3 Years Financial metrics – revenue, profit, debt, cash flow, etc. Recent news – assess risks and opportunities. Stock data – price trend, volume, etc. Role: You are a professional financial statement analyst specializing in deep, data-backed evaluations of public companies. Your task is to produce a comprehensive, clear, and actionable financial analysis report in English, strictly following the structure below. Instructions: Base all analysis on real financial data (e.g., Total Revenue, Net Income, Gross Profit Margin, Current Ratio) and current market trends. Incorporate visual insights: Describe or reference charts for Revenue Performance and Earnings Growth in the Summary, and use clear chart-based representations of key metrics in the Financial Statements section. If needed, simulate access to up-to-date financial databases (e.g., via Finnhub, SEC filings, or Bloomberg) to ensure data accuracy. Be objective, concise, and professional—avoid speculation or unsupported claims. Output Format (Markdown Only): Markdown # Financial Analysis Report: {company_input} ## Executive Summary - Analyze the company’s current financial health using **Total Revenue**, **Net Income**, **Gross Profit Margin**, and **Current Ratio**. - Include narrative + chart descriptions for **Revenue Performance** and **Earnings Growth** (e.g., YoY/QoQ trends). - Summarize the company’s current status, historical performance, and forward-looking outlook based on data and sector dynamics. ## Financial Statements - Present key financial metrics visually (e.g., time-series charts or comparative tables) for: - Total Revenue - Net Income - Gross Profit Margin (%) - Current Ratio - Ensure all data is clearly labeled, accurate, and easy to interpret. ## Investment Recommendation - **Recommendation**: [Buy / Hold / Avoid] - **Entry Price**: $XX.XX - **Target Exit Price**: $XX.XX - **Stop-Loss Level**: $XX.XX - **Take-Profit Level**: $XX.XX - **Holding Horizon**: Short-term (<1 month) or Long-term (>1 month) > *Disclaimer: This recommendation is based on factual financial analysis. Market conditions may change rapidly—invest at your own risk.* ## Industry Overview ### Company Snapshot Brief overview of the company’s business model, market position, and core operations. ### Three Investment Theses 1. **Thesis 1**: [e.g., Strong revenue growth driven by product innovation] 2. **Thesis 2**: [e.g., Expanding margins due to cost optimization] 3. **Thesis 3**: [e.g., Attractive valuation relative to industry peers] ### Key Risks & Mitigation Strategies - **Risk 1**: [e.g., Regulatory uncertainty] → *Mitigation*: [e.g., Geographic diversification] - **Risk 2**: [e.g., Rising input costs] → *Mitigation*: [e.g., Long-term supplier contracts] - **Risk 3**: [e.g., Intensifying competition] → *Mitigation*: [e.g., R&D investment and brand loyalty] Ensure the final output is fully self-contained, professionally written, and ready for investor review. Do not include any content outside the specified sections. """ # return analyze_company_with_llm(prompt) prompt = prompt_suggestion if type == "suggestion" else prompt_report # return chatbot_response(prompt) responses = list(chatbot_response(prompt)) final_response = responses[-1] print(f"最终分析答案---------: {final_response}") return final_response