Execution Overview

Per-asset-class translation of target positions to order actions

The execution layer is the only layer where asset-class branching is legitimate. Each executor knows how to convert a USD target notional into native orders for its specific asset class. shares for equity, contracts for options, yes-shares for prediction markets, leverage-aware size for perps.

Available executors

EquityExecutor Limit + marketable orders for stocks. The only fully-wired executor today.
OptionExecutor Limit orders at mid, spread discipline. Phase 7 work.
PredictionExecutor CLOB post-only, resolution-aware. Phase 7.
PerpExecutor Leverage + funding awareness. Phase 7.
Custom executors Write your own for exotic asset classes.

Executor protocol

python
from typing import Protocol, runtime_checkable

@runtime_checkable
class Executor(Protocol):
    asset_class: AssetClass

    def plan(
        self,
        target: TargetPosition,
        current: LedgerPosition | None,
        market: Market | None,
        feed: FeedData | None,
        available_cash: float,
    ) -> list[OrderAction]:
        ...

Every executor implements exactly this method. It takes a target in USD notional, the current position, and market info, and returns a list of concrete OrderActions.

Dispatcher

python
from horizon.executors import ExecutorDispatcher, EquityExecutor

dispatcher = ExecutorDispatcher()
dispatcher.register(EquityExecutor())
# dispatcher.register(OptionExecutor())   # etc.

# At runtime
actions = dispatcher.plan(target, current, market, feed, cash)

The dispatcher routes per-market by inspecting Market.asset_class and calling the executor registered for that class.

The default wiring

Horizon’s hz.run() auto-registers EquityExecutor for the Equity asset class. For other asset classes you’d register them explicitly:

python
hz.run(
    executors={
        Equity: EquityExecutor(),
        # Option: OptionExecutor(),    # future
        # Prediction: PredictionExecutor(),
    },
    ...
)

What an executor decides

Tests

tests/test_executors.py has 14 tests covering every path of EquityExecutor:

  • New long / new short
  • Reduce existing
  • Add to existing
  • Flip long → short (two orders)
  • Flat target closes existing
  • No-op when already at target
  • Below-min-shares no-op
  • Market vs limit selection
  • NaN feed → no action
  • Fractional shares

All green.

Next