feat(data): 财务/日线同步增量 + 新浪「两边一致」校验兜底 + 逐只进度
- financial 默认增量:按 A 股披露节奏判断已最新并跳过;--full 强制全量重拉 - Tushare fina_indicator 增加报告期窗口与 100 条/请求自动分页(修复老报告期静默截断) - 新浪兜底收紧为校验兜底:两源重叠历史一致才导入缺失键,行标记 source=sina; 财务可比字段取 eps/销售毛利率(ROE 两端口径不同不作依据),日线只比较最近重叠交易日 - CLI 输出逐只进度与导入内容描述(来源/行数/报告期与公告区间),失败股票留待重跑 - financial_indicator 增 source 列(迁移 d3f6c9a21b04);新增一致性/分页/服务测试
This commit is contained in:
@@ -169,3 +169,58 @@ class TestRateLimitBackoff:
|
||||
ts_mod.time.sleep = orig_sleep
|
||||
assert len(provider._pro.calls) == 3 # noqa: SLF001 —— 完整重试 3 次
|
||||
assert len(sleeps) >= 2
|
||||
|
||||
|
||||
def _quarter_ends(count: int) -> list[str]:
|
||||
"""最近 count 个季度末(YYYYMMDD,降序)。"""
|
||||
|
||||
ends: list[str] = []
|
||||
y, m = 2026, 6
|
||||
while len(ends) < count:
|
||||
ends.append(f"{y}{m:02d}30" if m in (6, 9) else f"{y}{m:02d}31")
|
||||
m -= 3
|
||||
if m <= 0:
|
||||
m += 12
|
||||
y -= 1
|
||||
return ends
|
||||
|
||||
|
||||
class _FakeProQueue:
|
||||
"""按调用顺序弹出 payload 的 Fake pro(模拟分页)。"""
|
||||
|
||||
def __init__(self, payloads: list[list[dict]]) -> None:
|
||||
self.payloads = list(payloads)
|
||||
self.kwargs: list[dict] = []
|
||||
|
||||
def fina_indicator(self, **kwargs):
|
||||
self.kwargs.append(kwargs)
|
||||
return self.payloads.pop(0)
|
||||
|
||||
|
||||
class TestGetFinancialWindow:
|
||||
def _record(self, end: str) -> dict:
|
||||
return {"ts_code": "600519.SH", "end_date": end, "ann_date": end, "eps": "1.0"}
|
||||
|
||||
def test_window_args_passed(self) -> None:
|
||||
ends = _quarter_ends(10)
|
||||
fake = _FakeProQueue([[self._record(e) for e in ends]])
|
||||
provider = TushareProvider(token="t", pro=fake)
|
||||
rows = provider.get_financial("600519.SH", date(2024, 1, 1), date(2026, 6, 30))
|
||||
assert len(rows) == 10
|
||||
assert fake.kwargs[0]["start_date"] == "20240101"
|
||||
assert fake.kwargs[0]["end_date"] == "20260630"
|
||||
|
||||
def test_paging_over_100_row_cap(self) -> None:
|
||||
"""单请求最多 100 条 → 超过必须回卷报告期窗口继续取,老数据不丢。"""
|
||||
newest = _quarter_ends(100)
|
||||
older = _quarter_ends(140)[100:] # 100 条之外更早的 40 个季度
|
||||
# 二次请求 end_date 必须早于首请求(分页回卷)
|
||||
fake = _FakeProQueue(
|
||||
[[self._record(e) for e in newest], [self._record(e) for e in older]]
|
||||
)
|
||||
provider = TushareProvider(token="t", pro=fake)
|
||||
rows = provider.get_financial("600519.SH", date(2000, 1, 1), date(2026, 6, 30))
|
||||
assert len(rows) == 100 + 40
|
||||
assert len(fake.kwargs) == 2
|
||||
assert fake.kwargs[1]["end_date"] < fake.kwargs[0]["end_date"]
|
||||
assert {r.report_date for r in rows} == {date.fromisoformat(e[:4] + "-" + e[4:6] + "-" + e[6:]) for e in newest + older}
|
||||
|
||||
Reference in New Issue
Block a user