Skip to main content

Agent-ready A-share market and research data SDK with Tushare, iFinD, MinIO, REST and MCP.

Project description

n-ashare-market

面向程序与 Agent 的 A 股市场数据 SDK。当前版本提供:

  • Tushare 历史日线:none / qfq / hfq
  • iFinD THS_RQ 实时行情快照;
  • Insight 历史 tick 与 1/5/15/30/60min K 线;
  • Insight 实时 tick/1min 单会话订阅与 SSE;
  • 完整覆盖旧 ashare-history-system 的 41 个数据集与 8 个引用表;
  • 在旧范围之上额外提供财务报表、Insight 1min/tick 和实时能力;
  • MinIO raw/curated Parquet、覆盖清单、实时归档和带鉴权的外部下载;
  • MinIO 实时小对象安全 compact;
  • 本地/远程 Python SDK;
  • FastAPI REST/OpenAPI;
  • MCP tools/resources;
  • JSON 友好的来源、新鲜度、覆盖度和 artifact 元数据。

Insight 使用独立 subprocess bridge,可继续运行在供应商要求的 Python 3.7 环境,主 SDK 保持 Python 3.11+。

1. 架构

Tushare history ─┐
iFinD snapshot ──┼─ MarketDataService ─ normalization ─ MinIO curated/catalog
Insight bridge ──┘                           └────────── MinIO realtime/artifacts
                           │
                           ├─ Python SDK
                           ├─ REST / OpenAPI
                           ├─ CLI
                           └─ MCP Server

MinIO 是持久化缓存和分发层,不承担实时消息总线职责。实时请求先由 iFinD 返回给调用方,再将快照微批归档到 MinIO。

详细设计见 docs/architecture.md,数据目录和全量重建见 docs/research.md,旧系统逐项覆盖见 docs/legacy-coverage.md

2. 安装

Python 需要 3.11 或更高版本。

cd ashare-market-sdk
python -m venv .venv
. .venv/bin/activate
pip install -e .
cp .env.example .env

从 PyPI 安装发布版本:

pip install n-ashare-market

从 Git 仓库安装 Python SDK

仓库发布后,客户端不需要复制源码。推荐打 tag 后固定版本安装:

pip install "n-ashare-market @ git+https://gitlab.thoughtyard.com.cn/aion/ashare-market-sdk.git@v0.5.2"

私有仓库建议使用已经配置好的 SSH key,避免把访问 token 写入命令或日志:

pip install "n-ashare-market @ git+ssh://git@gitlab.thoughtyard.com.cn/aion/ashare-market-sdk.git@v0.5.2"

如果以后把它放在一个 monorepo 的 ashare-market-sdk/ 子目录,则使用:

pip install "n-ashare-market @ git+https://gitlab.example.com/YOUR_ORG/YOUR_REPO.git@v0.5.2#subdirectory=ashare-market-sdk"

安装后验证命令是否在 PATH(这一步由部署人员执行):

ashare-market --help

iFinD 的 iFinDPy 使用官方 SDK 安装包,不包含在 PyPI 依赖中。运行 REST/MCP 的 Python 环境必须能够执行:

import iFinDPy

默认使用主服务当前 Python 运行 Insight bridge,不需要配置解释器路径。如果供应商 SDK 只能安装在 独立 Python 环境,该环境至少需要 Insight SDK、pandas 和可写 Parquet 的 pyarrow,再覆盖:

ASHARE_MARKET_INSIGHT_USERNAME=...
ASHARE_MARKET_INSIGHT_PASSWORD=...
ASHARE_MARKET_INSIGHT_PYTHON=/absolute/path/to/separate/.venv/bin/python

桥接部署细节见 docs/insight.md

然后在 .env 中配置:

ASHARE_MARKET_TUSHARE_TOKEN=...
ASHARE_MARKET_IFIND_USERNAME=...
ASHARE_MARKET_IFIND_PASSWORD=...

不要把真实 token、用户名或密码提交到仓库。

3. 启动 MinIO

docker compose -f deploy/docker-compose.minio.yml up -d
ashare-market ensure-buckets

默认地址:

  • S3 API:http://127.0.0.1:9000
  • Console:http://127.0.0.1:9001

ensure-buckets 会创建并启用版本控制:

  • ashare-curated
  • ashare-raw
  • ashare-realtime
  • ashare-artifacts
  • ashare-catalog

一键启动完整服务

配置好 .env 后,一条命令启动 MinIO、REST API、Streamable HTTP MCP、历史同步和实时监督器:

./deploy/start.sh

停止服务:

./deploy/stop.sh

不使用 Docker 时可先启动 MinIO,然后直接运行:

ashare-market serve --host 0.0.0.0 --port 8020

启动完成后,REST 地址为 http://<服务器>:8020,MCP 地址为 http://<服务器>:8020/mcp。MCP 作为 ASGI 子应用挂载到 REST 服务,共用同一个 MarketDataService、 MinIO client、查询缓存、Provider 限流器和运行时监督器。

默认自动同步 stock_basic,trade_cal,daily,daily_basic,adj_factor,stk_limit。启动监督器先刷新各表最近的增量数据,再让所有非引用且具有历史起点的已配置数据集从默认起点断点补齐到当前目标日;不传同步日期就是全量同步。查询和回测导出不会改变同步范围,只按照各自请求的 start_date/end_date/lookback_bars 读取本地数据。之后服务会在配置的数据就绪时间后持续刷新。实时订阅只有在 ASHARE_MARKET_RUNTIME_REALTIME_SYMBOLS 明确配置股票列表时才启用。运行状态可通过 GET /v1/runtime 查看;同步任务的实时 chunk/batch 进度通过 GET /v1/sync/status 查看;容器同步日志可通过 docker compose --project-directory . -f deploy/docker-compose.yml logs -f ashare-market 跟踪。

trade_cal 每次默认同步当前自然年的 01-01..12-31,包含尚未到来的交易日安排。A 股历史数据的有效全量起点统一为 1990-12-19。运行状态中的顶层 start_date/end_date 表示当前完整同步范围;最近 5 天的刷新范围仅保留在 recent_refresh 子字段中。全量 coverage 未闭合时状态为 partial/failed,不会再用 rows=0 冒充同步完成。

4. Python SDK

本地模式

本地模式在当前 Python 进程中直接调用 Tushare、iFinD 和 MinIO。

from ashare_market import AshareMarketClient

with AshareMarketClient() as client:
    bars = client.history.daily(
        ["000001.SZ", "600000.SH"],
        "2025-01-01",
        "2025-03-31",
        adjustment="qfq",
        cache_policy="cache_first",
    )
    print(bars.dataframe)
    print(bars.meta)

    # 标准化前的 Tushare pro_bar 原始字段。
    raw_bars = client.history.raw_daily(
        "000001.SZ",
        "2025-01-01",
        "2025-01-31",
    )

    quotes = client.realtime.quotes(["000001.SZ", "600000.SH"])
    print(quotes.dataframe)

    artifact = client.history.export_daily(
        "000001.SZ",
        "2020-01-01",
        "2025-01-01",
        file_format="parquet",
    )
    print(artifact["download_url"])
    client.download_artifact(artifact, "daily.parquet")

    minute = client.history.minutes(
        "000001.SZ",
        "2026-07-16 09:30:00+08:00",
        "2026-07-16 15:00:00+08:00",
        frequency="5min",
        adjustment="qfq",
    )

    ticks = client.history.ticks(
        "000001.SZ",
        "2026-07-16 09:30:00+08:00",
        "2026-07-16 10:00:00+08:00",
    )

    indicators = client.research.query(
        "fina_indicator",
        symbols="000001.SZ",
        start_date="2024-01-01",
        end_date="2026-07-17",
    )

    # reference 数据集不需要日期,使用 TTL 缓存。
    stocks = client.research.query("stock_basic")

远程模式

from ashare_market import AshareMarketClient

with AshareMarketClient(
    base_url="http://127.0.0.1:8020",
    api_key="your-api-key",
) as client:
    bars = client.history.daily("000001.SZ", "2025-01-01", "2025-01-31")
    index_bars = client.research.query(
        "index_daily",
        symbols="000300.SH",
        start_date="2025-01-01",
        end_date="2025-01-31",
    )

    # 一次生成回测窗口需要的三张完整 Parquet;不再把全市场拆成上千次 JSON 请求。
    bundle = client.backtests.export(
        ["000001.SZ", "600000.SH"],
        "2026-07-01",
        "2026-07-17",
        lookback_bars=120,
    )
    for dataset, artifact in bundle["datasets"].items():
        client.download_artifact(artifact, f"{dataset}.parquet")

远程 history.daily() 会估算查询规模;超过阈值时,SDK 自动提交异步回测 bundle、轮询短状态请求并下载 daily Parquet。bundle 根据请求参数解析 lookback 窗口,只从本地缓存读取该范围;如果 coverage 尚未完成,任务会明确失败并提示等待全量同步,不会在查询过程中隐式启动另一种同步范围。同期生成的 daily_basic/stk_limit artifact 会保留在当前 client 中,后续相同窗口的 research 查询直接下载, 现有策略适配器不需要把 5200 只股票拆成小批,也不需要修改返回类型。

SDK 主服务应该在哪里运行

生产环境推荐在一台常驻 Linux 数据服务器上运行单实例 REST 服务和 MCP 服务。Tushare、iFinD、 Insight 与 MinIO 凭证只放在服务器;研究终端、策略程序和 Agent 只安装 Python 包并使用上面的 base_url 远程模式。这样缓存、额度控制、Insight 会话和审计口径只有一份。

  • REST 主服务使用单 Uvicorn worker;当前 Insight session 状态在进程内,多 worker 会产生多个互不共享的会话。
  • MCP stdio 可运行在 Agent 所在机器并通过远程 Python SDK/REST 访问主服务;受信任环境也可直接在数据服务器运行 MCP。
  • MinIO 开发时可以同机,生产建议独立磁盘或独立节点,并备份 catalog bucket。
  • 只有单机研究或开发场景才建议本地模式;它会让每个客户端分别持有 Provider 登录和频次。

systemd 示例见 deploy/ashare-market.service.example,完整运维说明见 docs/operations.md

缓存策略

策略 行为
cache_only 只读 MinIO,不调用 Provider;允许返回部分覆盖
cache_first coverage commit 完整时读 MinIO,否则从 Tushare 刷新并写 MinIO
refresh 强制从 Tushare 获取,并发布新的不可变对象和 commit
direct 直接从 Tushare 获取,不读写 MinIO

5. REST / OpenAPI

ashare-market api --host 127.0.0.1 --port 8020
  • OpenAPI:https://ashare-data.thoughtyard.com.cn/docs
  • GET /health:只显示配置能力,不登录 Provider;
  • GET /ready:连接 MinIO 并确保 bucket 存在;
  • GET /v1/datasets
  • GET /v1/datasets/{name}/schema
  • GET /v1/compatibility/ashare-history-system
  • GET /v1/runtime:同步、紧凑化和实时状态;
  • GET /v1/artifacts/{object_name}:经 REST 同源鉴权下载真实对象;
  • POST /v1/history/daily
  • POST /v1/history/daily-raw
  • POST /v1/history/daily/export:提交异步 daily Parquet 导出任务,立即返回 job id;
  • POST /v1/backtests/export:提交异步 daily/daily_basic/stk_limit 完整 Parquet bundle;
  • GET /v1/exports/jobs/{job_id}:查询任务进度并在完成后取得 artifact;
  • POST /v1/realtime/quotes
  • POST /v1/coverage/daily
  • POST /v1/coverage/daily-raw
  • POST /v1/history/intraday
  • POST /v1/coverage/intraday
  • POST /v1/realtime/sessions
  • GET /v1/realtime/sessions/{id}/events
  • GET /v1/realtime/sessions/{id}/stream
  • POST /v1/realtime/compact
  • GET /v1/research/datasets
  • POST /v1/research/query
  • POST /v1/research/coverage
  • POST /v1/research/sync
  • POST /v1/datasets/sync(通用别名)。

日线示例:

curl -X POST https://ashare-data.thoughtyard.com.cn/v1/history/daily \
  -H 'Content-Type: application/json' \
  -H 'X-API-Key: your-api-key' \
  -d '{
    "symbols":["000001.SZ"],
    "start_date":"2025-01-01",
    "end_date":"2025-01-31",
    "adjustment":"qfq",
    "cache_policy":"cache_first"
  }'

当结果超过 ASHARE_MARKET_API_MAX_ROWS,接口会创建完整 Parquet artifact。Python 客户端看到 truncated=true 后会自动通过带 X-API-Key 的同源代理下载完整 Parquet,不再静默返回前 2,000 行。 ASHARE_MARKET_PUBLIC_BASE_URL 配置后,meta.artifact.download_url 是外部可达的 REST URL;未配置时返回 /v1/artifacts/... 相对路径,不再暴露容器内的 minio:9000

为什么数据目录里只有 xl.meta

deploy/data 是 MinIO 的私有 XL 后端目录,不是普通文件导出目录。一个逻辑上的 .parquet S3 对象在磁盘上会表现为 同名目录和 xl.meta,小对象还可能直接内联在元数据中;因此不能对该目录直接运行 parquet-tools。应从 MinIO Console、 S3/mc 或上述 REST artifact 接口下载对象后再检查,例如:

parquet-tools inspect daily.parquet

新写 EOD 数据按“请求批次 + 交易日”合并成 symbol_bucket=all;后台还会从最近月份向历史月份逐月生成活跃紧凑快照。 旧 hash 小对象暂不物理删除,读取会在紧凑快照更新后自动跳过它们,便于回滚和后续按生命周期安全清理。

6. MCP / Agent

stdio 模式:

ashare-market mcp --transport stdio

Streamable HTTP 随 REST 服务一起启动:

ashare-market serve --host 0.0.0.0 --port 8020

客户端连接 http://<服务器>:8020/mcp。配置 ASHARE_MARKET_API_KEY 后,REST 与 MCP 都要求相同的 X-API-Key;对外暴露时仍应通过反向代理配置 TLS。

可用工具:

  • market_list_datasets
  • market_get_schema
  • market_get_legacy_coverage
  • market_get_realtime_quotes
  • market_get_daily_bars
  • market_get_raw_daily_bars
  • market_get_raw_daily_coverage
  • market_get_daily_coverage
  • market_create_daily_export
  • market_create_backtest_export
  • market_get_export_job
  • market_get_minute_bars
  • market_get_tick_history
  • market_get_intraday_coverage
  • market_create_intraday_export
  • market_start_insight_session
  • market_get_insight_session
  • market_get_insight_events
  • market_stop_insight_session
  • market_compact_realtime
  • market_list_research_datasets
  • market_query_research
  • market_get_research_coverage
  • market_create_research_export
  • market_sync_research_dataset
  • market_sync_dataset

可用 resources:

  • ashare://datasets/catalog
  • ashare://datasets/{dataset}/schema
  • ashare://research/catalog
  • ashare://compatibility/ashare-history-system

通用 stdio MCP 配置示例:

{
  "mcpServers": {
    "ashare-market": {
      "command": "/absolute/path/to/ashare-market-sdk/.venv/bin/ashare-market-mcp",
      "env": {
        "ASHARE_MARKET_MINIO_ENDPOINT": "127.0.0.1:9000"
      }
    }
  }
}

凭证应配置在服务器的 .env 或密钥系统中,不要复制到 Agent prompt 或 MCP tool 参数里。

7. CLI

ashare-market datasets
ashare-market legacy-coverage
ashare-market daily --symbols 000001.SZ --start 2025-01-01 --end 2025-01-31
ashare-market quotes --symbols 000001.SZ,600000.SH
ashare-market coverage --symbols 000001.SZ --start 2025-01-01 --end 2025-01-31
ashare-market daily --symbols 000001.SZ --start 2020-01-01 --end 2025-01-01 --export parquet
ashare-market intraday --symbols 000001.SZ \
  --start '2026-07-16 09:30:00+08:00' --end '2026-07-16 15:00:00+08:00' \
  --kind 5min --adjustment qfq

# 实时 session 由常驻 API 服务持有;CLI 通过 REST 操作它。
ashare-market --base-url http://127.0.0.1:8020 stream-start \
  --symbols 000001.SZ,600000.SH --tick --kline
ashare-market --base-url http://127.0.0.1:8020 stream-sessions
ashare-market --base-url http://127.0.0.1:8020 stream-events SESSION_ID --after 0
ashare-market --base-url http://127.0.0.1:8020 stream-stop SESSION_ID

ashare-market compact-realtime --dataset tick --trade-date 2026-07-17

ashare-market research-list
ashare-market research fina_indicator --symbols 000001.SZ \
  --start 2024-01-01 --end 2026-07-17

# 默认按 coverage 断点续跑;不传日期时使用数据集默认全量起点。
ashare-market research-sync daily_basic
ashare-market research-sync income --start 2010-01-01 --end 2026-07-17
# `sync` 是面向全部注册数据集的等价短命令。
ashare-market sync daily
ashare-market sync weekly
ashare-market sync etf_daily --symbols 510300.SH,159915.SZ
ashare-market sync index_daily --symbols 000300.SH
ashare-market sync kline_5min --symbols 000001.SZ --start 2026-01-01 --end 2026-07-17

8. 当前边界

  • 股票、ETF、指数和概念/行业代码型行情要求明确代码列表;全市场日频与事件表支持按日期分块同步。
  • MinIO catalog 采用不可变 JSON commit,并有 TTL 索引缓存和有界并发读取;更大规模部署仍可引入数据库或 Iceberg catalog。
  • iFinD 实时快照为请求式 THS_RQ;推送式 tick/1min 由 Insight 提供。
  • 当前实时 manager 状态保存在 API 进程内,API 重启后需重新创建 session;已归档数据不受影响。
  • EOD 旧小对象由后台按月紧凑,无需从 Provider 重抓;物理清理旧版本仍由运维生命周期策略控制。
  • 已覆盖旧系统全部 41+8 数据;基金范围目前仅包含旧系统已有的场内 ETF 日线,不扩展债券、期货、宏观和海外市场。
  • MinIO 内数据的共享范围必须符合 Tushare、iFinD 和 Insight 的账户授权与再分发条款。

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

n_ashare_market-0.5.2.tar.gz (107.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

n_ashare_market-0.5.2-py3-none-any.whl (91.9 kB view details)

Uploaded Python 3

File details

Details for the file n_ashare_market-0.5.2.tar.gz.

File metadata

  • Download URL: n_ashare_market-0.5.2.tar.gz
  • Upload date:
  • Size: 107.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for n_ashare_market-0.5.2.tar.gz
Algorithm Hash digest
SHA256 ee09f75c562736136544174f646e13cc9dfe8b26e5731c285c53880edf20c944
MD5 30e8dfc6c325a497d1d46abe65b20835
BLAKE2b-256 b536ac90d238dc65a79e52cbc5023095f94e733160b91b9f406ab133789bf86b

See more details on using hashes here.

File details

Details for the file n_ashare_market-0.5.2-py3-none-any.whl.

File metadata

File hashes

Hashes for n_ashare_market-0.5.2-py3-none-any.whl
Algorithm Hash digest
SHA256 8f25ee0cd874717d31106fdb21178838fc399f5f3eb2a570b0d3a1434805765b
MD5 674f9a30d64bbb88aac91bc4e803800d
BLAKE2b-256 400ed74209fb945bfc740e6946aa464117f895500da80b0cb29a845889b8826f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page