Skip to main content
When you need to fill a large order without moving the market, Horizon provides three execution algorithms: TWAP (time-weighted), VWAP (volume-weighted), and Iceberg (hidden size). Each splits a parent order into smaller child orders managed by the engine.

TWAP (Time-Weighted Average Price)

Splits a large order into equal-sized slices submitted at regular time intervals:

How TWAP works

Each slice is submitted as an independent limit order at the current market price. The algorithm:
  1. Divides duration_secs by num_slices to get the interval (6 seconds above).
  2. On each on_tick() call, checks if enough time has passed for the next slice.
  3. Submits a child order of total_size / num_slices contracts.
  4. Tracks total filled across all children and marks complete when the target is reached.

When to use TWAP

  • Low-urgency fills where minimizing market impact matters more than speed.
  • Markets with thin books where placing the full size at once would walk the book.
  • Predictable scheduling: TWAP gives you even participation over the time window.

VWAP (Volume-Weighted Average Price)

Slices the order proportionally to a volume profile, concentrating execution during high-volume periods:

How VWAP works

The volume profile determines how much of the total order goes into each time slice:
Each weight in the profile is normalized by the total weight, then multiplied by the target size. Slices are evenly spaced in time across duration_secs.

When to use VWAP

  • Benchmarking against market VWAP: your fills will match the volume pattern.
  • High-volume windows: concentrate execution when liquidity is deepest.
  • Relative value strategies where you want to match the market’s natural flow.

Building a volume profile

You can construct volume profiles from historical data or use common patterns:

Iceberg (Hidden Size)

Shows only a small visible portion of the total order. When the visible slice fills, a new one is placed:

How Iceberg works

The algorithm:
  1. Places a limit order for show_size contracts.
  2. On each on_tick(), checks whether the visible order is still open.
  3. When the visible order fills, calculates remaining size and places a new visible slice.
  4. Repeats until the full target size is filled.

When to use Iceberg

  • Avoid signaling: other market participants cannot see your true order size.
  • Thin prediction markets where showing 100 contracts would discourage counterparty flow.
  • Passive fills: each slice rests at your limit price, earning the spread.

Running an Algo in a Loop

All three algorithms follow the same ExecAlgo interface. Here is a complete example driving TWAP inside a loop:

Comparison

API Reference

All algorithms inherit from ExecAlgo and share these properties and methods:

Constructor signatures