Non-Interactive Dispatch
qx.dispatch() opens an interactive menu. You pick a mode, select a tune, watch the results. That's fine at a terminal. But what if you want to run a backtest from a cron job? Re-optimize overnight without a screen? Run a papertrade in a Docker container with no stdin?
You need dispatch without the interactive part.
Set the environment variable QTRADEX_NONINTERACTIVE to any truthy value:
QTRADEX_NONINTERACTIVE=1 python mybot.py
Instead of the menu, dispatch parses CLI flags from sys.argv and runs the specified action directly. No prompts, no animations, no select() menus. Just the result.
Tune selection
You need to tell dispatch which parameter set to use. Every action except --optimize needs a tune loaded into the bot first.
| Flag | Behavior |
|---|---|
--tune best |
Best ROI tune from saved tunes (default) |
--tune latest |
Most recently saved tune |
--tune bot |
Use bot.tune defaults as-is |
--tune drop |
Use midpoints from self.clamps (neutral starting point) |
QTRADEX_NONINTERACTIVE=1 python mybot.py --tune best --backtest
If no saved tunes exist and you use --tune best or --tune latest, dispatch falls back to bot.tune.
Actions
Exactly one action flag runs per invocation. If you specify more than one, the first in this order wins: --optimize, --backtest, --papertrade, --autobacktest, --monte-carlo.
--backtest (default)
Runs a backtest with plot=False, show=False — no UI output. The metrics dict is printed to stdout:
QTRADEX_NONINTERACTIVE=1 python mybot.py
No action flag = backtest mode by default.
--optimize [NAME]
Runs the specified optimizer. Valid names: QPSO (default), LSGA, IPSE, AION, GridSearch, RL.
QTRADEX_NONINTERACTIVE=1 python mybot.py --optimize LSGA
Omit the name for QPSO:
QTRADEX_NONINTERACTIVE=1 python mybot.py --optimize
The best tune for each metric is saved automatically when the optimizer finishes (GridSearch and RLPPO save tunes too — they call end_optimization() just like the others).
--papertrade
Runs papertrade mode. Runs until interrupted (SIGINT, SIGTERM, or Ctrl+C in a foreground session).
QTRADEX_NONINTERACTIVE=1 python mybot.py --tune best --papertrade
--autobacktest
Runs the auto-backtest sequence and exits.
--monte-carlo
Runs Monte Carlo simulation and exits.
Optimization timeout
Optimizers can run indefinitely. In a CI pipeline or overnight job, you need a hard stop.
Pass --timeout with a number of seconds:
QTRADEX_NONINTERACTIVE=1 python mybot.py --optimize LSGA --timeout 3600
This sets optimizer.options.timeout = 3600 before the run. When the timeout fires, the optimizer calls end_optimization() to save its best tunes and exits cleanly. Works with every optimizer that supports the timeout option (QPSO, LSGA, IPSE, AION, GridSearch, RLPPO).
Combining flags
# Nightly re-optimize, 2-hour budget
QTRADEX_NONINTERACTIVE=1 python mybot.py --tune bot --optimize LSGA --timeout 7200
# Morning report — latest tune, backtest, no UI
QTRADEX_NONINTERACTIVE=1 python mybot.py --tune latest --backtest
# Deploy papertrade in Docker
CMD ["sh", "-c", "QTRADEX_NONINTERACTIVE=1 python /app/bot.py --tune best --papertrade"]
--help
Prints usage with all available flags and exits:
QTRADEX_NONINTERACTIVE=1 python mybot.py --help
What doesn't change
Everything else is the same. Your bot class, your Data setup, your tune files, your tunes/ directory — none of that changes. Dispatch is still dispatch; it just skips the interactive parts. The same dispatch(bot, data, wallet, **kwargs) call works identically whether the env var is set or not.