Execution
Plan, simulate, submit, and monitor BULK trades through Market Lab.
Execution
Market Lab has two execution entry points:
- CLI commands for explicit operator-driven orders
ctx.tradeandctx.cancelfor deployed strategy scripts
Both use the same validation and BULK adapter. Live mutations are signed and serialized inside mlabd.
Live execution can place real orders. Use
--dry-runfor CLI orders andscript backtestfor strategy scripts before enabling live execution.
Requirements
Execution requires:
- a BULK account
- an active BULK agent created with
mlab auth set bulk - a symbol in the embedded BULK market catalog
mlab auth status
mlab daemon statusThe main wallet private key is used only to authorize or revoke the agent. Market Lab stores the agent credential in the operating system keychain and loads it only inside mlabd for live signing.
Dry Run
mlab trade long BTC/USDT --notional 10 --dry-runA dry run:
- resolves the configured BULK account
- obtains a reference price for market orders
- normalizes size from
--sizeor--notional - validates embedded market rules
- prints the complete
TradePlan - does not sign, submit, or start
mlabd
Place an Order
mlab trade long BTC/USDT --notional 100 --leverage 5
mlab trade short BTC/USDT --size 0.001 --leverage 3Terminal mode prints the normalized plan and asks for confirmation. Structured live output requires --yes because it cannot prompt:
mlab trade long BTC/USDT --notional 100 --yes --output jsonEvery order must specify exactly one of --size or --notional. Explicit size must align with the market lot size. A notional order is converted to size and floored to that lot size.
Market and Limit Orders
Market order:
mlab trade long BTC/USDT \
--notional 100 \
--type market \
--dry-runLimit order:
mlab trade short BTC/USDT \
--size 0.001 \
--type limit \
--price 65000 \
--tif alo \
--dry-runLimit time-in-force values:
gtc: good until cancelledioc: immediate or cancelalo: add liquidity only
--price and non-default --tif are valid only for limit orders. Limit prices must align with the embedded tick size.
Native Protection
Attach a stop loss, take profit, or both:
mlab trade long BTC/USDT \
--notional 100 \
--leverage 5 \
--sl 63000 \
--tp 69000 \
--dry-runBULK protection is signed in the same transaction as the parent:
--slcreates a native stop action--tpcreates a native take-profit action- both create a native OCO range
- protection activates after the parent fills
- one OCO trigger cancels its sibling
Market Lab does not poll prices to emulate protection. Trigger prices must align with the tick size and be on the correct side of the entry. Protection cannot be attached to a reduce-only order.
Leverage and Reduce Only
mlab trade long BTC/USDT \
--notional 100 \
--leverage 5 \
--reduce-only \
--dry-runLeverage starts at 1 and cannot exceed the embedded market maximum. --reduce-only is passed into the signed BULK order.
Account State
mlab positions
mlab orders
mlab fillsFilter to one Market Lab symbol:
mlab positions --symbol BTC/USDT --output json
mlab orders --symbol BTC/USDT --output json
mlab fills --symbol BTC/USDT --output jsonThese are read-only BULK account requests and do not start mlabd.
Cancel and Close
mlab cancel BTC/USDT <ORDER_ID> --dry-run
mlab cancel BTC/USDT <ORDER_ID>Close creates a reduce-only market order in the opposite direction for the complete position size:
mlab close BTC/USDT --dry-runThe symbol is optional in interactive terminal mode. Pass it explicitly for structured output or non-interactive use when several positions exist.
Script Execution
Strategy scripts use the same normalized execution request:
const order = ctx.trade({
key: `entry-${candle.t}`,
side: 'long',
notional: 100,
leverage: 5,
order: { type: 'market' },
sl: 63000,
tp: 69000,
})script backtestintercepts this call with the historical simulator.script runkeeps execution disabled.script run --venue bulkroutes it to live BULK execution throughmlabd.
Returned script signals and intents do not place live orders. See Script Execution for request fields, idempotency, cancellation, jobs, and onExecution.
Runtime
Live CLI orders and deployed script jobs use the persistent mlabd process. It owns:
- agent-key access and signing
- nonce sequencing
- order and cancellation submission
- script job and idempotency state
- order correlation and event delivery
- the BULK account WebSocket
The runtime starts automatically when a live command or script job needs it and remains active until stopped.
mlab daemon start
mlab daemon status
mlab daemon events --limit 20
mlab daemon stopRuntime files live under:
~/.market-lab/execution/
mlabd.sock
runtime.json
events.jsonl
mlabd.log
jobs/The runtime directory is owner-only (0700) and the Unix socket is owner-only (0600).
Account WebSocket
mlabd subscribes to BULK account events instead of polling REST on a timer.
The stream provides:
- initial account state
- order updates and fills
- position and margin changes
- liquidations and ADL events
- cancellation failures
The daemon reconnects with bounded backoff after a disconnect. Once reconnected, it performs one REST order-history and fill recovery for the disconnected interval, then resumes WebSocket-driven state. No scheduled REST reconciliation runs while the stream is healthy.
mlab daemon status reports:
- account stream connection state
- last account event timestamp
- last gap recovery timestamp
- tracked open-order count
- active script-job count
- last runtime error
Runtime Events
Inspect the global runtime journal:
mlab daemon events --limit 20 --output jsonlIt includes CLI submission and tracking events such as:
order_submittedorder_cancelledorder_tracking_startedorder_statusaccount_wsaccount_recovery_fill
Deployed script execution has a per-job event journal delivered through onExecution. Inspect the script’s combined output with:
mlab script logs <JOB_ID> --follow --output jsonlTOML Configuration
version = 1
[market]
symbol = "BTC/USDT"
[execution]
venue = "bulk"
notional = 100
order_type = "market"
leverage = 5
sl = 63000
tp = 69000
reduce_only = false
dry_run = true
yes = false
[output]
format = "terminal"mlab trade long --config marketlab.tomlCLI values override TOML values. Do not put wallet keys or agent credentials in TOML.
Validation Boundary
Before signing, Market Lab rejects:
- unknown or non-trading markets
- unsupported order types or time-in-force values
- size values not aligned with lot size
- limit or protection prices not aligned with tick size
- invalid stop-loss or take-profit direction
- estimated notional below the market minimum
- leverage above the market maximum
- protection attached to reduce-only orders
- mismatched symbols, accounts, or cancel order IDs
Market rules come from the versioned BULK snapshot embedded in the binary:
mlab markets --provider bulk --symbol BTC/USDT