# Market Lab v0.0.6 (/changelog/v0.0.6)



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

## Multi-symbol scripting [#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 [#source-selectors]

```text
<symbol>@<source>@<provider>
<symbol>@<source>@<exchange>@<provider>
```

Examples:

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

Short symbols are normalized internally:

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

### Backtest several symbols [#backtest-several-symbols]

```bash
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:

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

Every `onData` payload identifies the source symbol:

```js
input.symbol
input.source
input.source_type
```

### Trade an explicit symbol [#trade-an-explicit-symbol]

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

```js
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 [#toml]

Symbols also belong to source keys in `marketlab.toml`:

```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:

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

## Classic paired Grid [#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.

```text
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:

```text
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 [#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 [#removed-behavior]

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

### Risk and profit [#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.

```bash
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.
