通达信客户端协议详细设计

基础帧
- 请求帧
  - `Prefix`: `0x0C`
  - `MsgSeq`: `uint32 LE`（tdxlite 用十六进制字符串保存）
  - `Unknown`: `uint8=0x01`
  - `Length1/Length2`: `uint16 LE`（等于 `Body长度 + 2`，含 `Type` 字段）
  - `Type`: `uint16 LE`（以十六进制串形式写入，如 K线 `2d05`）
  - `Body`: 业务负载，由各协议定义
- 响应帧
  - `PrefixResp`: `0xB1CB7400`
  - `CompressedFlag`: `uint8`（常见 `0x1c` 表示压缩）
  - `MsgSeq`: `uint32 LE`
  - `Unknown`: `uint8`
  - `Type`: `uint16 LE`
  - `ZipLength`: `uint16 LE`
  - `Length`: `uint16 LE`
  - `Body`: 若 `ZipLength!=Length` 则使用 zlib 解压；tdxlite 自动处理

编码规则
- 价格（`get_price`）：首字节 6 位数据 + 符号位(bit6) + 延续位(bit7)，后续字节每字节 7 位数据，逐组左移累加；支持负值。K线单位缩放为 `/1000`。
- 成交量/成交额（`get_volume`）：读取 `uint32` 再做单位转换为自然量额值（兼容传输整数避免浮点误差的做法）。
- 时间（`parse_datetime`）：分钟类包含时分打包，日/周/月/季/年为 `YYYYMMDD`，解析后返回 `datetime`。

消息类型与字段
1) 连接/心跳/信息
- `beat_heart` (`0d00`)
  - 请求：`Body=<B 0x01>`
  - 响应：依次 `B(1) year(H) day(B) month(B) minute(B) hour(B) B second(B)`，随后多个日期与保留段；tdxlite 提取 `body_date_time`、`body_server_name` 等。
- `heart_beat` (`0400`)：可选扩展，响应通常返回 `date(uint32)`。
- `info` (`1500`)：响应包含延迟、服务器签名、信息文本、当前时间与区域标志等。
- `announcement` (`0a00`)：响应包含 `expire_date, title, author, content`（GBK）。
- `exchange_announcement` (`0200`)：响应为交易所公告标志及文本（GBK）。
- `upgrade_tip` (`db0f`)：请求体包含 `tdxlevel` 与版本号，响应返回提示文本与链接。

2) 市场与列表
- `statistic_stock_count` (`4e04`)
  - 请求：`<H market, I date>`
  - 响应：`<H count>`
- `stock_list` (`4d04`)
  - 请求：`<H market, I start, I count, I 0>`
  - 响应（每条 37 字节）：`code(6s GBK), vol(H), name(8s GBK), _(8s), unknown1(4s), decimal_point(B), pre_close(f), unknown2(H), unknown3(H)`
- `stock_list_b` (`5004`)
  - 请求：`<H market, H start>`
  - 响应（每条 29 字节）：`code(6s GBK), vol(H), name(8s GBK), unknown1(4s), decimal_point(B), pre_close(f), unknown2(H), unknown3(H)`

3) 行情
- `quote_detail` (`3e05`)
  - 请求：头部固定 8 字节 + `count(H)` + 重复 `<B market, 6s code>`
  - 响应：
    - 基本：`market(B)`、`code(6s)`、`active1(H)`、`price(get_price)`、`last_close/open/high/low`（均为相对 `price` 的差值；需累加）
    - 时间：`server_time(get_price)`（需格式化为 `HH:MM:SS.sss`），`after_hour(get_price)`
    - 量额：`vol(get_price)`、`cur_vol(get_price)`、`amount(f)`、`s_vol/b_vol(get_price)`、`s_amount/b_amount(get_price)`
    - 盘口：重复 5 次的 `bid/ask(get_price)` 与 `bid_vol/ask_vol(get_price)`，价格需对 `price` 累加
    - 其他：`v1(H), unknown(4s), v2(h), active2(H)` 与若干保留字段
- `quotes_list` (`4b05`)
  - 请求：`<HHHHHHHHH>` 包含 `category, _, start, count, 0, 5, 0, 1, 0`
  - 响应：字段与 `quote_detail` 类似但盘口可能简化为 1 档

4) 分时与分笔
- `minute_time_data` (`1d05`)
  - 请求：`<H market, 6s code, I 0>`
  - 响应：`<H count>` 后每条 `price(get_price)`（增量累计，单位 `/100`）、`unknown(get_price)`、`vol(get_price)`
- `transaction_data` (`c50f`)
  - 请求：`<H market, 6s code, H start, H count>`
  - 响应：每条 `time(HH:MM)`、`price(get_price)`（增量累计）、`vol(get_price)`、`trans(get_price)`、`buyorsell(get_price)`（0 买/1 卖）、`unknown(get_price)`
- `history_minute_time_data` (`b40f`)
  - 请求：在 `minute_time_data` 前加 `date(I)`（`YYYYMMDD`）
  - 响应：同当日分时
- `history_transaction_data` (`b50f`)
  - 请求：在 `transaction_data` 前加 `date(I)`
  - 响应：同当日分笔

5) K线（`kline_data: 2d05`）
- 请求：`<H market, 6s code, B kline_type, B 0, H 1, H start, H count, 10s reserved>`；`count<=800`
- 响应：`<H count>` 后每条 `date(uint32)` + 四价差值 + 成交量/额；价格单位需 `/1000`，并按“上一收盘为基准累计”解码。

6) 公司信息
- `company_category` (`cf02`)
  - 请求：`<H market, 6s code, I 0>`
  - 响应：`count(H)` 与若干条目，含 `name(GBK)`、`filename(80B)`、`start(I)`、`length(I)` 等
- `company_content` (`d002`)
  - 请求：`<H market, 6s code, H 0, 80s filename, I start, I length, I 0>`（文件名不足 80 补齐）
  - 响应：正文文本（GBK），需清理 `\x00`
- `finance_info` (`1000`)
  - 请求：`<H 1, B market, 6s code>`
  - 响应：大量财务字段（流通股本/总股本/省份/行业/IPO日期等）与资产负债/利润/现金流等，数值通常需乘以万或换算为自然单位
- `xdxr_info` (`0f00`)
  - 请求：`<H 1, B market, 6s code>`
  - 响应：事件列表，包含类别（1–14）与日期，按类别存储分红、配股、送转股、缩股、权证等，附带盘前/盘后流通与总股本变化

扩展到 tdxlite 的策略
- 在 `constants.MsgType` 中新增对应十六进制串；请求类在 `req/` 下继承 `BaseReq` 并实现 `msg_body`；解析器在 `parse/` 下用 `@BaseParse.register(MsgType.xxx)` 注册并使用 bitstring 流解码，结果写入 `resp_data.body_*`。
- 统一辅助：使用 `utils.get_price/get_volume` 与 `parse_utils.parse_datetime`，对字符串采用 GBK 解码并清洗 `\x00`。