Metadata-Version: 2.5
Name: mootdx2
Version: 1.5.2
Summary: 通达信数据读取接口.
Project-URL: Homepage, https://www.mootdx.com
Project-URL: Repository, https://github.com/mootdx/mootdx
Author-email: bopo <huzhe19900925@126.com>
License-File: AUTHORS.rst
License-File: LICENSE
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Natural Language :: English
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Requires-Python: >=3.8
Requires-Dist: click>=8.1.3
Requires-Dist: filelock>=3.12.0
Requires-Dist: httpx>=0.25.0
Requires-Dist: mini-racer>=0.12.0
Requires-Dist: prettytable>=3.5.0
Requires-Dist: pyyaml>=6.0.3
Requires-Dist: tenacity>=8.1.0
Requires-Dist: tqdm>=4.66.0
Requires-Dist: typing-extensions>=4.5.0
Description-Content-Type: text/markdown

# mootdx2 对外接口与数据能力全景

`mootdx2` 模块为量化交易和行情数据分析提供对接通达信及权威金融数据源的完整接口体系。其数据能力涵盖：**统一日 K 线智能管理（离线优先+自动增量）**、**在线行情与底层双模驱动**、**本地二进制数据极速解析**、**巨潮资讯公告数据**、**专业历史财务报表解析**、**股票与 ETF 通用复权**、**增量防封数据同步**、**交易日历**、**北交所行情**、**板块管理**与**数据导出**等。

> **核心特性**：
> 1. **全链路复权支持**：所有返回 K 线类数据的接口（`bars`、`k`、`daily`、`index` 等）均原生支持 `adjust='qfq'`（前复权）/ `adjust='hfq'`（后复权）参数，在底层自动完成复权后直接返回。复权模块采用统一通用流水线，同时支持股票与各类 ETF（包含 588xxx 科创板、56xxxx 等）的除权除息（现金分红、送转股、配股）及扩缩股（份额折算）。
> 2. **离线优先与高可用**：提供 `DailyDataManager`，优先秒级读取本地通达信目录；本地缺失或过期时自动触发增量拉取并持久化至长效缓存，兼顾纯离线的高性能与在线数据的时效性。
> 3. **底层驱动双模支持**：支持内置纯净 Python 原生协议驱动（`native`）与经典兼容驱动（`tdxpy`），免除外部魔改依赖污染。
> 4. **模块解耦与精准导入规范**：支持顶层便捷导入（如 `from mootdx2 import DailyDataManager, CninfoClient, holiday`）与生产级精准子模块导入（`from mootdx2.daily import DailyDataManager`、`from mootdx2.cninfo import CninfoClient`、`from mootdx2.utils.holiday import holiday`），实现毫秒级按需冷启动并消除循环依赖风险。

---

## 目录索引

- [一、统一日 K 线管理器 (mootdx2.daily.DailyDataManager) 【推荐】](#一统一日-k-线管理器-mootdx2dailydailydatamanager-推荐)
- [二、在线行情数据接口 (mootdx2.quotes.Quotes)](#二在线行情数据接口-mootdx2quotesquotes)
- [三、本地历史数据读取接口 (mootdx2.reader.Reader)](#三本地历史数据读取接口-mootdx2readerreader)
- [四、通达信底层协议驱动与离线解析 (mootdx2.tdx)](#四通达信底层协议驱动与离线解析-mootdx2tdx)
- [五、巨潮资讯独立公告数据源 (mootdx2.cninfo.CninfoClient)](#五巨潮资讯独立公告数据源-mootdx2cninfocninfoclient)
- [六、专业财务数据报表解析 (mootdx2.financial / mootdx2.affair)](#六专业财务数据报表解析-mootdx2financial--mootdx2affair)
- [七、增量防封数据同步工具 (mootdx2.sync)](#七增量防封数据同步工具-mootdx2sync)
- [八、复权计算与因子能力](#八复权计算与因子能力)
- [九、交易日历与节假日数据 (mootdx2.utils.holiday)](#九交易日历与节假日数据-mootdx2utilsholiday)
- [十、北交所实时行情 (mootdx2.utils.stock_bj_a)](#十北交所实时行情-mootdx2utilsstock_bj_a)
- [十一、自定义板块管理 (mootdx2.tools.customize)](#十一自定义板块管理-mootdx2toolscustomize)
- [十二、数据导出与格式转换工具](#十二数据导出与格式转换工具)
- [十三、服务器管理与高可用基础设施](#十三服务器管理与高可用基础设施)
- [十四、客户端精准对接与核心子模块导入规范](#十四客户端精准对接与核心子模块导入规范)

---

## 一、统一日 K 线管理器 (`mootdx2.daily.DailyDataManager`) 【推荐】

量化回测与生产分析推荐的首选入口。实现了**离线优先机制**：优先读取通达信本地 `.day` 文件，零网络开销；若本地缺失、未安装通达信或数据未覆盖最新交易日，则在 `auto_download=True` 时自动通过在线防封通道拉取并写入长效缓存。

```python
from mootdx2 import DailyDataManager

# 初始化（可指定通达信路径，不指定则自动探测环境变量 MOOTDX2_TDX_DIR 或操作系统默认目录）
manager = DailyDataManager(tdxdir="tests/fixtures")
```

### 核心方法列表

| 接口方法 | 参数说明 | 返回值与功能说明 |
| :--- | :--- | :--- |
| `get_daily(...)` | `symbol`: 证券代码 (如 `'600036'`)<br>`start`: 起始日期 (如 `'2023-01-01'`)<br>`end`: 结束日期 (如 `'2023-12-31'`)<br>`adjust`: 复权类型 (`'qfq'`/`'hfq'`/`None`)<br>`auto_download`: 缺失时自动在线补齐 (默认 `True`)<br>`offset`: 历史条数上限 (默认 `800`) | **单标的日 K 线**：返回以日期为索引的 `pd.DataFrame`，按需自动执行前/后复权处理。 |
| `get_daily_batch(...)` | `symbols`: 证券代码列表<br>`start`/`end`/`adjust`/`auto_download`/`offset` 同上 | **批量日 K 线获取**：返回字典 `Dict[str, Optional[pd.DataFrame]]`，便于多标的并发分析。 |
| `batch_sync(...)` | `symbols`: 代码列表<br>`offset`: 同步条数 (默认 `800`)<br>`delay`: 单请求节流微延时 (秒，默认 `0.08`)<br>`batch_size`: 批次大小 (默认 `50`)<br>`batch_delay`: 批次间休眠 (默认 `1.0`)<br>`show_progress`: 是否显示进度条 (默认 `True`) | **批量更新并落盘**：盘后自动化调度专用，内置分批节流防封策略与长效缓存。 |
| `is_offline_ready` | 属性 (Property) | **布尔值**：检测本地通达信目录是否就绪可用。 |

### 核心机制与外部使用常见问题 (FAQ)

#### Q1: 本地 `.day` 这类离线文件谁去下载？靠什么下载？
* **途径 A（通达信客户端手工/自带）**：安装了 Windows 通达信客户端的使用者，可通过客户端菜单栏的 **【系统】 -> 【盘后数据下载】**，一键拉取全市场历史日线，自动保存在 `vipdoc/sh/lday/*.day` 与 `vipdoc/sz/lday/*.day` 中。
* **途径 B（纯代码/全自动化定时任务）**：无需手工点击，使用者可通过盘后定时任务脚本（如每日 15:35 调度）调用 `DailyDataManager.batch_sync(symbols)` 或 CLI 命令行 `mootdx2 bundle`。模块会自动连接通达信行情主站分批次、带微延时（防封 IP）增量下载历史 K 线，并自动写入磁盘长效缓存池（`~/.mootdx2/caches/daily/`），后续完全实现秒级离线读取。

#### Q2: Mac / Linux / Docker 无通达信环境，如何提前下载并构建本地离线数据？
即使没有 Windows 桌面客户端，Mac 和 Linux 用户也完全可以提前下载全量离线数据，常用以下两种方式：

##### 方法一：用 mootdx2 在 Mac / Linux 直接提前生成标准通达信 `.day` 文件（纯正离线文件）
`mootdx2` 内部完整内置了通达信二进制编码器（`mootdx2.tdx.offline.write_daily`）。在没有安装 Windows 通达信的情况下，Mac / Linux 可以直接在线抓取并一键编码输出为标准的 `sh000001.day` 文件：

```python
from pathlib import Path
from mootdx2.quotes import Quotes
from mootdx2.tdx.offline.write_daily import write_daily_bars

# 1. 在 Mac / Linux 本地创建通达信标准目录结构
tdx_dir = Path("./my_tdx/vipdoc/sh/lday")
tdx_dir.mkdir(parents=True, exist_ok=True)

# 2. 在线抓取历史 K 线并直接编码写入 .day 二进制文件
client = Quotes.factory("std")
df_bars = client.bars(symbol="600036", frequency=9, offset=800)

target_file = tdx_dir / "sh600036.day"
write_daily_bars(target_file, df_bars)
print(f"成功在本地生成通达信标准离线日线: {target_file}")
```
* **生成之后怎么用？**
  初始化指定该目录即可：`DailyDataManager(tdxdir="./my_tdx")`。此时为纯正的本地 `.day` 离线读取，断网亦可高速回测。

##### 方法二：代码级提前批量预热缓存池（量化回测最推荐）
如果您不需要通达信专有的 `.day` 二进制文件结构，只想提前把历史数据一次性存到本地磁盘、回测时零网络延迟直读：

```python
from mootdx2 import DailyDataManager

manager = DailyDataManager()

# 提前一次性批量把全市场或自选标的下载到本地磁盘长效缓存 (~/.mootdx2/caches/daily/)
manager.batch_sync(
    symbols=["600036", "600519", "000001", "510300"],
    offset=800,       # 历史条数
    delay=0.08,       # 自动微延时防封
    batch_size=50,
)
```
* **执行一次后**：所有历史数据已持久化落盘至 `~/.mootdx2/caches/daily/`。
* **回测时**：调用 `manager.get_daily("600036", auto_download=False)`，直接毫秒级读取本地磁盘，**不发任何网络请求**。

#### Q3: 外面的使用者怎么用？（双模自适应运行）
使用者完全无需纠结自己是否有通达信环境，`DailyDataManager` 内部实现了全自动双模检测：
1. **模式 1：Windows 本地客户端模式（毫秒级纯离线）**
   * 使用者本地已装有通达信，初始化时传入路径 `DailyDataManager(tdxdir="C:/new_tdx")` 或配置系统环境变量 `MOOTDX2_TDX_DIR`。
   * 读取日线时直接解析本地二进制 `.day`，零网络请求、极速加载。若本地历史文件未覆盖最新交易日，则仅针对近期增量部分自动联网补齐。
2. **模式 2：Linux / macOS / Docker 纯代码模式（无通达信软件）**
   * 初始化直接留空：`DailyDataManager()`。
   * 模块检测到无本地 `.day` 目录后，自动切换为 **在线防封增量同步 + 磁盘长效持久化缓存模式**。首次调用自动下载并落盘，二次调用直接纯离线读取本地缓存，兼顾便捷性与高性能。

#### Q4: 下游持久化（如 Parquet / DuckDB / ClickHouse）职责边界是什么？
* **mootdx2 的核心职责**：交付**高品质、精准复权（前复权/后复权）、时效完整的 `pd.DataFrame`**，并在内部做好长效防封缓存。
* **外部使用者的落盘自由**：外部量化团队或使用者拿到 `df` 后，可根据自身量化系统架构自由持久化（例如直接调用 `df.to_parquet(f"data/daily/{symbol}.parquet")` 存入列式存储池，或写入数据库）。完整盘后定时更新与下游 Parquet 落盘范例请参阅 `sample/02_reader/daily_sync_cron_demo.py`。

#### Q5: 为什么在线获取是“实盘数据”？怎么严格区分实盘数据 vs 盘后数据？（量化避坑必读）

在实际量化生产与回测中，必须严格区分**实盘数据（Intraday / Real-time）**与**盘后数据（EOD / End-Of-Day）**：

##### 1. 核心属性与差异对照

| 维度 | 实盘数据 (Intraday / Real-time) | 盘后数据 (EOD / End-Of-Day) |
| :--- | :--- | :--- |
| **生成时间** | 交易时段（工作日 09:15~11:30，13:00~15:00） | 收盘清算完成之后（通常 15:30 以后） |
| **最新 Bar 状态** | **未闭合 (Open / Incomplete)**：价格随即时撮合跳动，成交量/金额持续累加 | **已闭合 (Finalized / Closed)**：全日数据完全固化，不可更改 |
| **获取渠道** | 在线直连主站接口（`mootdx2.quotes.Quotes`） | 本地离线 `.day` 文件（`Reader`）、盘后归档数据或清算缓存 |
| **复权因子时效** | 盘中按当日除权除息即时折算 | 交易所完成日终结账后的标准基准因子 |
| **典型应用场景** | 盘中实时监控、即时指标预警、实盘交易信号触发 | 策略历史回测、盘后选股、风控核算、历史归档 |

##### 2. 为什么 `candlestick_qfq.py` 等在线脚本获取的是实盘数据？
- **直连实时行情主站**：脚本默认使用 `Quotes.factory(market='std').bars(symbol, frequency=9)`。在交易时段（9:30~15:00）内，通达信返回的最后一根日 K 线属于**正在跳动的盘中未闭合 Bar**。
- **动态切片特性**：此时日 K 线的 `close` 是**最新撮合成交价**，`high`/`low` 随盘中极值刷新，`vol`/`amount` 仅为截至当前的累计成交量和成交额。

##### 3. 代码级精确识别与状态判定

可在数据加载与策略入口加入状态断言，规避盘中未闭合 Bar 误入策略日线计算：

```python
import datetime
from mootdx2.utils.holiday import is_trade_date

def is_market_trading() -> bool:
    """判断当前时间是否处于 A 股连续竞价交易时间"""
    now = datetime.datetime.now()
    today_str = now.strftime("%Y-%m-%d")
    
    # 1. 必须是法定交易日
    if not is_trade_date(today_str):
        return False
    
    # 2. 盘中交易时段（包含集合竞价阶段 09:15-11:30, 13:00-15:00）
    t = now.time()
    return (datetime.time(9, 15) <= t <= datetime.time(11, 30)) or \
           (datetime.time(13, 0) <= t <= datetime.time(15, 0))

# 校验最新一根 Bar 的状态：
bars = client.bars(symbol="600036", frequency=9, offset=10)
last_bar_date = str(bars.iloc[-1]["datetime"])[:10]
today_date = datetime.datetime.now().strftime("%Y-%m-%d")

if last_bar_date == today_date and is_market_trading():
    # 最后一根为未闭合的实盘动态 Bar，不可直接当成已完结日线进行指标回测
    is_bar_closed = False
else:
    # 历史 Bar 或收盘后的完整 Bar
    is_bar_closed = True
```

##### 4. 量化开发避坑要点
1. **防止前视偏差（Lookahead Bias）**：
   策略回测必须使用**已闭合**的数据。若在盘中以未走完的日 K 线收盘价计算信号发单，实质上使用了未定型的未来数据。
2. **前复权因子的即时生效**：
   除权除息日当天开盘前，复权因子已发生跳变。若使用旧的离线 XDXR 缓存对实盘价格进行前复权，会导致当天开盘出现巨大断层。在交易日盘中计算复权时应确保 XDXR 数据同步更新至最新状态。

---

## 二、在线行情数据接口 (`mootdx2.quotes.Quotes`)

通过 `Quotes.factory(market='std'|'ext', driver='native'|'compat')` 创建行情实例。
- **市场类型**：`market='std'`（标准市场：沪深 A 股/指数）、`market='ext'`（扩展市场：期权、期货、港股等）。
- **底层驱动**：`driver='native'`（内置纯净 Python 协议驱动）、`driver='compat'`（兼容经典驱动，默认）。

### 1. 标准市场行情接口 (`StdQuotes`)

| 接口方法 | 参数说明 | 数据内容 |
| :--- | :--- | :--- |
| `quotes(symbol)` | `symbol`: 股票代码或代码列表 | **实时日行情快照**：最新价、昨收、今开、最高/最低、买卖五档报价及量、成交量、成交额等。 |
| `bars(symbol, frequency, start, offset, adjust)` | `frequency`: K 线周期<br>`start`/`offset`: 范围<br>`adjust`: 复权类型 (`'qfq'`/`'hfq'`) | **K 线数据**（支持前/后复权）：OHLCV + 成交额。周期支持 1分钟/5分钟/15分钟/30分钟/1小时/日/周/月/季/年线。 |
| `index(symbol, frequency, start, offset)` | 同上 | **指数 K 线数据**（如上证指数 `000001`）。 |
| `index_bars(...)` | 同上 | **指数 K 线数据**（`index` 的等价方法）。 |
| `k(symbol, begin, end, adjust)` | `begin`/`end`: 日期范围<br>`adjust`: 复权类型 | **指定日期范围的日 K 线数据**（支持前/后复权）。 |
| `minute(symbol)` | `symbol`: 股票代码 | **当天实时分时数据**：每分钟的成交价、成交量。 |
| `minutes(symbol, date)` | `date`: `YYYYMMDD` | **历史分时数据**：指定日期的分钟级明细。 |
| `transaction(symbol, start, offset)` | 范围参数 | **实时分笔成交 (Tick)**：每笔交易的时间、价格、成交量、买卖方向。 |
| `transactions(symbol, start, offset, date)` | 日期及范围 | **历史分笔成交 (Tick)**：指定日期的逐笔成交。 |
| `finance(symbol)` | `symbol`: 股票代码 | **财务基本信息**：流通股本、总股本、省份、行业等。 |
| `xdxr(symbol)` | `symbol`: 股票代码 | **除权除息历史数据**：分红、配股、送转股明细，用于复权计算。 |
| `stock_count(market)` | `market`: `0` 深圳, `1` 上海 | **市场股票数量**。 |
| `stocks(market)` | `market`: 市场代码 | **股票列表**：指定市场的所有股票代码、名称等信息。 |
| `stock_all()` | 无 | **全市场股票列表**：汇总沪深两市所有证券。 |
| `block(tofile)` | `tofile`: 保存路径（可选） | **板块信息**：概念、行业、区域板块的分类及成分股归属。 |
| `F10C(symbol)` | `symbol`: 股票代码 | **公司 F10 目录信息**。 |
| `F10(symbol, name)` | `name`: 章节名称（可选） | **公司 F10 详情**：股东研究、经营分析等文本信息。 |
| `traffic()` | 无 | **网络流量统计**：当前连接的数据传输统计。 |

### 2. 扩展市场行情接口 (`ExtQuotes`)

| 接口方法 | 数据内容 |
| :--- | :--- |
| `markets()` | **实时市场列表**：所有可用的市场标识及名称。 |
| `instrument_count()` | **商品总数量**。 |
| `instrument(start, offset)` | **证券代码/合约列表**（分页）。 |
| `instruments()` | **全量证券/合约列表**（自动翻页）。 |
| `quote(market, symbol)` | **五档行情**：最新价、买卖五档、持仓量、成交量等。 |
| `minute(market, symbol)` | **当天分时数据**。 |
| `minutes(market, symbol, date)` | **历史分时数据**。 |
| `bars(frequency, market, symbol, start, offset)` | **扩展市场 K 线数据**。 |
| `transaction(market, symbol, start, offset)` | **分笔成交**。 |
| `transactions(market, symbol, date, start, offset)` | **历史分笔成交**。 |

---

## 三、本地历史数据读取接口 (`mootdx2.reader.Reader`)

通过 `Reader.factory(market='std'|'ext', tdxdir=...)` 创建本地数据读取器。解析通达信本地客户端的二进制数据文件（`.day` / `.lc1` / `.lc5` 等），实现**纯离线/极速数据读取**。

### 1. 标准市场本地读取 (`StdReader`)

| 接口方法 | 参数与选项 | 数据内容 |
| :--- | :--- | :--- |
| `daily(symbol, auto_download, adjust)` | `auto_download=False`<br>`adjust='qfq'/'hfq'/None` | **本地日线 K 线**（支持前/后复权）。本地缺失且 `auto_download=True` 时自动联网下载并缓存（24h TTL）。 |
| `minute(symbol, suffix)` | `suffix=1` 或 `5` | **本地分钟 K 线**：`suffix=1` 读 1 分钟线，`suffix=5` 读 5 分钟线。 |
| `fzline(symbol)` | `symbol`: 股票代码 | **本地 5 分钟 K 线**（`minute(symbol, suffix=5)` 的便捷别名）。 |
| `xdxr(symbol)` | `symbol`: 股票代码 | **本地除权除息数据**：优先读取本地缓存，未命中则联网拉取并写缓存。 |
| `block(symbol, group=False)` | `group`: 是否分组 | **本地板块/成分股数据**：解析 `block_zs.dat`、`block_fg.dat`、`block_gn.dat` 等板块文件。 |
| `block_new(name, symbol, group=False)` | 板块名称与成分股 | **自定义板块读写**：查询或创建通达信本地自定义板块成分股（写入 `.blk` + `blocknew.cfg`）。 |

### 2. 扩展市场本地读取 (`ExtReader`)

| 接口方法 | 数据内容 |
| :--- | :--- |
| `daily(symbol)` | **本地扩展市场日线数据**。 |
| `minute(symbol)` | **本地扩展市场 1 分钟 K 线**。 |
| `fzline(symbol)` | **本地扩展市场 5 分钟 K 线**。 |

---

## 四、通达信底层协议驱动与离线解析 (`mootdx2.tdx`)

提供脱离高层封装、直接对接底层协议驱动与本地二进制文件的原生能力，适合高性能数据处理或深度协议定制场景。

### 1. 底层驱动工厂 (`mootdx2.tdx.factory`)

```python
from mootdx2.tdx.factory import create_hq_client

# 创建原生/兼容协议客户端
client = create_hq_client(driver="native", auto_retry=True)  # 可选 "native" 或 "tdxpy"
with client.connect(host="119.147.212.81", port=7709):
    bars = client.get_security_bars(category=9, market=1, code="600036", start=0, count=10)
```

| 驱动选项 | 说明 |
| :--- | :--- |
| `driver="native"` | **内置纯净驱动**：mootdx2 原生纯 Python 编写的协议实现 (`NativeTdxHqAPI`)，无外部第三方重打包依赖。 |
| `driver="tdxpy"` | **经典兼容驱动**：加载外部兼容驱动，并自动激活纯净防污染握手补丁。 |

### 2. 底层离线二进制解析器 (`mootdx2.tdx.offline`)

直接读取通达信客户端数据文件并解析为 `SecurityBar` 数据结构：

```python
from mootdx2.tdx.offline import read_daily_bars, read_5min_bars, find_daily_bar_file

# 1. 直接解析日线文件 (.day)
bars = read_daily_bars("tests/fixtures/vipdoc/sh/lday/sh000001.day")

# 2. 直接解析 5 分钟线文件 (.lc5)
min_bars = read_5min_bars("tests/fixtures/vipdoc/sh/fzline/sh688001.lc5")

# 3. 自动定位标的日线文件路径
file_path = find_daily_bar_file(market=1, code="000001", vipdoc="tests/fixtures/vipdoc")
```

| 核心接口 | 功能说明 |
| :--- | :--- |
| `read_daily_bars(file_path)` | 直接解析 `.day` 二进制文件，返回 `List[SecurityBar]`（包含年月日、开高低收、成交量、成交金额）。 |
| `read_min_bars(file_path)` | 直接解析 1 分钟 `.lc1` 二进制文件，返回分钟级 `List[SecurityBar]`。 |
| `read_5min_bars(file_path)` | 直接解析 5 分钟 `.lc5` 二进制文件，返回 5 分钟级 `List[SecurityBar]`。 |
| `find_daily_bar_file(market, code, vipdoc)` | 根据市场标识 (`0` 深圳, `1` 上海) 与证券代码，在 `vipdoc` 目录下快速定位对应 `.day` 文件路径。 |

---

## 五、巨潮资讯独立公告数据源 (`mootdx2.cninfo.CninfoClient`)

独立于通达信协议的 HTTP 公告检索客户端（基于标准库 `urllib`，零第三方依赖）。动态对接巨潮官方权威 `orgId` 映射表，支持全市场股票（尤其 601xxx、688xxx 段）历史公告检索与 PDF 附件直链获取。

```python
from mootdx2 import CninfoClient

client = CninfoClient(timeout=15.0)

# 1. 获取 DataFrame 格式公告列表
df = client.get_announcements(code="600519", count=10, page=1, to_df=True)
print(df[["date", "type", "title", "pdf_url"]])

# 2. 获取结构化 Announcement 对象列表
records = client.get_announcements(code="688017", count=3, page=1, to_df=False)
for item in records:
    print(item.date, item.title, item.pdf_url)
```

### 核心方法与数据模型

| 方法 / 属性 | 参数说明 | 功能与返回说明 |
| :--- | :--- | :--- |
| `get_announcements(...)` | `code`: 股票代码 (如 `'600519'`)<br>`count`: 获取条数 (默认 `10`)<br>`page`: 分页页码 (从 `1` 开始)<br>`to_df`: 是否转为 DataFrame (默认 `True`) | **历史公告检索**：<br>当 `to_df=True` 时返回 `pd.DataFrame`，字段包含 `id`, `code`, `name`, `date`, `type`, `title`, `url`, `pdf_url` 等；<br>当 `to_df=False` 时返回 `List[Announcement]` 对象列表。 |
| `Announcement` 数据类 | 数据结构模型属性 | `id`: 公告编号<br>`secCode`/`secName`: 股票代码及简称<br>`title`: 公告标题<br>`type`: 公告类型（如年报、决议、分红）<br>`date`: 发布日期<br>`url`: 巨潮网页端详情 URL<br>`pdf_url`: 原始 PDF 附件直链 |

---

## 六、专业财务数据报表解析 (`mootdx2.financial` / `mootdx2.affair`)

提供对通达信专业财务数据（`gpcw*.zip` / `gpcw*.dat`）的高性能解析，覆盖 580+ 专业财务科目，并原生提供**中文/英文表头映射**。

### 1. 专业财务模块 (`mootdx2.financial`)

```python
from mootdx2.financial import FinancialList, FinancialReader

# 1. 探查服务器最新发布的财务包清单
financial_list = FinancialList()
records = financial_list.parse(financial_list.content())
# 每条记录包含: filename (如 gpcw20240630.zip), filesize, hash

# 2. 解析本地财务文件为 DataFrame（支持中文表头）
df = FinancialReader.to_data("tmp/affairs/gpcw20240630.zip", header="zh")
print(df[["基本每股收益", "每股净资产", "净资产收益率", "主营业务收入", "净利润"]])
```

| 接口类 / 方法 | 功能说明 |
| :--- | :--- |
| `FinancialList.content()` / `parse()` | 探查通达信服务器上的 `tdxfin/gpcw.txt` 报表发布清单，解析包含文件名、大小及 MD5 哈希的列表。 |
| `FinancialReader.to_data(filepath, header="zh"|"en")` | 解析本地 `.zip` 归档或解压后的 `.dat` 财务文件，自动将 580+ 字段映射为中文友好表头（或标准英文缩写）。 |
| `Financial.content(filename, downdir)` | 从服务器下载指定的财务压缩包文件。 |

### 2. 基础财务接口 (`mootdx2.affair.Affair`)

| 接口方法 | 功能说明 |
| :--- | :--- |
| `Affair.files()` | 获取可用的历史财务文件列表。 |
| `Affair.fetch(downdir, filename)` | 下载指定财务文件，未指定则批量下载全量财务包。 |
| `Affair.parse(downdir, filename)` | 解析指定的财务 `.zip` 文件，返回完整财务 DataFrame。 |

### 3. 580+ 财务字段大类拆解

1. **每股与核心收益指标**：`基本每股收益`、`扣除非经常性损益每股收益`、`每股净资产`、`每股未分配利润`、`每股资本公积金`、`每股经营现金流量`、`净资产收益率 (ROE)`。
2. **资产负债表核心**：`货币资金`、`交易性金融资产`、`应收账款`、`存货`、`长期股权投资`、`固定资产`、`无形资产`、`短期借款`、`长期借款`、`实收资本（股本）`、`归属于母公司所有者权益合计` 等。
3. **利润表核心**：`营业收入`、`营业成本`、`销售/管理/财务费用`、`投资收益`、`营业利润`、`利润总额`、`归属于母公司所有者的净利润`。
4. **现金流量表核心**：`经营活动现金流入/出及净额`、`购建固定资产支付现金`、`取得借款收到现金`、`现金及现金等价物净增加额`。
5. **财务衍生与分析比率**：`流动比率`、`速动比率`、`资产负债率`、`存货周转率`、`营收增长率(%)`、`净利润增长率(%)`、`销售毛利率/净利率`。
6. **金融行业专用科目**：银行（`吸收存款`、`贷款垫款`、`利息净收入`）、保险（`已赚保费`、`准备金净额`）、证券（`代理买卖证券款`、`融出资金`）。

---

## 七、增量防封数据同步工具 (`mootdx2.sync`)

针对大批量标的的高频同步场景，内置**并发节流防封策略**与**长效磁盘缓存**。

```python
from mootdx2 import sync_daily, sync_xdxr

# 1. 批量同步日 K 线（分批防封调度）
sync_res = sync_daily(
    symbols=["600000", "600036", "000001"],
    offset=800,
    delay=0.08,        # 单任务微延时
    batch_size=50,     # 每 50 只标的一组
    batch_delay=1.0,   # 组间休眠 1 秒
    cache=True,
    show_progress=True,
)

# 2. 批量同步除权除息因子（90天长效缓存，已存在有效缓存自动跳过）
xdxr_stat = sync_xdxr(
    symbols=["600036", "510300"],
    force=False,
    workers=4,
    delay=0.05,
)
```

| 接口方法 | 参数说明 | 功能与返回说明 |
| :--- | :--- | :--- |
| `sync_daily(...)` | `symbols`: 标的代码列表<br>`offset`: 同步条数<br>`delay`: 单请求延时<br>`batch_size`: 批次大小<br>`batch_delay`: 批次间休眠<br>`cache`: 是否写入长效缓存 | **批量增量更新日 K 线**：返回字典 `{'total': int, 'success': int, 'data': Dict[str, pd.DataFrame]}`，支持长效缓存防封。 |
| `sync_xdxr(...)` | `symbols`: 标的代码列表<br>`file`: 包含代码的文本文件路径<br>`force`: 强制覆盖已有缓存<br>`workers`: 并发线程数 (默认 `4`)<br>`delay`: 节流微延时 | **批量预同步除权除息因子**：90 天长效缓存，智能过滤已缓存标的，返回包含成功数、跳过数及文件映射的统计字典。 |

---

## 八、复权计算与因子能力

`mootdx2` 统一了股票与 ETF 的全套复权计算流水线：

### 1. 透传式复权（推荐用法）

所有日线及历史 K 线接口均支持 `adjust` 参数：

```python
# 1. 在线获取招商银行前复权日 K 线
quotes = Quotes.factory("std")
df_qfq = quotes.bars(symbol="600036", frequency=9, adjust="qfq")

# 2. 离线读取沪深 300ETF 前复权日 K 线
reader = Reader.factory("std", tdxdir="~/new_tdx")
df_etf = reader.daily(symbol="510300", adjust="qfq")
```

`adjust` 参数支持的值：`'qfq'` / `'01'` / `'before'`（前复权），`'hfq'` / `'02'` / `'after'`（后复权）。

### 2. 股票与 ETF 通用复权流水线 (`mootdx2.tools.reversion`)

| 接口方法 | 功能说明 |
| :--- | :--- |
| `reversion(symbol, stock_data, xdxr, type_)` | **通用复权主入口**：自动识别标的类型。若是 ETF 基金（15/16/50/51/56/588 等）则自动走扩缩股折算逻辑；若是股票则按送转股、分红派息、配股综合流水线计算。 |
| `etf_reversion(data, xdxr, adjust)` | **ETF 专属复权**：基于 `xdxr` 中 `category==11`（基金折算/分红）的扩缩股比例与现金分红执行前/后复权。 |
| `_reversion(bfq_data, xdxr_data, type_)` | **A 股股票经典复权算法**：基于送转股比例、现金分红与配股价计算复权因子与调整价。 |
| `factor_reversion(symbol, method, raw)` | **Sina 预计算因子兜底**：当本地或通达信 XDXR 数据缺失时，自动回退使用新浪预计算因子完成复权。 |

### 3. 复权因子序列获取 (`mootdx2.utils.factor` / `mootdx2.contrib.adjust`)

| 接口方法 | 数据内容与来源 |
| :--- | :--- |
| `fq_factor(symbol, method)` | 获取单只股票或 ETF 的**历史前/后复权因子时间序列**（从新浪获取，24h 本地缓存），自动适配股票与 ETF 字段差异。 |
| `get_adjust_year(symbol, year, factor)` | 从同花顺获取指定年份的前/后复权 OHLCV 数据，作为备选复权数据源。 |

---

## 九、交易日历与节假日数据 (`mootdx2.utils.holiday`)

| 接口方法 | 返回值与功能说明 |
| :--- | :--- |
| `holidays()` | **沪深 A 股全量历史交易日历**（从新浪获取并 JS 解密），返回包含交易日期的 DataFrame，本地 24h 缓存。 |
| `holiday2(date)` | 查询指定日期是否为交易日，返回匹配的 DataFrame 行。 |
| `holiday(date, country)` | **多国交易日历**（通达信官方源），判断指定日期是否休市，返回布尔值。 |
| `holiday_(date, country)` | 同 `holiday()`，但返回匹配的 DataFrame 记录行。 |

---

## 十、北交所实时行情 (`mootdx2.utils.stock_bj_a`)

| 接口方法 | 数据内容 |
| :--- | :--- |
| `stock_bj_a()` | **北交所全部股票实时全景行情**（东方财富通道），包含：最新价、涨跌幅、成交量、成交额、换手率、市盈率(动态)、量比、5分钟涨跌、市净率、总市值、流通市值、年初至今涨跌幅等。 |

---

## 十一、自定义板块管理 (`mootdx2.tools.customize`)

对接通达信客户端本地 `blocknew.cfg` 与自定义板块 `.blk` 文件：

| 接口方法 | 功能说明 |
| :--- | :--- |
| `Customize.search(name, group)` | **查询自定义板块**：按板块名称搜索，支持分组返回。 |
| `Customize.create(name, symbol)` | **创建自定义板块**：写入板块名称与成分股代码列表。 |
| `Customize.update(name, symbol, overflow)` | **更新自定义板块**：追加或全量覆盖成分股代码。 |
| `Customize.remove(name)` | **删除自定义板块**：清理板块记录及关联 `.blk` 二进制文件。 |

---

## 十二、数据导出与格式转换工具

### 1. 多格式 DataFrame 导出 (`mootdx2.utils.to_file`)

| 支持扩展名 | 格式说明 |
| :--- | :--- |
| `.csv` | 标准逗号分隔 CSV 文件（UTF-8 编码） |
| `.xlsx` / `.xls` | Microsoft Excel 电子表格 |
| `.h5` | 高性能 HDF5 数据集 |
| `.json` | JSON 格式文本（records 数组） |

### 2. 通达信导出文件转 CSV (`mootdx2.tools.tdx2csv`)

| 接口方法 | 功能说明 |
| :--- | :--- |
| `txt2csv(infile, outfile)` | 将通达信导出的 GBK 编码 `.txt` 转换为标准 `date, open, high, low, close, volume, amount` CSV。 |
| `batch(src, dst)` | 异步多任务批量转换指定目录下的所有通达信导出文件。 |

---

## 十三、服务器管理与高可用基础设施

### 1. 最优服务器测速与健康检查 (`mootdx2.server`)

| 接口方法 | 功能说明 |
| :--- | :--- |
| `bestip(limit, console, sync)` | **测速并选出最快服务器**：针对 HQ（标准行情）、EX（扩展行情）、GP（财务数据）三类节点测速，写入 `~/.mootdx2/config.json`。 |
| `check_server(sync)` | 服务器连通性快速探测。 |
| `ServerManager` | 运行期**请求级故障自动转移**：连续失败达阈值后自动重连至备用最优节点。 |

### 2. 多级缓存策略

- **内存与 DataFrame 缓存** (`pd_cache`)：按函数签名与参数哈希自动缓存 Pandas 结果，过期自动刷新。
- **文件级持久化缓存** (`file_cache` / Pickle)：除权除息因子、交易日历、复权因子均支持长效缓存（`~/.mootdx2/caches/`），实现首次联网、后续秒级离线。
- **日线增量同步缓存**：`sync_daily` 与 `DailyDataManager` 自动将增量拉取的数据落地到磁盘，保障高频调用不被主站流控。

### 3. CLI 命令行便捷工具

```bash
# 在线获取行情
mootdx2 quotes -s 600000 -a bars

# 读取本地数据
mootdx2 reader -s 600000 -a daily

# 探测并保存最优服务器
mootdx2 bestip

# 财务文件探查、下载与解析
mootdx2 affair -l
mootdx2 affair -f gpcw20231231
mootdx2 affair -p gpcw20231231 -o out.csv

# 批量拉取行情数据
mootdx2 bundle -s 600000,000001 -o output/
```

---

> **关于 Level-2 与板块资金流向说明**
>
> 通达信开放的通信接口基于 Level-1 基础行情，**不存在直接的"板块资金流向"汇总接口**。资金流向指标需基于 `transactions`（逐笔分笔成交数据及买卖挂单方向）在客户端自行计算统计，或对接外部 Level-2 / 衍生金融数据源。

---

## 十四、客户端精准对接与核心子模块导入规范

为彻底杜绝外部客户端（如 `kdata`、自定义量化引擎）因全局顶层 `__init__.py` 损坏带来的级联导入故障，同时兼顾冷启动性能与模块解耦，推荐客户端按核心子目录进行精准按需导入。

### 1. 核心子模块精准导入速查表

| 功能域 / 业务场景 | 生产级推荐引入路径 | 核心暴露对象 / 接口 |
| :--- | :--- | :--- |
| **通达信底层离线二进制解析** | `from mootdx2.tdx.offline import ...` | `read_daily_bars`（日线解析）、`read_min_bars`（1分线）、`read_5min_bars`（5分线）、`find_daily_bar_file`（定位.day路径） |
| **通达信底层协议驱动工厂** | `from mootdx2.tdx.factory import ...` | `create_hq_client`（创建纯原生 Python 或兼容协议客户端） |
| **通达信底层传输与状态同步** | `from mootdx2.tdx.transport import ...` | `sync`（底层握手与协议保活探针） |
| **本地通达信目录综合读取器** | `from mootdx2.reader import ...` | `Reader`（支持标准/扩展市场日线与分时 DataFrame 读取） |
| **统一日 K 线管理器 (离线+增量)** | `from mootdx2.daily import ...` | `DailyDataManager`（离线优先、自动增量补全、防封节流调度） |
| **通用股票与 ETF 精密复权** | `from mootdx2.tools.reversion import ...` | `reversion`（全自动除权除息/扩缩股流水线）、`etf_reversion` |
| **通达信自定义板块管理** | `from mootdx2.tools.customize import ...` | `Customize`（读写 `blocknew.cfg` 与 `.blk` 文件） |
| **巨潮资讯公告与研报直链** | `from mootdx2.cninfo import ...` | `CninfoClient`（全市场股票公告检索与官方 PDF 附件获取） |
| **交易日历与休市判定** | `from mootdx2.utils.holiday import ...` | `holiday`（交易日判定）、`holidays`（历史全量交易日序列） |
| **专业财务数据报表解析** | `from mootdx2.financial import ...` | `FinancialReader`（580+ 财务字段中英文映射）、`FinancialList` |
| **在线实时与历史行情客户端** | `from mootdx2.quotes import ...` | `Quotes`（标准/扩展市场 Level-1 实时盘口、分笔成交、K线） |
| **最优服务器测速与配置** | `from mootdx2.server import ...` | `bestip`、`check_server`、`ServerManager` |

---

### 2. 核心子目录常用对接代码范例

#### (1) 底层二进制极速直读 (`mootdx2.tdx.offline`)
直接解析本地通达信 `.day`、`.lc1`、`.lc5` 二进制文件为结构化对象，适合底层高性能量化回测：
```python
from mootdx2.tdx.offline import read_daily_bars, read_5min_bars, find_daily_bar_file

# 直接解析通达信日线文件
bars = read_daily_bars("/path/to/vipdoc/sh/lday/sh600036.day")
for bar in bars[-3:]:
    print(bar.datetime, bar.open, bar.high, bar.low, bar.close, bar.vol)

# 根据代码与市场 (0=深圳, 1=上海) 定位本地 .day 路径
day_path = find_daily_bar_file(market=1, code="600036", vipdoc="/path/to/vipdoc")
```

#### (2) 日 K 线智能管理与增量防封同步 (`mootdx2.daily`)
量化工程首选入口，离线优先秒级直读，过期自动联网增量拉取并落地长效缓存：
```python
from mootdx2.daily import DailyDataManager

manager = DailyDataManager(tdxdir="tests/fixtures")
# 获取前复权日线 DataFrame
df_qfq = manager.get_daily("600036", adjust="qfq", auto_download=True)
```

#### (3) 股票与 ETF 通用精密复权 (`mootdx2.tools.reversion`)
自动识别标的类型，支持 ETF 扩缩股折算与股票送转股、分红配股复权：
```python
from mootdx2.tools.reversion import reversion

df_adjusted = reversion(symbol="510300", stock_data=df_raw, xdxr=df_xdxr, type_="qfq")
```

#### (4) 交易日历判定与全量序列 (`mootdx2.utils.holiday`)
```python
from mootdx2.utils.holiday import holiday, holidays

is_trade_day = holiday("2024-10-01", country="China")  # 国庆休市 -> False
df_calendar = holidays()  # 获取历史完整交易日历 DataFrame
```

#### (5) 巨潮资讯独立公告检索 (`mootdx2.cninfo`)
```python
from mootdx2.cninfo import CninfoClient

client = CninfoClient(timeout=15.0)
df_announcements = client.get_announcements(code="600519", count=10, to_df=True)
```

