Skip to main content

Horizon Design Principles

Rust Core

All critical paths run in Rust: risk checks, order management, position tracking, exchange communication, and fill processing. Python never touches the hot path.

No IPC

Python calls Rust directly via PyO3. Zero serialization overhead. No sockets, no message queues, no JSON encoding between layers.

f64 Everywhere

All numeric values at the Python boundary use f64 for simplicity. No Decimal conversion needed.

Enum Dispatch

Exchange backends use enum dispatch (ExchangeBackend) instead of trait objects. Avoids dynamic dispatch overhead and unsafe downcasts.

Component Overview

Horizon Engine

The Engine is the central orchestrator. It owns:
  • RiskManager: 8-point risk pipeline that every order passes through
  • OrderManager: tracks order lifecycle with DashMap for concurrent access
  • PositionTracker: maintains positions with atomic P&L calculations
  • ContingentManager: manages stop-loss, take-profit, and bracket orders with OCO linking
  • Exchange Map: multiple exchange backends keyed by name (e.g., "paper", "polymarket", "kalshi", "alpaca", "ibkr", "coinbase", "robinhood")
  • FeedManager: tokio runtime with spawned async tasks for WebSocket/REST feeds
  • Database: optional SQLite persistence layer for crash recovery

Exchange Model

Exchanges are registered by name in a HashMap<String, ExchangeBackend>. The first exchange becomes the primary (default for routing). Additional exchanges can be added via add_exchange(). All exchanges implement the Exchange trait:
  • submit_order(): submit an order to the exchange
  • cancel_order(): cancel a single order
  • cancel_all(): cancel all orders
  • cancel_for_market(): cancel orders for a specific market
  • drain_fills(): pull pending fills
  • fetch_positions(): sync positions from the exchange
  • amend_order(): amend an order’s price and/or size (cancel+resubmit on live, in-place on paper)
Prediction market exchanges (Polymarket, Kalshi) use Side::Yes / Side::No. Equity and crypto exchanges (Alpaca, IBKR, Coinbase, Robinhood) use Side::Long. The Side enum carries through the entire pipeline — risk checks, position tracking, and fill processing all handle both conventions.

Feed System

The FeedManager owns a tokio runtime. Each feed runs as a spawned async task:
FeedTransportUpdate Model
BinanceWSWebSocketReal-time trade stream
PolymarketBookWebSocketOrderbook snapshots
KalshiBookHTTP pollingOrderbook polling
AlpacaWebSocketEquity/crypto quotes and trades
IBKRHTTP pollingStocks, options, ForecastEx market data
RESTFeedHTTP pollingGeneric REST endpoint
Feed data is stored in a shared DashMap<String, FeedSnapshot> and read by the Python layer each cycle via engine.feed_snapshot(name).

Contingent Orders

The ContingentManager manages synthetic stop-loss and take-profit orders. These are not sent to the exchange. Instead, the engine monitors triggers each tick cycle and converts them to real OrderRequests when conditions are met.
  • Stop-loss: triggers when price crosses below (sell) or above (buy) the trigger level
  • Take-profit: triggers on price target or unrealized PnL threshold
  • OCO linking: two contingent orders can be linked so that when one triggers, the other is automatically canceled
  • Bracket orders: entry order + stop-loss + take-profit, all submitted and linked in one call

Persistence Layer

SQLite with WAL mode provides crash recovery and an audit trail:
  • fills: append-only journal with INSERT OR IGNORE dedup
  • order_events: order lifecycle log (one row per status change)
  • position_snapshots: periodic snapshots for fast recovery
  • risk_events: kill switch activations, violations
  • strategy_runs: run start/end timestamps
Recovery works by loading the latest position snapshot and replaying fills since that snapshot.

Horizon Data Flow

Pipeline Function → list[Quote]

   cancel_market()          ← cancel stale orders

   tick() / poll_fills()    ← process fills from exchange

   check_contingent_triggers() ← fire stop-loss / take-profit

   submit_quotes()          ← route through risk pipeline

   Risk Pipeline (8 checks) ← reject or pass

   Exchange Backend          ← submit to exchange

   OrderManager              ← track order state

   PositionTracker           ← update on fill

   Database                  ← persist fill + order event

Monitoring Stack

Horizon provides three monitoring layers:
LayerComponentDescription
MetricsMetricsServerPrometheus /metrics endpoint with counters, gauges, and histograms
AlertsAlertManagerMulti-channel alerts (Discord, Telegram, webhooks, log) with cooldown throttling
CalibrationCalibrationTrackerTracks prediction accuracy with Brier scores over time (prediction markets)
DashboardTUI (Textual)Real-time terminal dashboard with P&L, positions, orders, risk, fills, feeds