Skip to content

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.