TradingTWAP Orders

TWAP Orders

Time-Weighted Average Price (TWAP) orders split a large parent order into smaller suborders executed at regular intervals, minimizing market impact for institutional-size trades.

Parameters

ParameterDefaultDescription
total_sizeRequiredTotal quantity to execute
duration_secsRequiredTotal execution window in seconds
suborder_interval_secs30 secondsTime between each suborder
max_slippage_bps300 (3%)Maximum allowed slippage per suborder
max_catchup_multiplier3xMaximum multiplier for catch-up suborders
reduce_onlyfalseIf true, suborders only reduce existing positions

How It Works

Suborder Generation

The TWAP engine ticks at each suborder_interval_secs boundary and generates a suborder sized to match the expected cumulative fill rate:

normal_suborder_size = total_size * suborder_interval / duration

Example: A 30,000-unit order over 300 seconds (5 minutes) with 30-second intervals:

normal_suborder = 30,000 * 30 / 300 = 3,000 units per suborder
total_suborders = 300 / 30 = 10 suborders

Catch-Up Logic

If a suborder fails to fill (due to slippage limits or insufficient liquidity), the TWAP engine tracks the deficit between expected and actual fills. On the next tick, it attempts to catch up:

deficit = expected_cumulative_fill - actual_dispatched_size
suborder_size = min(deficit, max_catchup_multiplier * normal_suborder_size, remaining_size)

With a 3x catch-up multiplier and a normal suborder of 3,000 units, a single catch-up suborder can be up to 9,000 units.

Example sequence:

TimeSlots ElapsedTargetDispatchedDeficitSuborder Size
t+0s13,00003,0003,000
t+30s26,0003,0003,0003,000
t+120s5 (skipped 2)15,0006,0009,0009,000 (capped at 3x)

Slippage Protection

Each suborder is submitted with a price limit derived from the max_slippage_bps parameter:

  • For buy suborders: limit_price = reference_price * (1 + max_slippage_bps / 10,000)
  • For sell suborders: limit_price = reference_price * (1 - max_slippage_bps / 10,000)

If the market price exceeds the slippage limit, the suborder is skipped and the deficit accumulates for the next catch-up attempt.

TWAP Lifecycle

States

StatusDescription
ActiveTWAP is running and generating suborders
CompleteAll size has been dispatched (remaining_size = 0)
CancelledUser cancelled the TWAP before completion

Creation

A TWAP order is created with validation:

  • total_size must be greater than 0
  • duration_secs must be greater than 0 and at least equal to suborder_interval_secs
  • max_slippage_bps must be greater than 0

Cancellation

Only the owner can cancel an active TWAP. Cancellation:

  • Stops all future suborder generation
  • Does not affect previously dispatched (and potentially filled) suborders
  • Cannot be undone — cancelled TWAPs cannot be restarted

Completion

A TWAP completes automatically when remaining_size reaches 0. The status transitions to Complete and no further suborders are generated.

Use Cases

  • Large position entry/exit: Spread a $10M position across 30 minutes to minimize slippage
  • Algorithmic execution: Automate execution without constant manual intervention
  • Benchmark tracking: Execute at a time-weighted average price for compliance or portfolio rebalancing

Multiple Concurrent TWAPs

Users can have multiple active TWAP orders simultaneously across different markets. Each TWAP operates independently with its own timer, catch-up state, and completion tracking.