快速开始
创建本地环境
uv venv
uv pip install --python .venv -e .[dev,docs]
运行测试
uv run --python .venv\Scripts\python.exe pytest tests
运行 CLI
uv run --python .venv\Scripts\python.exe python -m zelqor.cli --help
运行最小回测请求
可以先准备一个 request.json:
{
"schemaVersion": 2,
"marketData": {
"type": "clickhouse",
"source": {
"mode": "config_file",
"configPath": "config.toml"
}
},
"strategy": {
"type": "python_file",
"path": "examples/loadable_selector_strategy.py",
"kind": "selector"
},
"metadata": {
"requestId": "bt_quickstart_001",
"caller": "quickstart"
},
"dateRange": {
"startDate": "2025-03-24",
"endDate": "2025-03-28"
},
"capital": {
"initialCash": 100000
},
"runtime": {
"output": {
"includeDailyPools": true,
"includeDailyDecisions": true,
"includeTrades": true,
"includePositionsByDate": true,
"includeEquityCurve": true
}
},
"params": {
"limit": 2
}
}
然后执行:
uv run --python .venv\Scripts\python.exe python -m zelqor.cli run-backtest --request-file request.json
如果你只想看轻量结果,可以改成:
uv run --python .venv\Scripts\python.exe python -m zelqor.cli run-backtest --request-file request.json --summary-only
如果你想把结果直接写到文件,可以改成:
uv run --python .venv\Scripts\python.exe python -m zelqor.cli run-backtest --request-file request.json --output-file result.json
如果你想直接拿统一任务 envelope,可以改成:
uv run --python .venv\Scripts\python.exe python -m zelqor.cli run-backtest --request-file request.json --task-envelope
仓库里也已经放好了两个可直接参考的请求模板:
examples/request_loadable_selector.jsonexamples/request_loadable_stateful_step.json
现在这条命令会真实执行:
- 加载 ClickHouse provider
- 加载
examples/loadable_selector_strategy.py - 按交易日运行 selector
- 输出真实
BacktestResult
如果你想改成 stateful step 示例,可以把 strategy.path 改成:
examples/loadable_stateful_step_strategy.py
如果你想走模块路径加载,可以把 strategy 改成:
{
"type": "python_module",
"path": "zelqor.strategy.examples.loadable_selector_module",
"kind": "selector"
}
当前 schema 已经统一为 strategy 字段。
marketData 现在也支持更正式的配置来源写法:
marketData.source.mode == "config_file"marketData.source.mode == "env"
另外,宿主现在可以通过 runtime.output 控制结果保留项。
CLI 返回的 BacktestResult 现在也会稳定包含:
metadataruntime.outputAppliedruntime.omittedSections
另外,直接调用:
run_selector_backtest(...)run_stateful_step_backtest(...)
返回的 BacktestResult 现在也会保留传入的宿主 metadata。
这几个 direct API 现在同样支持传入 runtime,用法和 request 模式下的 runtime.output 保持一致。
如果你在 Python 宿主里更希望得到“成功结果或错误结果”的统一返回值,而不是自己包装异常,可以使用:
run_backtest_safe(...)
如果你想进一步拿到固定 envelope 形状:
okrequestIdresulterror
可以使用:
run_backtest_task(...)
如果请求里带了 metadata.requestId,CLI 在校验失败或运行失败时也会尽量把这个 requestId 带回错误 JSON。
CLI 的失败输出现在也是结构化结果,至少包含:
okcodemessagestagerequestIddetails
CLI 的成功输出现在支持:
- 默认完整
BacktestResult --summary-only--output-file--task-envelope
如果你之前已经写过旧请求文件,需要同步改名:
selector->strategyselectorType->strategyTypemarketData.configPath/useEnv->marketData.source
运行最小回测执行核心
当前仓库已经有一个最小可运行的回测执行核心,入口在:
zelqor.backtest.run_precomputed_pool_backtestzelqor.api.run_precomputed_backtestzelqor.backtest.scheduler.DayCallbackPayloadzelqor.backtest.create_backtest_statezelqor.backtest.step_backtest_dayzelqor.backtest.finalize_backtest_result
这条链路当前适合:
- 已经有交易日列表
- 已经有每日股票池
daily_pools - 想先验证买入、持有、卖出和权益变化
- 想在回测过程中逐日观察股票池、成交和权益变化
当前最小回测执行核心支持的成交时点包括:
opennext_openhighhigh_limitlimit_upaverageavgvwap- 默认
close
其中平均价口径为:
amount / volume- 如果
volume <= 0,则自动回退到close
对应实现见:
src/zelqor/backtest/engine.pysrc/zelqor/backtest/scheduler.pytests/test_backtest_engine.py
如果你想直接体验逐日推进骨架,可以运行:
examples/run_step_backtest.py
这个示例会:
- 创建
BacktestState - 构造
BacktestStepConfig - 按交易日循环调用
step_backtest_day(...) - 最后通过
finalize_backtest_result(...)汇总最终结果
运行方式:
uv run --python .venv\Scripts\python.exe examples/run_step_backtest.py
运行 selector 回测最小链路
当前仓库也已经打通了一条更接近日频股票池策略的最小链路,入口在:
zelqor.strategy.interfaces.DailyPoolSelectorzelqor.strategy.interfaces.SelectorContextzelqor.strategy.selector.build_daily_poolszelqor.api.run_selector_backtest
这条链路当前适合:
- selector 直接在策略脚本中实现
- 每个交易日先生成股票池
- 再把
daily_pools交给最小回测执行核心
对应实现见:
src/zelqor/strategy/interfaces.pysrc/zelqor/strategy/selector.pysrc/zelqor/api.pytests/test_selector_pipeline.py
运行 stateful step 策略最小链路
当前仓库已经支持更适合复杂跨日状态策略的正式接入方式,入口在:
zelqor.strategy.interfaces.StrategyStepContextzelqor.strategy.interfaces.StrategyDayDecisionzelqor.strategy.interfaces.StatefulStepStrategyzelqor.api.run_stateful_step_backtest
这条链路当前适合:
- 策略需要维护观察池、待确认池或冷却期
- 每个交易日都要推进自己的内部状态机
- 策略负责决定今天买入池,引擎负责成交、持仓和权益
对应实现见:
src/zelqor/strategy/interfaces.pysrc/zelqor/api.pyexamples/run_stateful_step_limit_up_then_limit_up.pytests/test_stateful_strategy_pipeline.py
如果你想看当前仓库内一个完整的 stateful step 示例,可以运行:
examples/run_stateful_step_limit_up_then_limit_up.py
这个示例当前演示的是:
- 首次涨停先进入待入池列表
- 下一交易日收盘后才正式进入观察池
- 后续再次涨停触发买入
- 每个交易日结束后实时打印状态、买卖和权益
运行方式:
uv run --python .venv\Scripts\python.exe examples/run_stateful_step_limit_up_then_limit_up.py
如果你想更详细理解这个示例内部是怎么运作的,可以继续看:
docs/stateful-step-example.md
使用 ClickHouse 配置
环境变量方式:
$env:CH_HOST="127.0.0.1"
$env:CH_USER="default"
$env:CH_PASSWORD="secret"
$env:CH_DATABASE="jqdata"
Python 中读取:
from zelqor.models import ClickHouseConfig
config = ClickHouseConfig.from_env()
更多配置方式见“ClickHouse 配置”页面。
使用日志
zelqor 现在内置了基于标准库 logging 的日志能力。
默认日志级别来源于:
ZELQOR_LOG_LEVEL
例如:
$env:ZELQOR_LOG_LEVEL="INFO"
如果你要看更细节的 SQL 和内部流程,可以改成:
$env:ZELQOR_LOG_LEVEL="DEBUG"
examples 里的常用脚本已经会自动初始化日志。
当前日志会覆盖这些关键节点:
- ClickHouse 配置加载
- ClickHouseProvider 初始化
- 交易日 / universe / bars 查询
- selector 每日执行
- 回测开始 / 结束
- 每个交易日的推进
- 买入 / 卖出成交
运行配置加载示例
仓库内提供了一个最小配置示例:
examples/load_config.py
它会演示:
ClickHouseConfig.from_file(...)ClickHouseConfig.from_env()
运行方式:
uv run --python .venv\Scripts\python.exe examples/load_config.py
验证远程 ClickHouse 连通性
仓库内提供了一个真实库联调测试:
tests/test_clickhouse_live_integration.py
推荐步骤:
- 复制
config.example.toml为本地config.toml - 按你的远程 ClickHouse 信息修改配置
- 执行真实联调测试
uv run --python .venv\Scripts\python.exe pytest tests/test_clickhouse_live_integration.py -q
如果没有找到配置文件,测试会自动 skip,不会误报失败。
运行最小日线读取示例
仓库内提供了一个最小可运行示例:
examples/read_daily_bars.py
它会优先读取仓库根目录下的 config.toml,如果没有找到,则回退到环境变量。
它会在同一个文件里分别调用:
provider.get_daily_bars(..., as_numpy=False)provider.get_daily_bars(..., as_numpy=True)
运行方式:
uv run --python .venv\Scripts\python.exe examples/read_daily_bars.py
运行交易日示例
如果你想看交易日列表和下一交易日:
examples/read_trading_dates.py
运行方式:
uv run --python .venv\Scripts\python.exe examples/read_trading_dates.py
运行 universe 示例
如果你想看某个交易日的股票池:
examples/read_universe.py
运行方式:
uv run --python .venv\Scripts\python.exe examples/read_universe.py
运行最近 N 根日线读取示例
仓库内也提供了一个窗口读取示例:
examples/read_recent_bars.py
它会在同一个文件里分别调用:
provider.get_bars(..., count=20, as_numpy=False)provider.get_bars(..., count=20, as_numpy=True)
运行方式:
uv run --python .venv\Scripts\python.exe examples/read_recent_bars.py
运行兼容层示例
如果你想看旧脚本风格的 get_bars_compat(...):
examples/get_bars_compat.py
运行方式:
uv run --python .venv\Scripts\python.exe examples/get_bars_compat.py
运行最小回测执行核心示例
如果你想直接验证当前最小回测执行核心:
examples/run_precomputed_backtest.py
这个示例会:
- 读取一小段交易日
- 从第一天的 universe 中取前两只股票作为
daily_pools - 调用
run_precomputed_backtest(...) - 打印 summary、成交数量和最后一天权益
运行方式:
uv run --python .venv\Scripts\python.exe examples/run_precomputed_backtest.py
运行 selector 回测示例
如果你想直接验证 selector -> daily_pools -> backtest:
examples/run_selector_backtest.py
这个示例会:
- 读取一小段交易日
- 在每个交易日调用 selector 生成股票池
- 调用
run_selector_backtest(...) - 通过
on_day逐日打印股票池、买卖和权益 - 打印 summary、第一天股票池和第一笔成交
运行方式:
uv run --python .venv\Scripts\python.exe examples/run_selector_backtest.py
使用逐日回调
run_precomputed_backtest(...)、run_selector_backtest(...) 和 run_stateful_step_backtest(...) 现在都支持:
on_day
你可以传入一个回调函数,在每个交易日结束后获取一份摘要:
from zelqor.backtest.scheduler import DayCallbackPayload
def on_day(payload: DayCallbackPayload) -> None:
print(payload.trade_date, payload.pool_codes, payload.buys, payload.sells, payload.equity)
当前回调对象里包含:
trade_datepool_codesbuyssellsnotescashmarket_valueequitypositionswarnings
运行 selector 策略骨架示例
如果你想看更接近真实策略代码的写法,仓库里还提供了两个骨架:
examples/selector_numpy_skeleton.pyexamples/selector_polars_skeleton.py
这两个示例分别展示:
- 如何使用
SelectorContext + 结构化 NumPy - 如何使用
SelectorContext + Polars
运行方式:
uv run --python .venv\Scripts\python.exe examples/selector_numpy_skeleton.py
uv run --python .venv\Scripts\python.exe examples/selector_polars_skeleton.py
构建文档站
uv run --python .venv\Scripts\python.exe mkdocs build
本地预览文档站
uv run --python .venv\Scripts\python.exe mkdocs serve