diff --git a/backend/app/cli/sync.py b/backend/app/cli/sync.py index 6bd16f2..930ba98 100644 --- a/backend/app/cli/sync.py +++ b/backend/app/cli/sync.py @@ -91,21 +91,34 @@ def _symbols_of(args) -> list[str]: def cmd_daily(args) -> int: + from sqlalchemy import func + + from app.infrastructure.persistence.sqlalchemy.models.market import StockDailyModel + symbols = _symbols_of(args) start = _parse_day(args.start) if args.start else date(2005, 1, 1) end = _parse_day(args.end) if args.end else date.today() total = 0 + skipped = 0 with _session_ctx() as session: provider = _failover_provider(session) bar_repo = SqlAlchemyDailyBarRepository(session) factor_repo = SqlAlchemyAdjustFactorRepository(session) + # 增量基准:本地数据已到该日期即视为「已最新」,resume 时不再调 API + global_latest = ( + session.scalar(select(func.max(StockDailyModel.trade_date))) if args.resume else None + ) for i, symbol in enumerate(symbols, start=1): begin = start if args.resume: latest = bar_repo.latest_date(symbol) if latest is not None: + if global_latest is not None and latest >= global_latest: + skipped += 1 # 已同步到本地最新交易日,无需续拉 + continue begin = max(begin, latest + timedelta(days=1)) if begin > end: + skipped += 1 # 无待拉区间(如区间已含在本地) continue try: bars = provider.get_daily(symbol, begin, end) @@ -119,7 +132,10 @@ def cmd_daily(args) -> int: except DataSourceError as exc: print(f" [warn] {symbol} 拉取失败: {exc}", file=sys.stderr) session.commit() - print(f"[daily] {len(symbols)} 只股票合计写入 {total} 根日线(含复权因子)") + detail = f"[daily] {len(symbols)} 只股票合计写入 {total} 根日线(含复权因子)" + if args.resume: + detail += f";增量跳过(已最新){skipped} 只(本地最新 {global_latest})" + print(detail) return 0