mirror of
https://ghfast.top/https://github.com/aeroxw/tick-stock-panel.git
synced 2026-09-12 22:34:18 +08:00
- #224 screener 自定义 SQL 的内存连接关闭 enable_external_access, 注入的 read_parquet/COPY 文件读写直接报错 (安全) - #232 指数展示缓存百分数口径在消费边界显式 /100: pipeline._bench_rt_pct_of 与 abnormal_moves._bench_rt_pct 两处, 修复 3/10/30 日偏离值被放大两个数量级 - #223 盘后管道按同日 daily/enriched 行数比较检测实时合并提前 创建的部分分区, 删除后由增量重算全市场补齐 - #215 _basic_filter_for_asset 扩展中和股票专属键 (price_min/max/boards), 并应用到回测/挖掘/策略扫描三个运行期入口, 修复 ETF 静默零信号
63 lines
2.5 KiB
Python
63 lines
2.5 KiB
Python
"""#223 回归: 盘后管道必须识别并重算覆盖不全的 enriched 分区。
|
|
|
|
自选实时路径 (merge_live_enriched_asset) 会在全市场 enriched 生成前提前
|
|
创建当日分区 (只有几只自选); 仅按日期目录计数比较会把它误判为完整分区
|
|
而跳过计算, 造成日K连续缺失与均线错误。_prune_partial_enriched_partitions
|
|
按同日 daily/enriched 行数比较, 发现部分分区即删除, 让增量重算按"新日期"
|
|
全市场补齐。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from datetime import date
|
|
from pathlib import Path
|
|
|
|
import polars as pl
|
|
|
|
from app.jobs.daily_pipeline import _prune_partial_enriched_partitions
|
|
|
|
|
|
def _write_partition(base: Path, day: str, symbols: list[str]) -> None:
|
|
part = base / f"date={day}"
|
|
part.mkdir(parents=True, exist_ok=True)
|
|
pl.DataFrame({"symbol": symbols, "close": [1.0] * len(symbols)}).write_parquet(
|
|
part / "part.parquet"
|
|
)
|
|
|
|
|
|
def test_partial_partition_is_pruned(tmp_path) -> None:
|
|
daily = tmp_path / "kline_daily"
|
|
enriched = tmp_path / "kline_daily_enriched"
|
|
# 2026-08-28: daily 全市场 100 只, enriched 只有实时写入的 5 只 (issue 实测形态)
|
|
_write_partition(daily, "2026-08-28", [f"s{i:06d}" for i in range(100)])
|
|
_write_partition(enriched, "2026-08-28", [f"s{i:06d}" for i in range(5)])
|
|
# 前一日两边都是完整的 → 不动
|
|
_write_partition(daily, "2026-08-27", ["a", "b"])
|
|
_write_partition(enriched, "2026-08-27", ["a", "b"])
|
|
|
|
pruned = _prune_partial_enriched_partitions(daily, enriched)
|
|
|
|
assert pruned == ["2026-08-28"]
|
|
assert not (enriched / "date=2026-08-28").exists()
|
|
assert (enriched / "date=2026-08-27").exists() # 完整分区保留
|
|
|
|
|
|
def test_complete_partitions_untouched(tmp_path) -> None:
|
|
daily = tmp_path / "kline_daily"
|
|
enriched = tmp_path / "kline_daily_enriched"
|
|
syms = [f"s{i:06d}" for i in range(50)]
|
|
_write_partition(daily, "2026-09-01", syms)
|
|
_write_partition(enriched, "2026-09-01", syms)
|
|
|
|
assert _prune_partial_enriched_partitions(daily, enriched) == []
|
|
assert (enriched / "date=2026-09-01" / "part.parquet").exists()
|
|
|
|
|
|
def test_enriched_date_without_daily_is_left_alone(tmp_path) -> None:
|
|
# 今日日K尚未同步时, 实时创建的当日分区留给当日正常流程处理
|
|
daily = tmp_path / "kline_daily"
|
|
enriched = tmp_path / "kline_daily_enriched"
|
|
_write_partition(enriched, str(date.today()), ["only_watchlist"])
|
|
|
|
assert _prune_partial_enriched_partitions(daily, enriched) == []
|
|
assert (enriched / f"date={date.today()}").exists()
|