From f3aa9729d64b12f5d8b80ac57ddb1d59635855e4 Mon Sep 17 00:00:00 2001 From: zlei9 Date: Sun, 29 Mar 2026 08:22:41 +0800 Subject: [PATCH] Initial commit with translated description --- SKILL.md | 255 +++++++++++++++++++ _meta.json | 6 + references/futures_api.md | 207 +++++++++++++++ references/stock_api.md | 162 ++++++++++++ scripts/market.py | 524 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 1154 insertions(+) create mode 100644 SKILL.md create mode 100644 _meta.json create mode 100644 references/futures_api.md create mode 100644 references/stock_api.md create mode 100644 scripts/market.py diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..c3f14ab --- /dev/null +++ b/SKILL.md @@ -0,0 +1,255 @@ +--- +name: Tushare Pro +slug: tushare +description: "通过Tushare API获取中国股票和期货市场数据。支持股票报价、期货数据、公司基本面和宏观经济指标。在用户需要中国市场金融数据时使用。需要TUSHARE_TOKEN环境变量。" +metadata: + { + "openclaw": { + "requires": { + "env": ["TUSHARE_TOKEN"], + "bins": ["python3", "pip3"] + }, + "install": [ + { + "id": "pip-deps", + "kind": "python", + "package": "tushare pandas", + "label": "Install Python dependencies" + } + ] + } + } +--- + +# Tushare 金融数据接口 + +获取中国 A 股市场和期货市场的实时及历史数据。 + +## 前提条件 + +### 1. 注册 Tushare 账号 + +访问 https://tushare.pro/weborder/#/login?reg=503098 注册账号并获取 API Token。 + +### 2. 配置 Token + +```bash +# 添加到 ~/.zshrc +export TUSHARE_TOKEN="your-api-token-here" +``` + +然后执行: +```bash +source ~/.zshrc +``` + +### 3. 安装依赖 + +```bash +pip3 install tushare pandas --user +``` + +## 快速开始 + +### 获取股票列表 + +```bash +python3 scripts/market.py stock_basic +``` + +### 获取日线行情 + +```bash +python3 scripts/market.py daily --ts_code 000001.SZ --start_date 20240101 --end_date 20240131 +``` + +### 获取实时行情 + +```bash +python3 scripts/market.py realtime 000001 +``` + +## 股票数据 + +### 股票基础信息 + +```bash +python3 scripts/market.py stock_basic +python3 scripts/market.py stock_basic --exchange SSE # 仅上交所 +python3 scripts/market.py stock_basic --exchange SZSE # 仅深交所 +``` + +### 日线行情 + +```bash +# 获取单只股票近期数据 +python3 scripts/market.py daily --ts_code 000001.SZ + +# 指定日期范围 +python3 scripts/market.py daily --ts_code 600519.SH --start_date 20240101 --end_date 20240131 + +# 获取指定交易日全市场数据 +python3 scripts/market.py daily --trade_date 20240115 +``` + +### 周线行情 + +```bash +# 获取周线数据 +python3 scripts/market.py weekly --ts_code 000001.SZ + +# 指定日期范围 +python3 scripts/market.py weekly --ts_code 600519.SH --start_date 20230101 --end_date 20240131 +``` + +### 月线行情 + +```bash +# 获取月线数据 +python3 scripts/market.py monthly --ts_code 000001.SZ + +# 指定日期范围 +python3 scripts/market.py monthly --ts_code 600519.SH --start_date 20200101 --end_date 20240131 +``` + +**股票代码格式**: +- 深交所:`000001.SZ`, `000002.SZ`, `300001.SZ` (创业板) +- 上交所:`600000.SH`, `600519.SH`, `688001.SH` (科创板) + +### 实时行情 + +```bash +python3 scripts/market.py realtime 000001 +python3 scripts/market.py realtime 600519 +``` + +### 资金流向 + +```bash +# 获取指定股票资金流向 +python3 scripts/market.py moneyflow --ts_code 000001.SZ + +# 获取指定日期全市场资金流向 +python3 scripts/market.py moneyflow --trade_date 20240115 +``` + +### 公司信息 + +```bash +python3 scripts/market.py company +``` + +## 期货数据 + +### 期货合约基础信息 + +```bash +python3 scripts/market.py fut_basic + +# 指定交易所 +python3 scripts/market.py fut_basic --exchange CFFEX # 中金所 +python3 scripts/market.py fut_basic --exchange SHFE # 上期所 +python3 scripts/market.py fut_basic --exchange DCE # 大商所 +python3 scripts/market.py fut_basic --exchange CZCE # 郑商所 +``` + +**交易所代码**: +- `CFFEX` - 中国金融期货交易所 +- `SHFE` - 上海期货交易所 +- `DCE` - 大连商品交易所 +- `CZCE` - 郑州商品交易所 +- `INE` - 上海国际能源交易中心 + +### 期货日线行情 + +```bash +# 获取铜期货数据 +python3 scripts/market.py fut_daily --ts_code CU.SHF + +# 获取沪深300股指期货 +python3 scripts/market.py fut_daily --ts_code IF.CFX + +# 指定日期范围 +python3 scripts/market.py fut_daily --ts_code RB.SHF --start_date 20240101 --end_date 20240131 +``` + +**期货代码格式**: +- 上期所:`CU.SHF` (铜), `RB.SHF` (螺纹钢), `AU.SHF` (黄金) +- 大商所:`M.DCE` (豆粕), `I.DCE` (铁矿石) +- 郑商所:`SR.CZC` (白糖), `CF.CZC` (棉花) +- 中金所:`IF.CFX` (沪深300), `IC.CFX` (中证500) + +### 期货持仓排名 + +```bash +python3 scripts/market.py fut_holding --trade_date 20240115 --symbol CU +``` + +## 宏观经济 + +### GDP 数据 + +```bash +python3 scripts/market.py gdp +``` + +输出示例: +``` +📈 GDP数据 (88 条): + +2023年4季度: GDP 347909亿元, 增速 5.2% +2023年3季度: GDP 319992亿元, 增速 4.9% +... +``` + +### CPI 数据 + +```bash +python3 scripts/market.py cpi +``` + +### PPI 数据 + +```bash +python3 scripts/market.py ppi +``` + +## 命令速查表 + +| 命令 | 功能 | 示例 | +|------|------|------| +| `stock_basic` | 股票基础信息 | `--exchange SSE` | +| `daily` | 日线行情 | `--ts_code 000001.SZ --start_date 20240101` | +| `weekly` | 周线行情 | `--ts_code 000001.SZ --start_date 20230101` | +| `monthly` | 月线行情 | `--ts_code 000001.SZ --start_date 20200101` | +| `realtime` | 实时行情 | `000001` | +| `moneyflow` | 资金流向 | `--ts_code 000001.SZ` | +| `company` | 公司信息 | - | +| `fut_basic` | 期货基础信息 | `--exchange SHFE` | +| `fut_daily` | 期货日线 | `--ts_code CU.SHF` | +| `fut_holding` | 持仓排名 | `--symbol CU` | +| `gdp` | GDP数据 | - | +| `cpi` | CPI数据 | - | +| `ppi` | PPI数据 | - | + +## 常见问题 + +**错误:请设置 TUSHARE_TOKEN 环境变量** +→ 在 `~/.zshrc` 中添加 `export TUSHARE_TOKEN="your-token"` 并执行 `source ~/.zshrc` + +**错误:没有数据返回** +→ 检查股票/期货代码格式是否正确(如:000001.SZ, CU.SHF) + +**错误:权限不足** +→ Tushare 部分接口需要积分或付费权限,请在官网查看接口权限要求 + +**如何获取股票代码?** +```bash +python3 scripts/market.py stock_basic | grep "平安" +``` + +## 参考文档 + +- 股票接口文档: [references/stock_api.md](references/stock_api.md) +- 期货接口文档: [references/futures_api.md](references/futures_api.md) +- Tushare 官网: https://tushare.pro diff --git a/_meta.json b/_meta.json new file mode 100644 index 0000000..a54ce82 --- /dev/null +++ b/_meta.json @@ -0,0 +1,6 @@ +{ + "ownerId": "kn7cf8pks04nj5d8r97e45bzdh80enwz", + "slug": "tushare", + "version": "1.0.9", + "publishedAt": 1773796777210 +} \ No newline at end of file diff --git a/references/futures_api.md b/references/futures_api.md new file mode 100644 index 0000000..4508176 --- /dev/null +++ b/references/futures_api.md @@ -0,0 +1,207 @@ +# Tushare 期货接口文档 + +官方文档: https://tushare.pro/document/2?doc_id=134 + +## 基础信息接口 + +### fut_basic - 期货合约基础信息 + +**输入参数**: + +| 名称 | 类型 | 必选 | 描述 | +|------|------|------|------| +| exchange | str | N | 交易所代码 | +| fut_type | str | N | 合约类型 (1: 普通合约 2: 主力合约) | + +**输出字段**: + +| 名称 | 类型 | 描述 | +|------|------|------| +| ts_code | str | 合约代码 | +| symbol | str | 交易标的 | +| exchange | str | 交易所 | +| name | str | 合约名称 | +| fut_code | str | 合约标码 | +| multiplier | float | 合约乘数 | +| trade_unit | str | 交易单位 | +| per_unit | float | 最小变动价位 | +| delivery_date | str | 交割日期 | +| delist_date | str | 最后交易日期 | +| list_date | str | 上市日期 | +| last_ddate | str | 最后交割日 | +| trade_time_desc | str | 交易时间描述 | + +## 行情接口 + +### fut_daily - 期货日线行情 + +**输入参数**: + +| 名称 | 类型 | 必选 | 描述 | +|------|------|------|------| +| trade_date | str | N | 交易日期 | +| ts_code | str | N | 合约代码 | +| exchange | str | N | 交易所 | +| start_date | str | N | 开始日期 | +| end_date | str | N | 结束日期 | + +**输出字段**: + +| 名称 | 类型 | 描述 | +|------|------|------| +| ts_code | str | 合约代码 | +| trade_date | str | 交易日期 | +| pre_close | float | 昨收盘价 | +| pre_settle | float | 昨结算价 | +| open | float | 开盘价 | +| high | float | 最高价 | +| low | float | 最低价 | +| close | float | 收盘价 | +| settle | float | 结算价 | +| change1 | float | 涨跌1(收盘价-昨结算价) | +| change2 | float | 涨跌2(结算价-昨结算价) | +| vol | float | 成交量(手) | +| amount | float | 成交金额(万元) | +| oi | float | 持仓量(手) | +| oi_chg | float | 持仓量变化 | +| exchange | str | 交易所 | + +### fut_holding - 每日持仓排名 + +**输入参数**: + +| 名称 | 类型 | 必选 | 描述 | +|------|------|------|------| +| trade_date | str | N | 交易日期 | +| symbol | str | N | 合约代码(不带年份月份) | +| exchange | str | N | 交易所 | + +**输出字段**: + +| 名称 | 类型 | 描述 | +|------|------|------| +| trade_date | str | 交易日期 | +| symbol | str | 合约符号 | +| broker | str | 期货公司会员 | +| vol | int | 成交量 | +| vol_chg | int | 成交量变动 | +| long_hld | int | 多单持仓 | +| long_chg | int | 多单持仓变动 | +| short_hld | int | 空单持仓 | +| short_chg | int | 空单持仓变动 | +| exchange | str | 交易所 | + +### fut_wsr - 期货仓单日报 + +**输入参数**: + +| 名称 | 类型 | 必选 | 描述 | +|------|------|------|------| +| trade_date | str | N | 交易日期 | +| symbol | str | N | 合约代码 | +| exchange | str | N | 交易所 | + +**输出字段**: + +| 名称 | 类型 | 描述 | +|------|------|------| +| trade_date | str | 交易日期 | +| symbol | str | 合约代码 | +| wsr_num | int | 仓单数量 | +| wsr_num_chg | int | 仓单数量变化 | +| wsr_unit | str | 仓单单位 | +| close | float | 收盘价 | +| exchange | str | 交易所 | + +### fut_settle - 期货结算参数 + +**输入参数**: + +| 名称 | 类型 | 必选 | 描述 | +|------|------|------|------| +| trade_date | str | N | 交易日期 | +| exchange | str | N | 交易所 | + +**输出字段**: + +| 名称 | 类型 | 描述 | +|------|------|------| +| trade_date | str | 交易日期 | +| ts_code | str | 合约代码 | +| exchange | str | 交易所 | +| settle | float | 结算价 | +| trading_fee_rate | float | 交易手续费率 | +| trading_fee | float | 交易手续费 | +| delivery_fee | float | 交割手续费 | +| min_price_chg | float | 最小变动价位 | + +## 期货代码说明 + +### 交易所代码 + +| 代码 | 交易所 | 主要品种 | +|------|--------|----------| +| SHFE | 上海期货交易所 | 铜、铝、锌、黄金、原油、螺纹钢 | +| DCE | 大连商品交易所 | 豆粕、豆油、铁矿石、焦炭、玉米 | +| CZCE | 郑州商品交易所 | 棉花、白糖、PTA、菜粕、甲醇 | +| CFFEX | 中国金融期货交易所 | 沪深300、中证500、国债期货 | +| INE | 上海国际能源交易中心 | 原油期货 | +| GFEX | 广州期货交易所 | 工业硅、碳酸锂 | + +### 常见品种代码 + +| 品种 | 代码 | 交易所 | +|------|------|--------| +| 铜 | CU | SHFE | +| 铝 | AL | SHFE | +| 锌 | ZN | SHFE | +| 黄金 | AU | SHFE | +| 白银 | AG | SHFE | +| 原油 | SC | INE | +| 螺纹钢 | RB | SHFE | +| 热轧卷板 | HC | SHFE | +| 天然橡胶 | RU | SHFE | +| 豆粕 | M | DCE | +| 豆油 | Y | DCE | +| 棕榈油 | P | DCE | +| 铁矿石 | I | DCE | +| 焦炭 | J | DCE | +| 焦煤 | JM | DCE | +| 玉米 | C | DCE | +| 棉花 | CF | CZCE | +| 白糖 | SR | CZCE | +| PTA | TA | CZCE | +| 甲醇 | MA | CZCE | +| 菜粕 | RM | CZCE | +| 玻璃 | FG | CZCE | +| 纯碱 | SA | CZCE | +| 沪深300指数期货 | IF | CFFEX | +| 中证500指数期货 | IC | CFFEX | +| 上证50指数期货 | IH | CFFEX | +| 10年期国债期货 | T | CFFEX | +| 5年期国债期货 | TF | CFFEX | + +### 合约代码格式 + +期货合约代码由 **品种代码 + 到期年月** 组成: + +- `CU2403` - 2024年3月到期的铜合约 +- `RB2405` - 2024年5月到期的螺纹钢合约 +- `IF2403` - 2024年3月到期的沪深300股指期货 + +主力合约通常用 `.SHF`, `.DCE`, `.CZC`, `.CFX` 后缀表示: +- `CU.SHF` - 铜主力合约(上期所) +- `M.DCE` - 豆粕主力合约(大商所) +- `IF.CFX` - 沪深300主力合约(中金所) + +## 交易时间 + +### 日盘(上午 + 下午) +- 上午:09:00 - 10:15, 10:30 - 11:30 +- 下午:13:30 - 15:00 + +### 夜盘(部分品种) +- 21:00 - 23:00(有色金属、黑色系等) +- 21:00 - 02:30(原油、贵金属等) + +具体交易时间因品种而异,请参考各交易所规定。 diff --git a/references/stock_api.md b/references/stock_api.md new file mode 100644 index 0000000..c956d34 --- /dev/null +++ b/references/stock_api.md @@ -0,0 +1,162 @@ +# Tushare 股票接口文档 + +官方文档: https://tushare.pro/document/2?doc_id=14 + +## 基础信息接口 + +### stock_basic - 股票基础信息 + +**输入参数**: + +| 名称 | 类型 | 必选 | 描述 | +|------|------|------|------| +| ts_code | str | N | TS股票代码 | +| name | str | N | 股票名称 | +| exchange | str | N | 交易所 (SSE/SZSE) | +| market | str | N | 市场类型 | +| is_hs | str | N | 是否沪深港通 (N/H/S) | +| list_status | str | N | 上市状态 (L上市/D退市/P暂停上市) | + +**输出字段**: + +| 名称 | 类型 | 描述 | +|------|------|------| +| ts_code | str | TS代码 | +| symbol | str | 股票代码 | +| name | str | 股票名称 | +| area | str | 地域 | +| industry | str | 所属行业 | +| fullname | str | 股票全称 | +| enname | str | 英文全称 | +| cnspell | str | 拼音缩写 | +| market | str | 市场类型 | +| exchange | str | 交易所代码 | +| curr_type | str | 交易货币 | +| list_status | str | 上市状态 | +| list_date | str | 上市日期 | +| delist_date | str | 退市日期 | +| is_hs | str | 是否沪深港通标的 | + +## 行情接口 + +### daily - 日线行情 + +**输入参数**: + +| 名称 | 类型 | 必选 | 描述 | +|------|------|------|------| +| ts_code | str | N | 股票代码 | +| trade_date | str | N | 交易日期 (YYYYMMDD) | +| start_date | str | N | 开始日期 | +| end_date | str | N | 结束日期 | + +**输出字段**: + +| 名称 | 类型 | 描述 | +|------|------|------| +| ts_code | str | 股票代码 | +| trade_date | str | 交易日期 | +| open | float | 开盘价 | +| high | float | 最高价 | +| low | float | 最低价 | +| close | float | 收盘价 | +| pre_close | float | 昨收价 | +| change | float | 涨跌额 | +| pct_chg | float | 涨跌幅 | +| vol | float | 成交量(手) | +| amount | float | 成交额(千元) | + +### moneyflow - 个股资金流向 + +**输入参数**: + +| 名称 | 类型 | 必选 | 描述 | +|------|------|------|------| +| ts_code | str | N | 股票代码 | +| trade_date | str | N | 交易日期 | +| start_date | str | N | 开始日期 | +| end_date | str | N | 结束日期 | + +**输出字段**: + +| 名称 | 类型 | 描述 | +|------|------|------| +| ts_code | str | 股票代码 | +| trade_date | str | 交易日期 | +| buy_sm_vol | int | 小单买入量(手) | +| buy_sm_amount | float | 小单买入金额(万元) | +| sell_sm_vol | int | 小单卖出量(手) | +| sell_sm_amount | float | 小单卖出金额(万元) | +| buy_md_vol | int | 中单买入量(手) | +| buy_md_amount | float | 中单买入金额(万元) | +| sell_md_vol | int | 中单卖出量(手) | +| sell_md_amount | float | 中单卖出金额(万元) | +| buy_lg_vol | int | 大单买入量(手) | +| buy_lg_amount | float | 大单买入金额(万元) | +| sell_lg_vol | int | 大单卖出量(手) | +| sell_lg_amount | float | 大单卖出金额(万元) | +| buy_elg_vol | int | 特大单买入量(手) | +| buy_elg_amount | float | 特大单买入金额(万元) | +| sell_elg_vol | int | 特大单卖出量(手) | +| sell_elg_amount | float | 特大单卖出金额(万元) | +| net_mf_vol | int | 净流入量(手) | +| net_mf_amount | float | 净流入额(万元) | + +## 公司信息接口 + +### stock_company - 上市公司基本信息 + +**输入参数**: + +| 名称 | 类型 | 必选 | 描述 | +|------|------|------|------| +| ts_code | str | N | 股票代码 | +| exchange | str | N | 交易所代码 | + +**输出字段**: + +| 名称 | 类型 | 描述 | +|------|------|------| +| ts_code | str | 股票代码 | +| exchange | str | 交易所代码 | +| chairman | str | 董事长 | +| manager | str | 总经理 | +| secretary | str | 董秘 | +| reg_capital | float | 注册资本(万元) | +| setup_date | str | 注册日期 | +| province | str | 所在省份 | +| city | str | 所在城市 | +| introduction | str | 公司介绍 | +| website | str | 公司主页 | +| email | str | 电子邮件 | +| office | str | 办公地址 | +| employees | int | 员工人数 | +| main_business | str | 主要业务及产品 | +| business_scope | str | 经营范围 | + +## 股票代码说明 + +### 交易所代码 + +| 代码 | 交易所 | +|------|--------| +| SSE | 上海证券交易所 | +| SZSE | 深圳证券交易所 | + +### 市场类型 + +| 代码 | 含义 | +|------|------| +| 主板 | 沪市主板、深市主板 | +| 中小板 | 深市中小板(已合并至主板) | +| 创业板 | 深市创业板 (300xxx.SZ) | +| 科创板 | 沪市科创板 (688xxx.SH) | +| 北交所 | 北京证券交易所 | + +### 代码后缀 + +| 后缀 | 含义 | +|------|------| +| .SH | 上海证券交易所 | +| .SZ | 深圳证券交易所 | +| .BJ | 北京证券交易所 | diff --git a/scripts/market.py b/scripts/market.py new file mode 100644 index 0000000..c02b76e --- /dev/null +++ b/scripts/market.py @@ -0,0 +1,524 @@ +#!/usr/bin/env python3 +""" +Tushare 金融数据接口 +支持:股票行情、期货数据、基本面数据、宏观经济 +""" + +import os +import sys +import json +import argparse +from datetime import datetime, timedelta +from typing import Optional, Dict, List + +# 尝试导入 tushare +try: + import tushare as ts + TUSHARE_AVAILABLE = True +except ImportError: + TUSHARE_AVAILABLE = False + print("⚠️ tushare 库未安装,请先运行: pip3 install tushare --user") + +def get_pro_api(): + """获取 Tushare Pro API 实例""" + if not TUSHARE_AVAILABLE: + return None + + token = os.getenv('TUSHARE_TOKEN') + if not token: + print("❌ 错误: 请设置 TUSHARE_TOKEN 环境变量") + print("获取方式: https://tushare.pro/register") + return None + + ts.set_token(token) + return ts.pro_api() + +# ==================== 股票数据 ==================== + +def get_stock_basic(exchange: str = '', list_status: str = 'L') -> List[Dict]: + """获取股票基础信息""" + pro = get_pro_api() + if not pro: + return [] + + try: + df = pro.stock_basic(exchange=exchange, list_status=list_status) + return df.to_dict('records') + except Exception as e: + print(f"❌ 获取股票基础信息失败: {e}") + return [] + +def get_daily(ts_code: str = '', trade_date: str = '', start_date: str = '', end_date: str = '') -> List[Dict]: + """获取日线行情""" + pro = get_pro_api() + if not pro: + return [] + + try: + df = pro.daily(ts_code=ts_code, trade_date=trade_date, + start_date=start_date, end_date=end_date) + return df.to_dict('records') + except Exception as e: + print(f"❌ 获取日线行情失败: {e}") + return [] + +def get_weekly(ts_code: str = '', trade_date: str = '', start_date: str = '', end_date: str = '') -> List[Dict]: + """获取周线行情""" + pro = get_pro_api() + if not pro: + return [] + + try: + df = pro.weekly(ts_code=ts_code, trade_date=trade_date, + start_date=start_date, end_date=end_date) + return df.to_dict('records') + except Exception as e: + print(f"❌ 获取周线行情失败: {e}") + return [] + +def get_monthly(ts_code: str = '', trade_date: str = '', start_date: str = '', end_date: str = '') -> List[Dict]: + """获取月线行情""" + pro = get_pro_api() + if not pro: + return [] + + try: + df = pro.monthly(ts_code=ts_code, trade_date=trade_date, + start_date=start_date, end_date=end_date) + return df.to_dict('records') + except Exception as e: + print(f"❌ 获取月线行情失败: {e}") + return [] + +def get_realtime_quote(ts_code: str) -> Optional[Dict]: + """获取实时行情(使用旧版接口)""" + if not TUSHARE_AVAILABLE: + return None + + try: + df = ts.get_realtime_quotes(ts_code) + if df is not None and not df.empty: + return df.iloc[0].to_dict() + return None + except Exception as e: + print(f"❌ 获取实时行情失败: {e}") + return None + +def get_stock_company(ts_code: str = '') -> List[Dict]: + """获取上市公司基本信息""" + pro = get_pro_api() + if not pro: + return [] + + try: + df = pro.stock_company(ts_code=ts_code) + return df.to_dict('records') + except Exception as e: + print(f"❌ 获取公司信息失败: {e}") + return [] + +def get_top10_holders(ts_code: str, start_date: str = '', end_date: str = '') -> List[Dict]: + """获取前十大股东""" + pro = get_pro_api() + if not pro: + return [] + + try: + df = pro.top10_holders(ts_code=ts_code, start_date=start_date, end_date=end_date) + return df.to_dict('records') + except Exception as e: + print(f"❌ 获取股东信息失败: {e}") + return [] + +def get_moneyflow(ts_code: str = '', trade_date: str = '') -> List[Dict]: + """获取个股资金流向""" + pro = get_pro_api() + if not pro: + return [] + + try: + df = pro.moneyflow(ts_code=ts_code, trade_date=trade_date) + return df.to_dict('records') + except Exception as e: + print(f"❌ 获取资金流向失败: {e}") + return [] + +# ==================== 期货数据 ==================== + +def get_fut_basic(exchange: str = '', fut_type: str = '2') -> List[Dict]: + """获取期货合约基础信息""" + pro = get_pro_api() + if not pro: + return [] + + try: + df = pro.fut_basic(exchange=exchange, fut_type=fut_type) + return df.to_dict('records') + except Exception as e: + print(f"❌ 获取期货基础信息失败: {e}") + return [] + +def get_fut_daily(ts_code: str = '', trade_date: str = '', start_date: str = '', end_date: str = '') -> List[Dict]: + """获取期货日线行情""" + pro = get_pro_api() + if not pro: + return [] + + try: + df = pro.fut_daily(ts_code=ts_code, trade_date=trade_date, + start_date=start_date, end_date=end_date) + return df.to_dict('records') + except Exception as e: + print(f"❌ 获取期货日线失败: {e}") + return [] + +def get_fut_holding(trade_date: str = '', symbol: str = '') -> List[Dict]: + """获取每日持仓排名""" + pro = get_pro_api() + if not pro: + return [] + + try: + df = pro.fut_holding(trade_date=trade_date, symbol=symbol) + return df.to_dict('records') + except Exception as e: + print(f"❌ 获取持仓排名失败: {e}") + return [] + +def get_fut_wsr(trade_date: str = '') -> List[Dict]: + """获取仓单日报""" + pro = get_pro_api() + if not pro: + return [] + + try: + df = pro.fut_wsr(trade_date=trade_date) + return df.to_dict('records') + except Exception as e: + print(f"❌ 获取仓单数据失败: {e}") + return [] + +def get_fut_settle(trade_date: str = '', exchange: str = '') -> List[Dict]: + """获取期货结算参数""" + pro = get_pro_api() + if not pro: + return [] + + try: + df = pro.fut_settle(trade_date=trade_date, exchange=exchange) + return df.to_dict('records') + except Exception as e: + print(f"❌ 获取结算参数失败: {e}") + return [] + +# ==================== 宏观经济 ==================== + +def get_gdp() -> List[Dict]: + """获取GDP数据""" + pro = get_pro_api() + if not pro: + return [] + + try: + df = pro.cn_gdp() + return df.to_dict('records') + except Exception as e: + print(f"❌ 获取GDP数据失败: {e}") + return [] + +def get_cpi() -> List[Dict]: + """获取CPI数据""" + pro = get_pro_api() + if not pro: + return [] + + try: + df = pro.cn_cpi() + return df.to_dict('records') + except Exception as e: + print(f"❌ 获取CPI数据失败: {e}") + return [] + +def get_ppi() -> List[Dict]: + """获取PPI数据""" + pro = get_pro_api() + if not pro: + return [] + + try: + df = pro.cn_ppi() + return df.to_dict('records') + except Exception as e: + print(f"❌ 获取PPI数据失败: {e}") + return [] + +# ==================== 输出格式化 ==================== + +def print_stock_basic(data: List[Dict]): + """打印股票基础信息""" + if not data: + print("📭 没有数据") + return + + print(f"\n📈 股票列表 ({len(data)} 只):\n") + print(f"{'代码':<12} {'名称':<15} {'行业':<15} {'上市日期':<12}") + print("-" * 60) + + for item in data[:50]: # 限制显示数量 + ts_code = item.get('ts_code', 'N/A') + name = item.get('name', 'Unknown')[:14] + industry = item.get('industry', '-')[:14] + list_date = item.get('list_date', '-') + print(f"{ts_code:<12} {name:<15} {industry:<15} {list_date:<12}") + +def print_daily(data: List[Dict]): + """打印日线行情""" + if not data: + print("📭 没有数据") + return + + print(f"\n📊 日线行情 ({len(data)} 条):\n") + print(f"{'日期':<12} {'开盘':<10} {'收盘':<10} {'最高':<10} {'最低':<10} {'成交量':<12}") + print("-" * 70) + + for item in data[:20]: + trade_date = item.get('trade_date', '-') + open_price = item.get('open', 0) + close = item.get('close', 0) + high = item.get('high', 0) + low = item.get('low', 0) + vol = item.get('vol', 0) + + change = item.get('change', 0) + pct_chg = item.get('pct_chg', 0) + + emoji = "🟢" if pct_chg > 0 else "🔴" if pct_chg < 0 else "⚪" + + print(f"{trade_date:<12} {open_price:<10.2f} {close:<10.2f} {high:<10.2f} {low:<10.2f} {vol:<12}") + print(f" {emoji} 涨跌: {change:+.2f} ({pct_chg:+.2f}%)") + print() + +def print_fut_basic(data: List[Dict]): + """打印期货基础信息""" + if not data: + print("📭 没有数据") + return + + print(f"\n📦 期货合约 ({len(data)} 个):\n") + print(f"{'代码':<15} {'名称':<20} {'交易所':<10} {'合约类型':<10}") + print("-" * 60) + + for item in data[:50]: + ts_code = item.get('ts_code', 'N/A') + name = item.get('name', 'Unknown')[:18] + exchange = item.get('exchange', '-') + fut_type = item.get('fut_type', '-') + print(f"{ts_code:<15} {name:<20} {exchange:<10} {fut_type:<10}") + +def print_fut_daily(data: List[Dict]): + """打印期货日线""" + if not data: + print("📭 没有数据") + return + + print(f"\n📊 期货日线 ({len(data)} 条):\n") + print(f"{'日期':<12} {'开盘':<10} {'收盘':<10} {'最高':<10} {'最低':<10} {'持仓':<10}") + print("-" * 70) + + for item in data[:20]: + trade_date = item.get('trade_date', '-') + open_price = item.get('open', 0) + close = item.get('close', 0) + high = item.get('high', 0) + low = item.get('low', 0) + oi = item.get('oi', 0) # 持仓量 + + change = close - open_price + + emoji = "🟢" if change > 0 else "🔴" if change < 0 else "⚪" + + print(f"{trade_date:<12} {open_price:<10.2f} {close:<10.2f} {high:<10.2f} {low:<10.2f} {oi:<10.0f}") + +def print_moneyflow(data: List[Dict]): + """打印资金流向""" + if not data: + print("📭 没有数据") + return + + print(f"\n💰 资金流向 ({len(data)} 条):\n") + print(f"{'代码':<12} {'日期':<12} {'净流入':<12} {'主力净流入':<12}") + print("-" * 55) + + for item in data[:20]: + ts_code = item.get('ts_code', '-') + trade_date = item.get('trade_date', '-') + net_mf = item.get('net_mf', 0) / 10000 # 万元 + net_mf_amount = item.get('net_mf_amount', 0) / 10000 + + emoji = "🟢" if net_mf > 0 else "🔴" + + print(f"{ts_code:<12} {trade_date:<12} {emoji} {net_mf:<10.1f}万 {net_mf_amount:<10.1f}万") + +# ==================== 主程序 ==================== + +def main(): + parser = argparse.ArgumentParser(description='Tushare 金融数据接口') + subparsers = parser.add_subparsers(dest='command', help='可用命令') + + # 股票基础信息 + stock_basic = subparsers.add_parser('stock_basic', help='获取股票基础信息') + stock_basic.add_argument('--exchange', default='', help='交易所 (SSE/SZSE)') + + # 日线行情 + daily = subparsers.add_parser('daily', help='获取日线行情') + daily.add_argument('--ts_code', required=True, help='股票代码 (如: 000001.SZ)') + daily.add_argument('--start_date', help='开始日期 (YYYYMMDD)') + daily.add_argument('--end_date', help='结束日期 (YYYYMMDD)') + daily.add_argument('--trade_date', help='交易日期 (YYYYMMDD)') + + # 周线行情 + weekly = subparsers.add_parser('weekly', help='获取周线行情') + weekly.add_argument('--ts_code', required=True, help='股票代码 (如: 000001.SZ)') + weekly.add_argument('--start_date', help='开始日期 (YYYYMMDD)') + weekly.add_argument('--end_date', help='结束日期 (YYYYMMDD)') + weekly.add_argument('--trade_date', help='交易日期 (YYYYMMDD)') + + # 月线行情 + monthly = subparsers.add_parser('monthly', help='获取月线行情') + monthly.add_argument('--ts_code', required=True, help='股票代码 (如: 000001.SZ)') + monthly.add_argument('--start_date', help='开始日期 (YYYYMMDD)') + monthly.add_argument('--end_date', help='结束日期 (YYYYMMDD)') + monthly.add_argument('--trade_date', help='交易日期 (YYYYMMDD)') + + # 实时行情 + realtime = subparsers.add_parser('realtime', help='获取实时行情') + realtime.add_argument('ts_code', help='股票代码') + + # 公司信息 + subparsers.add_parser('company', help='获取上市公司信息') + + # 资金流向 + moneyflow = subparsers.add_parser('moneyflow', help='获取资金流向') + moneyflow.add_argument('--ts_code', help='股票代码') + moneyflow.add_argument('--trade_date', help='交易日期') + + # 期货基础 + fut_basic = subparsers.add_parser('fut_basic', help='获取期货基础信息') + fut_basic.add_argument('--exchange', default='', help='交易所') + + # 期货日线 + fut_daily = subparsers.add_parser('fut_daily', help='获取期货日线') + fut_daily.add_argument('--ts_code', required=True, help='期货代码 (如: CU.SHF)') + fut_daily.add_argument('--start_date', help='开始日期') + fut_daily.add_argument('--end_date', help='结束日期') + + # 期货持仓 + fut_holding = subparsers.add_parser('fut_holding', help='获取期货持仓排名') + fut_holding.add_argument('--trade_date', help='交易日期') + fut_holding.add_argument('--symbol', help='合约代码') + + # 宏观经济 + subparsers.add_parser('gdp', help='获取GDP数据') + subparsers.add_parser('cpi', help='获取CPI数据') + subparsers.add_parser('ppi', help='获取PPI数据') + + args = parser.parse_args() + + if not args.command: + parser.print_help() + return + + if not TUSHARE_AVAILABLE: + print("\n❌ 请先安装 tushare:") + print(" pip3 install tushare --user") + return + + # 执行命令 + if args.command == 'stock_basic': + data = get_stock_basic(exchange=args.exchange) + print_stock_basic(data) + + elif args.command == 'daily': + data = get_daily(ts_code=args.ts_code, trade_date=args.trade_date, + start_date=args.start_date, end_date=args.end_date) + print_daily(data) + + elif args.command == 'weekly': + data = get_weekly(ts_code=args.ts_code, trade_date=args.trade_date, + start_date=args.start_date, end_date=args.end_date) + print(f"\n📊 周线行情 ({len(data)} 条):\n") + print(f"{'日期':<12} {'开盘':<10} {'收盘':<10} {'最高':<10} {'最低':<10} {'成交量':<12}") + print("-" * 70) + for item in data[:20]: + trade_date = item.get('trade_date', '-') + open_price = item.get('open', 0) + close = item.get('close', 0) + high = item.get('high', 0) + low = item.get('low', 0) + vol = item.get('vol', 0) + print(f"{trade_date:<12} {open_price:<10.2f} {close:<10.2f} {high:<10.2f} {low:<10.2f} {vol:<12}") + + elif args.command == 'monthly': + data = get_monthly(ts_code=args.ts_code, trade_date=args.trade_date, + start_date=args.start_date, end_date=args.end_date) + print(f"\n📊 月线行情 ({len(data)} 条):\n") + print(f"{'日期':<12} {'开盘':<10} {'收盘':<10} {'最高':<10} {'最低':<10} {'成交量':<12}") + print("-" * 70) + for item in data[:20]: + trade_date = item.get('trade_date', '-') + open_price = item.get('open', 0) + close = item.get('close', 0) + high = item.get('high', 0) + low = item.get('low', 0) + vol = item.get('vol', 0) + print(f"{trade_date:<12} {open_price:<10.2f} {close:<10.2f} {high:<10.2f} {low:<10.2f} {vol:<12}") + + elif args.command == 'realtime': + data = get_realtime_quote(args.ts_code) + if data: + print(json.dumps(data, indent=2, ensure_ascii=False)) + + elif args.command == 'company': + data = get_stock_company() + print(f"\n🏢 上市公司信息 ({len(data)} 家):\n") + for item in data[:20]: + print(f"{item.get('ts_code')}: {item.get('chairman', '-')} - {item.get('main_business', '-')[:30]}...") + + elif args.command == 'moneyflow': + data = get_moneyflow(ts_code=args.ts_code, trade_date=args.trade_date) + print_moneyflow(data) + + elif args.command == 'fut_basic': + data = get_fut_basic(exchange=args.exchange) + print_fut_basic(data) + + elif args.command == 'fut_daily': + data = get_fut_daily(ts_code=args.ts_code, start_date=args.start_date, end_date=args.end_date) + print_fut_daily(data) + + elif args.command == 'fut_holding': + data = get_fut_holding(trade_date=args.trade_date, symbol=args.symbol) + print(f"\n📊 期货持仓排名 ({len(data)} 条):\n") + for item in data[:20]: + print(f"{item.get('trade_date')} {item.get('symbol')} {item.get('broker')}: {item.get('vol')} 手") + + elif args.command == 'gdp': + data = get_gdp() + print(f"\n📈 GDP数据 ({len(data)} 条):\n") + for item in data[:10]: + print(f"{item.get('year')}年{item.get('quarter')}季度: GDP {item.get('gdp')}亿元, 增速 {item.get('gdp_yoy')}%") + + elif args.command == 'cpi': + data = get_cpi() + print(f"\n📊 CPI数据 ({len(data)} 条):\n") + for item in data[:10]: + print(f"{item.get('month')}: 全国 {item.get('nt_val')}%, 城市 {item.get('town_val')}%, 农村 {item.get('cnt_val')}%") + + elif args.command == 'ppi': + data = get_ppi() + print(f"\n🏭 PPI数据 ({len(data)} 条):\n") + for item in data[:10]: + print(f"{item.get('month')}: PPI {item.get('ppi')}%, 环比 {item.get('ppi_mp')}%") + +if __name__ == '__main__': + main()