Run QuantConnect LEAN backtests and manage US equity algorithm development. Use when asked to backtest a trading strategy, run a LEAN algorithm, analyze back...
---
name: lean
description: Run QuantConnect LEAN backtests and manage US equity algorithm development. Use when asked to backtest a trading strategy, run a LEAN algorithm, analyze backtest results, download market data, or deploy to Interactive Brokers TWS. Covers algorithm creation, data management, config editing, and result analysis.
metadata:
{
"openclaw":
{
"requires": { "bins": ["dotnet"], "anyBins": ["python3", "python"], "env": ["LEAN_ROOT", "DOTNET_ROOT", "PYTHONNET_PYDLL"] },
"install":
[
{
"id": "dotnet",
"kind": "download",
"url": "https://dotnet.microsoft.com/download/dotnet/8.0",
"label": "Install .NET 8 SDK"
}
]
}
}
---
# LEAN Engine — QuantConnect Algorithmic Trading
## Prerequisites & Setup
### Required Environment Variables
| Variable | Purpose | Example |
|----------|---------|---------|
| `LEAN_ROOT` | Path to cloned LEAN repository | `/home/user/lean` |
| `DOTNET_ROOT` | Path to .NET SDK installation | `/home/user/.dotnet` |
| `PYTHONNET_PYDLL` | Path to Python shared library (required by LEAN's pythonnet) | `$LEAN_ROOT/.libs/libpython3.11.so.1.0` |
All three must be set before using this skill. Add to your shell profile:
```bash
export LEAN_ROOT="$HOME/lean"
export DOTNET_ROOT="$HOME/.dotnet"
export PATH="$PATH:$DOTNET_ROOT"
export PYTHONNET_PYDLL="$LEAN_ROOT/.libs/libpython3.11.so.1.0"
```
> **Note:** LEAN bundles its own Python shared library in `$LEAN_ROOT/.libs/`. If you built LEAN from source, the library should be there after `dotnet build`. If not, install `libpython3.11-dev` and point `PYTHONNET_PYDLL` to your system's `libpython3.11.so`.
### First-Time Setup
1. **Install .NET 8 SDK:**
```bash
# Linux/macOS
wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh
chmod +x dotnet-install.sh
./dotnet-install.sh --channel 8.0
export DOTNET_ROOT="$HOME/.dotnet"
export PATH="$PATH:$DOTNET_ROOT"
```
2. **Clone and build LEAN:**
```bash
git clone https://github.com/QuantConnect/Lean.git "$LEAN_ROOT"
cd "$LEAN_ROOT"
dotnet build QuantConnect.Lean.sln -c Debug
```
3. **Download initial market data:**
```bash
pip install yfinance pandas
python3 {baseDir}/scripts/download_us_universe.py --symbols sp500 --start 2020-01-01 --data-dir "$LEAN_ROOT/Data"
```
4. **Verify setup:**
```bash
ls "$LEAN_ROOT/Data/equity/usa/daily/" # Should list .zip files
ls "$LEAN_ROOT/Launcher/bin/Debug/" # Should contain QuantConnect.Lean.Launcher.dll
```
## Environment
- **LEAN source:** `$LEAN_ROOT/`
- **Launcher (pre-built):** `$LEAN_ROOT/Launcher/bin/Debug/`
- **Config:** `$LEAN_ROOT/Launcher/config.json`
- **Python algos:** `$LEAN_ROOT/Algorithm.Python/`
- **Market data:** `$LEAN_ROOT/Data/`
- **dotnet:** `$DOTNET_ROOT/dotnet` (add to PATH: `export PATH="$PATH:$DOTNET_ROOT"`)
## Quick Reference
### Run a Backtest
1. Place algorithm in `$LEAN_ROOT/Algorithm.Python/YourAlgo.py`
2. Edit config to point to it:
```bash
# Update config.json — set these fields:
# "algorithm-type-name": "YourClassName"
# "algorithm-language": "Python"
# "algorithm-location": "../../../Algorithm.Python/YourAlgo.py"
```
3. Run:
```bash
export PATH="$PATH:$DOTNET_ROOT"
cd "$LEAN_ROOT/Launcher/bin/Debug"
dotnet QuantConnect.Lean.Launcher.dll
```
4. Results appear in stdout + `$LEAN_ROOT/Results/`
**Or use the helper script:**
```bash
bash {baseDir}/scripts/run_backtest.sh YourClassName YourAlgo.py
```
### Config Editing
Edit `$LEAN_ROOT/Launcher/config.json` with these key fields:
| Field | Purpose | Example |
|-------|---------|---------|
| `algorithm-type-name` | Python class name | `"MyStrategy"` |
| `algorithm-language` | Language | `"Python"` |
| `algorithm-location` | Path to .py file | `"../../../Algorithm.Python/MyStrategy.py"` |
| `data-folder` | Market data path | `"../Data/"` |
| `environment` | Mode | `"backtesting"` or `"live-interactive"` |
For IB live trading, set environment to `"live-interactive"` and configure the
`ib-*` fields (account, username, password, host, port, trading-mode).
### Data Management
**Check available data:**
```bash
ls "$LEAN_ROOT/Data/equity/usa/daily/"
```
**Data format:** ZIP files containing CSV. Each line:
`YYYYMMDD HH:MM,Open*10000,High*10000,Low*10000,Close*10000,Volume`
Prices are stored as integers (multiply by 10000). LEAN handles conversion internally.
**Download more data:**
```bash
python3 {baseDir}/scripts/download_us_universe.py --symbols sp500 --data-dir "$LEAN_ROOT/Data"
```
See `{baseDir}/references/data-download.md` for additional methods to expand the universe.
### Writing Algorithms
LEAN Python algorithms inherit from `QCAlgorithm`:
```python
from AlgorithmImports import *
class MyAlgo(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2024, 1, 1)
self.SetEndDate(2025, 1, 1)
self.SetCash(100_000)
self.AddEquity("SPY", Resolution.Daily)
self.SetBenchmark("SPY")
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage,
AccountType.Margin)
def OnData(self, data):
if not self.Portfolio.Invested:
self.SetHoldings("SPY", 1.0)
```
Key API patterns:
- `self.History(symbol, periods, resolution)` — get historical bars
- `self.SetHoldings(symbol, weight)` — target portfolio weight
- `self.Liquidate(symbol)` — close position
- `self.AddUniverse(coarse_fn, fine_fn)` — dynamic universe selection
- `self.Schedule.On(date_rule, time_rule, action)` — scheduled events
- `self.Debug(msg)` — log output
### Analyzing Results
After a backtest run, check:
```bash
ls "$LEAN_ROOT/Results/"
# Key files: *-log.txt, *-order-log.txt, *.json (statistics)
```
### Rebuild LEAN (if source changes)
```bash
export PATH="$PATH:$DOTNET_ROOT"
cd "$LEAN_ROOT"
dotnet build QuantConnect.Lean.sln -c Debug
```
## Security Notes
### Config.json Safety
The `run_backtest.sh` script does **NOT** modify your original `config.json`. Instead, it:
1. Reads the original config as a template (read-only)
2. Creates a separate `config.backtest.json` with only algorithm fields changed (class name, file path, language, environment=backtesting)
3. Temporarily swaps it in for the LEAN run, then restores the original via a `trap` cleanup handler
The `configure_algo.py` helper performs the field substitution in an isolated output file. Your original config — including any Interactive Brokers credentials for live trading — is never modified.
**Modified fields (in the temp copy only):**
- `algorithm-type-name` — set to the requested class name
- `algorithm-language` — set to `Python`
- `algorithm-location` — set to the requested .py file path
- `environment` — set to `backtesting`
### Network Access
The setup instructions involve network downloads:
- `git clone` from GitHub (QuantConnect/Lean repository)
- `dotnet build` may restore NuGet packages
- `pip install yfinance pandas` installs Python packages from PyPI
- `download_us_universe.py` fetches market data from Yahoo Finance
All downloads are from well-known public sources. For maximum isolation, run setup in a container or VM.
### Environment Variables
This skill requires the following environment variables at runtime:
- `LEAN_ROOT` — path to your cloned LEAN repository
- `DOTNET_ROOT` — path to your .NET SDK installation
- `PYTHONNET_PYDLL` — path to Python shared library (auto-detected from `$LEAN_ROOT/.libs/` if not set)
These are declared in the skill metadata and must be set before use.
## Troubleshooting
- **"No data files found"** → Check `data-folder` in config.json points to correct path
- **Python import errors** → LEAN bundles its own Python; check `python-venv` config if using custom packages
- **Slow backtest** → Reduce universe size or date range; check Resolution (Minute >> Daily)
- **IB connection issues** → Verify TWS/Gateway is running, port matches config (default 4002 for Gateway)
- **`LEAN_ROOT` not set** → Add `export LEAN_ROOT="$HOME/lean"` to your shell profile
- **dotnet not found** → Add `export PATH="$PATH:$DOTNET_ROOT"` to your shell profile
- **`Runtime.PythonDLL was not set`** → Set `PYTHONNET_PYDLL` to the Python shared library path (see env var table above)
don't have the plugin yet? install it then click "run inline in claude" again.
by @clawhub
restructured original doc into implexa's six required components, made decision logic explicit (backtesting vs. live, python vs. c-sharp, data availability), documented edge cases (network timeouts, rate limits, config safety), separated setup from runtime procedure, and clarified output contract with result file locations and JSON schema.
Run backtests on trading strategies using QuantConnect's LEAN engine, develop and test US equity algorithms, manage market data, and deploy live trading to Interactive Brokers. use this skill when you need to validate a trading strategy against historical data, create a new algorithm, analyze backtest performance, download or update market datasets, or connect to live trading infrastructure.
| variable | purpose | example |
|---|---|---|
LEAN_ROOT |
path to cloned LEAN repository | /home/user/lean |
DOTNET_ROOT |
path to .NET SDK installation | /home/user/.dotnet |
PYTHONNET_PYDLL |
path to Python shared library for pythonnet binding | $LEAN_ROOT/.libs/libpython3.11.so.1.0 |
add these to your shell profile before first use:
export LEAN_ROOT="$HOME/lean"
export DOTNET_ROOT="$HOME/.dotnet"
export PATH="$PATH:$DOTNET_ROOT"
export PYTHONNET_PYDLL="$LEAN_ROOT/.libs/libpython3.11.so.1.0"
download_us_universe.py to fetch historical market data. no authentication required.$LEAN_ROOT/
Launcher/bin/Debug/ # pre-built launcher
QuantConnect.Lean.Launcher.dll
Launcher/config.json # runtime config (algorithm, data paths, broker settings)
Algorithm.Python/ # where you place .py algorithm files
Data/
equity/usa/daily/ # market data (ZIP files containing CSV)
input: none
action:
wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh
chmod +x dotnet-install.sh
./dotnet-install.sh --channel 8.0
export DOTNET_ROOT="$HOME/.dotnet"
export PATH="$PATH:$DOTNET_ROOT"
dotnet --version # verify
output: .NET 8.x SDK installed and in PATH. DOTNET_ROOT and PATH environment variables set.
input: $LEAN_ROOT environment variable set to target directory, .NET SDK available in PATH
action:
git clone https://github.com/QuantConnect/Lean.git "$LEAN_ROOT"
cd "$LEAN_ROOT"
dotnet build QuantConnect.Lean.sln -c Debug
output: full LEAN source tree in $LEAN_ROOT. compiled launcher at $LEAN_ROOT/Launcher/bin/Debug/QuantConnect.Lean.Launcher.dll. Python shared library at $LEAN_ROOT/.libs/libpython3.x.so.1.0 (auto-detected or manually installed).
input: python3, pip, $LEAN_ROOT set and built
action:
pip install yfinance pandas
python3 {baseDir}/scripts/download_us_universe.py \
--symbols sp500 \
--start 2020-01-01 \
--data-dir "$LEAN_ROOT/Data"
output: ZIP files containing daily OHLCV data in $LEAN_ROOT/Data/equity/usa/daily/. each ZIP file corresponds to one ticker. data format inside each ZIP: CSV with lines YYYYMMDD HH:MM,Open*10000,High*10000,Low*10000,Close*10000,Volume (prices stored as integers, multiplied by 10000 for precision).
input: algorithm source code (Python, inherits from QCAlgorithm)
action: place your .py file in $LEAN_ROOT/Algorithm.Python/YourAlgo.py. example:
from AlgorithmImports import *
class MyStrategy(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2024, 1, 1)
self.SetEndDate(2025, 1, 1)
self.SetCash(100_000)
self.AddEquity("SPY", Resolution.Daily)
self.SetBenchmark("SPY")
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage,
AccountType.Margin)
def OnData(self, data):
if not self.Portfolio.Invested:
self.SetHoldings("SPY", 1.0)
output: algorithm file exists at $LEAN_ROOT/Algorithm.Python/YourAlgo.py. class name extracted from the Python code (e.g., MyStrategy).
input: algorithm class name, path to .py file, data folder path, optionally Interactive Brokers credentials (if running live)
action: edit $LEAN_ROOT/Launcher/config.json. set these fields:
{
"algorithm-type-name": "MyStrategy",
"algorithm-language": "Python",
"algorithm-location": "../../../Algorithm.Python/YourAlgo.py",
"data-folder": "../Data/",
"environment": "backtesting"
}
for live trading to Interactive Brokers, also set:
{
"environment": "live-interactive",
"ib-account": "U1234567",
"ib-user-name": "your_ib_account",
"ib-password": "your_ib_password",
"ib-host": "127.0.0.1",
"ib-port": 4002
}
output: config.json updated with algorithm and broker settings. original config safely preserved (see step 6 for safe execution approach).
input: config.json populated (step 5), algorithm file in place (step 4), market data downloaded (step 3), LEAN built (step 2), environment variables set (step 1)
action: use helper script or direct dotnet invocation.
option A (helper script):
bash {baseDir}/scripts/run_backtest.sh MyStrategy YourAlgo.py
option B (direct):
export PATH="$PATH:$DOTNET_ROOT"
cd "$LEAN_ROOT/Launcher/bin/Debug"
dotnet QuantConnect.Lean.Launcher.dll
the helper script creates a temporary config.backtest.json from the original config, modifying only algorithm and environment fields. it then runs LEAN against the temp config and restores the original upon completion (via bash trap).
output: backtest runs to completion. logs printed to stdout. result files written to $LEAN_ROOT/Results/ (JSON statistics, order logs, algorithm logs).
input: completed backtest run
action: examine output files:
ls -la "$LEAN_ROOT/Results/"
cat "$LEAN_ROOT/Results/*-log.txt" # algorithm debug logs
cat "$LEAN_ROOT/Results/*-order-log.txt" # trade execution log
cat "$LEAN_ROOT/Results/*.json" # performance statistics
output: performance metrics extracted (total return, sharpe ratio, max drawdown, win rate, etc.). trade history reviewed. algorithm behavior validated against strategy intent.
input: changes made to LEAN source files (optional step, skip if not developing LEAN internals)
action:
export PATH="$PATH:$DOTNET_ROOT"
cd "$LEAN_ROOT"
dotnet build QuantConnect.Lean.sln -c Debug
output: recompiled LEAN binaries at $LEAN_ROOT/Launcher/bin/Debug/. new launcher ready for use.
if environment in config.json is set to "backtesting":
else if environment is set to "live-interactive":
ib-account, ib-user-name, ib-password are populated and valid.else:
if data files exist in $LEAN_ROOT/Data/equity/usa/daily/ for all requested symbols:
else if data files missing or date range incomplete:
$LEAN_ROOT/Data/equity/usa/daily/ or use alternative data source (see reference docs).if algorithm file is .py and inherits from QCAlgorithm:
algorithm-language to "Python" in config.json.PYTHONNET_PYDLL environment variable set correctly.else if algorithm is C# (.cs file):
algorithm-language to "CSharp".else:
if running backtests:
run_backtest.sh), which creates a temporary config and restores the original after execution.else if manually editing config.json for live trading:
self.Debug() calls), progress indicators.$LEAN_ROOT/Results/{timestamp}-order-log.txt: CSV format, one row per trade (symbol, quantity, entry/exit price, P&L, etc.).{timestamp}-log.txt: raw algorithm log output and LEAN engine diagnostics.{timestamp}-statistics.json: JSON object containing performance metrics:TotalReturn: decimal return (0.15 = 15%)SharpeRatio: decimal Sharpe ratioMaxDrawdown: decimal max drawdown (negative)WinRate: decimal fraction of profitable tradesProfitFactor: gross profit / gross lossTotalTrades: integer count of closed positions{timestamp}-backtest-results.json: full backtest metadata and trade history$LEAN_ROOT/Data/equity/usa/daily/SPY.zip)Date,Open,High,Low,Close,Volume. prices stored as integers (multiply by 10000). one bar per line.$LEAN_ROOT/Algorithm.Python/{AlgoName}.pyQCAlgorithm, defines Initialize() and OnData() methods.$LEAN_ROOT/Results/ with recent timestamps.{timestamp}-statistics.json is valid JSON and contains expected performance fields.{timestamp}-order-log.txt is non-empty (contains more than just headers).TotalTrades field in statistics > 0.{timestamp}-order-log.txt may be empty or contain only headers.TotalTrades field in statistics is 0.TotalReturn is likely 0 or matches cash interest (if configured).$LEAN_ROOT/Data/equity/usa/daily/.