Install and initialize Lean CLI

Prerequisites

Local backtests and reports run in Docker. Install Docker and verify that your user can access it. Lean CLI initialization also requires a QuantConnect organization on a paid tier.

This repository manages Lean CLI in its uv environment:

cd /home/hi/qrt
uv add lean
uv run lean --version

The tested version is lean 1.0.227. uv run lean ... is equivalent when the virtual environment is not activated.

Note

Lean CLI and the LEAN engine are different versioned components. The Python package supplies the CLI; local backtests run a Docker image such as quantconnect/lean:latest.

Configure Docker access

LEAN must reach Docker without sudo from the same Linux user that starts Python or Jupyter. With a system Docker daemon, add that user to the socket’s group:

sudo usermod -aG docker <username>
getent group docker

Group membership is captured when a login session starts. End every existing SSH, VS Code Remote SSH, terminal, and Jupyter session for that user, then reconnect. Verify the new session before opening the notebook:

id
stat -c 'owner=%U group=%G mode=%A' /var/run/docker.sock
docker version

id must include the socket group (normally docker), and docker version must print both Client and Server sections. Rootless Docker is also supported when it is configured for the Jupyter user.

Warning

Membership in the docker group is effectively root-level access to the host. Grant it only to trusted users. Never run the notebook as root, invoke the backtest with sudo, or pass a sudo password to q.bt.lean.

Tip

Closing a local VS Code window may leave its remote server and Jupyter kernels running. After changing groups, use Remote-SSH: Kill VS Code Server on Host…, close all connections to that host, and reconnect. See Docker permission denied.

Initialize a workspace

The tracked Sweden demo contains algorithms and generators but intentionally does not commit the organization-bound lean.json. Initialize it once per checkout:

cd /home/hi/qrt/lean/demo-generated-data
uv run lean init --organization <organization-name-or-id> --language python

Initialization creates:

demo-generated-data/
├── lean.json
└── data/
  • lean.json configures the engine and points data-folder at data.
  • data/ contains sample native LEAN data, market hours, and symbol properties.

Create ordinary projects with lean create-project NAME. The tested fixture instead keeps demo.py, universe_demo.py, and demo_sma.py at the workspace root and always passes the desired file explicitly.

Run commands through uv

Run commands from the repository environment, even after changing into a LEAN workspace:

cd /home/hi/qrt
uv run lean --version
uv run python lean/demo-generated-data/source/generate_data.py
uv run lean backtest lean/demo-generated-data/demo.py --no-update

uv run resolves Python and Lean CLI from /home/hi/qrt/.venv without depending on shell activation state.

Protect custom metadata

Lean CLI periodically replaces the public market-hours and symbol-properties databases. Disable the global refresh while maintaining custom entries:

uv run lean config set database-update-frequency _
uv run lean config list

The fixture also sets this workspace value in lean.json:

"file-database-last-update": "12/31/2099 00:00:00"

Keep the loose CSV providers when custom map and factor files are not packaged in LEAN’s bulk ZIP format:

"map-file-provider": "QuantConnect.Data.Auxiliary.LocalDiskMapFileProvider",
"factor-file-provider": "QuantConnect.Data.Auxiliary.LocalDiskFactorFileProvider"

Pin the engine for reproducibility

lean backtest ... --no-update uses the Docker image already present locally instead of pulling the latest tag. It does not disable database refreshes or pin an immutable image digest.

For durable production reproducibility, configure a versioned image tag or digest and record it with each run.

Back to top