Market LabDocs

Market Lab v0.0.6

Native multi-symbol scripts and a classic fixed paired-grid bot.

Market Lab v0.0.6 adds native multi-symbol scripting and rewrites Grid as a classic fixed paired bot.

Multi-symbol scripting

A script can now read and trade several symbols in one run. Symbols belong to sources instead of one global script flag.

This is a breaking syntax change. The old script-level --symbol flag is not supported.

Source selectors

<symbol>@<source>@<provider>
<symbol>@<source>@<exchange>@<provider>

Examples:

btc@candles@binancef
btc@trades@bulkf
btc@oi@hyperliquidf
btc@candles@binancef@mmt
zec@candles@binancef@mmt

Short symbols are normalized internally:

btc -> BTC/USDT
zec -> ZEC/USDT

Backtest several symbols

mlab script backtest strategy.js \
  --from 1704067200000 \
  --to 1704153600000 \
  --source btc@candles@binancef:timeframe=900 \
  --source zec@candles@binancef:timeframe=900

Scripts use the complete selector to read history:

const btc = history.source('btc@candles@binancef', 0)
const zec = history.source('zec@candles@binancef', 0)

Every onData payload identifies the source symbol:

input.symbol
input.source
input.source_type

Trade an explicit symbol

ctx.trade() and ctx.order() now require symbol:

ctx.trade({
  key: 'zec-entry',
  symbol: 'zec',
  position: 'open-long',
  margin: 100,
})

ctx.order({
  key: 'zec-bid',
  symbol: 'zec',
  side: 'buy',
  size: 10,
  order: {
    type: 'limit',
    price: 30,
    tif: 'alo',
  },
})

One symbol can provide the signal while another is traded. Live execution rejects a traded symbol that was not declared by the script's sources.

Backtests require every traded symbol to have its own price-bearing source, such as candles or orderbook. Data for BTC cannot be used as the execution price for ZEC. When a symbol has several price-bearing sources, its first configured source is the deterministic backtest reference.

Prices for every symbol at the same timestamp are loaded before script hooks run. Backtest trades, positions, and execution events now include their symbol.

A live script still has one --venue. Every declared symbol traded by that script executes through that venue.

TOML

Symbols also belong to source keys in marketlab.toml:

version = 1

[script]
path = "strategy.js"

[sources."btc@candles@binancef"]
timeframe = 900

[sources."zec@candles@binancef"]
timeframe = 900

[backtest]
from = 1704067200000
to = 1704153600000

Scripts no longer use [market].symbol to select an instrument. [market].symbol remains available to non-script trade commands.

Remove this old script syntax when migrating:

--symbol BTC/USDT
candles@binancef
candles@binancef@mmt

Classic paired Grid

The Grid bot is now a classic fixed paired grid. It anchors once at the startup midpoint and does not move its prices with the market.

BUY completes  -> place its paired SELL one step higher
SELL completes -> place its paired BUY one step lower

Each cell works independently. A fill places its opposite order without waiting for every other level to fill.

With a $100 center and a $1 step:

BUY  L1 at $99  -> SELL at $100
BUY  L2 at $98  -> SELL at $99

SELL L1 at $101 -> BUY at $100
SELL L2 at $102 -> BUY at $101

After a pair completes, that cell starts the same cycle again.

Fixed cells and fills

  • --levels sets the number of initial cells on each side.
  • --step-bps sets the fixed distance between adjacent prices.
  • Partial fills preserve the filled quantity and resubmit only the remainder.
  • A paired order that would cross waits until its fixed price becomes maker-safe.
  • Initial and eligible replacement orders support batch placement and cancellation.

Margin multiplied by leverage determines total working exposure. Initial exposure is divided equally across every buy and sell cell. Five levels per side create ten equal initial cells. There is no inventory-based size skew.

Removed behavior

  • midpoint recentering;
  • automatic recenter range;
  • soft reset;
  • inventory-skewed grid sizing;
  • same-side replenishment; and
  • --reset-threshold-pct.

Risk and profit

--stop-loss-pct remains the global bot stop loss. It is measured against allocated margin. When triggered, Market Lab cancels the bot's orders and unwinds bot-owned inventory.

Take profit is uncapped. There is no global take-profit percentage, so completed cells can keep cycling until duration, stop loss, manual shutdown, or an execution error ends the job.

The configured grid step is gross spread capture. Venue fees must be lower than the captured step for a completed cycle to be profitable. Fees, adverse movement, partial fills, and final unwind can still make the result unprofitable.

mlab bot run grid BTC/USDT \
  --venue bulkf \
  --margin 100 \
  --leverage 10 \
  --levels 5 \
  --step-bps 6 \
  --duration 3600 \
  --stop-loss-pct 5

The preview now identifies a classic grid, fixed paired cells, disabled recentering, one-step flips, and uncapped take profit.

Structured logs include bot.grid.flip events with the lane, level, old side, new side, paired price, and size.

On this page