Market LabDocs
Scripting V2 - PythonPlain Python Files

Getting Started

Set up Python, create a Scripting V2 strategy, and run its first backtest or live job.

Scripting V2 requires Python 3.9 or newer. Native jobs use your selected Python environment directly. Docker jobs reproduce it inside the daemon container.

Create an environment

Keep .venv beside the script so Market Lab discovers it automatically:

mkdir python-strategy
cd python-strategy
python3 -m venv .venv
.venv/bin/python -m pip install numpy pandas matplotlib

Market Lab resolves Python from --python, then an adjacent .venv, then python3 or python from PATH.

Write a script

Create strategy.py:

CANDLES = "btc@candles@hyperliquidf:timeframe=60"

script = {
    "name": "print-close",
    "version": "2",
    "lookback": 2,
}


def on_data(ctx, history):
    candle = history.source(CANDLES, 0)
    if candle is not None:
        print(f"latest close: {candle['c']}")

A Python V2 file needs a module-level script dictionary, "version": "2", and on_data(ctx, history). It needs no Market Lab import or base class.

history.source(...) is also the source declaration. Market Lab discovers the selector and its options before the job starts, so V2 does not use --source, TOML [sources], or script.sources.

Declare each feed with a literal string or a module-level string constant. A dynamic lookup may read an already-declared feed, but it cannot introduce a new subscription.

Backtest it

mlab script backtest strategy.py \
  --from 2026-07-15 \
  --to 2026-07-16

Dates are UTC. A date without a time means 00:00:00. Add an exact time when needed and quote it in the shell:

mlab script backtest strategy.py \
  --from "2026-07-15 09:30:00" \
  --to "2026-07-15 16:00:00"

Backtest execution uses Market Lab's simulator and never reaches an exchange.

Deploy it live

mlab script run strategy.py --duration 3600

The command snapshots the Python file and returns a job ID:

mlab script jobs
mlab script status <JOB_ID>
mlab script logs <JOB_ID> --follow
mlab script stop <JOB_ID>

Choose execution inside the script

Python V2 does not take --venue. Every execution request names its exchange:

ctx.trade(
    {
        "exchange": "hyperliquidf",
        "symbol": "BTC",
        "position": "open-long",
        "margin": 100,
        "leverage": 5,
        "order": {"type": "market"},
    }
)

Data and execution can use different exchanges. One job may also send requests to several execution exchanges.

BULK and Hyperliquid use mainnet by default. --testnet routes supported sources and execution requests in that job to testnet. HyperLink execution is mainnet-only.

Use marketlab.toml

version = 1

[script]
path = "strategy.py"
python = ".venv/bin/python"
duration = 3600

[script.params]
fast_period = 5
slow_period = 20
margin = 100

[backtest]
from = "2026-07-15"
to = "2026-07-16"

The source remains in history.source(...) inside strategy.py:

mlab script backtest
mlab script run

Do not add [execution].venue for Python V2. Each execution request names its own exchange. JavaScript Scripting V1 keeps its existing --source and job-wide --venue behavior.

Next, read Scripts and Sources.

On this page