mirror of
https://ghfast.top/https://github.com/aeroxw/easy_tdx_max.git
synced 2026-09-12 20:24:19 +08:00
feat: 完善实时行情字段并增加大文件拉取功能
1. 行情增强:解析 SecurityQuote 中的 limit_up (涨停价) 和 limit_down (跌停价)。 2. 新增命令:实现 GetReportFileCmd (0x06B9),支持从服务器拉取 base_info.zip 等大文件。 3. 客户端 API:TdxClient/AsyncTdxClient 增加 get_report_file 方法,支持自动分片。 4. 验证脚本:增加 verify_limits.py 和 verify_report_file.py 实测脚本。 5. 文档更新:README.md 同步 API 变更及数据模型更新。
This commit is contained in:
@@ -8,6 +8,7 @@ from .commands.base import BaseCommand
|
||||
from .commands.block_info import GetBlockInfoCmd, GetBlockInfoMetaCmd
|
||||
from .commands.company_info import GetCompanyInfoCategoryCmd, GetCompanyInfoContentCmd
|
||||
from .commands.finance_info import GetFinanceInfoCmd
|
||||
from .commands.report_file import GetReportFileCmd
|
||||
from .commands.minute_time import GetHistoryMinuteTimeDataCmd, GetMinuteTimeDataCmd
|
||||
from .commands.security_bars import GetIndexBarsCmd, GetSecurityBarsCmd
|
||||
from .commands.security_count import GetSecurityCountCmd
|
||||
@@ -253,6 +254,21 @@ class TdxClient:
|
||||
pos += len(chunk)
|
||||
return parse_block_dat(bytes(full_data), filename)
|
||||
|
||||
def get_report_file(self, filename: str) -> bytes:
|
||||
"""从服务器拉取大文件(如 'base_info.zip')。"""
|
||||
full_data = bytearray()
|
||||
pos = 0
|
||||
chunk_size = 30000
|
||||
while True:
|
||||
chunk = self._execute(GetReportFileCmd(filename, pos, chunk_size))
|
||||
if not chunk:
|
||||
break
|
||||
full_data.extend(chunk)
|
||||
pos += len(chunk)
|
||||
if len(chunk) < chunk_size:
|
||||
break
|
||||
return bytes(full_data)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 异步客户端
|
||||
@@ -423,3 +439,19 @@ class AsyncTdxClient:
|
||||
full_data.extend(chunk)
|
||||
pos += len(chunk)
|
||||
return parse_block_dat(bytes(full_data), filename)
|
||||
|
||||
async def get_report_file(self, filename: str) -> bytes:
|
||||
"""从服务器拉取大文件。"""
|
||||
full_data = bytearray()
|
||||
pos = 0
|
||||
chunk_size = 30000
|
||||
while True:
|
||||
chunk = await self._execute(GetReportFileCmd(filename, pos, chunk_size))
|
||||
if not chunk:
|
||||
break
|
||||
full_data.extend(chunk)
|
||||
pos += len(chunk)
|
||||
if len(chunk) < chunk_size:
|
||||
break
|
||||
return bytes(full_data)
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
"""大文件拉取命令(用于 base_info.zip, gpcw.txt 等)。"""
|
||||
|
||||
import struct
|
||||
|
||||
from .._binary import slice_bytes, unpack_from
|
||||
from ..exceptions import TdxDecodeError
|
||||
from .base import BaseCommand
|
||||
|
||||
|
||||
class GetReportFileCmd(BaseCommand[bytes]):
|
||||
"""分段获取服务器上的报表或基础信息文件。
|
||||
|
||||
Args:
|
||||
filename: 远程文件名。
|
||||
start: 起始偏移量。
|
||||
length: 请求数据长度(建议 30000)。
|
||||
"""
|
||||
|
||||
def __init__(self, filename: str, start: int, length: int = 30000) -> None:
|
||||
self.filename = filename.encode("ascii")
|
||||
self.start = start
|
||||
self.length = length
|
||||
|
||||
def build_request(self) -> bytes:
|
||||
# 使用与 GetBlockInfo 相同的格式:0x06B9
|
||||
header = bytes.fromhex("0c37186a00016e006e00b906")
|
||||
payload = struct.pack("<II", self.start, self.length)
|
||||
payload += (self.filename + b"\x00" * 100)[:100]
|
||||
return header + payload
|
||||
|
||||
def parse_response(self, body: bytes) -> bytes:
|
||||
if len(body) < 4:
|
||||
return b""
|
||||
return body[4:]
|
||||
@@ -195,6 +195,8 @@ class GetSecurityQuotesCmd(BaseCommand[list[SecurityQuote]]):
|
||||
ask5=(price_raw + ask5_d) / 100.0,
|
||||
ask_vol5=float(av5),
|
||||
rise_speed=rise_speed_raw / 100.0,
|
||||
limit_up=(price_raw + unknown_2) / 100.0,
|
||||
limit_down=(price_raw + unknown_3) / 100.0,
|
||||
unknown_2=unknown_2,
|
||||
unknown_3=unknown_3,
|
||||
unknown_5=unknown_5,
|
||||
|
||||
@@ -58,12 +58,14 @@ class SecurityQuote:
|
||||
ask5: float
|
||||
ask_vol5: float
|
||||
|
||||
# 已确认含义
|
||||
# 价格指标
|
||||
rise_speed: float # 涨速(原 reversed_bytes9 / 100)
|
||||
limit_up: float # 涨停价(由 unknown_2 / 100 转换)
|
||||
limit_down: float # 跌停价(由 unknown_3 / 100 转换)
|
||||
|
||||
# 未知字段:买卖量之后的两个变长整数
|
||||
unknown_2: int = field(default=0, repr=False) # 原 reversed_bytes2
|
||||
unknown_3: int = field(default=0, repr=False) # 原 reversed_bytes3
|
||||
# 未知字段:买卖量之后的两个变长整数(保留供进一步分析)
|
||||
unknown_2: int = field(default=0, repr=False) # 原始涨停价整数(price_raw + diff)
|
||||
unknown_3: int = field(default=0, repr=False) # 原始跌停价整数(price_raw + diff)
|
||||
|
||||
# 未知字段:尾部四个变长整数
|
||||
unknown_5: int = field(default=0, repr=False) # 原 reversed_bytes5
|
||||
|
||||
Reference in New Issue
Block a user