Skip to main content
The Engine is the core orchestrator. While hz.run() manages it for you, you can use it directly for advanced use cases, testing, or custom integration.

Construction

Paper exchange (default)

api_key is optional if you’ve set HORIZON_API_KEY as an environment variable. See Authentication.

Polymarket

Kalshi

With persistence

Full signature

Maker/taker fees

Split fees by liquidity role. Makers add liquidity (limit orders resting in the book), takers remove it (market orders or aggressive limit orders that cross the spread).
Each Fill includes an is_maker field indicating whether the order was a maker or taker. See Fill type.

Multi-Exchange

add_exchange

Add a secondary exchange to the engine.
Full signature matches the constructor parameters for each exchange type.
Each exchange type can only be registered once. Calling add_exchange("polymarket", ...) when Polymarket is already registered raises ValueError.

exchange_names

exchange_count

exchange_name

Get the primary exchange name (backward compatible):

set_netting_pair

Register a netting pair for cross-exchange risk reduction:

netting_pairs

Order Submission

All order methods support optional exchange parameter for routing:

submit_order

Submit an order through the risk pipeline. Returns the exchange-assigned order ID.

submit_quotes

Submit bid+ask quote pairs. Returns a list of order IDs (2 per quote: bid + ask).

submit_market_order

Order Amendment

amend_order

Amend an existing order’s price and/or size.
  • Paper exchange: Returns the same order ID (amendment is applied in-place).
  • Live exchanges (Polymarket, Kalshi): Performs a cancel+resubmit under the hood, returning a new order ID.
  • At least one of new_price or new_size must be provided.
  • Raises ValueError if the order is not found.
Each successful amendment increments the order’s amendment_count field. See Order type for details.

Contingent Orders (Stop-Loss / Take-Profit)

Contingent orders are triggered automatically when market conditions are met. They enable stop-loss and take-profit strategies, and can be linked together as OCO (one-cancels-other) pairs via bracket orders.

add_stop_loss

Registers a stop-loss contingent order. When the market price drops to or below the trigger_price, a market order is submitted automatically.

add_take_profit

Registers a take-profit contingent order. When the market price rises to or above the trigger_price (or the position PnL reaches trigger_pnl if set), a market order is submitted automatically.

submit_bracket

Submit an entry order with linked stop-loss and take-profit as an OCO (one-cancels-other) group.
When either the stop-loss or take-profit triggers, its OCO partner is automatically canceled.

check_contingent_triggers

Check all pending contingent orders for a market against the current price and trigger any that match.
hz.run() calls check_contingent_triggers automatically on every tick. You only need to call this manually when using the engine directly.

cancel_contingent

Cancel a specific contingent order by its ID.
If the contingent order is part of an OCO pair, only the specified order is canceled (the partner remains active).

pending_contingent_orders

List all pending (not yet triggered) contingent orders.
See ContingentOrder type for field details.

Smart Order Routing

submit_order_smart

Route an order to the exchange with the best available price based on current feed data.
  • Buy orders are routed to the exchange with the lowest ask price.
  • Sell orders are routed to the exchange with the highest bid price.
  • If no feed data is available or prices are equal, the order is sent to fallback_exchange (or the primary exchange if None).
Smart routing requires active feeds for each exchange. Start feeds before using submit_order_smart.

Cancel

cancel

Cancel a single order by ID. Looks up the exchange automatically:

cancel_all

Cancel all orders across all exchanges:

cancel_market

Cancel all orders for a specific market across all exchanges:

Fills & Positions

tick

Tick the paper exchange with a price and process fills:

poll_fills

Poll fills from all live exchanges:

process_fill

Manually inject a fill:

update_mark_price

Update mark price for unrealized P&L calculation:

sync_positions

Fetch positions from an exchange and reconcile:

Queries

Each Order returned includes an amendment_count field (number of times the order has been amended). See Order type for details.

Runtime Parameters

Runtime parameters are injected into ctx.params every cycle when using hz.run() with hot_reload() in the pipeline.

Risk Controls

Feed Management

Persistence

Multi-Outcome Event Management

Register and query multi-outcome events. See Multi-Outcome Events for the full guide.

register_event

Register an event with its outcome market IDs:

event_exposure

Total exposure across all outcome markets in an event:

event_positions

All positions in markets belonging to an event:

event_parity_check

Check whether outcome prices sum to ~1.0 using current feed data:

market_event_id

Reverse lookup - which event does a market belong to?

registered_events

All registered events and their market IDs:

Arbitrage Execution

execute_arbitrage

Submit a cross-exchange arbitrage trade with atomic rollback. Both legs go through the risk pipeline with Fill-Or-Kill semantics.
  • Both legs use TimeInForce.FOK (Fill Or Kill)
  • If the sell leg fails after the buy succeeds, the buy order is automatically canceled
  • Returns (buy_order_id, sell_order_id) on success
  • Raises an exception if risk rejects either leg
See Arbitrage Executor for the full guide including arb_scanner() and arb_sweep().

Maintenance

Shutdown Behavior

When the Engine is dropped (Python garbage collection or explicit del):
  1. Position snapshot is saved to the database
  2. Strategy run is ended in the database
  3. All orders are canceled across all exchanges
  4. All feeds are stopped