Skip to main content

Overview

The ExchangeSimulator is a stateful, event-driven simulator that mirrors live trading behavior without risking real capital. It maintains realistic orderbook state, applies slippage and fees, and automatically triggers stop-loss and take-profit orders.
The simulator is the default execution backend in development. Production uses the Lighter API for real trading.

Architecture

Key Components:
  1. AccountState: Tracks cash, positions, P&L, and exit plans per trading account
  2. MarketState: Fetches and caches live orderbook data from exchanges
  3. OrderMatching: Simulates realistic fills with slippage and partial fills
  4. Auto-Close Engine: Monitors positions and triggers exits when stop/target hit

Initialization & Bootstrap

The simulator is initialized once per server lifecycle:
Database Rehydration: On startup, the simulator restores all open positions from the Orders table:
This ensures auto-close triggers work correctly even after server restarts. The Orders table is the single source of truth.

Account State Management

Each trading account has its own AccountState instance:

Order Matching Engine

The simulator applies realistic orderbook matching:
Slippage Simulation:
Default slippage is 10 bps (0.1%). This models liquidity taking cost and price impact.

Auto-Close Engine

Every refreshIntervalMs (default: 5s), the simulator:
  1. Fetches latest market prices
  2. Checks all open positions for stop/target triggers
  3. Queues auto-close orders
  4. Executes closes and updates database
Trigger Logic:
Auto-closes are fire-and-forget. If an auto-close fails (e.g., orderbook unavailable), the position remains open and the trigger is cleared to prevent retry loops.

Event Bus

The simulator emits events for real-time UI updates:

Configuration Options

Switching to Live Trading

To use the Lighter API instead of the simulator:
  1. Set USE_LIVE_TRADING=true in .env.local
  2. Configure Lighter API key: LIGHTER_API_KEY=your_key
  3. The trading logic automatically uses lighterApi.placeOrder() instead of simulator.placeOrder()
Both backends use the same Orders table schema, so switching between simulator and live trading is seamless.

Testing & Debugging

Reset a specific account’s simulator state:
Get current account snapshot:

Autonomous Trading Loop

How agents interact with the simulator

Database Schema

Orders table structure and exit plans

Order Execution

Order placement and fill tracking

Deployment Guide

Deploy the backend with trading configuration