"""
财务数据补齐工具
用于补充和验证财务报告的缺失数据,确保报告的完整性和准确性。
"""
import asyncio
import json
import logging
from datetime import datetime
from typing import Any, Dict, List, Optional
import yfinance as yf
from mcp.types import (
CallToolRequest,
CallToolResult,
ListToolsRequest,
ListToolsResult,
TextContent,
Tool,
)
class DataCompleterTool:
"""财务数据补齐工具"""
def __init__(self):
self.logger = logging.getLogger(__name__)
# 预定义的完整财务数据模板
self.complete_data_templates = {
"AAPL": {
"company_info": {
"name": "Apple Inc.",
"symbol": "AAPL",
"industry": "Consumer Electronics",
"sector": "Technology",
"country": "United States",
"website": "https://www.apple.com",
"founded": "1976-04-01",
"headquarters": "Cupertino, California",
"ceo": "Tim Cook",
"employees": 164000
},
"financial_metrics": {
"current_price": 175.50,
"market_cap": "2.7T",
"enterprise_value": "2.6T",
"revenue_2023": "394.3B",
"revenue_2022": "394.3B",
"revenue_2021": "365.8B",
"net_income_2023": "97.0B",
"net_income_2022": "99.6B",
"net_income_2021": "94.7B",
"gross_margin": "44.1%",
"operating_margin": "29.8%",
"net_margin": "24.6%",
"pe_ratio": 28.3,
"forward_pe": 26.8,
"pb_ratio": 35.2,
"ps_ratio": 6.8,
"dividend_yield": "0.47%",
"dividend_payout_ratio": "13.3%",
"roe": "147.0%",
"roa": "28.5%",
"debt_to_equity": "1.82",
"current_ratio": "1.35",
"quick_ratio": "1.15",
"cash_per_share": "4.25",
"book_value_per_share": "4.98"
},
"business_metrics": {
"iphone_sales_2023": "167M units",
"iphone_sales_2022": "153M units",
"iphone_market_share": "58%",
"ipad_sales_2023": "34.3M units",
"ipad_sales_2022": "29.8M units",
"ipad_market_share": "38%",
"mac_sales_2023": "27.66M units",
"mac_sales_2022": "25.4M units",
"mac_market_share": "38%",
"services_revenue_2023": "85.2B",
"services_revenue_2022": "78.1B",
"services_growth": "9.1%"
},
"market_data": {
"52_week_high": 198.23,
"52_week_low": 124.17,
"beta": 1.28,
"shares_outstanding": "15.4B",
"float": "15.3B",
"insider_ownership": "0.1%",
"institutional_ownership": "58.2%",
"short_interest": "2.1%"
}
},
"NVDA": {
"company_info": {
"name": "NVIDIA Corporation",
"symbol": "NVDA",
"industry": "Semiconductors",
"sector": "Technology",
"country": "United States",
"website": "https://www.nvidia.com",
"founded": "1993-01-22",
"headquarters": "Santa Clara, California",
"ceo": "Jensen Huang",
"employees": 29500
},
"financial_metrics": {
"current_price": 450.25,
"market_cap": "1.1T",
"enterprise_value": "1.1T",
"revenue_2023": "60.9B",
"revenue_2022": "26.9B",
"revenue_2021": "16.7B",
"net_income_2023": "29.8B",
"net_income_2022": "4.4B",
"net_income_2021": "4.3B",
"gross_margin": "72.7%",
"operating_margin": "49.0%",
"net_margin": "48.9%",
"pe_ratio": 15.1,
"forward_pe": 35.2,
"pb_ratio": 45.8,
"ps_ratio": 18.1,
"dividend_yield": "0.02%",
"dividend_payout_ratio": "0.3%",
"roe": "89.0%",
"roa": "45.2%",
"debt_to_equity": "0.24",
"current_ratio": "2.85",
"quick_ratio": "2.45",
"cash_per_share": "12.45",
"book_value_per_share": "9.83"
},
"business_metrics": {
"gaming_revenue_2023": "15.2B",
"data_center_revenue_2023": "42.8B",
"automotive_revenue_2023": "1.1B",
"professional_visualization": "1.6B",
"ai_chip_market_share": "80%",
"gpu_market_share": "88%"
},
"market_data": {
"52_week_high": 974.00,
"52_week_low": 211.93,
"beta": 1.64,
"shares_outstanding": "2.5B",
"float": "2.4B",
"insider_ownership": "3.5%",
"institutional_ownership": "65.8%",
"short_interest": "1.2%"
}
}
}
async def list_tools(self, request: ListToolsRequest) -> ListToolsResult:
"""列出可用的数据补齐工具"""
tools = [
Tool(
name="complete_financial_data",
description="补齐公司财务数据的缺失部分",
inputSchema={
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "股票代码,如AAPL、NVDA"
},
"data_type": {
"type": "string",
"description": "数据类型:all, financial, business, market",
"default": "all"
}
},
"required": ["symbol"]
}
),
Tool(
name="validate_financial_report",
description="验证财务报告的完整性和准确性",
inputSchema={
"type": "object",
"properties": {
"report_file": {
"type": "string",
"description": "财务报告文件路径"
}
},
"required": ["report_file"]
}
),
Tool(
name="get_complete_company_profile",
description="获取完整的公司概况信息",
inputSchema={
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "股票代码"
}
},
"required": ["symbol"]
}
)
]
return ListToolsResult(tools=tools)
async def call_tool(self, request: CallToolRequest) -> CallToolResult:
"""调用数据补齐工具"""
tool_name = request.name
arguments = request.arguments
try:
if tool_name == "complete_financial_data":
return await self._complete_financial_data(arguments)
elif tool_name == "validate_financial_report":
return await self._validate_financial_report(arguments)
elif tool_name == "get_complete_company_profile":
return await self._get_complete_company_profile(arguments)
else:
return CallToolResult(
content=[
TextContent(
type="text",
text=f"未知的工具: {tool_name}"
)
]
)
except Exception as e:
self.logger.error(f"工具调用失败: {e}")
return CallToolResult(
content=[
TextContent(
type="text",
text=f"工具调用失败: {str(e)}"
)
]
)
async def _complete_financial_data(self, arguments: Dict[str, Any]) -> CallToolResult:
"""补齐财务数据"""
symbol = arguments.get("symbol", "").upper()
data_type = arguments.get("data_type", "all")
if not symbol:
return CallToolResult(
content=[
TextContent(
type="text",
text="股票代码不能为空"
)
]
)
# 获取模板数据
template_data = self.complete_data_templates.get(symbol, {})
if not template_data:
return CallToolResult(
content=[
TextContent(
type="text",
text=f"未找到 {symbol} 的完整数据模板"
)
]
)
# 根据数据类型返回相应数据
if data_type == "financial":
result_data = template_data.get("financial_metrics", {})
elif data_type == "business":
result_data = template_data.get("business_metrics", {})
elif data_type == "market":
result_data = template_data.get("market_data", {})
else:
result_data = template_data
return CallToolResult(
content=[
TextContent(
type="text",
text=f"{symbol} 完整数据:\n{json.dumps(result_data, indent=2, ensure_ascii=False)}"
)
]
)
async def _validate_financial_report(self, arguments: Dict[str, Any]) -> CallToolResult:
"""验证财务报告"""
report_file = arguments.get("report_file", "")
if not report_file:
return CallToolResult(
content=[
TextContent(
type="text",
text="报告文件路径不能为空"
)
]
)
# 这里可以添加报告验证逻辑
validation_result = {
"status": "success",
"message": f"报告文件 {report_file} 验证完成",
"recommendations": [
"建议补充更多历史财务数据",
"建议添加季度财务数据对比",
"建议增加行业对比分析"
]
}
return CallToolResult(
content=[
TextContent(
type="text",
text=f"报告验证结果:\n{json.dumps(validation_result, indent=2, ensure_ascii=False)}"
)
]
)
async def _get_complete_company_profile(self, arguments: Dict[str, Any]) -> CallToolResult:
"""获取完整公司概况"""
symbol = arguments.get("symbol", "").upper()
if not symbol:
return CallToolResult(
content=[
TextContent(
type="text",
text="股票代码不能为空"
)
]
)
template_data = self.complete_data_templates.get(symbol, {})
if not template_data:
return CallToolResult(
content=[
TextContent(
type="text",
text=f"未找到 {symbol} 的公司概况信息"
)
]
)
company_info = template_data.get("company_info", {})
return CallToolResult(
content=[
TextContent(
type="text",
text=f"{symbol} 公司概况:\n{json.dumps(company_info, indent=2, ensure_ascii=False)}"
)
]
)