# Grid Market Maker (/bots/grid)



The Grid bot runs a classic fixed grid. It places buy and sell cells around the startup midpoint, then turns every completed order into its opposite:

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

The grid is anchored once when the bot starts. Its prices do not follow the midpoint.

## Run it [#run-it]

Preview the grid without creating a job:

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

Remove `--dry-run` to deploy it:

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

The command returns after deployment. The bot continues inside `mlabd`.

`--venue` accepts `bulkf`, `hyperliquidf`, `hyperlinkf`, or `hyperliquid` for outcomes. Use a scoped symbol such as `xyz:TSLA` for a HIP-3 grid on `hyperliquidf` or `hyperlinkf`. BULK and Hyperliquid use mainnet by default; add `--testnet` when the market exists there. HyperLink is mainnet-only and uses `mlab auth set hyperlink`.

## Outcome markets [#outcome-markets]

Use the existing Grid bot with an outcome market ID:

```bash
mlab bot run grid 1009 \
  --venue hyperliquid \
  --margin 100 \
  --duration 3600 \
  --levels 5 \
  --step-bps 20
```

Do not add `--leverage`. Outcome markets do not use it, and Market Lab rejects the flag. Leverage is not stored or shown in the plan or status.

Market Lab resolves the complete Yes and No pair and splits collateral into equal shares. A normalized grid buy sells No, while a normalized grid sell sells Yes. When one leg completes, its cell flips to the paired price. After both legs complete, Market Lab splits that cell's allocation again and replenishes it.

Half of the initial Yes and No inventory supports the starting ladder. The other half is reserved for paired orders after initial fills, so the first flips are not blocked by every share already resting in the book.

Shutdown cancels owned orders, merges balanced Yes and No shares, and sells unmatched residual shares that meet the venue's minimum order rules. Outcome PnL includes realized proceeds, unrealized value, fees, completed cycles, split and merge sizes, and remaining inventory.

The fixed-grid rules below still apply. Outcome mode does not add midpoint recentering, soft reset, or inventory skew. See [Hyperliquid outcomes](/providers-execution/hyperliquid#outcome-markets) for the complete inventory lifecycle.

## How the grid works [#how-the-grid-works]

Assume the startup midpoint is `$100` and one grid step is `$1`:

```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 both legs complete, that cell starts the same cycle again.

This `$100` example illustrates the fixed cell logic on a perpetual market. Outcome Grid applies the same flip logic to normalized Yes prices, using complementary Yes and No sells.

Each cell works independently. A fill at one level places its paired order immediately; it does not wait for the rest of the grid to fill.

## Fixed prices [#fixed-prices]

Market Lab uses the startup midpoint to calculate every initial price:

* `--levels` sets the number of initial cells on each side.
* `--step-bps` sets the fixed distance between adjacent prices.
* prices are rounded to the venue's valid tick size.

The midpoint may move after the bot starts, but the stored grid prices do not move with it. There is no automatic recentering, soft reset, or inventory-based repricing.

If a paired order would cross the current book, Market Lab waits. It submits the order only when that fixed price is maker-safe again. It does not move the price or turn the order into a taker trade.

## Fills and replacement orders [#fills-and-replacement-orders]

A fully completed buy creates its paired sell one step higher. A fully completed sell creates its paired buy one step lower.

For a partial fill, Market Lab preserves the completed quantity and resubmits only the unfilled remainder. Initial orders and eligible replacement orders can be placed and cancelled in batches.

The paired side is the only replenishment. A completed buy does not place another buy at the same level, and a completed sell does not place another sell at the same level.

## Sizing [#sizing]

On perpetual venues, margin multiplied by leverage determines the bot's total working exposure. Market Lab divides that exposure equally across every initial buy and sell cell.

With five levels on each side:

```text
5 buy cells + 5 sell cells = 10 equal initial cells
```

For `$100` of margin at `10x`, the bot has approximately `$1,000` of working exposure before venue rounding. Each of the ten initial cells receives approximately `$100`.

There is no dynamic inventory skew. Every cell keeps its own cycle and quantity.

On outcome markets, margin is quote collateral for the initial split. There is no leverage. Half of the resulting Yes and No inventory starts on the ladder; half remains available for paired flips.

## Profit and fees [#profit-and-fees]

There is no global take-profit percentage. A cell captures its configured grid step when both paired legs complete, then continues cycling until:

* `--duration` ends;
* `--stop-loss-pct` triggers;
* the job is stopped manually; or
* an execution error requires shutdown.

The configured step is gross spread capture, not guaranteed profit. Venue fees must be lower than the captured step for a completed cycle to be profitable. Adverse movement, partial fills, latency, liquidation risk, and the final inventory unwind can also reduce or erase the result.

## Stop loss [#stop-loss]

`--stop-loss-pct` is a global bot stop measured against the margin allocated to this job, not its leveraged exposure.

With `$100` of margin and `--stop-loss-pct 5`, Market Lab reacts when bot-owned net PnL reaches approximately `-$5`. It cancels the bot's open grid orders, unwinds its remaining inventory, and ends the job.

Fast movement and unwind slippage can make the final loss larger than the configured amount. The threshold controls when Market Lab reacts; it does not guarantee an exit price.

## Preview [#preview]

`--dry-run` describes the plan before any job is created. The preview identifies:

* a classic grid;
* fixed paired grid cells;
* the startup anchor;
* recentering as disabled;
* each fill flipping one grid step to the opposite side; and
* take profit as uncapped.

Use the preview to inspect the complete ladder and compare the configured step with the venue's fees.

## Logs [#logs]

Follow the job:

```bash
mlab bot logs <JOB_ID> --follow
```

Structured logs include `bot.grid.flip` whenever a completed leg creates its pair. The event records:

* lane;
* level;
* old side;
* new side;
* paired price; and
* size.

This makes each cell's cycle visible without inferring it from account-level fills.

## Parameters [#parameters]

| Input             | Meaning                                                                                         |
| ----------------- | ----------------------------------------------------------------------------------------------- |
| `SYMBOL`          | Market to quote: `BTC`, a HIP-3 symbol such as `xyz:TSLA`, or an outcome side such as `1009:0`  |
| `--venue`         | Execution venue: `bulkf`, `hyperliquidf`, `hyperlinkf`, or `hyperliquid` for outcomes           |
| `--testnet`       | Use BULK or Hyperliquid testnet; not valid with `hyperlinkf`                                    |
| `--margin`        | Collateral allocated to the bot; quote collateral for an outcome split; conflicts with `--size` |
| `--size`          | Exact total working size in base units; conflicts with `--margin`                               |
| `--leverage`      | Multiplies margin on perpetual venues; rejected for outcome markets                             |
| `--duration`      | Maximum runtime in seconds                                                                      |
| `--levels`        | Number of initial cells on each side; default `3`, range `1-100`                                |
| `--step-bps`      | Fixed distance between adjacent grid prices; default `2`, must be positive                      |
| `--stop-loss-pct` | Optional net loss as a percentage of allocated margin; range `0-100%`                           |
| `--dry-run`       | Print the plan without creating a job or placing orders                                         |
| `--yes`           | Skip the live deployment confirmation                                                           |

`--reset-threshold-pct` has been removed. The fixed paired grid does not recenter or run a soft reset.

## Existing positions and shutdown [#existing-positions-and-shutdown]

The bot attributes inventory and PnL only to its own order IDs. An existing account position or another bot on the same symbol does not become part of this grid's inventory.

When the duration ends, the job is stopped, or an error requires shutdown, Market Lab cancels only this job's orders and unwinds only this job's unmatched quantity. Other algorithms remain responsible for their own exposure.

All activity still shares the same account collateral, liquidation risk, and venue self-trade rules.

## When to use it [#when-to-use-it]

A fixed paired grid is most suitable when price repeatedly moves through a range. A strong one-way move can complete several cells on one side and leave their opposite orders waiting for reversal.

> Grid is an execution system, not a profitability claim or trading advice.
