Metadata-Version: 2.5
Name: atst
Version: 1.4.3
Summary: Provider-first market-data runtime and TDX protocol toolkit with explicit Providers, direct Provider reads, Stateful streaming and canonical HTTP/WebSocket/MCP adapters
Project-URL: Homepage, https://github.com/coeasy/atst
Project-URL: Documentation, https://github.com/coeasy/atst/tree/main/docs
Project-URL: Issues, https://github.com/coeasy/atst/issues
Project-URL: Changelog, https://github.com/coeasy/atst/blob/main/CHANGELOG.md
Project-URL: Releases, https://github.com/coeasy/atst/releases
Author: atst contributors
License: MIT
License-File: LICENSE
Keywords: a-share,kline,market-data,protocol,quotation,realtime,stock,tdx,vipdoc,通达信
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Office/Business :: Financial :: Investment
Classifier: Typing :: Typed
Requires-Python: >=3.10
Provides-Extra: all
Requires-Dist: duckdb>=0.10; extra == 'all'
Requires-Dist: fastapi>=0.110; extra == 'all'
Requires-Dist: httpx>=0.26; extra == 'all'
Requires-Dist: pandas>=2.0; extra == 'all'
Requires-Dist: prometheus-client>=0.19; extra == 'all'
Requires-Dist: pyarrow>=14.0; extra == 'all'
Requires-Dist: tzdata>=2024.1; (sys_platform == 'win32') and extra == 'all'
Requires-Dist: uvicorn>=0.27; extra == 'all'
Requires-Dist: websockets>=13.0; extra == 'all'
Requires-Dist: zstandard>=0.22; extra == 'all'
Provides-Extra: dataframe
Requires-Dist: pandas>=2.0; extra == 'dataframe'
Provides-Extra: dev
Requires-Dist: build==1.6.1; extra == 'dev'
Requires-Dist: hatchling==1.32.4; extra == 'dev'
Requires-Dist: mypy==2.3.1; extra == 'dev'
Requires-Dist: packaging==26.3; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff==0.15.2; extra == 'dev'
Requires-Dist: twine==7.0.0; extra == 'dev'
Provides-Extra: duckdb
Requires-Dist: duckdb>=0.10; extra == 'duckdb'
Provides-Extra: metrics
Requires-Dist: prometheus-client>=0.19; extra == 'metrics'
Provides-Extra: parquet
Requires-Dist: pyarrow>=14.0; extra == 'parquet'
Provides-Extra: server
Requires-Dist: fastapi>=0.110; extra == 'server'
Requires-Dist: uvicorn>=0.27; extra == 'server'
Requires-Dist: websockets>=13.0; extra == 'server'
Provides-Extra: tools
Requires-Dist: tzdata>=2024.1; (sys_platform == 'win32') and extra == 'tools'
Requires-Dist: zstandard>=0.22; extra == 'tools'
Provides-Extra: web
Requires-Dist: httpx>=0.26; extra == 'web'
Description-Content-Type: text/markdown

# atst

> **TongDaXin Standard Data eXchange** — 通达信行情数据通用协议基础设施
>
> 类比 HTTP 世界的 `requests` 库：稳定、标准、可组合，专注协议层，不做应用层业务。

- 当前版本：`1.4.3`（源码候选；尚未打 tag）· 最新已发布 GitHub Release：[`v1.4.2`](https://github.com/coeasy/atst/releases/tag/v1.4.2) 已发布；本包**不在 PyPI**。Trusted Publisher 与 `pypi` 环境已配置，版本 tag 推送后工作流会执行 OIDC 上传。· [v1.0.0 发布说明](docs/releases/v1.0.0.md) · [v1.1.0 发布说明](docs/releases/v1.1.0.md) · [v1.2.0 发布说明](docs/releases/v1.2.0.md) · [v1.2.1 发布说明](docs/releases/v1.2.1.md) · [v1.2.2 发布说明](docs/releases/v1.2.2.md) · [v1.3.0 发布说明](docs/releases/v1.3.0.md) · [v1.4.0 发布说明](docs/releases/v1.4.0.md) · [v1.4.1 发布说明](docs/releases/v1.4.1.md) · [v1.4.2 发布说明](docs/releases/v1.4.2.md) · [v1.4.3 发布说明](docs/releases/v1.4.3.md) · [CHANGELOG](CHANGELOG.md)

---

## 项目简介

### 是什么

atst 是通达信（TDX）行情数据的**通用底层协议基础设施**。它完整覆盖 TDX 的 5 套协议族，提供从原始二进制帧解析到统一查询内核（`Client`）的全链路数据接入能力。

### 解决什么问题

| 痛点 | atst 的解法 |
|---|---|
| TDX 协议封闭、逆向工程门槛高 | 85 命令账本 + 61 精确解析器 + 三级分派 + YAML 协议规范 |
| 单一数据源不可靠 | 14 个 Provider 注册表 + 195 capability 声明；**provider-first**：一次请求绑定一个 Provider，跨源只在显式 `FallbackPolicy` 下发生 |
| 数据来源不可追溯 | 每个结果携带 `Provenance`（provider/channel/capability/命令），溯源不符即抛，杜绝静默换源 |
| 数据请求被隐式缓存污染 | 执行路径**零缓存**：每次请求直达绑定 Provider |
| 同步/异步 API 分裂 | 签名镜像双客户端（`TdxClient` / `AsyncTdxClient`）+ 奇偶门禁 |
| 协议命令持续演进 | YAML 规范驱动 + codegen 自动生成 + golden_audit 三旗标防漂移 |
| 主站可用性差 | 主站池治理 + 三级路由降级 + 后台测速排序 + 社区候选注入 |

### 谁在用

量化交易开发者、金融数据工程师、行情中间件开发者、AI Agent（量化策略 / 选股 / 回测 / 因子计算）。

### 不是

回测引擎、选股系统、交易终端、Web 可视化平台 —— 专注协议层与数据接入层，向上可组合到任意应用。

---

## 为什么选择 atst

- **协议全覆盖**：5 套 TDX 协议族、85 命令、61 精确解析器，YAML 规范驱动 + codegen 自动生成，未知命令可探测、可自采集、可验证闭环。
- **数据可追溯、不静默换源**：每个结果携带 `Provenance`（provider/channel/capability/命令），provider-first 不变量保证一次请求绑定一个 Provider，跨源只在显式 `FallbackPolicy` 下发生。
- **零缓存、单一执行内核**：请求直达绑定 Provider，无聚合降级路由、无隐式缓存层——结果永远最新、来源永远可解释。
- **同步/异步 + 四套服务面**：签名镜像双客户端，CLI / HTTP REST / WebSocket / MCP 全部只翻译为同一 `Client` 调用，AI Agent 可直接接入。
- **零硬依赖**：所有第三方库均为可选 extra，核心可在纯净环境运行。
- **洁净室原创**：规格驱动 + License 隔离 + AST 相似度审计，原创合规。

> 类比 HTTP 世界的 `requests`：稳定、标准、可组合，专注协议层，不做应用层业务。

---

## 架构总览

```
┌─────────────────────────────────────────────────────────────────────┐
│                      服务面（可选部署，只翻译不执行）                   │
│  CLI 32 子命令 · HTTP REST 12 端点 · WebSocket JSON-RPC · MCP 9 工具   │
├─────────────────────────────────────────────────────────────────────┤
│                  Client / AsyncClient（唯一业务入口）                  │
│  17 便捷方法（bars/quotes/snapshot/minute/trades/stream/call…）        │
│  execute(QuerySpec) · typed(CapabilityQuery) · execute_with_policy    │
├─────────────────────────────────────────────────────────────────────┤
│              UnifiedRuntime（唯一执行内核，零缓存）                     │
│  QueryPlanner.compile → QueryPlan（单 Provider / 单 Channel）          │
│  DirectProviderExecutor：DIRECT_BINDINGS 281 条精确绑定                │
│  流式：StreamSpec/StreamPlanner → StatefulQuoteStream                 │
├─────────────────────────────────────────────────────────────────────┤
│              catalog/（静态声明与一致性审计，无执行）                   │
│  capability 目录 + 规划期签名校验（fail-closed）                        │
│  Provider channel→adapter 绑定表 · Provider 隔离契约/守卫/审计          │
├─────────────────────────────────────────────────────────────────────┤
│              providers/（14 Provider · 195 capability 唯一事实源）      │
│  tdx(85 命令) · tencent/sina/eastmoney/baidu/jsl/boc/iwencai(web 多源)│
│  local_vipdoc(reader 本地二进制) · builtin · derived(显式聚合)          │
├─────────────────────────────────────────────────────────────────────┤
│                      协议核心层                                        │
│  commands(85 账本) · registry(三级分派 + 异常收口) · parsers(61 × 5 族) │
│  codec(帧/原语) · transport(池/心跳/测速) · client/(TdxClient 同步异步)  │
├─────────────────────────────────────────────────────────────────────┤
│                      基础设施层                                        │
│  错误体系(E1-E9 九域) · 可观测性(Prometheus/StatsD/OTLP)               │
│  配置(6 源合并) · 安全(TLS/脱敏) · 输出(DataFrame/Parquet/CSV/DuckDB)   │
│  反馈(遥测/统计) · 工具链(capture/codegen/golden_audit/spec_audit)      │
└─────────────────────────────────────────────────────────────────────┘
```

**设计原则**：每层可独立使用，零强制上层依赖。底层协议库可用，上层内核可选。
**唯一执行路径**：请求只能沿 `Client → UnifiedRuntime → DirectProviderExecutor → Provider`
下行；不存在第二条内核、聚合降级路由或隐式缓存层（由 `tests/architecture/` 守卫锁定）。

---

## 核心特性

### 协议层

| 特性 | 说明 |
|---|---|
| **5 套协议族** | 7709 标准 / 7727 扩展市场 / MAC 专属 / F10 资料 / 商品语义 |
| **85 命令账本 · 61 精确解析器** | L1 精确 → L2 通用启发 → L3 原始透传 三级分派；解析器逃逸原生异常统一收口为 `ParseError` |
| **YAML 协议规范** | `PROTOCOL_SPEC/` 规范驱动 + `codegen` 自动生成 + `spec_audit` 双向漂移检查 |
| **协议探测** | `atst probe 0x052D` 探测未知命令的二进制帧结构 |

### 客户端层

| 特性 | 说明 |
|---|---|
| **同步/异步双 API** | `TdxClient` + `AsyncTdxClient`（签名镜像、奇偶门禁） |
| **多协议族客户端** | GoodsClient / ExMarketClient / MacClient / F10Client |
| **主站池治理** | `DEFAULT_HOST_POOL` / `POOL_BY_FAMILY` / `RankingStore` + 三级路由降级 + 社区候选注入 |

### 数据源层

| 特性 | 说明 |
|---|---|
| **HTTP Web 45+ 源类** | 东财/新浪/腾讯/集思录/港股/中行等，`httpx` / `urllib` 双栈，31 模块；各家适配器按 Provider 归入 `web/<provider>/adapters.py`，跨 Provider 的域模块（资金流/龙虎榜/新闻/问财…）留 `web/` 包根 |
| **本地 vipdoc 解析** | `reader/` 解析通达信本地 `.day` / `.min` / 板块 / 财务二进制文件 |
| **Provider 注册表** | `providers/` 声明 14 Provider × 195 capability × channel，是唯一事实源；`catalog/provider_bindings.py` 声明 channel→adapter 绑定 |
| **流式订阅** | `Client.stream` → `StatefulQuoteStream`（轮询基类 QuoteStream/AsyncQuoteStream；engine 内核：ReconnectPolicy + BackpressureQueue + DeltaMerger + GapFiller + StreamEngine） |

### 输出与服务层

| 特性 | 说明 |
|---|---|
| **数据出口（`atst/output/`）** | `write()` 认 4 种格式：DataFrame / Parquet / CSV / DuckDB；`Sink` 3 种格式（不含 CSV，CSV 只走 `write()` 或 `to_csv()`），全部原子写；读回面对称补齐——`from_parquet()` 读落盘日线、`from_csv()` 读回人工加工过的 CSV（全 `str`，不隐式推断类型）|
| **统一业务入口** | `Client` / `AsyncClient`（17 便捷方法 + `execute`/`typed`/`call` 通用面），永不隐式换源、永不缓存 |
| **HTTP REST 网关** | 12 端点（capability 白名单 + TaskStore 钳制），只翻译为 `Client` 调用；另有 2 支**只读本地代码表**的清单端点（不发外呼）|
| **WebSocket JSON-RPC** | 长连接实时推送 |
| **MCP 工具服务** | 9 工具，AI Agent 可直接调用 |

### 单一执行内核（`atst/runtime/`）

| 特性 | 说明 |
|---|---|
| **唯一内核** | `UnifiedRuntime`：`QuerySpec → QueryPlan → 绑定执行 → QueryResult`，零缓存、无请求合并 |
| **精确绑定执行** | `DirectProviderExecutor` 按 `DIRECT_BINDINGS[(provider, channel, capability)]`（281 条）直调实现 |
| **规划期 fail-closed** | `catalog/capability.py::validate_call` 用**真实方法签名**绑定参数，参数错误在 I/O 前抛 |
| **执行身份与溯源** | `runtime/identity.py` + `runtime/provenance.py`：结果 provenance 与计划身份不符即抛 |
| **显式跨源编排** | `runtime/orchestration.py`：仅当调用方给出 `FallbackPolicy` 时按序尝试，逐次记入 `OrchestratedResult` |
| **启动三方对账** | `runtime/audit.py::audit_runtime`：registry / catalog / bindings 不一致即报错 |
| **60+ Typed Query 契约** | 10 领域基类 + 9 Domain Record 族，字段名与内核方法签名一一对应（`Client.typed`） |
| **批量执行** | `Client.quotes_batch()` → `BatchResult`：逐 symbol 三态（ok/missing/failed）、保序、串行直连单一 Provider（无隐藏换源） |
| **流式生命周期** | `StreamSpec`/`StreamPlanner` + `StatefulQuoteStream`（订阅/退订/状态查询） |

### 基础设施

| 特性 | 说明 |
|---|---|
| **零硬依赖** | 所有第三方库均为可选 extra |
| **错误分类树** | 九域 code 段（E1–E9）+ 每个异常自带 `RetryAdvice`；类清单以 `atst.errors` 现读为准，文档不抄录会过期的数字（`docs/errors.md`） |
| **可观测性** | zero-dep 指标注册表 + Prometheus/StatsD/OTLP 三导出器 |
| **传输与错误卫生** | TDX 连接可按 `security.use_tls` 走 TLS（默认关，`ssl.create_default_context()` 校验主机名）；错误上下文按关键字脱敏后才可外发。凭据存储**不在本库范围内**（ADR-007-010 已删除三级 CredentialStore）；HTTP 传输层同样**不做** Provider 主机白名单——该守卫从未接入任何生产链路，已在单内核收敛时移除，单源边界由调用方自证，内核侧的跨源约束只有一条：选定的 Provider 不会被悄悄换成别家 |
| **原创合规** | 洁净室工程规范：规格驱动 + License 隔离 + AST 相似度审计 + Golden 数据自采集 |

---

## 协议覆盖矩阵

| 协议族 | 端口 | 覆盖范围 | 命令账本 | 精确解析器 | 通用/透传 |
|---|---|---|---|---|---|
| **7709 标准**（`quotation`） | 7709 | A 股行情（K 线/实时/证券计数；分时与逐笔在结构化面已下线，见 [`docs/providers/tdx.md`](docs/providers/tdx.md)） | 39 | 18 | 是 |
| **7727 扩展市场**（`ex_quotation`） | 7727 | 港股/美股/期货/外汇/期权 | 17 | 15 | 是 |
| **MAC 专属**（`mac_quotation`） | 7709 | 板块/指数/概念/财务 | 16 | 16 | 是 |
| **F10 资料**（`f10`） | 7709 | 公司概况/股东/财务/交易信息 | 2 | 1 | 是 |
| **商品语义**（`goods`） | 7727 | 商品品种/合约/行情 | 11 | 11 | 是 |

> 未知命令自动归档至 `PROTOCOL_SPEC/UNKNOWN/`，工具链支持 `capture` 采集 → `codegen` 生成 → `spec_audit` 验证闭环。

---

## 功能对比

| 能力 | atst | mootdx | easy_tdx | easyquotation |
|---|---|---|---|---|
| TDX 协议覆盖 | 85 命令 / 61 精确解析器 / 5 协议族 | ~20 命令 | ~15 命令 | ❌（HTTP only） |
| 三级分派 | L1 精确 → L2 启发 → L3 透传 | 仅 L1 | 仅 L1 | ❌ |
| 同步 + 异步 | ✅ 双客户端 | ❌（仅同步） | ❌（仅同步） | ❌ |
| HTTP Web 多源 | 45+ 源 / 14 Provider 注册表 | ❌ | ❌ | ✅（单一源） |
| 本地 vipdoc 解析 | ✅ 多格式 | ❌ | ❌ | ❌ |
| 流式订阅 | ✅ engine 内核 | ❌ | ❌ | ❌ |
| 主站池治理 | ✅ 多主站 + 测速 + 社区注入 | 基础 | 基础 | ❌ |
| 统一业务入口 | ✅ `Client` 17 方法 + 通用 `execute`/`typed` | ❌ | ❌ | ✅（仅行情） |
| HTTP/WS/MCP 服务 | ✅ 三模式 | ❌ | ❌ | ❌ |
| 溯源与 provider-first | ✅ Provenance 强制 + 显式 FallbackPolicy | ❌ | ❌ | ❌ |
| 可观测性 | ✅ Prometheus/StatsD/OTLP | ❌ | ❌ | ❌ |
| YAML 协议规范 | ✅ + codegen + spec_audit | ❌ | ❌ | ❌ |
| 零硬依赖 | ✅ 所有 extra 可选 | 有硬依赖 | 有硬依赖 | 有硬依赖 |

---

## 安装

```bash
pip install "atst[all]"             # ← 尚不可用：本包目前不在 PyPI 上（见下）
pip install -e ".[dev]"              # 开发体验（pytest/ruff/mypy/pytest-asyncio/hatchling）
```

> **装包的实际口径**（实测）：`https://pypi.org/pypi/atst/json` 返回
> `{"message": "Not Found"}`——PyPI 上没有 `atst` 这个名字，所以 `pip install atst`
> 与上面第一行的 extras 安装今天都装不到东西。可用的安装路径只有两条：
>
> ```bash
> git clone https://github.com/coeasy/atst.git && cd atst
> pip install ".[all]"                       # 从源码
> pip install "atst[all] @ file:///绝对路径/atst-<版本>-py3-none-any.whl"   # 从构建产物
> python -m build                            # 产物在 dist/；make build 走同一套 canonical 校验
> ```
>
> extras 的名字（`dataframe` / `parquet` / `duckdb` / `web` / `metrics` /
> `server` / `tools` / `all`）是仓内 `pyproject.toml` 声明的那一套，从源码或
> wheel 装时同样可用；本节只在真正上架 PyPI 后才需要改写。

> `[project.optional-dependencies].dev` 已声明，本地与 CI 使用同一
> 门禁口径（覆盖率阈值只在 `pyproject.toml [tool.coverage.report] fail_under` 写一次，
> Makefile/CI 不再各传 `--cov-fail-under`），不再有「装了依赖却跑不出 `--cov`」的漂移。

### Optional Extras

| Extra       | 依赖                        | 功能               |
|-------------|---------------------------|--------------------|
| `dataframe` | pandas                    | DataFrame 输出     |
| `parquet`   | pyarrow                   | Parquet 写出（`to_parquet` / `Sink("parquet")`） |
| `duckdb`    | duckdb                    | DuckDB 写出（`to_duckdb` / `Sink("duckdb")`） |
| `web`       | httpx                     | HTTP Web 行情源    |
| `metrics`   | prometheus-client         | Prometheus 导出    |
| `server`    | fastapi, uvicorn, websockets | HTTP REST 网关 + WebSocket RPC |
| `tools`     | tzdata (win32 only), zstandard | capture 工具链（时区 + zstd 编码） |
| `dev`       | pytest/pytest-cov/pytest-asyncio/ruff/mypy/hatchling | 开发体验 |
| `all`       | 以上非 dev 项的并集        | 完整功能           |

> **MCP 工具服务不需要 extra**：`atst/integration/mcp/` 是纯标准库的
> JSON-RPC over stdio，全仓对 `pydantic` / `mcp` 两个包没有运行期依赖。

---

## 发布流程（GitHub Release 后自动构建安装包）

本仓的发布由 `.github/workflows/wheels.yml` 自动化：**推送一个 `vX.Y.Z` 标签即触发**，CI 会
构建 canonical wheel + sdist、校验字节级可复现性、生成 `SHA256SUMS.txt` 与
`RELEASE-METADATA.json`，创建**草稿** GitHub Release 并附带产物，最后在草稿通过后自动发布。
这就是"GitHub 发布之后自动构建安装包"的入口——你只需要在 GitHub 上发布一个 `vX.Y.Z` 标签，
其余由流水线完成。

> 流水线刻意以**标签推送**为唯一发布触发器（CI 契约 `test_release_identity_uses_tag_push...`
> 强制），以保证版本身份永远来自标签 + `atst/_version.py` 单一事实源，避免重复构建与
> 版本漂移。`release:` 事件触发器被同一契约排除，因此不要改成 `on: release`。

### 切一个发布

1. 改版本号：编辑 `atst/_version.py` 的 `__version__`（单一事实源；`pyproject.toml` 通过
   `[tool.hatch.version]` 动态读取，不要写死静态 `version=`）。
2. 补版本文档：在 `CHANGELOG.md` 加 `## [X.Y.Z] - YYYY-MM-DD` 小节，并在 `docs/releases/`
   目录下新增以版本号命名的发布说明（已有范例见 `docs/releases/v1.0.0.md`）。**这两处是硬门禁**：
   `build-dist` 的身份步会断言 `docs/releases/v<version>.md` 存在、且 `CHANGELOG.md` 含
   `## [<version>]` 标题，缺一即以 `SystemExit` 让流水线直接变红。
3. 提交并打标签：
   ```bash
   git add -A && git commit -m "release: vX.Y.Z"
   git tag vX.Y.Z && git push origin vX.Y.Z
   ```
4. 流水线自动：构建 → 复现性校验 → 草稿 Release + 产物 → 发布。
   - PyPI 发布是**显式 opt-in**：仅当仓库变量 `PUBLIC_RELEASE=true` 时，
     `publish-pypi` 才用 OIDC trusted publishing 上传（重复版本会被
     `scripts/check_pypi_release.py` 校验并安全跳过）。默认不发布到 PyPI。首次启用前，
     还需在 PyPI 创建 pending Trusted Publisher；准确字段与 GitHub 环境配置见
     [`docs/release-publishing.md`](docs/release-publishing.md)。
   - Docker 镜像同理，需 `PUBLIC_RELEASE=true` 且 `PUBLISH_DOCKER=true`。

### 运行前提：Actions 必须真的能把 job 跑起来

流水线依赖 GitHub Actions 实际调度 runner。**私有仓库**的 Actions 消耗账号付费分钟——当免费
额度用尽、没有有效付款方式、或 spending limit 不足时，job **根本不会启动**：每个 job 会在几秒内
`failure`，步骤数为 0、runner 名为空，页面提示
`The job was not started because recent account payments have failed or your spending limit needs to be increased.`。
这**与仓库代码无关**（本地 `make gates` 全绿也照样如此）。

处理方式（任一）：把仓库设为 **public**（公开仓库的 Actions 分钟免费）；或到
`Settings → Billing and plans` 补付款方式并提高 Actions spending limit；额度重置后重推 `vX.Y.Z`
标签即可重新触发。runner 镜像迁移预告（`ubuntu-latest will migrate to Ubuntu 26 ...`）只是提示，不是失败原因。

### 本地构建与冒烟（不发布）

```bash
python scripts/build_package.py --smoke               # PEP 517 隔离构建 + 校验 + 临时 venv 冒烟安装
python scripts/build_package.py --verify-only --dist-out dist   # 只校验已有产物
```

校验要求恰好 **1 个 wheel + 1 个 sdist**，二者携带完整运行时源码闭包与 `py.typed`，
并通过 `twine check`。

---

## 兼容性

| 维度 | 支持范围 |
|---|---|
| **Python** | 3.10+（使用了 `X \| Y` 类型语法与 `zoneinfo`） |
| **操作系统** | Windows 10/11 · macOS 12+ · Linux（主流发行版） |
| **CI 矩阵** | Ubuntu 3.10/3.11/3.12/3.13/3.14 + Windows 3.11/3.12 |
| **网络** | TCP 7709/7727（TDX 主站）+ HTTPS（Web 源） |
| **存储** | 文件系统（`~/.atst/` 配置/主站排名/反馈）+ Parquet/DuckDB |

---

## 快速开始

### 协议层直连（`TdxClient`，可脱离内核使用）

```python
from atst.client import TdxClient

client = TdxClient()

bars = client.bars("sh600519", period="day", count=80)  # K 线
quotes = client.quotes(["sh600519", "sz000001"])  # 实时行情
count = client.security_count(market=1)  # 1=上海, 0=深圳
```

### 协议层异步（`AsyncTdxClient`）

```python
import asyncio
from atst.client import AsyncTdxClient


async def main():
    client = AsyncTdxClient()
    bars, quotes = await asyncio.gather(
        client.bars("sh600519", period="day", count=80),
        client.quotes(["sh600519", "sz000001"]),
    )
    print(len(bars), len(quotes))


asyncio.run(main())
```

### 统一查询内核（`Client`，195 项 capability）

```python
from atst import Client, FallbackPolicy, QuerySpec
from atst.typed_query import FundHoldingsQuery

client = Client()

# 1) 便捷方法：每个结果自带 provenance，零缓存、不静默换源
bars = client.bars("sh600519", period="day", count=80)
print(len(bars.data), bars.meta.provider, bars.meta.channel)

quotes = client.quotes(["sh600519", "sz000001"])

# 2) 通用面：任何 capability 走同一入口，参数在规划期按真实签名校验
spec = QuerySpec.build("bars", symbols="sh600519", period="day", count=30)
result = client.execute(spec)

# 3) 类型化糖衣：冻结 dataclass 契约 → 内核 → 强类型 Domain Record
typed = client.typed(FundHoldingsQuery(code="000001"))
print(typed.capability, len(typed.data))

# 4) 批量：逐 symbol 三态（ok/missing/failed），保序
batch = client.quotes_batch(["sh600519", "sz000001"])

# 5) 跨源只在显式策略下发生（默认永不发生）
orchestrated = client.quotes(["sh600519"], policy=FallbackPolicy(providers=("tdx", "tencent")))

client.close()
```

### 内核异步（`AsyncClient`，同一入口）

```python
import asyncio
from atst import AsyncClient


async def main():
    async with AsyncClient() as client:
        bars, quotes = await asyncio.gather(
            client.bars("sh600519", period="day", count=80),
            client.quotes(["sh600519", "sz000001"]),
        )
        print(len(bars.data), len(quotes.data))


asyncio.run(main())
```

> `TdxClient` / `AsyncTdxClient`（`atst.client`）是协议层客户端，可脱离内核单独使用；
> 服务面（CLI/HTTP/WS/MCP）全部只翻译为 `Client` 调用，不自行选源、不缓存。

### CLI（32 子命令）

```bash
atst bars sh600519 --period day --count 80     # K 线
atst quotes sh600519 sz000001                  # 实时行情
atst server-test                               # 主站测速
atst serve --bind 0.0.0.0 --port 8000           # HTTP 服务
atst probe 0x052D                              # 协议探测
atst feedback stats                            # 使用统计

# 主站池巡检
atst hosts audit --family quotation            # 仅 7709 标准族
atst hosts audit                               # 全 5 族并发巡检
atst hosts --hosts-file extra_hosts.json audit  # 注入社区贡献主站候选
atst hosts audit --report /tmp/audit.json --markdown /tmp/audit.md
```

---

## 核心代码文件地图

```
atst/
├── client/         # api.py —— Client / AsyncClient 唯一业务入口（17 便捷方法 + execute/typed/call）
│                   # core/sync/async_/factory —— TdxClient 传输层与共享纯协议 SSOT
├── runtime/        # 唯一执行内核：kernel(零缓存)/executor(281 绑定)/orchestration(显式跨源)
│                   #   /audit(启动三方对账)/identity/provenance(溯源守卫)
├── catalog/        # 静态声明与一致性审计：capability(目录+规划期签名校验)/provider_bindings
│                   #   /provider_contract/provider_guard/*_audit —— 无执行、无选源
├── providers/      # 14 Provider × 195 capability × channel 注册表（唯一事实源）
├── query.py        # QuerySpec/QueryPlan/QueryPlanner + 指纹
├── result.py       # QueryResult + ResultMeta + Provenance
├── batch.py        # BatchResult/BatchItem 三态批量契约
├── typed_query.py  # 60+ CapabilityQuery 冻结契约 + TypedQueryResult
├── stream_contract.py  # StreamSpec/StreamPlanner 流式契约
├── errors.py       # 错误分类树（E1-E9 九域）+ RetryAdvice
├── diagnostics.py  # 结果侧数据瑕疵的唯一发射口（WarningCode + 收集器，strict 的判据来源）
├── error_envelope.py
├── protocol/       # commands(85 账本)/registry(三级分派+异常收口)/parsers(61 × 5 族)
├── codec/          # framing(帧)/primitive(原语 + count_guard + zlib strict)
├── transport/      # base(RLock 租约)/async_/pool(4 槽)/ratelimit/speedtest/hosts/sniff
├── client/         # core.py(同步/异步共享纯协议 SSOT) + sync/async_/factory + 5 族客户端
├── web/            # 45+ HTTP 源类（惰性导入）+ 域 Mixin 会话 + 共享分页器
│                   #   tencent/sina/eastmoney/baidu/jsl/boc 六包按 Provider 承载 adapters.py
├── reader/         # vipdoc 本地文件解析（day/min/板块/财务）
├── profile/        # 数据规格探测（帧/文件双探测器 + presets）
├── domain/         # symbol(单一事实源)/models/finance 记录/adjust/calendar
├── streaming/      # QuoteStream/AsyncQuoteStream（轮询+diff）/push + engine 内核
├── output/         # DataFrame/Parquet/CSV/DuckDB 原子写
├── sink/           # LocalDaySink：写回 vipdoc .day 二进制
├── charset/        # 字符集自动探测（GBK/GB18030/Big5/UTF-8）
├── config/         # 6 源合并 + 严格校验 + env 归一
├── integration/    # runtime_http(12 端点)/runtime_ws/runtime_ws_server/mcp(9 工具)/serialization
├── observability/  # 指标注册表 + Prometheus/StatsD/OTLP 导出器 + start_exporter
├── feedback/       # 错误/用量上报 + 遥测 + 使用统计
├── tools/          # capture/spec_audit/codegen/golden_audit/golden_expand/check_originality
├── trade/          # 交易协议模拟器（实验性可选模块：SimTransport 纯内存模拟，不接入内核）
├── __main__.py     # python -m atst 入口（与 atst 控制台脚本等价）
├── universe/      # 标的清单（按类别取全部标的：代码表/新浪节点/tdx 段表三级降级）
└── cli/            # CLI 入口（32 子命令；数据命令全部经 Client，6 个传输/诊断命令除外，见 runtime_commands.py）
```

---

## Provider 选择与跨源策略

**默认永不跨源**（provider-first 不变量）：

```
QuerySpec(capability, provider=None|显式)
   → QueryPlanner：provider 为 None 时按注册表偏好选唯一 Provider；多 channel 冲突则要求显式指定
   → QueryPlan(单 provider, 单 channel) → DirectProviderExecutor → 该 Provider 的实现
   → QueryResult(meta.provenance 记录实际来源；与计划身份不符 → 抛错)
```

- Provider 不可用/失败：只抛出该 Provider 的错误，**不自动换源**（历史上"5 级降级 + 熔断 +
  合成数据"路由已随 v12 门面层物理删除）。
- 需要跨源时由调用方显式声明顺序：`client.quotes(symbols, policy=FallbackPolicy(providers=("tdx","tencent")))`
  → `ProviderOrchestrator` 按序尝试，返回 `OrchestratedResult`（逐步记录成败与最终来源）。
- 时效性：`currentness`（`CurrentnessMode`）声明口径，`deadline_ms` 只是执行预算；
  `options` 袋里只有 `atst.query.EXECUTED_OPTIONS` 列出的键会被执行面读取，其余键——包括
  `atst.query.REJECTED_OPTIONS` 里的策略键（过期容忍、部分放行）——一律当场拒绝：
  每次请求都回源，不存在可容忍的过期副本，partial 也始终是结果事实。

---

## 主站池治理与巡检

主站池由 `DEFAULT_HOST_POOL` / `POOL_BY_FAMILY` 定义，运行时通过 `RankingStore`
（`~/.atst/server_ranking.json`）落盘延迟样本并驱动三级路由降级。巡检工具：

```bash
# 通过 CLI（推荐）
atst hosts audit --family quotation --timeout 3 --workers 20 --samples 3

# 或调用脚本（支持 --report / --markdown / --strict / --no-save-ranking）
python scripts/audit_hosts.py --family all --report audit.json

# 外部候选注入（社区贡献主站入口）
cat > extra_hosts.json <<'JSON'
{
  "quotation": [
    {"host": "218.75.126.9", "port": 7709, "name": "custom-1"}
  ],
  "ex_quotation": [
    {"host": "180.153.180.86", "port": 7727, "name": "custom-2"}
  ]
}
JSON
atst hosts --hosts-file extra_hosts.json audit
```

输出：每族 healthy/degraded/offline 三态 + JSON/Markdown 报告；候选延迟样本写
`~/.atst/server_ranking.json`（可 `--no-save-ranking` 关闭）。CI 中已配置
周三 09:00 UTC 定期巡检（`host-audit` job，非硬门禁）。

---

## 质量与门禁

```bash
pytest tests/                                   # 全量测试（离线，无网络）
make gates                                      # 12 步确定性门禁：lint+format→mypy→全量→bridges→golden→spec→对抗→可达性→originality→benchmark→interface-probe→docs
python -m atst.tools.golden_audit --gate       # Golden L1 真实样本门禁（530 payload）
python -m pytest tests/adversarial -q           # 对抗矩阵（9 payload × 85 命令，逃逸=0）
python scripts/audit_reachability.py --strict   # 可达性门禁（孤儿=0）
python scripts/contract_audit.py --ci           # Typed 契约↔注册表↔Domain Record 五段对账 + 内核编译审计（注册能力缺声明形状即 ERROR 阻断；Domain Record 待映射项按 PENDING 报告）
python -m pytest --cov=atst           # 覆盖率门禁（阈值单源：pyproject fail_under=77）
```

- CI：12 jobs；测试矩阵 Ubuntu 3.10–3.14 加 Windows 3.11/3.12；周一 08:00 UTC 全量确定性门禁，
  周三 09:00 UTC 定期 `host-audit`
- 架构守卫：`tests/architecture/`（唯一内核、零缓存、无聚合降级路由、根级命名空间白名单、
  已删层不可复活）+ `tests/provider_isolation/`（Provider 隔离与溯源）
- Ruff：`ruff check` 与 `ruff format --check` 均 0 错（dev 依赖钉版 `ruff==0.15.2`）
- mypy：`mypy atst/` 0 错（含 `--warn-unused-ignores`）
- Pre-commit hooks：`ruff check --fix` + `ruff format --check`

---

## 路线图

### 当前阶段：v1.4.3 发布候选（未打 tag）

GitHub 最新已发布版本是 `v1.4.2`；源码候选 `v1.4.3` 完成本地构建与回归后尚未打 tag。当前内核为单执行路径、零缓存、provider-first：
85 命令 / 61 精确解析器 / 5 协议族 / 14 Provider / 195 capability / 281 条精确绑定。

| 里程碑 | 状态 |
|---|---|
| 协议层：命令账本 + 解析器 + YAML 规范 + codegen 闭环 | ✅ |
| 单内核收敛：零缓存直调、无隐式跨源 | ✅ |
| Typed Capability 契约 + Domain Record 归一 | ✅ |
| 流式订阅：StreamSpec / StreamPlanner + StatefulQuoteStream | ✅ |
| 服务面：CLI / HTTP REST / WebSocket / MCP | ✅ |
| 文档-代码一致性门禁 | ✅ |

### 后续规划

| 方向 | 说明 |
|---|---|
| 发布硬化 | 按 CI 环境数字重钉覆盖率阈值；PyPI 上架为显式 opt-in（仓库变量 `PUBLIC_RELEASE=true`） |
| 流式增量执行 | 流式数据增量合并 + 补数完整性保证 |
| 协议探测扩展 | 更多未知命令的自动采集 → codegen → spec_audit 闭环 |
| 多市场深化 | 港股/美股/期货/外汇/期权覆盖的字段级实测补齐 |
| 可达性收口 | 孤儿=0，每条豁免记录都被门禁盯着（死记录/过期记录/重复条目即红） |
| 对外面增强 | 扩充 MCP 工具与 HTTP 端点，覆盖高频使用场景 |

---

## 文档导航

| 文档 | 内容 |
|---|---|
| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | **现行架构**（分层/内核/契约/服务面，与代码同轮钉死）|
| [docs/api/interfaces.md](docs/api/interfaces.md) | **项目接口文档**（全部公开接口面汇总）|
| [docs/quickstart.md](docs/quickstart.md) | 快速入门 |
| [docs/api/README.md](docs/api/README.md) | API 索引（内核/协议/传输/服务面/基础设施）|
| [docs/configuration.md](docs/configuration.md) | 配置段、合并层与环境变量归一 |
| [docs/cookbook/](docs/cookbook/README.md) | 场景示例（批量 K 线/显式跨源/离线 vipdoc/流式/Sinks/自定义命令/单内核）|
| [docs/migration/](docs/migration/README.md) | 从 mootdx/easy_tdx/easyquotation 迁移 |
| [docs/providers/](docs/providers/README.md) | 逐 Provider 能力与口径 |
| [docs/tdx_status.md](docs/tdx_status.md) | TDX 全接口连通性矩阵（真机逐项实测口径）|
| [docs/adr/](docs/adr/README.md) | 架构决策记录索引（逐条编号/状态/出处，含 ADR-011 流式内核取舍与两处编号撞号登记）|
| [docs/FAQ.md](docs/FAQ.md) | 常见问题 |
| [docs/troubleshooting.md](docs/troubleshooting.md) | 排障指南 |
| [docs/errors.md](docs/errors.md) | 错误体系与 RetryAdvice 使用指南 |
| [PROTOCOL_SPEC/](PROTOCOL_SPEC/README.md) | 协议命令 YAML 规范 + codegen/spec_audit 闭环 |
| [CHANGELOG.md](CHANGELOG.md) | 版本变更记录（含 native 弃用时间线 v1.5.0/v1.6.0）|
| [docs/releases/v1.0.0.md](docs/releases/v1.0.0.md) | v1.0.0 正式发布说明、兼容性与验证结果 |
| [docs/releases/v1.1.0.md](docs/releases/v1.1.0.md) | v1.1.0 正式发布说明（V6 L3 三源落地 + 执行器分派泛化 + 接口文档对齐） |
| [docs/releases/v1.2.0.md](docs/releases/v1.2.0.md) | v1.2.0 正式发布说明（对标 5 项目补齐 18 项缺口能力 + 能力状态面 + 文档对齐） |
| [docs/releases/v1.2.1.md](docs/releases/v1.2.1.md) | v1.2.1 正式发布说明（本地安装实测收口：10 项缺口能力端点真机验证转 alive + cninfo 源断链修复） |
| [docs/releases/v1.2.2.md](docs/releases/v1.2.2.md) | v1.2.2 正式发布说明（时区依赖机器本地时区的根因修复：时间戳与交易时段统一按市场时区 Asia/Shanghai） |
| [docs/releases/v1.3.0.md](docs/releases/v1.3.0.md) | v1.3.0 正式发布说明（按类别取标的清单：`atst.universe` 三级降级源 + CLI/HTTP 两面 + 同步脚本 `--fetch-list` / `--doctor`） |
| [docs/releases/v1.4.0.md](docs/releases/v1.4.0.md) | v1.4.0 正式发布说明（写读对称收口：`atst.output.from_csv` + 断点唯一事实源收敛到磁盘 + 扁平文件迁移收尾 + `--doctor` 空文件修复指引） |
| [docs/archive/](docs/archive/README.md) | 历史计划、对标审计与设计快照（**都不是现行契约**）|

---

## 贡献

欢迎贡献代码、文档、协议规范、主站候选、测试数据。请阅读：

- [CONTRIBUTING.md](CONTRIBUTING.md)
- [GOVERNANCE.md](GOVERNANCE.md)
- [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)
- [SECURITY.md](SECURITY.md)

---

## 许可证

MIT License - 详见 [LICENSE](LICENSE)
