From ecbb45b8ef22b2c4b455f3caa0b397fdd7e9fa8c Mon Sep 17 00:00:00 2001 From: shy3130 <415333856@qq.com> Date: Sun, 6 Sep 2026 22:35:24 +0800 Subject: [PATCH] =?UTF-8?q?feat(pipeline):=20=E7=9B=98=E5=90=8E=E7=AE=A1?= =?UTF-8?q?=E9=81=93=E9=BB=98=E8=AE=A4=2015:35,=20=E4=B8=8E=E7=9B=98?= =?UTF-8?q?=E5=90=8E=E5=9B=BA=E5=AE=9A=E4=BB=B7=E7=BB=88=E7=82=B9=20(15:30?= =?UTF-8?q?)=20=E6=8B=89=E5=BC=80=E7=BC=93=E5=86=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实测 2026-09-04 数据: 836 只可比标的中 24 只日K量大于分钟K合计 (最大 5.4%), 差额产生于 15:00 收盘后的盘后时段 (盘后固定价/大宗类成交计入 日成交量但不产生分钟K) —— 盘中实时落盘的日K注定缺失该尾巴, 只有 15:30 之后的官方日线才完整。 - 默认调度 15:30 → 15:35: 避开供应商日线未定稿窗口, 也与 quote 定版 重试窗口终点 (15:30) 不再精确重合 - set_pipeline_schedule 保存下限从 15:00 收紧到 15:35 (存量已存配置 不迁移, 读取不钳制, 仅下次显式保存时生效) - 定时复盘默认 15:10 (即时复盘走实时快照缓存, 不依赖管道) 刻意不动 验证: set 钳制冒烟 (15:30→15:35, 15:35/15:36 原样); ruff 与 HEAD 基线 一致无新增; pytest prefer/pipeline/daily 相关 128 通过。 --- backend/app/jobs/daily_pipeline.py | 5 +++-- backend/app/services/preferences.py | 18 ++++++++++++------ docs/features.md | 4 ++-- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/backend/app/jobs/daily_pipeline.py b/backend/app/jobs/daily_pipeline.py index 5ed61fd..fdc38f5 100644 --- a/backend/app/jobs/daily_pipeline.py +++ b/backend/app/jobs/daily_pipeline.py @@ -2,7 +2,8 @@ 调度: 09:10 盘前 — 同步个股维表 instruments (全量覆盖) - 15:30 盘后 — 日K同步 + 增量除权因子 + enriched 计算 + 刷新视图 + 15:35 盘后 — 日K同步 + 增量除权因子 + enriched 计算 + 刷新视图 + (默认 15:35: 盘后固定价 15:30 终止 + 供应商日线定稿缓冲, 见 preferences) 盘后同步策略: 日 K: QuoteService 交易时段已实时落盘 → 有数据时跳过 batch,首次拉 1 年区间 @@ -1123,7 +1124,7 @@ def start_scheduler(repo: KlineRepository, capset: CapabilitySet) -> AsyncIOSche """启动调度器。 工作日 09:10 — 同步个股维表 - 工作日 HH:MM — 盘后管道(时间由用户偏好决定,默认 15:30) + 工作日 HH:MM — 盘后管道(时间由用户偏好决定,默认 15:35) """ from app.services import preferences sched = preferences.get_pipeline_schedule() diff --git a/backend/app/services/preferences.py b/backend/app/services/preferences.py index 45ffdda..210761a 100644 --- a/backend/app/services/preferences.py +++ b/backend/app/services/preferences.py @@ -487,17 +487,23 @@ def set_pipeline_index_symbols(symbols: str) -> str: def get_pipeline_schedule() -> dict: - """返回盘后管道调度时间 {"hour": 15, "minute": 30}。""" - d = load().get("pipeline_schedule", {"hour": 15, "minute": 30}) - return {"hour": d.get("hour", 15), "minute": d.get("minute", 30)} + """返回盘后管道调度时间 {"hour": 15, "minute": 35}。 + + 默认 15:35 而非 15:30 整: 盘后固定价交易 15:30 才彻底结束, 且供应商 + 聚合含盘后量的官方日K需要时间 —— 整点即拉可能写入不含盘后成交的 + 日线, 也与 quote 定版重试窗口终点 (15:30) 精确重合。留 5 分钟缓冲。 + """ + d = load().get("pipeline_schedule", {"hour": 15, "minute": 35}) + return {"hour": d.get("hour", 15), "minute": d.get("minute", 35)} def set_pipeline_schedule(hour: int, minute: int) -> dict: h = max(0, min(23, hour)) m = max(0, min(59, minute)) - # 盘后不早于 15:00 - if h * 60 + m < 15 * 60: - h, m = 15, 0 + # 盘后管道不早于 15:35: 15:30 盘后固定价才终止 (量/额此前仍会变), + # 且供应商官方日线定稿需要缓冲 —— 更早启动可能固化不含盘后量的当日分区 + if h * 60 + m < 15 * 60 + 35: + h, m = 15, 35 save({"pipeline_schedule": {"hour": h, "minute": m}}) return {"hour": h, "minute": m} diff --git a/docs/features.md b/docs/features.md index 495b78a..03a8afa 100644 --- a/docs/features.md +++ b/docs/features.md @@ -34,7 +34,7 @@ - **原子信号**:MA / MACD 金叉死叉 · N 日新高新低 · 布林突破 - **复权**:基于除权因子自动前复权,回测与指标口径一致 -盘后管道(15:30 CST 自动触发)会重新拉日 K + 重算 enriched 表。 +盘后管道(默认 15:35 CST 自动触发; 盘后固定价 15:30 终止 + 供应商日线定稿缓冲)会重新拉日 K + 重算 enriched 表。 --- @@ -202,7 +202,7 @@ timeseries 模式的表 (如人气排行) 默认只能从开启拉取之日起 ### 盘后定时管道 -APScheduler 15:30 CST 自动:拉日 K → 重算 enriched 表 → 跑监控规则。 +APScheduler 默认 15:35 CST 自动:拉日 K → 重算 enriched 表 → 跑监控规则。 ### 令牌桶限流