mirror of
https://ghfast.top/https://github.com/aeroxw/easy-tdx.git
synced 2026-09-12 20:24:16 +08:00
Merge commit 'e3e8dd4'
# Conflicts: # CHANGELOG.md # pyproject.toml # src/easy_tdx/commands/security_bars.py
This commit is contained in:
@@ -1,15 +1,19 @@
|
||||
"""获取 K 线数据命令(支持全部周期)。"""
|
||||
|
||||
import logging
|
||||
import struct
|
||||
|
||||
from .._binary import unpack_from
|
||||
from ..codec.datetime_ import get_datetime
|
||||
from ..codec.price import get_price
|
||||
from ..codec.volume import get_volume
|
||||
from ..exceptions import TdxDecodeError
|
||||
from ..models.bar import SecurityBar
|
||||
from ..models.enums import KlineCategory, Market
|
||||
from .base import BaseCommand
|
||||
|
||||
_log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GetSecurityBarsCmd(BaseCommand[list[SecurityBar]]):
|
||||
"""获取指定股票的 K 线数据。
|
||||
@@ -63,12 +67,7 @@ class GetSecurityBarsCmd(BaseCommand[list[SecurityBar]]):
|
||||
pre_diff_base = 0
|
||||
cat = int(self.category)
|
||||
|
||||
# 服务器偶发返回的 ret_count 与 body 实际长度不匹配(pytdx/mootdx 均
|
||||
# 有类似报告):ret_count 撒谎或网络帧粘包/截断,循环到中途 pos 已
|
||||
# 读到底("剩余 0 字节")。改用"取 min(ret_count, body 可解析条数)"
|
||||
# 策略——TdxDecodeError 视为记录边界,提前结束循环并丢弃残缺尾记录,
|
||||
# 而不是让整批数据 500。调用方拿到的是完整记录(少几根 K 线比全崩好)。
|
||||
for _ in range(ret_count):
|
||||
for i in range(ret_count):
|
||||
record_start = pos
|
||||
try:
|
||||
year, month, day, hour, minute, pos = get_datetime(cat, body, pos)
|
||||
@@ -80,10 +79,21 @@ class GetSecurityBarsCmd(BaseCommand[list[SecurityBar]]):
|
||||
|
||||
vol, pos = get_volume(body, pos)
|
||||
amount, pos = get_volume(body, pos)
|
||||
except Exception:
|
||||
# 残缺尾记录:body 已读到底或字段不完整,丢弃本条并停止。
|
||||
# 不重新抛出—— degrade gracefully,返回已解析的完整记录。
|
||||
break
|
||||
except TdxDecodeError as e:
|
||||
# TDX 服务端偶发截断:响应头声称有 N 条,但 body 末尾若干条
|
||||
# 被切掉(停牌/退市/分页边界常见)。丢弃残缺的末条,保留已
|
||||
# 成功解析的前若干条,避免一条坏数据让整页 500。
|
||||
if bars:
|
||||
_log.warning(
|
||||
"K线响应在第 %d/%d 条处被截断(%s),已丢弃末尾残缺记录,"
|
||||
"返回前 %d 条",
|
||||
i + 1,
|
||||
ret_count,
|
||||
e,
|
||||
len(bars),
|
||||
)
|
||||
return bars
|
||||
raise
|
||||
|
||||
# 差分还原(与 pytdx 完全一致)
|
||||
open_abs = open_diff + pre_diff_base
|
||||
@@ -126,9 +136,7 @@ class GetIndexBarsCmd(GetSecurityBarsCmd):
|
||||
pre_diff_base = 0
|
||||
cat = int(self.category)
|
||||
|
||||
# 同 GetSecurityBarsCmd:ret_count 与 body 实际长度偶发不匹配,
|
||||
# 残缺尾记录提前 break,详见父类同名注释。
|
||||
for _ in range(ret_count):
|
||||
for i in range(ret_count):
|
||||
record_start = pos
|
||||
try:
|
||||
year, month, day, hour, minute, pos = get_datetime(cat, body, pos)
|
||||
@@ -143,9 +151,20 @@ class GetIndexBarsCmd(GetSecurityBarsCmd):
|
||||
|
||||
# 指数记录额外 4 字节:上涨家数 + 下跌家数(各 uint16 LE)
|
||||
pos += 4
|
||||
except Exception:
|
||||
break
|
||||
except TdxDecodeError as e:
|
||||
if bars:
|
||||
_log.warning(
|
||||
"指数K线响应在第 %d/%d 条处被截断(%s),已丢弃末尾残缺记录,"
|
||||
"返回前 %d 条",
|
||||
i + 1,
|
||||
ret_count,
|
||||
e,
|
||||
len(bars),
|
||||
)
|
||||
return bars
|
||||
raise
|
||||
|
||||
# 差分还原(与 pytdx 完全一致)
|
||||
open_abs = open_diff + pre_diff_base
|
||||
close_abs = open_abs + close_diff
|
||||
high_abs = open_abs + high_diff
|
||||
|
||||
Reference in New Issue
Block a user