程序员量化交易实战 31:给每日任务加运行时间窗
原创 · 约 9 分钟阅读 · 阅读 --
Last updated on

程序员量化交易实战 31:给每日任务加运行时间窗

作者: Alex Xiang


程序员量化交易实战 31:给每日任务加运行时间窗

古董级程序员,大厂出来后一直在创业公司,现在仍活跃在一线做 AI 相关的开发。这个专栏会把一个 A 股量化平台从 0 到 1 拆开写:数据、策略、回测、模拟盘、提醒和生产化,尽量用真实代码和真实运行结果说话。更完整的更新也会同步到微信公众号「字与码」。

第 30 篇生成了每日运行健康报告。系统已经能告诉我们一次模拟盘运行是健康、警告还是阻断。

第 31 篇开始处理另一个生产化问题:任务不能什么时候想跑就跑。模拟盘日报如果在行情没收完、复权没更新、人工还没确认的时候运行,结果再漂亮也不可信。

ZiCode 工程师设置每日运行时间窗

时间窗解决什么

定时任务最怕两种错误。

一种是晚了不跑,日报缺一天。另一种是早了乱跑,拿着半截数据生成建议。

第 31 章不直接接 cron,也不绑定具体调度平台,只抽一个小对象:给定当前时间和允许运行窗口,判断现在能不能跑;如果不能跑,告诉调用方下一次窗口从什么时候开始。

场景结果
当前时间在窗口内allowed=True
当前时间在窗口外allowed=False,返回 next_run_at
窗口跨午夜支持 23:0001:00 这类配置

运行窗口对象

第 31 章新增 app/run_window.py

@dataclass(frozen=True)
class RunWindow:
    start: time
    end: time
    timezone_name: str = "Asia/Shanghai"


@dataclass(frozen=True)
class RunWindowStatus:
    allowed: bool
    reason: str
    next_run_at: datetime | None = None

这里的 timezone_name 暂时只是配置说明,当前判断直接使用传入 datetime 的时区。这样第一版足够简单,后面接真实调度时再统一做时区转换。

判断逻辑

普通时间窗很好判断,start <= now <= end

跨午夜窗口要单独处理,例如 23:0001:0000:30 也应该被允许。

def is_within_run_window(now: datetime, window: RunWindow) -> bool:
    current = now.time()
    if window.start <= window.end:
        return window.start <= current <= window.end
    return current >= window.start or current <= window.end

窗口外的场景会计算下一次开始时间。

candidate = datetime.combine(now.date(), window.start, tzinfo=now.tzinfo)
if candidate <= now:
    candidate += timedelta(days=1)

这段逻辑不主动睡眠,也不启动后台任务。它只提供一个确定的判定结果,方便上层调度器决定跳过、延迟还是报警。

当前联动运行结果

第 31-35 篇现在可以通过同一条命令运行:

uv run python -m scripts.chapter_examples paper-ops-check

这条命令会先判断运行时间窗,再生成归档、历史摘要、数据缺口计划和运维检查清单。时间窗部分输出如下:

paper-ops-check 命令生成的运行时间窗判断结果

示例里当前时间是 15:20,窗口是 15:10-15:40,所以 allowed=True。这里的判断不是策略逻辑,而是运行准入逻辑:系统先确认现在是可信的运行时段,再进入后面的归档和检查。

测试覆盖

这章的测试不复杂,但边界必须明确。

uv run pytest tests/test_run_window.py

测试覆盖三种情况:

  • 15:1015:40 内,15:20 允许运行。
  • 16:00 已经错过当天窗口,下一次运行时间是第二天 15:10
  • 23:0001:00 的跨午夜窗口,23:3000:30 都允许,02:00 不允许。

本章更新与代码仓库

本章更新内容:

  • 新增 app/run_window.py
  • 实现 RunWindowRunWindowStatus
  • 支持普通窗口和跨午夜窗口。
  • 窗口外返回下一次可运行时间。
  • 增加 paper-ops-check 联动示例,展示时间窗如何进入每日运维检查链路。
  • 新增 tests/test_run_window.py,覆盖窗口内、窗口外和跨午夜场景。

代码仓库:

https://github.com/ax2/zi-quant-platform

本章代码:

git clone https://github.com/ax2/zi-quant-platform.git
cd zi-quant-platform
git checkout chapter-31
uv sync --extra dev
uv run pytest tests/test_run_window.py

第 31 章提交为 4ce2ca8,tag 为 chapter-31

本篇小结

运行时间窗是一个很小的模块,但它把“什么时候可以跑”从调度器里抽了出来。

第 31 篇以后,每日流程不再只关心自己能不能算,还要先确认现在是不是一个可信的运行时间。下一篇会把每日运行结果落成稳定归档文件,方便后续做历史统计和追查。