
Tushare Mcp
- 61 installs
- 61 repo stars
- Updated March 16, 2026
- kirkluokun/awesome-a-stock-openclawskills
Helps with ai & agent building tasks.
About
tushare-mcp is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- tushare-mcp
- AI & Agent Building
- AI-coding skill
Tushare Mcp by the numbers
- 61 all-time installs (skills.sh)
- +1 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #6,381 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/kirkluokun/awesome-a-stock-openclawskills --skill tushare-mcpAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 61 |
|---|---|
| repo stars | ★ 61 |
| Last updated | March 16, 2026 |
| Repository | kirkluokun/awesome-a-stock-openclawskills ↗ |
What it does
Helps with ai & agent building tasks.
Files
Tushare MCP 数据技能
鉴权变量:TUSHARE_API_KEY。通过 MCP 服务器调用 Tushare Pro API,不再需要写 Python 脚本。
核心规则
1. 使用 MCP tool,不写脚本 — 所有数据通过 tushare_* tool 获取 2. 先用 ToolSearch 加载 — MCP tool 是 deferred 的,调用前必须 ToolSearch("tushare ...") 加载 3. 日期格式 YYYYMMDD 或 YYYY-MM-DD — 两种都支持,MCP 内部自动转换 4. 默认返回 100 行 — 需要更多数据用 _limit 参数 5. 数据输出遵循存储规范 — 见 output-storage.md
使用流程
1. 确认需求 → 需要什么数据?
2. 查 tool 索引 → reference/tool-index.md 找到对应 tool
3. ToolSearch 加载 → ToolSearch("+tushare <关键词>")
4. 调用 tool → 传参获取数据
5. 存储/展示 → 按 output-storage.md 规范处理快速定位 Tool
| 需求场景 | 用哪个 tool | 关键参数 |
|---|---|---|
| 查某只股票行情 | tushare_daily | ts_code, start_date, end_date |
| 查财务三表 | tushare_income/balancesheet/cashflow | ts_code, period |
| 查指数走势 | tushare_index_daily | ts_code, start_date, end_date |
| 查 ETF 行情 | tushare_fund_daily | ts_code, trade_date |
| 查港股行情 | tushare_hk_daily | ts_code, start_date, end_date |
| 查美股行情 | tushare_us_daily | ts_code, start_date, end_date |
| 查宏观 GDP | tushare_cn_gdp | q(季度如 2024Q1) |
| 查利率 Shibor | tushare_shibor | start_date, end_date |
| 查龙虎榜 | tushare_top_list | trade_date |
| 查研究报告 | tushare_research_report | ts_code, start_date, end_date |
| 技术面因子 | tushare_stk_factor_pro | ts_code, start_date, end_date |
| 筹码分布 | tushare_cyq_chips | ts_code, trade_date |
| 涨跌停统计 | tushare_limit_list_d | trade_date |
| 资金流向 | tushare_moneyflow | ts_code, trade_date |
| 融资融券 | tushare_margin | trade_date |
| 实时分钟线 | tushare_rt_min | ts_code |
完整 tool 索引:reference/tool-index.md
代码格式说明
| 市场 | 代码格式 | 示例 |
|---|---|---|
| 沪市 | XXXXXX.SH | 600000.SH |
| 深市 | XXXXXX.SZ | 000001.SZ |
| 北交所 | XXXXXX.BJ | 430047.BJ |
| 港股 | XXXXX.HK | 00700.HK |
| 美股 | TICKER | AAPL |
| 指数 | XXXXXX.SH/SZ | 000001.SH(上证综指) |
| ETF | XXXXXX.SH/SZ | 510050.SH |
| 期货 | 品种代码.交易所 | CU2401.SHF |
已知限制
- 港股/美股财务数据需 15000 积分,积分不足会报错
- 部分高级接口需要单独开通权限(如 rt_min 实时分钟线)
- 单次请求默认 100 行上限,大批量需多次请求或调
_limit
调研纪要/PDF 场景
需要处理“调研纪要原文/关注问题”时,先读:
- 调研纪要/PDF 处理指引
参考
- Tool 完整索引 — 按场景分类的 158 个 tool
- 数据输出规范 — 文件存储路径和格式
- 查询模式手册 — 常见分析场景的 tool 组合
- 调研纪要/PDF 处理指引 — 纪要抓取、权限回退与输出模板
{
"name": "tushare-mcp",
"version": "1.0.0",
"description": "Tushare Pro MCP 数据技能。通过 158+ 个 MCP tool 获取 A股/港股/美股/基金/期货/债券/宏观数据。替代旧版 tushare-finance skill,无需写 Python 脚本。",
"author": "kirkluokun",
"tags": ["金融数据", "MCP", "A股", "港股", "美股", "基金", "期货", "债券", "宏观经济", "Tushare"],
"license": "MIT",
"replaces": "tushare-finance-2.0.6",
"dependencies": {
"mcp": "tushare-pro"
}
}
# ============================================================
# Tushare Pro MCP 环境配置
# ============================================================
# 使用方法:
# 1. 复制本文件为 .env → cp .env.example .env
# 2. 填入你的真实 Token
#
# .env 查找顺序(优先级从高到低):
# 1. 系统环境变量(已设置则不覆盖)
# 2. 本技能文件夹下的 .env
# 3. 上一级目录的 .env(适用于多技能共享同一份密钥)
# ============================================================
# Tushare Pro API Token(A 股金融数据核心依赖)
# 获取地址:https://tushare.pro/register(注册后在个人中心获取 Token)
# 注意:部分高级接口需要积分,详见 https://tushare.pro/document/1?doc_id=108
TUSHARE_API_KEY=your_tushare_token_here
# Python
__pycache__/
*.pyc
*.pyo
.venv/
# Data (SQLite 数据库,自动生成,不提交)
data/
# IDE
.idea/
.vscode/
*.swp
# pytest
.pytest_cache/
# OS
.DS_Store
Tushare Pro MCP — 未实现接口备忘
220 个接口中已实现 154 个(70%),剩余 66 个按优先级分类如下。
---
已停用/暂停 (6个) — 不需要实现
| 接口文档 | API | 说明 |
|---|---|---|
| 转融券交易汇总(停) | slb_sec | 已停用 |
| 转融券交易明细(停) | slb_sec_detail | 已停用 |
| 做市借券交易汇总(停) | slb_len_mm | 已停用 |
| 股票开户数据(停) | stk_account | 已停用 |
| 股票开户数据(旧) | stk_account_old | 旧版已废弃 |
| 同花顺涨跌停榜单 | limit_list_ths | 已被 limit_list_d 替代 |
---
爬虫/实时数据 (7个) — 需爬虫权限,按需实现
| 接口文档 | API | 说明 |
|---|---|---|
| 实时Tick(爬虫) | realtime_quote | 爬虫权限 |
| 实时成交(爬虫) | realtime_tick | 爬虫权限 |
| 实时排名(爬虫) | realtime_list | 爬虫权限 |
| 实时日线 | rt_k | A股实时K线 |
| ETF实时日线 | rt_etf_k | ETF实时K线 |
| 港股实时日线 | rt_hk_k | 港股实时K线 |
| 指数实时日线 | rt_idx_k | 指数实时K线 |
---
技术面因子 (5个) — 需专业版/高积分
| 接口文档 | API | 说明 |
|---|---|---|
| 股票技术面因子 | stk_factor | 普通版 |
| 股票技术面因子(专业版) | stk_factor_pro | 专业版 |
| 基金技术面因子(专业版) | fund_factor_pro | 专业版 |
| 可转债技术面因子(专业版) | cb_factor_pro | 专业版 |
| 指数技术面因子(专业版) | idx_factor_pro | 专业版 |
---
非金融数据 (8个) — 与投研无关
| 接口文档 | API | 说明 |
|---|---|---|
| 电影日度票房 | bo_daily | 电影 |
| 电影周度票房 | bo_weekly | 电影 |
| 电影月度票房 | bo_monthly | 电影 |
| 影院日度票房 | bo_cinema | 电影 |
| 全国电影剧本备案数据 | film_record | 广电 |
| 全国电视剧备案公示数据 | teleplay_record | 广电 |
| 国家政策库 | npr | 政策文本 |
| 新闻通讯(长篇) | major_news | 长篇新闻 |
---
重复/衍生接口 (8个) — 功能已被现有接口覆盖
| 接口文档 | API | 说明 |
|---|---|---|
| 复权行情 | pro_bar | 通过 adj_factor + daily 计算即可 |
| 港股复权行情 | hk_daily + hk_adjfactor | 已有组合替代 |
| 美股复权行情 | us_daily + us_adjfactor | 已有组合替代 |
| 周_月线行情(每日更新) | stk_weekly_monthly | 已有 weekly/monthly |
| 周_月线复权行情(每日更新) | — | 已有 weekly/monthly + adj_factor |
| 备用行情 | bak_daily | daily 的备用,不常用 |
| 通用行情接口 | pro_bar | 各品种行情已分别实现 |
| 数据索引 | — | 元数据索引页,非API |
---
低优先级可选接口 (32个) — 按需实现
港股/美股补充
| 接口文档 | API |
|---|---|
| 港股通每月成交统计 | ggt_monthly |
| 美股财务指标数据 | us_fina_indicator |
基金补充
| 接口文档 | API |
|---|---|
| 基金销售行业数据 | fund_sales_vol |
| 各渠道公募基金销售保有规模占比 | fund_sales_ratio |
| 销售机构公募基金销售保有规模 | fund_sales_vol |
板块/热榜补充
| 接口文档 | API |
|---|---|
| 同花顺App热榜数 | ths_hot |
| 榜单数据(开盘啦) | kpl_list |
| 东财概念和行业指数行情 | dc_daily |
债券/柜台
| 接口文档 | API |
|---|---|
| 柜台流通式债券报价 | bc_otcqt |
| 柜台流通式债券最优报价 | bc_bestotcqt |
| 大宗交易(债券) | bond_blk |
| 大宗交易明细(债券) | bond_blk_detail |
沪深市场补充
| 接口文档 | API |
|---|---|
| 深圳市场每日交易情况 | sz_daily_info |
| 沪深股通持股明细 | hk_hold |
| 中央结算系统持股统计 | ccass_hold |
| 北交所新旧代码对照 | bse_mapping |
| 股票历史列表 | bak_basic |
盘前/竞价
| 接口文档 | API |
|---|---|
| 每日股本(盘前) | stk_premarket |
| 融资融券标的(盘前) | margin_secs |
| 股票开盘集合竞价数据 | stk_auction_o |
| 股票收盘集合竞价数据 | stk_auction_c |
| 开盘竞价成交(当日) | stk_auction |
期货补充
| 接口文档 | API |
|---|---|
| 历史分钟行情(期货) | ft_mins |
| 实时分钟行情(期货) | rt_fut_min |
| 日线行情(南华) | fut_daily (重复?) |
其他
| 接口文档 | API |
|---|---|
| Shibor报价数据 | shibor_quote |
| 历史Tick行情 | tick_data |
| 转融资交易汇总 | slb_len |
| 神奇九转指标 | stk_nineturn |
| 上证e互动问答 | irm_qa_sh |
| 深证易互动问答 | irm_qa_sz |
| 台湾电子产业月营收 | tmt_twincome |
| 台湾电子产业月营收明细 | tmt_twincomedetail |
| 社区捐助 | — |
[project]
name = "tushare-pro-mcp"
version = "0.1.0"
description = "Tushare Pro MCP Server - A股数据 MCP 工具服务"
requires-python = ">=3.11"
dependencies = [
"fastmcp>=2.0.0",
"tushare>=1.4.0",
"pandas>=2.0.0",
"tabulate>=0.9.0",
]
[project.optional-dependencies]
dev = [
"pytest>=8.0.0",
"pytest-asyncio>=0.24.0",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/tushare_mcp"]
Tushare Pro MCP Server
A股金融数据 MCP 工具服务,基于 Tushare Pro API,通过 FastMCP 以 stdio 模式运行。
概览
- 154 个 MCP Tools,覆盖 Tushare 220 个接口的 70%
- 30 个功能模块,按业务领域组织
- 167 个单元测试,全部通过
数据覆盖
| 模块 | 文件 | Tools | 说明 |
|---|---|---|---|
| A股行情 | stock.py | 10 | 日/周/月线、涨跌停、复权因子、停复牌、曾用名、IPO等 |
| 财务报表 | finance.py | 7 | 利润表、资产负债表、现金流量表、财务指标、审计、主营、披露日期 |
| 指数 | index.py | 8 | 指数行情(日/周/月)、基本信息、成分权重、国际指数、大盘指标 |
| 宏观经济 | macro.py | 19 | GDP、PMI、货币供应、社融、Shibor/Hibor/Libor、美国国债利率、LPR、黄金、民间借贷 |
| 业绩 | earnings.py | 3 | 业绩预告、快报、券商盈利预测 |
| 行业分类 | classify.py | 4 | 申万行业分类/成分、中信行业日行情/成分 |
| 新闻 | news.py | 2 | 新闻快讯、新闻联播 |
| 融资融券 | margin.py | 2 | 交易汇总、明细 |
| 龙虎榜 | billboard.py | 2 | 每日明细、机构交易 |
| 股东 | holder.py | 5 | 股东人数、前十大股东/流通股东、增减持、CCASS持股 |
| 公司行为 | corporate.py | 6 | 分红、回购、解禁、质押统计/明细、管理层薪酬 |
| 资金流向 | moneyflow.py | 5 | 资金流向、沪深港通资金、十大成交股、大宗交易 |
| 概念板块 | concept.py | 5 | 开盘啦概念/成分、同花顺指数/行情/成分 |
| 东财板块 | dc_board.py | 3 | 东财指数行情、板块成分、人气榜 |
| 通达信板块 | tdx_board.py | 3 | 通达信指数/日线/成分 |
| 涨跌停 | limit.py | 2 | 涨跌停统计、连板天梯 |
| 筹码分析 | chips.py | 2 | 筹码分布、筹码指标 |
| 游资 | hotmoney.py | 2 | 游资名录、每日明细 |
| 研究 | research.py | 3 | 上市公司公告、管理层、券商金股 |
| 港股 | hk.py + hk_finance.py | 9 | 基础信息、日线、复权因子、交易日历、港股通、三大财务报表、财务指标 |
| 美股 | us.py + us_finance.py | 7 | 基础信息、日线、复权因子、交易日历、三大财务报表 |
| 基金 | fund.py | 8 | 基金列表、净值、分红、持仓、管理人、经理、规模、复权因子 |
| ETF | etf.py | 4 | ETF基本信息、日线、份额规模、跟踪指数 |
| 期货 | futures.py | 9 | 主力映射、日线、仓单、涨跌停、周报、合约列表、结算参数、持仓排名、周月线 |
| 外汇 | forex.py | 2 | 基础信息、日线行情 |
| 期权 | option.py | 2 | 合约信息、日线行情 |
| 债券 | bond.py | 8 | 可转债基础/行情/发行/利率/赎回/转股结果/转股价变动、债券回购 |
| 分钟行情 | minutes.py | 6 | A股/港股/ETF/期权分钟行情、实时分钟 |
安装
# 克隆项目
cd openclaw-skills/tushare-pro-mcp
# 创建虚拟环境
uv venv
source .venv/bin/activate
# 安装依赖
uv pip install -e ".[dev]"配置
在 ~/.claude.json 中注册 MCP 服务器:
{
"mcpServers": {
"tushare-pro": {
"command": "/path/to/tushare-pro-mcp/.venv/bin/python",
"args": ["-m", "tushare_mcp.server"],
"env": {
"TUSHARE_API_KEY": "your_tushare_token_here"
}
}
}
}需要在 Tushare Pro 注册并获取 token。不同接口需要不同积分等级(120 ~ 10000+)。
环境变量说明:使用 TUSHARE_API_KEY。架构
server.py (FastMCP) → tools/*.py → client.py → tushare API
↓
formatter.py → JSON/Markdown- client.py: 纯函数封装层,每个接口一个函数,统一日期格式化 + 频率限制
- *tools/.py**: MCP tool 注册层,调用 client + formatter,捕获 TushareError
- formatter.py: DataFrame →
{api, total_rows, returned_rows, truncated, data} - rate_limiter.py: 300ms 最小调用间隔
- errors.py: TushareError / TokenError / ApiError 异常体系
使用
所有 tool 名称以 tushare_ 开头,支持以下通用参数:
| 参数 | 说明 | 默认值 |
|---|---|---|
_format | 输出格式 (json / markdown) | json |
_limit | 最大返回行数 | 100 |
日期参数支持 YYYYMMDD 或 YYYY-MM-DD 两种格式。
示例:
tushare_daily(ts_code="000001.SZ", trade_date="2026-02-27")
tushare_income(ts_code="000001.SZ", period="20251231", _format="markdown")
tushare_index_daily(ts_code="000300.SH", start_date="2026-01-01", end_date="2026-02-27")测试
.venv/bin/python -m pytest tests/ -v未实现接口
约 66 个接口未实现,详见 docs/remaining-apis.md。主要包括:
- 已停用接口 (6个)
- 爬虫/实时数据 (7个)
- 技术面因子/专业版 (5个)
- 非金融数据 (8个)
- 重复/衍生接口 (8个)
- 低优先级可选 (32个)
开发
新增接口的标准流程:
1. client.py — 添加 API 函数 2. tools/*.py — 添加 MCP tool 注册 3. server.py — 注册新模块(如需新建模块) 4. tests/ — 添加单元测试 5. pytest tests/ — 确认全绿
数据输出规范
输出根目录
~/.openclaw/workspace/data/tushare/严禁写入 workspace 根目录。
目录结构
按任务类型组织子目录:
data/tushare/
├── daily/ # 日线行情快照
├── financial/ # 财务报表数据
├── index/ # 指数数据
├── macro/ # 宏观经济数据
├── research/ # 研报、盈利预测
├── fund/ # 基金数据
├── hk/ # 港股数据
├── us/ # 美股数据
├── futures/ # 期货数据
├── bond/ # 债券/可转债
├── reports/ # 生成的分析报告
└── temp/ # 临时数据(可清理)文件命名
{数据类型}_{标的}_{日期范围}.{格式}示例:
daily_000001.SZ_20250101-20250228.csvincome_600000.SH_2024Q1-2024Q4.csvindex_000001.SH_20250201-20250228.csv
输出格式
| 场景 | 格式 | 说明 |
|---|---|---|
| 临时查看 | 直接展示 | 小量数据直接在对话中展示 |
| 数据分析 | CSV | 大量数据存 CSV 供后续处理 |
| 报告输出 | Markdown | 分析结论用 Markdown 格式 |
| 模型输入 | CSV/JSON | 供财务模型使用 |
规则
1. 单次查询结果 < 20 行:直接在对话中展示,不存文件 2. 单次查询结果 >= 20 行:存文件,返回文件路径和摘要 3. 分析报告:存入 reports/ 目录 4. 中间数据:存入 temp/,提醒用户可清理
常见查询模式
个股全景分析
一只股票的完整画像,需组合以下 tool:
| 步骤 | Tool | 说明 |
|---|---|---|
| 1 | tushare_stock_basic | 基本信息(行业、上市日期) |
| 2 | tushare_daily | 近期行情 |
| 3 | tushare_daily_basic | 估值指标(PE/PB/换手率) |
| 4 | tushare_income + tushare_balancesheet + tushare_cashflow | 财务三表 |
| 5 | tushare_fina_indicator | 财务指标(ROE/毛利率等) |
| 6 | tushare_top10_holders | 十大股东 |
| 7 | tushare_stk_factor_pro | 技术面因子(MA/MACD/KDJ/BOLL) |
| 8 | tushare_moneyflow | 资金流向 |
| 9 | tushare_concept_detail | 所属概念板块 |
财务三表分析(3-Statements)
tushare_income → 利润表(营收、净利润、毛利)
tushare_balancesheet → 资产负债表(总资产、负债、股东权益)
tushare_cashflow → 现金流量表(经营/投资/筹资现金流)
tushare_fina_indicator → 衍生指标(ROE/ROA/毛利率/净利率)
tushare_fina_mainbz → 主营业务构成(按产品/地区)典型参数:ts_code='600000.SH', period='20240930'
DCF 估值所需数据
| 数据 | Tool |
|---|---|
| 历史营收/净利润 | tushare_income |
| 历史自由现金流 | tushare_cashflow |
| 资本结构 | tushare_balancesheet |
| 行业 beta | tushare_daily + tushare_index_daily 回归计算 |
| 无风险利率 | tushare_yc_cb(国债收益率曲线) |
| 行业可比公司 | tushare_index_member_all 找同行业 |
| 可比公司估值 | tushare_daily_basic 批量取 PE/PB |
可比公司分析(Comps)
1. tushare_index_classify → 找到目标公司所属申万行业
2. tushare_index_member_all → 获取同行业所有公司
3. tushare_daily_basic → 批量获取 PE/PB/PS/市值
4. tushare_fina_indicator → 批量获取 ROE/毛利率/净利率
5. tushare_income → 营收增速对比盈利预测 & 研报
tushare_forecast → 公司业绩预告(预增/预减/扭亏)
tushare_express → 业绩快报
tushare_broker_recommend → 券商月度金股推荐
tushare_research_report → 券商研究报告(含PDF下载链接)
tushare_report_rc → 卖方盈利预测一致预期行业/板块分析
# 申万行业
tushare_index_classify → 行业分类列表
tushare_index_member_all → 行业成分股
tushare_sw_daily → 行业指数日线
tushare_ci_daily → 中信行业日线
# 概念板块
tushare_concept → 概念列表
tushare_concept_detail → 概念成分股
# 同花顺板块
tushare_ths_index → 同花顺板块列表
tushare_ths_daily → 同花顺板块日线
tushare_ths_member → 同花顺板块成分
# 东财板块
tushare_dc_index → 东财板块列表
tushare_dc_member → 东财板块成分
tushare_dc_hot → 东财热门板块市场情绪 & 异动
tushare_limit_list_d → 当日涨跌停列表
tushare_limit_cpt_list → 涨停板封单统计
tushare_top_list → 龙虎榜明细
tushare_top_inst → 龙虎榜机构明细
tushare_hm_detail → 游资每日操作
tushare_moneyflow → 个股资金流向
tushare_block_trade → 大宗交易
tushare_stk_holdertrade → 股东增减持宏观经济
tushare_cn_gdp → GDP
tushare_cn_pmi → PMI
tushare_cn_m → 货币供应量(M0/M1/M2)
tushare_sf_month → 社会融资规模
tushare_eco_cal → 经济日历
tushare_shibor → Shibor
tushare_lpr → LPR
tushare_yc_cb → 国债收益率曲线跨市场对比
# A/H 溢价
tushare_stk_ah_comparison → A/H 股溢价率
# 沪深港通
tushare_moneyflow_hsgt → 北向/南向资金流向
tushare_hsgt_top10 → 沪深股通十大成交股
tushare_ggt_top10 → 港股通十大成交股
tushare_ggt_daily → 港股通每日成交统计
# 全球指数
tushare_index_global → 全球主要指数行情基金分析
tushare_fund_basic → 基金列表(场内E/场外O)
tushare_fund_nav → 基金净值
tushare_fund_portfolio → 基金持仓明细
tushare_fund_manager → 基金经理信息
tushare_fund_share → 基金份额变动(申购赎回)
tushare_fund_div → 基金分红
tushare_fund_company → 基金公司列表ETF 分析
tushare_etf_basic → ETF 列表
tushare_fund_daily → ETF 日线行情
tushare_etf_share_size → ETF 规模变动
tushare_etf_index → ETF 关联指数
tushare_etf_mins → ETF 分钟行情调研纪要 / PDF 处理指引
当用户要“调研纪要原文/关注问题”时,按下面顺序执行:
1. 先拿结构化调研记录:tushare_stk_surv(日期区间 + ts_code) 2. 再尝试公告列表:tushare_anns 3. 若 `tushare_anns` 报权限/积分不足:明确告知并切换到“外部PDF直连+本地解析”
PDF 获取与解析故障处理
web_fetch对部分站点会因网络安全策略报错(如 Blocked: private/internal/special-use IP)- 这不等于用户无权限,优先改用:
curl -L <pdf_url> -o /tmp/xxx.pdf- 本地解析 PDF 文本(如
pypdf) - 输出时要明确:
- 来源文件名/日期/编号
- 关注问题列表(Q)与公司答复要点(A)
- 哪些内容来自原文,哪些是二次归纳
建议话术(遇到权限/抓取失败时)
- “
tushare_anns当前权限不足,我改用公开PDF直连抓取并本地解析,结果以原文为准。” - “
web_fetch被站点策略拦截,不是账号权限问题,已切换为可直连下载方案。”
输出模板(建议)
1. 会议信息(时间、形式、接待方、机构类型) 2. 关注问题(按优先级 1/2/3) 3. 管理层答复要点(逐条对应问题) 4. 可验证指标(后续跟踪口径)
Tool 完整索引
158 个 MCP tool,按场景分类。调用前需先 ToolSearch("+tushare <关键词>") 加载。
---
A股行情
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_stock_basic | 股票列表 | exchange, list_status |
tushare_daily | 日线行情 | ts_code, trade_date, start_date, end_date |
tushare_weekly | 周线行情 | ts_code, trade_date, start_date, end_date |
tushare_monthly | 月线行情 | ts_code, trade_date, start_date, end_date |
tushare_daily_basic | 每日指标(PE/PB/换手率/市值) | ts_code, trade_date |
tushare_adj_factor | 复权因子 | ts_code, trade_date |
tushare_stk_limit | 涨跌停价格 | ts_code, trade_date |
tushare_suspend_d | 停复牌信息 | ts_code, trade_date, suspend_type |
tushare_stk_mins | A股分钟行情 | ts_code, freq, start_date, end_date |
tushare_rt_min | 实时分钟行情 | ts_code |
A股基本信息
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_namechange | 股票曾用名 | ts_code |
tushare_stock_company | 上市公司信息 | ts_code, exchange |
tushare_new_share | 新股上市信息 | start_date, end_date |
tushare_stock_st | ST 标记 | ts_code |
tushare_stock_hsgt | 沪深港通成分 | ts_code, hs_type |
tushare_stk_managers | 管理层信息 | ts_code |
tushare_stk_rewards | 管理层薪酬持股 | ts_code, end_date |
tushare_trade_cal | 交易日历 | exchange, start_date, end_date |
tushare_daily_info | 每日市场总貌 | trade_date, exchange |
财务数据
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_income | 利润表 | ts_code, period, start_date, end_date |
tushare_balancesheet | 资产负债表 | ts_code, period, start_date, end_date |
tushare_cashflow | 现金流量表 | ts_code, period, start_date, end_date |
tushare_fina_indicator | 财务指标(ROE/毛利率等) | ts_code, period, start_date, end_date |
tushare_fina_audit | 审计意见 | ts_code, period |
tushare_fina_mainbz | 主营业务构成 | ts_code, period, type |
tushare_disclosure_date | 财报披露日期 | end_date |
盈利预测 & 研报
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_forecast | 业绩预告 | ts_code, ann_date, period |
tushare_express | 业绩快报 | ts_code, ann_date, period |
tushare_report_rc | 卖方盈利预测 | ts_code |
tushare_broker_recommend | 券商月度金股 | month |
tushare_research_report | 券商研究报告(含PDF链接) | ts_code, start_date, end_date |
tushare_anns | 上市公司公告 | ts_code, trade_date, start_date, end_date |
股东数据
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_stk_holdernumber | 股东人数 | ts_code, end_date |
tushare_top10_holders | 十大股东 | ts_code, period |
tushare_top10_floatholders | 十大流通股东 | ts_code, period |
tushare_stk_holdertrade | 股东增减持 | ts_code, ann_date |
tushare_ccass_hold | 中央结算系统持股明细 | ts_code, hk_code, trade_date |
tushare_ccass_hold_stat | 中央结算系统持股汇总 | ts_code, hk_code, trade_date |
公司行为
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_dividend | 分红送股 | ts_code, ann_date |
tushare_repurchase | 股票回购 | ts_code, ann_date |
tushare_share_float | 限售解禁 | ts_code, ann_date |
tushare_pledge_stat | 股权质押统计 | ts_code |
tushare_pledge_detail | 股权质押明细 | ts_code |
tushare_stk_surv | 机构调研明细 | ts_code, trade_date |
技术分析
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_stk_factor_pro | 技术面因子(MA/MACD/KDJ/BOLL/RSI) | ts_code, start_date, end_date |
tushare_stk_nineturn | 神奇九转指标 | ts_code, trade_date |
tushare_cyq_chips | 筹码分布 | ts_code, trade_date |
tushare_cyq_perf | 筹码绩效 | ts_code, trade_date |
龙虎榜
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_top_list | 龙虎榜每日明细 | trade_date |
tushare_top_inst | 龙虎榜机构明细 | trade_date |
融资融券
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_margin | 融资融券交易汇总 | trade_date, exchange_id |
tushare_margin_detail | 融资融券交易明细 | ts_code, trade_date |
资金流向
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_moneyflow | 个股资金流向 | ts_code, trade_date |
tushare_moneyflow_hsgt | 沪深港通资金流向 | trade_date |
tushare_hsgt_top10 | 沪深股通十大成交股 | trade_date, market_type |
tushare_ggt_top10 | 港股通十大成交股 | trade_date, market_type |
tushare_block_trade | 大宗交易 | ts_code, trade_date |
涨跌停
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_limit_list_d | 涨跌停列表 | trade_date, limit_type |
tushare_limit_cpt_list | 涨停板封单统计 | trade_date |
游资
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_hm_list | 游资名录 | — |
tushare_hm_detail | 游资每日操作明细 | trade_date, hm_name |
指数数据
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_index_basic | 指数基本信息 | market, category |
tushare_index_daily | 指数日线 | ts_code, trade_date, start_date, end_date |
tushare_index_weekly | 指数周线 | ts_code, start_date, end_date |
tushare_index_monthly | 指数月线 | ts_code, start_date, end_date |
tushare_index_weight | 指数成分和权重 | index_code, trade_date |
tushare_index_dailybasic | 大盘指数每日指标 | ts_code, trade_date |
tushare_index_global | 国际主要指数 | ts_code, trade_date |
行业分类
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_index_classify | 申万行业分类 | level, src |
tushare_index_member_all | 申万行业成分 | index_code, is_new |
tushare_sw_daily | 申万行业日线 | ts_code, trade_date |
tushare_ci_daily | 中信行业日线 | ts_code, trade_date |
tushare_ci_index_member | 中信行业成分 | ts_code |
板块
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_concept | 概念板块列表 | src |
tushare_concept_detail | 概念板块成分 | id, ts_code |
tushare_ths_index | 同花顺板块指数 | exchange, type |
tushare_ths_daily | 同花顺板块日线 | ts_code, trade_date |
tushare_ths_member | 同花顺板块成分 | ts_code |
tushare_dc_index | 东财板块列表 | — |
tushare_dc_member | 东财板块成分 | ts_code |
tushare_dc_hot | 东财热门板块 | trade_date |
tushare_tdx_index | 通达信板块列表 | — |
tushare_tdx_daily | 通达信板块日线 | ts_code, trade_date |
tushare_tdx_member | 通达信板块成分 | ts_code |
ETF
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_etf_basic | ETF 列表 | market |
tushare_fund_daily | ETF/基金日线行情 | ts_code, trade_date |
tushare_etf_share_size | ETF 规模变动 | ts_code, trade_date |
tushare_etf_index | ETF 关联指数 | ts_code |
tushare_etf_mins | ETF 分钟行情 | ts_code, freq, start_date, end_date |
基金
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_fund_basic | 基金列表 | market, status |
tushare_fund_nav | 基金净值 | ts_code, end_date |
tushare_fund_div | 基金分红 | ts_code, ann_date |
tushare_fund_portfolio | 基金持仓 | ts_code, ann_date |
tushare_fund_company | 基金公司 | — |
tushare_fund_manager | 基金经理 | ts_code |
tushare_fund_share | 基金份额变动 | ts_code, trade_date |
tushare_fund_adj | 基金复权因子 | ts_code, trade_date |
港股
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_hk_basic | 港股列表 | list_status |
tushare_hk_tradecal | 港股交易日历 | start_date, end_date |
tushare_hk_daily | 港股日线 | ts_code, trade_date |
tushare_hk_adjfactor | 港股复权因子 | ts_code, trade_date |
tushare_ggt_daily | 港股通每日成交 | trade_date |
tushare_hk_mins | 港股分钟行情 | ts_code, freq, start_date, end_date |
港股财务
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_hk_income | 港股利润表 | ts_code, period |
tushare_hk_balancesheet | 港股资产负债表 | ts_code, period |
tushare_hk_cashflow | 港股现金流量表 | ts_code, period |
tushare_hk_fina_indicator | 港股财务指标 | ts_code, period |
美股
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_us_basic | 美股列表 | classify |
tushare_us_tradecal | 美股交易日历 | start_date, end_date |
tushare_us_daily | 美股日线 | ts_code, trade_date |
tushare_us_adjfactor | 美股复权因子 | ts_code, trade_date |
美股财务
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_us_income | 美股利润表 | ts_code, period |
tushare_us_balancesheet | 美股资产负债表 | ts_code, period |
tushare_us_cashflow | 美股现金流量表 | ts_code, period |
A/H 对比
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_stk_ah_comparison | A/H 股溢价率 | ts_code, trade_date |
期货
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_fut_basic | 期货合约列表 | exchange, fut_type |
tushare_fut_mapping | 主力/连续合约映射 | ts_code, trade_date |
tushare_fut_daily | 期货日线 | ts_code, trade_date |
tushare_fut_wsr | 仓单日报 | trade_date, symbol |
tushare_ft_limit | 期货涨跌停 | ts_code, trade_date |
tushare_fut_weekly_detail | 期货交易所周报 | trade_date, symbol |
tushare_fut_settle | 期货结算参数 | ts_code, trade_date |
tushare_fut_holding | 期货持仓排名 | trade_date, symbol, exchange |
tushare_fut_wm | 期货周/月行情 | ts_code, trade_date, date_type |
外汇
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_fx_obasic | 外汇基本信息 | exchange, classify |
tushare_fx_daily | 外汇日线 | ts_code, trade_date |
期权
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_opt_basic | 期权合约列表 | exchange, opt_code |
tushare_opt_daily | 期权日线 | ts_code, trade_date |
tushare_opt_mins | 期权分钟行情 | ts_code, freq, start_date, end_date |
可转债
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_cb_basic | 可转债基本信息 | ts_code |
tushare_cb_daily | 可转债日线 | ts_code, trade_date |
tushare_cb_issue | 可转债发行 | ts_code |
tushare_cb_rate | 可转债票面利率 | ts_code |
tushare_cb_call | 可转债赎回信息 | ts_code |
tushare_cb_share | 可转债转股结果 | ts_code |
tushare_cb_price_chg | 可转债转股价变动 | ts_code |
tushare_repo_daily | 债券回购日线 | ts_code, trade_date |
新闻
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_news | 新闻快讯 | start_date, end_date, src |
tushare_cctv_news | 新闻联播文字 | date |
利率
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_shibor | Shibor 利率 | start_date, end_date |
tushare_lpr | LPR 贷款基准利率 | start_date, end_date |
tushare_hibor | Hibor(香港) | start_date, end_date |
tushare_libor | Libor(伦敦) | start_date, end_date |
tushare_yc_cb | 中国国债收益率曲线 | ts_code, trade_date |
美国利率 & 国债
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_us_tycr | 美国国债收益率 | start_date, end_date |
tushare_us_trycr | 美国实际国债收益率 | start_date, end_date |
tushare_us_tltr | 美国长期国债利率 | start_date, end_date |
tushare_us_trltr | 美国实际长期国债利率 | start_date, end_date |
tushare_us_tbr | 美国短期国债利率 | start_date, end_date |
宏观经济
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_cn_gdp | GDP | q(季度) |
tushare_cn_pmi | PMI | start_date, end_date |
tushare_cn_m | 货币供应量(M0/M1/M2) | start_date, end_date |
tushare_eco_cal | 经济日历 | start_date, end_date |
tushare_sf_month | 社会融资规模 | start_date, end_date |
黄金 & 民间借贷
| Tool | 说明 | 关键参数 |
|---|---|---|
tushare_sge_basic | 上海金交所基本信息 | — |
tushare_sge_daily | 上海金交所日线 | ts_code, trade_date |
tushare_gz_index | 广州民间借贷利率指数 | start_date, end_date |
tushare_wz_index | 温州民间借贷利率指数 | start_date, end_date |
"""Tushare Pro MCP Server — A股数据 MCP 工具服务"""
"""允许 python -m tushare_mcp.server 启动"""
from .server import main
main()
"""
Tushare MCP 异常类型定义
所有自定义异常都继承自 TushareError,方便统一捕获。
"""
class TushareError(Exception):
"""Tushare MCP 基础异常"""
pass
class InsufficientPointsError(TushareError):
"""积分不足,无法调用该接口"""
pass
class RateLimitError(TushareError):
"""API 调用频率超限"""
pass
class ApiError(TushareError):
"""Tushare API 返回错误"""
def __init__(self, api_name: str, message: str) -> None:
self.api_name = api_name
super().__init__(f"[{api_name}] {message}")
class TokenError(TushareError):
"""Token 未配置或无效"""
pass
"""
DataFrame 格式转换
将 pandas DataFrame 转为 MCP tool 返回的标准格式。
支持 json 和 markdown 两种输出。
"""
import json
from typing import Any
import pandas as pd
def format_response(
df: pd.DataFrame,
api_name: str,
output_format: str = "json",
limit: int = 100,
) -> dict[str, Any]:
"""
将 DataFrame 转换为 MCP tool 标准响应
Args:
df: tushare 返回的 DataFrame
api_name: 接口名称,用于元信息
output_format: 输出格式(json 或 markdown)
limit: 最大返回行数
Returns:
标准响应字典,包含 api, total_rows, returned_rows, truncated, data
"""
total_rows = len(df)
truncated = total_rows > limit
df_limited = df.head(limit)
returned_rows = len(df_limited)
if output_format == "markdown":
data = _df_to_markdown(df_limited)
else:
data = _df_to_json(df_limited)
return {
"api": api_name,
"total_rows": total_rows,
"returned_rows": returned_rows,
"truncated": truncated,
"data": data,
}
def _df_to_json(df: pd.DataFrame) -> list[dict[str, Any]]:
"""DataFrame → 字典列表,NaN 转为 None"""
return json.loads(df.to_json(orient="records", date_format="iso"))
def _df_to_markdown(df: pd.DataFrame) -> str:
"""DataFrame → Markdown 表格"""
if df.empty:
return "*无数据*"
return df.to_markdown(index=False)
"""
频率限制器
Tushare Pro API 有调用频率限制,这里用简单的时间间隔控制。
默认最小间隔 300ms,避免触发服务端限流。
"""
import time
import threading
class RateLimiter:
"""
线程安全的频率限制器
Args:
min_interval: 两次调用之间的最小间隔(秒)
"""
def __init__(self, min_interval: float = 0.3) -> None:
self._min_interval = min_interval
self._last_call: float = 0.0
self._lock = threading.Lock()
def wait(self) -> None:
"""等待直到可以发起下一次调用"""
with self._lock:
now = time.monotonic()
elapsed = now - self._last_call
if elapsed < self._min_interval:
time.sleep(self._min_interval - elapsed)
self._last_call = time.monotonic()
"""
Tushare Pro MCP Server 入口
通过 FastMCP 创建 MCP 服务器,注册所有 tool 模块。
启动方式:python -m tushare_mcp.server
"""
from fastmcp import FastMCP
from .tools import (
stock, finance, index, macro, earnings, classify, news,
margin, billboard, holder, corporate, moneyflow, concept,
hk, hk_finance, us, us_finance, fund, etf,
futures, forex, option, bond, research,
dc_board, tdx_board, limit, chips, hotmoney, minutes,
data_store,
)
# 创建 MCP 服务器实例
mcp = FastMCP(
"Tushare Pro",
instructions=(
"A股金融数据服务。通过 tushare_* 系列工具获取股票行情、财务报表、指数数据等。"
"所有日期参数支持 YYYYMMDD 或 YYYY-MM-DD 格式。"
"返回结果默认限制 100 行,可通过 _limit 参数调整。"
),
)
# 注册各模块的 tools
stock.register(mcp)
finance.register(mcp)
index.register(mcp)
macro.register(mcp)
earnings.register(mcp)
classify.register(mcp)
news.register(mcp)
margin.register(mcp)
billboard.register(mcp)
holder.register(mcp)
corporate.register(mcp)
moneyflow.register(mcp)
concept.register(mcp)
hk.register(mcp)
hk_finance.register(mcp)
us.register(mcp)
us_finance.register(mcp)
fund.register(mcp)
etf.register(mcp)
futures.register(mcp)
forex.register(mcp)
option.register(mcp)
bond.register(mcp)
research.register(mcp)
dc_board.register(mcp)
tdx_board.register(mcp)
limit.register(mcp)
chips.register(mcp)
hotmoney.register(mcp)
minutes.register(mcp)
data_store.register(mcp)
def main() -> None:
"""启动 MCP 服务器(stdio 模式)"""
mcp.run()
if __name__ == "__main__":
main()
"""
SQLite 数据存储引擎
将 MCP 获取的 tushare 数据持久化到本地 SQLite,
建立索引方便未来数据回溯和历史查询。
两层表结构:
- data_index: 元数据索引表(每次查询一条记录)
- data_{api_name}: 每个 API 一张数据表(动态建表)
"""
import json
import logging
import sqlite3
from datetime import datetime
from typing import Any, Optional
import pandas as pd
logger = logging.getLogger(__name__)
# pandas dtype → SQLite 类型映射
_DTYPE_MAP = {
"int64": "INTEGER",
"Int64": "INTEGER",
"float64": "REAL",
"Float64": "REAL",
"object": "TEXT",
"bool": "INTEGER",
"datetime64[ns]": "TEXT",
}
class DataStore:
"""
SQLite 数据存储
每次 API 调用的结果自动保存:
1. 在 data_index 写一条索引记录
2. 在 data_{api_name} 表写入数据行
"""
def __init__(self, db_path: str) -> None:
"""
初始化存储引擎
Args:
db_path: SQLite 数据库文件路径
"""
self._db_path = db_path
self._conn = sqlite3.connect(db_path, check_same_thread=False)
# 启用 WAL 模式,提高并发读写性能
self._conn.execute("PRAGMA journal_mode=WAL")
self._ensure_index_table()
def _ensure_index_table(self) -> None:
"""创建索引表(如果不存在)"""
self._conn.executescript("""
CREATE TABLE IF NOT EXISTS data_index (
id INTEGER PRIMARY KEY AUTOINCREMENT,
api_name TEXT NOT NULL,
query_params TEXT,
ts_code TEXT,
trade_date TEXT,
start_date TEXT,
end_date TEXT,
row_count INTEGER,
columns TEXT,
table_name TEXT,
saved_at TEXT DEFAULT (datetime('now','localtime'))
);
CREATE INDEX IF NOT EXISTS idx_index_api_name ON data_index(api_name);
CREATE INDEX IF NOT EXISTS idx_index_ts_code ON data_index(ts_code);
CREATE INDEX IF NOT EXISTS idx_index_saved_at ON data_index(saved_at);
""")
self._conn.commit()
def save(self, api_name: str, params: dict[str, Any], df: pd.DataFrame) -> int:
"""
保存 API 返回的 DataFrame
Args:
api_name: 接口名称(如 "daily"、"income")
params: 原始查询参数(过滤 None 后的)
df: tushare 返回的 DataFrame
Returns:
索引记录 id
"""
if df.empty:
return -1
table_name = f"data_{api_name}"
# 确保数据表存在且列齐全
self._ensure_data_table(table_name, df)
# 写索引记录
query_id = self._insert_index(api_name, params, df, table_name)
# 写数据行
self._insert_data(table_name, query_id, df)
return query_id
def query_index(
self,
api_name: Optional[str] = None,
ts_code: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
limit: int = 50,
) -> pd.DataFrame:
"""
查询索引表
Args:
api_name: 按接口名筛选
ts_code: 按股票代码筛选
start_date: 保存时间起始(YYYY-MM-DD)
end_date: 保存时间截止(YYYY-MM-DD)
limit: 返回行数上限
Returns:
索引记录 DataFrame
"""
conditions = []
values: list[Any] = []
if api_name:
conditions.append("api_name = ?")
values.append(api_name)
if ts_code:
conditions.append("ts_code = ?")
values.append(ts_code)
if start_date:
conditions.append("saved_at >= ?")
values.append(start_date)
if end_date:
conditions.append("saved_at <= ?")
values.append(end_date + " 23:59:59")
where = " AND ".join(conditions) if conditions else "1=1"
sql = f"SELECT * FROM data_index WHERE {where} ORDER BY saved_at DESC LIMIT ?"
values.append(limit)
return pd.read_sql_query(sql, self._conn, params=values)
def read_data(
self,
query_id: Optional[int] = None,
api_name: Optional[str] = None,
ts_code: Optional[str] = None,
limit: int = 100,
) -> pd.DataFrame:
"""
从本地数据库读取历史数据(不调用 API)
三种查询模式:
1. 按 query_id 精确读取某次查询的数据
2. 按 api_name 读取某类数据(如所有 daily 数据)
3. 按 api_name + ts_code 读取特定标的数据
Args:
query_id: 索引记录 id(精确匹配某次查询)
api_name: 接口名称(如 daily, income)
ts_code: 股票/标的代码(需配合 api_name 使用)
limit: 最大返回行数
Returns:
数据 DataFrame
"""
# 按 query_id 精确查询
if query_id is not None:
# 先从索引表找到 table_name
cursor = self._conn.execute(
"SELECT table_name FROM data_index WHERE id = ?", (query_id,)
)
row = cursor.fetchone()
if row is None:
return pd.DataFrame()
table_name = row[0]
sql = f'SELECT * FROM "{table_name}" WHERE _query_id = ? LIMIT ?'
return pd.read_sql_query(sql, self._conn, params=[query_id, limit])
# 按 api_name + 可选 ts_code 查询
if api_name is None:
return pd.DataFrame()
table_name = f"data_{api_name}"
# 检查表是否存在
cursor = self._conn.execute(
"SELECT name FROM sqlite_master WHERE type='table' AND name=?",
(table_name,),
)
if cursor.fetchone() is None:
return pd.DataFrame()
conditions = []
values: list[Any] = []
if ts_code:
conditions.append('"ts_code" = ?')
values.append(ts_code)
where = " AND ".join(conditions) if conditions else "1=1"
sql = f'SELECT * FROM "{table_name}" WHERE {where} ORDER BY rowid DESC LIMIT ?'
values.append(limit)
return pd.read_sql_query(sql, self._conn, params=values)
def close(self) -> None:
"""关闭数据库连接"""
self._conn.close()
# ==================== 内部方法 ====================
def _insert_index(
self,
api_name: str,
params: dict[str, Any],
df: pd.DataFrame,
table_name: str,
) -> int:
"""写索引记录,返回自增 id"""
# 从参数中提取常用字段方便查询
ts_code = params.get("ts_code")
trade_date = params.get("trade_date")
start_date = params.get("start_date")
end_date = params.get("end_date")
columns = list(df.columns)
cursor = self._conn.execute(
"""INSERT INTO data_index
(api_name, query_params, ts_code, trade_date, start_date, end_date,
row_count, columns, table_name)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
(
api_name,
json.dumps(params, ensure_ascii=False, default=str),
ts_code,
trade_date,
start_date,
end_date,
len(df),
json.dumps(columns, ensure_ascii=False),
table_name,
),
)
self._conn.commit()
return cursor.lastrowid # type: ignore[return-value]
def _ensure_data_table(self, table_name: str, df: pd.DataFrame) -> None:
"""
确保数据表存在,列齐全
如果表不存在则创建;如果有新列则 ALTER TABLE ADD COLUMN。
"""
# 检查表是否存在
cursor = self._conn.execute(
"SELECT name FROM sqlite_master WHERE type='table' AND name=?",
(table_name,),
)
if cursor.fetchone() is None:
# 建新表
self._create_data_table(table_name, df)
return
# 表已存在,检查是否需要加列
existing_cols = self._get_table_columns(table_name)
for col in df.columns:
if col not in existing_cols:
sqlite_type = self._map_dtype(df[col].dtype)
self._conn.execute(
f'ALTER TABLE "{table_name}" ADD COLUMN "{col}" {sqlite_type}'
)
logger.info("表 %s 新增列: %s %s", table_name, col, sqlite_type)
self._conn.commit()
def _create_data_table(self, table_name: str, df: pd.DataFrame) -> None:
"""从 DataFrame 创建数据表"""
col_defs = ['"_query_id" INTEGER']
for col in df.columns:
sqlite_type = self._map_dtype(df[col].dtype)
col_defs.append(f'"{col}" {sqlite_type}')
sql = f'CREATE TABLE "{table_name}" ({", ".join(col_defs)})'
self._conn.execute(sql)
# 为 _query_id 建索引,方便按查询批次检索
self._conn.execute(
f'CREATE INDEX IF NOT EXISTS "idx_{table_name}_qid" ON "{table_name}"("_query_id")'
)
self._conn.commit()
logger.info("创建数据表: %s (%d 列)", table_name, len(df.columns))
def _insert_data(self, table_name: str, query_id: int, df: pd.DataFrame) -> None:
"""批量插入数据行"""
# 构造 INSERT 语句
cols = ["_query_id"] + list(df.columns)
placeholders = ", ".join(["?"] * len(cols))
col_names = ", ".join(f'"{c}"' for c in cols)
sql = f'INSERT INTO "{table_name}" ({col_names}) VALUES ({placeholders})'
# 准备数据:NaN → None
rows = []
for _, row in df.iterrows():
values = [query_id]
for col in df.columns:
val = row[col]
# pandas NaN/NaT → None(SQLite NULL)
if pd.isna(val):
values.append(None)
else:
values.append(val)
rows.append(values)
self._conn.executemany(sql, rows)
self._conn.commit()
def _get_table_columns(self, table_name: str) -> set[str]:
"""获取已有表的列名集合"""
cursor = self._conn.execute(f'PRAGMA table_info("{table_name}")')
return {row[1] for row in cursor.fetchall()}
@staticmethod
def _map_dtype(dtype: Any) -> str:
"""pandas dtype → SQLite 类型"""
dtype_str = str(dtype)
return _DTYPE_MAP.get(dtype_str, "TEXT")
"""MCP tool 注册模块"""
"""
龙虎榜 MCP Tools
包含:top_list(龙虎榜每日明细), top_inst(龙虎榜机构交易明细)
"""
from typing import Optional
from fastmcp import FastMCP
from .. import client
from ..formatter import format_response
from ..errors import TushareError
def register(mcp: FastMCP) -> None:
"""将龙虎榜相关 tools 注册到 MCP 实例"""
@mcp.tool()
def tushare_top_list(
trade_date: str,
ts_code: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询龙虎榜每日交易明细,含涨跌幅、成交额、净买入等。积分要求:2000。
Args:
trade_date: 交易日期(YYYYMMDD 或 YYYY-MM-DD,必填)
ts_code: 股票代码
fields: 返回字段,逗号分隔
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.top_list(
trade_date=trade_date,
ts_code=ts_code,
fields=fields,
)
return format_response(df, "top_list", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_top_inst(
trade_date: str,
ts_code: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询龙虎榜机构成交明细,含营业部名称、买卖额等。积分要求:5000。
Args:
trade_date: 交易日期(YYYYMMDD 或 YYYY-MM-DD,必填)
ts_code: 股票代码
fields: 返回字段,逗号分隔
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.top_inst(
trade_date=trade_date,
ts_code=ts_code,
fields=fields,
)
return format_response(df, "top_inst", _format, _limit)
except TushareError as e:
return {"error": str(e)}
"""
债券/可转债 MCP Tools
包含:cb_basic(可转债基础信息), cb_daily(可转债行情), cb_issue(可转债发行),
cb_rate(票面利率), cb_call(赎回信息), cb_share(转股结果),
cb_price_chg(转股价变动), repo_daily(债券回购日行情)
"""
from typing import Optional
from fastmcp import FastMCP
from .. import client
from ..formatter import format_response
from ..errors import TushareError
def register(mcp: FastMCP) -> None:
"""将债券/可转债相关 tools 注册到 MCP 实例"""
@mcp.tool()
def tushare_cb_basic(
ts_code: Optional[str] = None,
list_date: Optional[str] = None,
exchange: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询可转债基础信息。积分要求:2000。
Args:
ts_code: 转债代码
list_date: 上市日期
exchange: 交易所代码
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.cb_basic(
ts_code=ts_code,
list_date=list_date,
exchange=exchange,
fields=fields,
)
return format_response(df, "cb_basic", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_cb_daily(
ts_code: Optional[str] = None,
trade_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询可转债行情数据。积分要求:2000。
Args:
ts_code: 转债代码
trade_date: 交易日期
start_date: 开始日期
end_date: 结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.cb_daily(
ts_code=ts_code,
trade_date=trade_date,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "cb_daily", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_cb_issue(
ts_code: Optional[str] = None,
ann_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询可转债发行数据。积分要求:2000。
Args:
ts_code: 转债代码
ann_date: 公告日期
start_date: 开始日期
end_date: 结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.cb_issue(
ts_code=ts_code,
ann_date=ann_date,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "cb_issue", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_cb_rate(
ts_code: str,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询可转债票面利率。积分要求:5000。
Args:
ts_code: 转债代码(必填)
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.cb_rate(ts_code=ts_code, fields=fields)
return format_response(df, "cb_rate", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_cb_call(
ts_code: Optional[str] = None,
ann_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询可转债赎回信息。积分要求:5000。
Args:
ts_code: 转债代码
ann_date: 公告日期
start_date: 开始日期
end_date: 结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.cb_call(
ts_code=ts_code,
ann_date=ann_date,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "cb_call", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_cb_share(
ts_code: str,
ann_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询可转债转股结果。积分要求:2000。
Args:
ts_code: 转债代码(必填)
ann_date: 公告日期
start_date: 开始日期
end_date: 结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.cb_share(
ts_code=ts_code,
ann_date=ann_date,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "cb_share", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_cb_price_chg(
ts_code: str,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询可转债转股价变动。需单独权限,积分不足会返回错误。
Args:
ts_code: 转债代码(必填)
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.cb_price_chg(ts_code=ts_code, fields=fields)
return format_response(df, "cb_price_chg", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_repo_daily(
ts_code: Optional[str] = None,
trade_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询债券回购日行情。积分要求:2000。
Args:
ts_code: 回购代码
trade_date: 交易日期
start_date: 开始日期
end_date: 结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.repo_daily(
ts_code=ts_code,
trade_date=trade_date,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "repo_daily", _format, _limit)
except TushareError as e:
return {"error": str(e)}
"""
筹码分析 MCP Tools
包含:cyq_chips(筹码分布), cyq_perf(筹码分布指标)
"""
from typing import Optional
from fastmcp import FastMCP
from .. import client
from ..formatter import format_response
from ..errors import TushareError
def register(mcp: FastMCP) -> None:
"""将筹码分析相关 tools 注册到 MCP 实例"""
@mcp.tool()
def tushare_cyq_chips(
ts_code: str,
trade_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询个股筹码分布数据。积分要求:5000+。
Args:
ts_code: 股票代码(必填)
trade_date: 交易日期
start_date: 开始日期
end_date: 结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.cyq_chips(
ts_code=ts_code,
trade_date=trade_date,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "cyq_chips", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_cyq_perf(
ts_code: str,
trade_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询个股筹码分布指标。积分要求:5000+。
Args:
ts_code: 股票代码(必填)
trade_date: 交易日期
start_date: 开始日期
end_date: 结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.cyq_perf(
ts_code=ts_code,
trade_date=trade_date,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "cyq_perf", _format, _limit)
except TushareError as e:
return {"error": str(e)}
"""
行业分类 MCP Tools
包含:index_classify(申万行业分类), index_member_all(申万行业成分),
ci_daily(中信行业指数日行情), ci_index_member(中信行业成分)
"""
from typing import Optional
from fastmcp import FastMCP
from .. import client
from ..formatter import format_response
from ..errors import TushareError
def register(mcp: FastMCP) -> None:
"""将行业分类相关 tools 注册到 MCP 实例"""
@mcp.tool()
def tushare_index_classify(
index_code: Optional[str] = None,
level: Optional[str] = None,
src: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询申万行业分类(2014版28个一级/2021版31个一级)。积分要求:2000。用于 comps 同行筛选。
Args:
index_code: 指数代码
level: 行业级别(L1一级 L2二级 L3三级)
src: 指数版本(SW2014 或 SW2021)
fields: 返回字段
_format: 输出格式(json/markdown)
_limit: 最大返回行数
"""
try:
df = client.index_classify(
index_code=index_code,
level=level,
src=src,
fields=fields,
)
return format_response(df, "index_classify", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_index_member_all(
l1_code: Optional[str] = None,
l2_code: Optional[str] = None,
l3_code: Optional[str] = None,
ts_code: Optional[str] = None,
is_new: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询申万行业成分(分级),支持一/二/三级。积分要求:2000。
Args:
l1_code: 一级行业代码
l2_code: 二级行业代码
l3_code: 三级行业代码
ts_code: 股票代码
is_new: 是否最新(Y/N,默认Y)
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.index_member_all(
l1_code=l1_code,
l2_code=l2_code,
l3_code=l3_code,
ts_code=ts_code,
is_new=is_new,
fields=fields,
)
return format_response(df, "index_member_all", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_ci_daily(
ts_code: Optional[str] = None,
trade_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询中信行业指数日行情。积分要求:5000。
Args:
ts_code: 行业代码
trade_date: 交易日期
start_date: 开始日期
end_date: 结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.ci_daily(
ts_code=ts_code,
trade_date=trade_date,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "ci_daily", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_ci_index_member(
l1_code: Optional[str] = None,
l2_code: Optional[str] = None,
l3_code: Optional[str] = None,
ts_code: Optional[str] = None,
is_new: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询中信行业成分股。积分要求:5000。
Args:
l1_code: 一级行业代码
l2_code: 二级行业代码
l3_code: 三级行业代码
ts_code: 股票代码
is_new: 是否最新(Y/N,默认Y)
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.ci_index_member(
l1_code=l1_code,
l2_code=l2_code,
l3_code=l3_code,
ts_code=ts_code,
is_new=is_new,
fields=fields,
)
return format_response(df, "ci_index_member", _format, _limit)
except TushareError as e:
return {"error": str(e)}
"""
概念板块 MCP Tools
包含:concept(概念板块列表), concept_detail(概念板块成分股),
ths_index(同花顺指数列表), ths_daily(同花顺指数行情), ths_member(同花顺概念成分)
"""
from typing import Optional
from fastmcp import FastMCP
from .. import client
from ..formatter import format_response
from ..errors import TushareError
def register(mcp: FastMCP) -> None:
"""将概念板块相关 tools 注册到 MCP 实例"""
@mcp.tool()
def tushare_concept(
trade_date: Optional[str] = None,
ts_code: Optional[str] = None,
name: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询概念题材列表(开盘啦数据源),每日盘后更新。积分要求:5000。
Args:
trade_date: 交易日期(YYYYMMDD 或 YYYY-MM-DD)
ts_code: 题材代码(xxxxxx.KP格式)
name: 题材名称
fields: 返回字段,逗号分隔
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.kpl_concept(
trade_date=trade_date,
ts_code=ts_code,
name=name,
fields=fields,
)
return format_response(df, "kpl_concept", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_concept_detail(
trade_date: Optional[str] = None,
ts_code: Optional[str] = None,
con_code: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询概念题材的成分股(开盘啦数据源)。积分要求:5000。
Args:
trade_date: 交易日期(YYYYMMDD 或 YYYY-MM-DD)
ts_code: 题材代码(xxxxxx.KP格式)
con_code: 成分股代码(如 000001.SZ)
fields: 返回字段,逗号分隔
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.kpl_concept_cons(
trade_date=trade_date,
ts_code=ts_code,
con_code=con_code,
fields=fields,
)
return format_response(df, "kpl_concept_cons", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_ths_index(
ts_code: Optional[str] = None,
exchange: Optional[str] = None,
type: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询同花顺概念和行业指数列表。积分要求:6000。
Args:
ts_code: 指数代码
exchange: 市场类型(A-A股 HK-港股 US-美股)
type: 指数类型(N-概念 I-行业 R-地域 S-特色 ST-风格 TH-主题 BB-宽基)
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.ths_index(
ts_code=ts_code,
exchange=exchange,
type=type,
fields=fields,
)
return format_response(df, "ths_index", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_ths_daily(
ts_code: Optional[str] = None,
trade_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询同花顺板块指数行情。积分要求:6000。
Args:
ts_code: 指数代码
trade_date: 交易日期
start_date: 开始日期
end_date: 结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.ths_daily(
ts_code=ts_code,
trade_date=trade_date,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "ths_daily", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_ths_member(
ts_code: Optional[str] = None,
con_code: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询同花顺概念板块成分股。积分要求:6000。
Args:
ts_code: 板块指数代码
con_code: 股票代码
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.ths_member(
ts_code=ts_code,
con_code=con_code,
fields=fields,
)
return format_response(df, "ths_member", _format, _limit)
except TushareError as e:
return {"error": str(e)}
"""
公司行为 MCP Tools
包含:dividend(分红送股), repurchase(股票回购), share_float(限售股解禁),
pledge_stat(股权质押统计), pledge_detail(股权质押明细), stk_surv(机构调研),
stk_rewards(管理层薪酬和持股)
"""
from typing import Optional
from fastmcp import FastMCP
from .. import client
from ..formatter import format_response
from ..errors import TushareError
def register(mcp: FastMCP) -> None:
"""将公司行为相关 tools 注册到 MCP 实例"""
@mcp.tool()
def tushare_dividend(
ts_code: Optional[str] = None,
ann_date: Optional[str] = None,
record_date: Optional[str] = None,
ex_date: Optional[str] = None,
imp_ann_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询分红送股数据,含每股分红、送转比例、除权除息日等。积分要求:2000。
注意:参数中至少一个不能为空。
Args:
ts_code: 股票代码(如 000001.SZ)
ann_date: 预案公告日
record_date: 股权登记日期
ex_date: 除权除息日
imp_ann_date: 实施公告日
fields: 返回字段,逗号分隔
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.dividend(
ts_code=ts_code,
ann_date=ann_date,
record_date=record_date,
ex_date=ex_date,
imp_ann_date=imp_ann_date,
fields=fields,
)
return format_response(df, "dividend", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_repurchase(
ann_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询上市公司回购股票数据。积分要求:600。
Args:
ann_date: 公告日期
start_date: 公告开始日期
end_date: 公告结束日期
fields: 返回字段,逗号分隔
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.repurchase(
ann_date=ann_date,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "repurchase", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_share_float(
ts_code: Optional[str] = None,
ann_date: Optional[str] = None,
float_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询限售股解禁数据。积分要求:120。
Args:
ts_code: 股票代码
ann_date: 公告日期
float_date: 解禁日期
start_date: 解禁开始日期
end_date: 解禁结束日期
fields: 返回字段,逗号分隔
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.share_float(
ts_code=ts_code,
ann_date=ann_date,
float_date=float_date,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "share_float", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_pledge_stat(
ts_code: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询股票质押统计数据,含质押次数、质押比例等。积分要求:500。
Args:
ts_code: 股票代码
end_date: 截止日期
fields: 返回字段,逗号分隔
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.pledge_stat(
ts_code=ts_code,
end_date=end_date,
fields=fields,
)
return format_response(df, "pledge_stat", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_pledge_detail(
ts_code: str,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询股票质押明细数据,含质押方、质押数量、起止日期等。积分要求:500。
Args:
ts_code: 股票代码(如 000001.SZ,必填)
fields: 返回字段,逗号分隔
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.pledge_detail(
ts_code=ts_code,
fields=fields,
)
return format_response(df, "pledge_detail", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_stk_surv(
ts_code: Optional[str] = None,
trade_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询上市公司机构调研记录数据。积分要求:5000。
Args:
ts_code: 股票代码
trade_date: 调研日期
start_date: 调研开始日期
end_date: 调研结束日期
fields: 返回字段,逗号分隔
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.stk_surv(
ts_code=ts_code,
trade_date=trade_date,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "stk_surv", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_stk_rewards(
ts_code: str,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询管理层薪酬和持股数据。积分要求:2000。
Args:
ts_code: TS股票代码(必填,支持多个)
end_date: 报告期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.stk_rewards(
ts_code=ts_code,
end_date=end_date,
fields=fields,
)
return format_response(df, "stk_rewards", _format, _limit)
except TushareError as e:
return {"error": str(e)}
"""
数据存储 MCP Tools
提供本地数据查询能力:
- tushare_data_index: 查询保存记录索引
- tushare_data_read: 从本地 DB 读取历史数据(不调 API)
"""
from typing import Optional
from fastmcp import FastMCP
from .. import client
from ..formatter import format_response
from ..errors import TushareError
def register(mcp: FastMCP) -> None:
"""将数据存储查询 tool 注册到 MCP 实例"""
@mcp.tool()
def tushare_data_index(
api_name: Optional[str] = None,
ts_code: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
_format: str = "json",
_limit: int = 50,
) -> dict:
"""查询本地已保存的数据索引。每次调用 tushare_* tool 获取的数据都会自动保存到本地 SQLite。
使用此接口可以查看历史保存了哪些数据,方便回溯。
Args:
api_name: 按接口名筛选(如 daily, income, index_daily)
ts_code: 按股票/标的代码筛选(如 000001.SZ)
start_date: 保存时间起始(YYYY-MM-DD),筛选 saved_at 字段
end_date: 保存时间截止(YYYY-MM-DD),筛选 saved_at 字段
_format: 输出格式(json/markdown),默认 json
_limit: 最大返回行数,默认 50
"""
try:
store = client._get_store()
df = store.query_index(
api_name=api_name,
ts_code=ts_code,
start_date=start_date,
end_date=end_date,
limit=_limit,
)
return format_response(df, "data_index", _format, _limit)
except Exception as e:
return {"error": f"查询数据索引失败: {e}"}
@mcp.tool()
def tushare_data_read(
query_id: Optional[int] = None,
api_name: Optional[str] = None,
ts_code: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""从本地数据库读取历史保存的数据,不调用 tushare API。
三种查询模式:
1. 按 query_id 读取某次查询的完整数据(最精确)
2. 按 api_name 读取某类数据的最新记录
3. 按 api_name + ts_code 读取特定标的的历史数据
建议先用 tushare_data_index 查到 query_id,再用本接口读取。
Args:
query_id: 索引记录 id(从 tushare_data_index 获取)
api_name: 接口名称(如 daily, income, index_daily)
ts_code: 股票/标的代码(需配合 api_name 使用)
_format: 输出格式(json/markdown),默认 json
_limit: 最大返回行数,默认 100
"""
try:
store = client._get_store()
df = store.read_data(
query_id=query_id,
api_name=api_name,
ts_code=ts_code,
limit=_limit,
)
source = f"local:{api_name or 'query_' + str(query_id)}"
return format_response(df, source, _format, _limit)
except Exception as e:
return {"error": f"读取本地数据失败: {e}"}
"""
东财板块 MCP Tools
包含:dc_index(东财概念和行业指数行情), dc_member(东财板块成分), dc_hot(东财人气榜)
"""
from typing import Optional
from fastmcp import FastMCP
from .. import client
from ..formatter import format_response
from ..errors import TushareError
def register(mcp: FastMCP) -> None:
"""将东财板块相关 tools 注册到 MCP 实例"""
@mcp.tool()
def tushare_dc_index(
ts_code: Optional[str] = None,
name: Optional[str] = None,
trade_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询东财概念和行业指数行情。积分要求:6000。
Args:
ts_code: 指数代码
name: 指数名称
trade_date: 交易日期
start_date: 开始日期
end_date: 结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.dc_index(
ts_code=ts_code,
name=name,
trade_date=trade_date,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "dc_index", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_dc_member(
ts_code: Optional[str] = None,
con_code: Optional[str] = None,
trade_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询东财概念和行业板块成分。积分要求:6000。
Args:
ts_code: 板块指数代码
con_code: 成分股代码
trade_date: 交易日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.dc_member(
ts_code=ts_code,
con_code=con_code,
trade_date=trade_date,
fields=fields,
)
return format_response(df, "dc_member", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_dc_hot(
trade_date: Optional[str] = None,
ts_code: Optional[str] = None,
market: Optional[str] = None,
hot_type: Optional[str] = None,
is_new: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询东财人气榜(热股数据)。积分要求:8000。
Args:
trade_date: 交易日期
ts_code: 股票代码
market: 市场
hot_type: 热度类型
is_new: 是否最新
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.dc_hot(
trade_date=trade_date,
ts_code=ts_code,
market=market,
hot_type=hot_type,
is_new=is_new,
fields=fields,
)
return format_response(df, "dc_hot", _format, _limit)
except TushareError as e:
return {"error": str(e)}
"""
业绩数据 MCP Tools
包含:forecast(业绩预告), express(业绩快报), report_rc(券商预测)
"""
from typing import Optional
from fastmcp import FastMCP
from .. import client
from ..formatter import format_response
from ..errors import TushareError
def register(mcp: FastMCP) -> None:
"""将业绩相关 tools 注册到 MCP 实例"""
@mcp.tool()
def tushare_forecast(
ts_code: Optional[str] = None,
ann_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
period: Optional[str] = None,
type: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询业绩预告数据。积分要求:2000。ts_code 和 ann_date 至少填一个。
Args:
ts_code: 股票代码(与 ann_date 二选一)
ann_date: 公告日期(与 ts_code 二选一)
start_date: 公告开始日期
end_date: 公告结束日期
period: 报告期(如 20231231 年报、20240630 半年报)
type: 预告类型(预增/预减/扭亏/首亏/续亏/续盈/略增/略减)
fields: 返回字段
_format: 输出格式(json/markdown)
_limit: 最大返回行数
"""
try:
df = client.forecast(
ts_code=ts_code,
ann_date=ann_date,
start_date=start_date,
end_date=end_date,
period=period,
type=type,
fields=fields,
)
return format_response(df, "forecast", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_express(
ts_code: str,
ann_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
period: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询业绩快报数据。积分要求:2000。
Args:
ts_code: 股票代码(必填)
ann_date: 公告日期
start_date: 公告开始日期
end_date: 公告结束日期
period: 报告期
fields: 返回字段
_format: 输出格式(json/markdown)
_limit: 最大返回行数
"""
try:
df = client.express(
ts_code=ts_code,
ann_date=ann_date,
start_date=start_date,
end_date=end_date,
period=period,
fields=fields,
)
return format_response(df, "express", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_report_rc(
ts_code: Optional[str] = None,
report_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询券商(卖方)盈利预测数据,包含EPS预期、目标价、评级等。积分要求:8000。
Args:
ts_code: 股票代码
report_date: 报告日期
start_date: 报告开始日期
end_date: 报告结束日期
fields: 返回字段
_format: 输出格式(json/markdown)
_limit: 最大返回行数
"""
try:
df = client.report_rc(
ts_code=ts_code,
report_date=report_date,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "report_rc", _format, _limit)
except TushareError as e:
return {"error": str(e)}
"""
ETF MCP Tools
包含:fund_daily(场内基金/ETF日线行情), etf_basic(ETF基本信息),
etf_share_size(ETF每日份额规模), etf_index(ETF跟踪指数基准)
"""
from typing import Optional
from fastmcp import FastMCP
from .. import client
from ..formatter import format_response
from ..errors import TushareError
def register(mcp: FastMCP) -> None:
"""将 ETF 相关 tools 注册到 MCP 实例"""
@mcp.tool()
def tushare_fund_daily(
ts_code: Optional[str] = None,
trade_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询场内基金/ETF日线行情。积分要求:5000。
Args:
ts_code: 基金/ETF代码
trade_date: 交易日期
start_date: 开始日期
end_date: 结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.fund_daily(
ts_code=ts_code,
trade_date=trade_date,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "fund_daily", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_etf_basic(
ts_code: Optional[str] = None,
index_code: Optional[str] = None,
list_status: Optional[str] = None,
exchange: Optional[str] = None,
mgr: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询国内ETF基础信息,含QDII。积分要求:8000。
Args:
ts_code: ETF代码
index_code: 跟踪指数代码
list_status: 上市状态(L上市 D退市 P待上市)
exchange: 交易所(SH上交所 SZ深交所)
mgr: 管理人简称
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.etf_basic(
ts_code=ts_code,
index_code=index_code,
list_status=list_status,
exchange=exchange,
mgr=mgr,
fields=fields,
)
return format_response(df, "etf_basic", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_etf_share_size(
ts_code: Optional[str] = None,
trade_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
exchange: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询ETF每日份额规模。积分要求:8000。
Args:
ts_code: ETF代码
trade_date: 交易日期
start_date: 开始日期
end_date: 结束日期
exchange: 交易所(SH/SZ)
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.etf_share_size(
ts_code=ts_code,
trade_date=trade_date,
start_date=start_date,
end_date=end_date,
exchange=exchange,
fields=fields,
)
return format_response(df, "etf_share_size", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_etf_index(
ts_code: Optional[str] = None,
pub_date: Optional[str] = None,
base_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询ETF跟踪指数基准信息。积分要求:8000。
Args:
ts_code: ETF代码
pub_date: 发布日期
base_date: 基日
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.etf_index(
ts_code=ts_code,
pub_date=pub_date,
base_date=base_date,
fields=fields,
)
return format_response(df, "etf_index", _format, _limit)
except TushareError as e:
return {"error": str(e)}
"""
财务报表 MCP Tools
包含:income, balancesheet, cashflow, fina_indicator, fina_audit, fina_mainbz, disclosure_date
"""
from typing import Optional
from fastmcp import FastMCP
from .. import client
from ..formatter import format_response
from ..errors import TushareError
def register(mcp: FastMCP) -> None:
"""将财务相关 tools 注册到 MCP 实例"""
@mcp.tool()
def tushare_income(
ts_code: str,
ann_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
period: Optional[str] = None,
report_type: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询上市公司利润表。积分要求:2000。单次最多返回100条,可通过日期分批获取。
Args:
ts_code: 股票代码(必填),如 000001.SZ
ann_date: 公告日期
start_date: 报告期开始日期
end_date: 报告期结束日期
period: 报告期(如 20231231 表示年报)
report_type: 报告类型(1合并报表 2单季合并等)
fields: 返回字段
_format: 输出格式(json/markdown)
_limit: 最大返回行数
"""
try:
df = client.income(
ts_code=ts_code,
ann_date=ann_date,
start_date=start_date,
end_date=end_date,
period=period,
report_type=report_type,
fields=fields,
)
return format_response(df, "income", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_balancesheet(
ts_code: str,
ann_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
period: Optional[str] = None,
report_type: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询上市公司资产负债表。积分要求:2000。单次最多返回100条。
Args:
ts_code: 股票代码(必填)
ann_date: 公告日期
start_date: 报告期开始日期
end_date: 报告期结束日期
period: 报告期
report_type: 报告类型
fields: 返回字段
_format: 输出格式(json/markdown)
_limit: 最大返回行数
"""
try:
df = client.balancesheet(
ts_code=ts_code,
ann_date=ann_date,
start_date=start_date,
end_date=end_date,
period=period,
report_type=report_type,
fields=fields,
)
return format_response(df, "balancesheet", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_cashflow(
ts_code: str,
ann_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
period: Optional[str] = None,
report_type: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询上市公司现金流量表。积分要求:2000。单次最多返回100条。
Args:
ts_code: 股票代码(必填)
ann_date: 公告日期
start_date: 报告期开始日期
end_date: 报告期结束日期
period: 报告期
report_type: 报告类型
fields: 返回字段
_format: 输出格式(json/markdown)
_limit: 最大返回行数
"""
try:
df = client.cashflow(
ts_code=ts_code,
ann_date=ann_date,
start_date=start_date,
end_date=end_date,
period=period,
report_type=report_type,
fields=fields,
)
return format_response(df, "cashflow", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_fina_indicator(
ts_code: str,
ann_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
period: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询财务指标数据(ROE、净利润率、毛利率等)。积分要求:2000。单次最多返回100条。
Args:
ts_code: 股票代码(必填)
ann_date: 公告日期
start_date: 报告期开始日期
end_date: 报告期结束日期
period: 报告期(如 20231231)
fields: 返回字段
_format: 输出格式(json/markdown)
_limit: 最大返回行数
"""
try:
df = client.fina_indicator(
ts_code=ts_code,
ann_date=ann_date,
start_date=start_date,
end_date=end_date,
period=period,
fields=fields,
)
return format_response(df, "fina_indicator", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_fina_audit(
ts_code: str,
ann_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
period: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询财务审计意见。积分要求:500。
Args:
ts_code: 股票代码(必填)
ann_date: 公告日期
start_date: 报告期开始日期
end_date: 报告期结束日期
period: 报告期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.fina_audit(
ts_code=ts_code,
ann_date=ann_date,
start_date=start_date,
end_date=end_date,
period=period,
fields=fields,
)
return format_response(df, "fina_audit", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_fina_mainbz(
ts_code: str,
period: Optional[str] = None,
type: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询主营业务构成,含按产品和按地区分类。积分要求:2000。
Args:
ts_code: 股票代码(必填)
period: 报告期(YYYYMMDD)
type: 类型(P按产品 D按地区,默认P)
start_date: 报告期开始日期
end_date: 报告期结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.fina_mainbz(
ts_code=ts_code,
period=period,
type=type,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "fina_mainbz", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_disclosure_date(
ts_code: Optional[str] = None,
end_date: Optional[str] = None,
pre_date: Optional[str] = None,
actual_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询财报披露日期表。积分要求:500。
Args:
ts_code: 股票代码
end_date: 财报周期(如20231231)
pre_date: 计划披露日期
actual_date: 实际披露日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.disclosure_date(
ts_code=ts_code,
end_date=end_date,
pre_date=pre_date,
actual_date=actual_date,
fields=fields,
)
return format_response(df, "disclosure_date", _format, _limit)
except TushareError as e:
return {"error": str(e)}
"""
外汇 MCP Tools
包含:fx_obasic(外汇基础信息), fx_daily(外汇日线行情)
"""
from typing import Optional
from fastmcp import FastMCP
from .. import client
from ..formatter import format_response
from ..errors import TushareError
def register(mcp: FastMCP) -> None:
"""将外汇相关 tools 注册到 MCP 实例"""
@mcp.tool()
def tushare_fx_obasic(
exchange: Optional[str] = None,
classify: Optional[str] = None,
ts_code: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询外汇基础信息(FXCM交易商)。积分要求:2000。
Args:
exchange: 交易商(如FXCM)
classify: 分类(FX/INDEX/COMMODITY/METAL/BUND/CRYPTO/FX_BASKET)
ts_code: TS代码
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.fx_obasic(
exchange=exchange,
classify=classify,
ts_code=ts_code,
fields=fields,
)
return format_response(df, "fx_obasic", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_fx_daily(
ts_code: Optional[str] = None,
trade_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
exchange: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询外汇日线行情。积分要求:2000。
Args:
ts_code: TS代码(如USDCNH.FXCM)
trade_date: 交易日期(GMT)
start_date: 开始日期
end_date: 结束日期
exchange: 交易商(如FXCM)
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.fx_daily(
ts_code=ts_code,
trade_date=trade_date,
start_date=start_date,
end_date=end_date,
exchange=exchange,
fields=fields,
)
return format_response(df, "fx_daily", _format, _limit)
except TushareError as e:
return {"error": str(e)}
"""
基金 MCP Tools
包含:fund_basic(基金列表), fund_nav(基金净值), fund_div(基金分红),
fund_portfolio(基金持仓), fund_company(基金管理人),
fund_manager(基金经理), fund_share(基金规模), fund_adj(基金复权因子)
"""
from typing import Optional
from fastmcp import FastMCP
from .. import client
from ..formatter import format_response
from ..errors import TushareError
def register(mcp: FastMCP) -> None:
"""将基金相关 tools 注册到 MCP 实例"""
@mcp.tool()
def tushare_fund_basic(
ts_code: Optional[str] = None,
market: Optional[str] = None,
status: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询公募基金列表,含场内和场外基金。积分要求:2000。
Args:
ts_code: 基金代码
market: 交易市场(E场内 O场外),默认E
status: 存续状态(D摘牌 I发行 L上市中)
fields: 返回字段,逗号分隔
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.fund_basic(
ts_code=ts_code,
market=market,
status=status,
fields=fields,
)
return format_response(df, "fund_basic", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_fund_nav(
ts_code: Optional[str] = None,
nav_date: Optional[str] = None,
market: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询公募基金净值数据。积分要求:2000。
Args:
ts_code: 基金代码(与 nav_date 二选一)
nav_date: 净值日期(与 ts_code 二选一)
market: E场内 O场外
start_date: 净值开始日期
end_date: 净值结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.fund_nav(
ts_code=ts_code,
nav_date=nav_date,
market=market,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "fund_nav", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_fund_div(
ts_code: Optional[str] = None,
ann_date: Optional[str] = None,
ex_date: Optional[str] = None,
pay_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询公募基金分红数据。积分要求:400。
Args:
ts_code: 基金代码(四选一)
ann_date: 公告日(四选一)
ex_date: 除息日(四选一)
pay_date: 派息日(四选一)
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.fund_div(
ts_code=ts_code,
ann_date=ann_date,
ex_date=ex_date,
pay_date=pay_date,
fields=fields,
)
return format_response(df, "fund_div", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_fund_portfolio(
ts_code: Optional[str] = None,
symbol: Optional[str] = None,
ann_date: Optional[str] = None,
period: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询公募基金持仓数据,季度更新。积分要求:5000。
Args:
ts_code: 基金代码(三选一)
symbol: 股票代码(三选一)
ann_date: 公告日期(三选一)
period: 季度
start_date: 报告期开始日期
end_date: 报告期结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.fund_portfolio(
ts_code=ts_code,
symbol=symbol,
ann_date=ann_date,
period=period,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "fund_portfolio", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_fund_company(
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询公募基金管理人列表。积分要求:1500。
Args:
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.fund_company(fields=fields)
return format_response(df, "fund_company", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_fund_manager(
ts_code: Optional[str] = None,
ann_date: Optional[str] = None,
name: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询公募基金经理数据,含简历信息。积分要求:500。
Args:
ts_code: 基金代码(支持多只,逗号分隔)
ann_date: 公告日期
name: 基金经理姓名
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.fund_manager(
ts_code=ts_code,
ann_date=ann_date,
name=name,
fields=fields,
)
return format_response(df, "fund_manager", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_fund_share(
ts_code: Optional[str] = None,
trade_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
market: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询基金规模数据,含ETF份额。积分要求:2000。
Args:
ts_code: 基金代码
trade_date: 交易日期
start_date: 开始日期
end_date: 结束日期
market: 市场代码(SH上交所 SZ深交所)
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.fund_share(
ts_code=ts_code,
trade_date=trade_date,
start_date=start_date,
end_date=end_date,
market=market,
fields=fields,
)
return format_response(df, "fund_share", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_fund_adj(
ts_code: Optional[str] = None,
trade_date: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询基金复权因子。积分要求:600。
Args:
ts_code: 基金代码(支持多只输入)
trade_date: 交易日期
start_date: 开始日期
end_date: 结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.fund_adj(
ts_code=ts_code,
trade_date=trade_date,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "fund_adj", _format, _limit)
except TushareError as e:
return {"error": str(e)}
"""
港股财务 MCP Tools
包含:hk_income(港股利润表), hk_balancesheet(港股资产负债表),
hk_cashflow(港股现金流量表), hk_fina_indicator(港股财务指标)
注意:这些接口需要 15000 积分或单独开权限。积分不足时返回错误信息,
调用方可据此 fallback 到 Yahoo Finance 等其他数据源。
"""
from typing import Optional
from fastmcp import FastMCP
from .. import client
from ..formatter import format_response
from ..errors import TushareError
def register(mcp: FastMCP) -> None:
"""将港股财务相关 tools 注册到 MCP 实例"""
@mcp.tool()
def tushare_hk_income(
ts_code: str,
period: Optional[str] = None,
ind_name: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询港股利润表。需15000积分或单独开权限,积分不足会返回错误。
Args:
ts_code: 股票代码(如 00001.HK,必填)
period: 报告期(YYYYMMDD)
ind_name: 指标名(如 营业额)
start_date: 报告期开始日期
end_date: 报告期结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.hk_income(
ts_code=ts_code,
period=period,
ind_name=ind_name,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "hk_income", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_hk_balancesheet(
ts_code: str,
period: Optional[str] = None,
ind_name: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询港股资产负债表。需15000积分或单独开权限,积分不足会返回错误。
Args:
ts_code: 股票代码(必填)
period: 报告期(YYYYMMDD)
ind_name: 指标名
start_date: 报告期开始日期
end_date: 报告期结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.hk_balancesheet(
ts_code=ts_code,
period=period,
ind_name=ind_name,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "hk_balancesheet", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_hk_cashflow(
ts_code: str,
period: Optional[str] = None,
ind_name: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询港股现金流量表。需15000积分或单独开权限,积分不足会返回错误。
Args:
ts_code: 股票代码(必填)
period: 报告期(YYYYMMDD)
ind_name: 指标名
start_date: 报告期开始日期
end_date: 报告期结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.hk_cashflow(
ts_code=ts_code,
period=period,
ind_name=ind_name,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "hk_cashflow", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_hk_fina_indicator(
ts_code: str,
period: Optional[str] = None,
report_type: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询港股财务指标(PE/PB/ROE等)。需15000积分或单独开权限,积分不足会返回错误。
Args:
ts_code: 股票代码(必填)
period: 报告期(YYYYMMDD)
report_type: 报告期类型(Q1/Q2/Q3/Q4)
start_date: 报告期开始日期
end_date: 报告期结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.hk_fina_indicator(
ts_code=ts_code,
period=period,
report_type=report_type,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "hk_fina_indicator", _format, _limit)
except TushareError as e:
return {"error": str(e)}
"""
游资 MCP Tools
包含:hm_list(游资名录), hm_detail(游资每日明细)
"""
from typing import Optional
from fastmcp import FastMCP
from .. import client
from ..formatter import format_response
from ..errors import TushareError
def register(mcp: FastMCP) -> None:
"""将游资相关 tools 注册到 MCP 实例"""
@mcp.tool()
def tushare_hm_list(
name: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询游资名录。积分要求:5000。
Args:
name: 游资名称
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.hm_list(
name=name,
fields=fields,
)
return format_response(df, "hm_list", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_hm_detail(
trade_date: Optional[str] = None,
ts_code: Optional[str] = None,
hm_name: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询游资每日交易明细。积分要求:10000。
Args:
trade_date: 交易日期
ts_code: 股票代码
hm_name: 游资名称
start_date: 开始日期
end_date: 结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.hm_detail(
trade_date=trade_date,
ts_code=ts_code,
hm_name=hm_name,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "hm_detail", _format, _limit)
except TushareError as e:
return {"error": str(e)}
"""
涨跌停 MCP Tools
包含:limit_list_d(每日涨跌停统计), limit_cpt_list(涨停股票连板天梯)
"""
from typing import Optional
from fastmcp import FastMCP
from .. import client
from ..formatter import format_response
from ..errors import TushareError
def register(mcp: FastMCP) -> None:
"""将涨跌停相关 tools 注册到 MCP 实例"""
@mcp.tool()
def tushare_limit_list_d(
trade_date: Optional[str] = None,
ts_code: Optional[str] = None,
limit_type: Optional[str] = None,
exchange: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询每日涨跌停统计(涨停/跌停/炸板)。积分要求:5000+。
Args:
trade_date: 交易日期
ts_code: 股票代码
limit_type: 涨跌停类型(U涨停 D跌停 Z炸板)
exchange: 交易所
start_date: 开始日期
end_date: 结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.limit_list_d(
trade_date=trade_date,
ts_code=ts_code,
limit_type=limit_type,
exchange=exchange,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "limit_list_d", _format, _limit)
except TushareError as e:
return {"error": str(e)}
@mcp.tool()
def tushare_limit_cpt_list(
trade_date: Optional[str] = None,
ts_code: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
fields: Optional[str] = None,
_format: str = "json",
_limit: int = 100,
) -> dict:
"""查询涨停股票连板天梯。积分要求:8000。
Args:
trade_date: 交易日期
ts_code: 股票代码
start_date: 开始日期
end_date: 结束日期
fields: 返回字段
_format: 输出格式(json/markdown),默认json
_limit: 最大返回行数,默认100
"""
try:
df = client.limit_cpt_list(
trade_date=trade_date,
ts_code=ts_code,
start_date=start_date,
end_date=end_date,
fields=fields,
)
return format_response(df, "limit_cpt_list", _format, _limit)
except TushareError as e:
return {"error": str(e)}
stock-tushare-pro-mcp