compare_strategies
Launch multiple backtest configs as one combined job, then poll a single job ID for progress and compare strategy results.
Instructions
Compare 2+ backtest configs sequentially and return one combined job.
Not confirm-gated (ADR-0003): same reasoning as start_backtest --
only ever starts simulations. configs is a list (len(configs) >= 2)
of dicts, each shaped exactly like one of start_backtest's own
mode-specific input shapes ({"mode": "data_files", "files": [...], ...} or {"mode": "current_bot_data", "exchange_id": ..., ...}), plus
an optional "label" key used as that config's own config_label in
get_job_result's later comparison/diff output (see
_child_config_label) -- stripped before being validated/passed to
start_backtest's own mode builders, which know nothing about it.
name is accepted (per the spec's input shape) but not otherwise used:
neither this tool's own output nor get_job_result's compare_strategies
output shape (both fully spec'd) has anywhere to put it.
Every config is validated (same rules start_backtest itself applies)
BEFORE any job -- parent or child -- is created, so a bad configs
entry never leaves a dangling queued job behind: raises
CompareStrategiesStartFailedError naming the offending configs[i]
for len(configs) < 2, an unknown mode, a missing required field for
that mode, or an unrecognized field name.
Creates one parent job (kind: "compare_strategies") with one child
kind: "backtest" job per config (job.child_job_ids, in the same
order as configs), then spawns ONE background asyncio.Task (tracked
via store.track_watcher_task, same as start_backtest) running
_run_compare_strategies, which submits each child sequentially
through the shared backtest_execution_lock -- see that function's own
docstring for the full sequencing/failure-isolation/cancellation
behavior.
Output: {"job_id": str, "state": "queued"|"running", "sub_job_count": int} -- returns immediately, same non-blocking pattern as
start_backtest (always "queued" in practice, since
asyncio.create_task never runs any of the background task
synchronously before this function returns). Poll get_job_status(job_id)
for combined progress/ETA and each child's own live state
(sub_jobs); call get_job_result(job_id) once state == "completed".
Progress notifications (milestone 11, ADR-0002 decision point 3): if
THIS call (the parent) carries a progressToken, notifications report
the COMBINED progress across all children (the exact same formula
get_job_status already uses for polling reads), never one child's own
raw percentage -- see _run_compare_strategies/
_make_compare_strategies_on_tick's own docstrings. Children are never
independently callable, so they never carry their own token.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| configs | Yes |