TWAP
Execute a parent order through time-weighted child orders on BULK.
TWAP
TWAP, or Time-Weighted Average Price, divides one parent order into smaller child orders and submits them at a fixed cadence. It is an execution strategy: you choose the side and amount; TWAP controls the schedule.
Market Lab's current TWAP implementation executes on BULK and uses market child orders.
TWAP can place real orders. Market child orders prioritize execution and can experience slippage. Always inspect the dry-run plan first.
Preview a TWAP
mlab strategy run twap BTC/USDT \
--exchange bulk \
--side buy \
--margin 100 \
--leverage 10 \
--duration 300 \
--interval 60 \
--dry-runA dry run:
- obtains the current BULK reference price
- multiplies
--marginby--leverageto create the target exposure - converts that exposure into a lot-aligned total size
- calculates the number and size of child orders
- validates every child against the market's minimum notional
- prints the complete strategy plan
- does not create a job or submit an order
The estimated margin and exposure can be slightly lower than requested because size is floored to the market's lot size.
Scheduling Logic
The child count is:
ceil(duration / interval)The normalized total size is divided across that many children. Distribution is performed in whole market lots, and any remainder lots are distributed without losing or exceeding the parent size.
For this configuration:
duration = 300 seconds
interval = 60 secondsTWAP creates five child orders scheduled at approximately:
0s, 60s, 120s, 180s, 240sThe first child is submitted immediately. The remaining children are submitted once per interval. Together, the five scheduled buckets cover the 300-second execution window.
--duration defines how long the parent execution is spread across. --interval defines how frequently a child is submitted. An interval alone cannot determine when the parent order should finish.
Submit a Live Job
Remove --dry-run to submit the strategy:
mlab strategy run twap BTC/USDT \
--exchange bulk \
--side buy \
--margin 100 \
--leverage 10 \
--duration 300 \
--interval 60Terminal mode prints the normalized plan and asks once for confirmation. After confirmation, mlab submits the immutable TWAP definition to mlabd, prints the job ID, and returns immediately. Closing the terminal does not stop the strategy.
Use --yes for non-interactive execution:
mlab strategy run twap BTC/USDT \
--exchange bulk \
--side sell \
--size 0.01 \
--duration 600 \
--interval 30 \
--yes \
--output jsonStructured live output requires --yes because JSON and JSONL modes cannot display an interactive confirmation prompt.
Arguments
| Argument | Required | Meaning |
|---|---|---|
SYMBOL | Yes | Market Lab symbol such as BTC/USDT |
--exchange | No | Execution exchange; currently bulk and defaults to bulk |
--side | Yes | Parent side: buy or sell |
--size | One amount | Total base-asset size |
--margin | One amount | Total quote collateral; multiplied by leverage at deployment |
--duration | Yes | Total execution window in seconds |
--interval | No | Seconds between child orders; defaults to 60 |
--leverage | No | Leverage applied to each child; defaults to 1 |
--reduce-only | No | Marks every child as reduce-only |
--dry-run | No | Print the plan without creating a job |
--yes | No | Skip the live terminal confirmation |
--output | No | terminal, json, or jsonl |
Set exactly one of --size or --margin.
When --margin is used, Market Lab multiplies it by leverage and resolves the resulting exposure to a fixed, lot-aligned parent size before the job is created. Later price changes affect the realized exposure of each market child, but they do not change the persisted target size.
Monitor the Job
The submission response includes a strategy job ID:
strategy_...Use it to manage the detached worker:
mlab strategy jobs
mlab strategy status <JOB_ID>
mlab strategy logs <JOB_ID> --follow
mlab strategy stop <JOB_ID>strategy logs contains:
- the normalized TWAP plan used by the worker
- one
strategy.child_orderrecord per submitted child - the venue order ID and submission status
- a final
strategy.run.finishedsummary - a
strategy.run.failedrecord when execution cannot continue
Job statuses are starting, running, stopping, stopped, completed, and failed.
Stop Behavior
Stopping a TWAP prevents future child orders. It does not reverse filled children or close the resulting position.
mlab strategy stop <JOB_ID>Every child submission includes its job ID and sequence. mlabd atomically verifies that the job is still active, that children arrive in order, and that each child size matches the persisted schedule. A child submitted after the job has stopped is rejected.
TWAP has no restart command. If a stopped job filled only part of the parent amount, inspect the job logs and account fills, calculate the desired remainder, and submit a new TWAP explicitly.
Market and Limit Execution
TWAP itself does not require market orders; a TWAP trajectory can use either market or limit children. Market Lab currently implements only market-child TWAP.
The following are not currently accepted by strategy run twap:
--type limit--price--tif
Limit TWAP requires additional lifecycle rules for resting orders, partial fills, cancellation, and the unfilled amount at expiration. Those semantics will be documented when limit-child TWAP is implemented. Market Lab will not silently treat a requested limit price as a market order.
Failure Behavior
The job stops and becomes failed when a child cannot be planned or submitted. Previously filled children remain filled; Market Lab does not roll them back.
Common validation failures include:
- total size is not aligned with the BULK lot size
- the schedule creates more children than available lots
- an individual child is below the market minimum notional
- requested leverage exceeds the market maximum
- authentication is missing or no longer matches the configured BULK account
Inspect both the job and its logs after a failure:
mlab strategy status <JOB_ID>
mlab strategy logs <JOB_ID>
mlab fills --symbol BTC/USDT