diff --git a/README.md b/README.md index 0b0fac2..419832f 100644 --- a/README.md +++ b/README.md @@ -166,8 +166,8 @@ market code name volunit decimal_point pre_close market code year month day category name fenhong peigujia songzhuangu peigu suogu xingquanjia fenshu -panqian_liutong panhou_liutong -qian_zongguben hou_zongguben +panqian_liutong panhou_liutong # 单位:万股 +qian_zongguben hou_zongguben # 单位:万股 _raw ``` @@ -190,6 +190,7 @@ name filename start length | 3 | `security_list` | `pre_close` 错用成交量解码函数 | 改用价格解码 | | 4 | `transaction` | 最后一个字段被 `_` 丢弃 | 保留为 `unknown_last` | | 5 | `minute_time` | `reversed1` 字段被丢弃 | 保留为 `unknown_1` | +| 6 | `xdxr_info` | 股本字段用 `float(uint32)` 直解,差约 374 倍 | 改用 `_decode_volume`(通达信自定义浮点),单位万股,与 `FinanceInfo` 完全吻合 | ## 架构 diff --git a/src/xmtdx/commands/xdxr_info.py b/src/xmtdx/commands/xdxr_info.py index b40e651..cee7737 100644 --- a/src/xmtdx/commands/xdxr_info.py +++ b/src/xmtdx/commands/xdxr_info.py @@ -8,6 +8,7 @@ import struct from .._binary import slice_bytes, unpack_from from ..codec.datetime_ import get_datetime +from ..codec.volume import _decode_volume from ..exceptions import TdxDecodeError from ..models.enums import Market from ..models.finance import XDXR_CATEGORY_NAMES, XdxrRecord @@ -93,9 +94,9 @@ class GetXdxrInfoCmd(BaseCommand[list[XdxrRecord]]): def _decode_share_count(raw: int) -> float: - """股本数量解码(uint32 → 股数)。 + """股本数量解码(通达信自定义4字节浮点 → 万股)。 - pytdx 使用 get_volume 但会产生错误结果(xdxr Bug #1 注释)。 - 目前保持与服务器原始整数一致,待进一步逆向确认正确解码方式。 + xdxr_info 的股本字段与成交量字段使用相同的自定义浮点编码, + 解码结果单位为万股,与 FinanceInfo.zong_guben / 10000 一致。 """ - return float(raw) + return _decode_volume(raw) diff --git a/src/xmtdx/models/finance.py b/src/xmtdx/models/finance.py index f0ab72d..ce4e3fa 100644 --- a/src/xmtdx/models/finance.py +++ b/src/xmtdx/models/finance.py @@ -34,11 +34,11 @@ class XdxrRecord: xingquanjia: float | None = None # 行权价 fenshu: float | None = None # 分数 - # category in [2..10](股本变动类) - panqian_liutong: float | None = None # 盘前流通股本 - panhou_liutong: float | None = None # 盘后流通股本 - qian_zongguben: float | None = None # 前总股本 - hou_zongguben: float | None = None # 后总股本 + # category in [2..10](股本变动类,单位:万股) + panqian_liutong: float | None = None # 盘前流通股本(万股) + panhou_liutong: float | None = None # 盘后流通股本(万股) + qian_zongguben: float | None = None # 前总股本(万股) + hou_zongguben: float | None = None # 后总股本(万股) _raw: bytes = field(default=b"", repr=False, compare=False) diff --git a/tests/unit/test_commands_offline.py b/tests/unit/test_commands_offline.py index 25352b7..cea9a01 100644 --- a/tests/unit/test_commands_offline.py +++ b/tests/unit/test_commands_offline.py @@ -263,6 +263,13 @@ def test_xdxr_info_parse(): assert all(len(r._raw) > 0 for r in recs) + # share count decode: 通达信自定义浮点,单位万股,与 FinanceInfo.zong_guben/10000 一致 + stock_recs = [r for r in recs if 2 <= r.category <= 10] + last = stock_recs[-1] + # 最近一条 hou_zongguben ≈ 3_330_583.75 万股(与 FinanceInfo.zong_guben 33_305_837_500 ÷ 10000 完全吻合) + assert last.hou_zongguben is not None + assert abs(last.hou_zongguben - 3_330_583.75) < 1.0 + # --------------------------------------------------------------------------- # finance_info