Quant Memo
Core

Discrete-Event Simulation

A simulation style that jumps straight from one meaningful event to the next — an order arriving, a trade filling — instead of stepping through fixed time ticks, so nothing is wasted simulating periods where nothing happens.

Prerequisites: Monte Carlo Integration

Simulating an order book minute by minute, checking every fixed tick whether anything happened, wastes effort on the vast majority of ticks where nothing changed and risks missing what happened within a tick if two things occur close together. Discrete-event simulation (DES) takes a different approach: it maintains a calendar of scheduled future events, always jumps directly to the next one, updates the system's state, and possibly schedules further future events — skipping all the "dead time" in between entirely. This makes it the standard way to simulate systems like limit order books, queues, and trading venues, where activity is bursty and irregular rather than smoothly continuous.

An analogy: a diary of appointments, not a stopwatch

Imagine tracking a busy office's day two ways. One way: check every single minute whether a meeting started, ended, or a phone rang — most checks find nothing happening, and you risk missing anything shorter than a minute. The other way: keep a diary listing only the next scheduled thing to happen — "10:14 meeting starts," "10:45 meeting ends," "11:02 phone call" — and jump your attention straight from one diary entry to the next, updating what you know about the office's state at each entry and adding new diary entries as things get scheduled (like a follow-up call triggered by the meeting). The second approach never wastes attention on empty time and never misses anything, however briefly it happens, because you only ever look exactly where something changes.

The mechanics, one symbol at a time

A discrete-event simulation maintains a state (the current configuration of the system — e.g., the order book's current bids and asks) and a future event list, a priority queue of scheduled events ordered by their timestamp. The core loop is:

  1. Pop the event with the smallest timestamp tt from the future event list.
  2. Advance the simulation clock to tt (skipping directly over any interval where nothing was scheduled).
  3. Process the event: update the state, and schedule any new future events it triggers (each with its own timestamp, often drawn as t+τt + \tau for some random duration τ\tau).
  4. Repeat until the event list is empty or a stopping condition is met.

The key quantity that drives realism is the interarrival time distribution — how the timestamp τ\tau for each new scheduled event is generated. A common choice is exponential interarrival times with rate λ\lambda, giving a Poisson process of arrivals (see queueing theory), but DES supports arbitrary distributions for any event type, unlike fixed-tick simulation which implicitly assumes events can only occur on tick boundaries.

The exponential distribution governs how far apart events are scheduled; the explorer below lets you inspect it under the Poisson setting — try a low versus high rate and notice how it shapes how bursty or sparse the resulting event calendar looks.

Distribution · poisson
mean 4.0024681012outcomes (k) →
mean 4.00std dev 2.00peak at k = 3

Worked example: a two-event order book

Suppose you're simulating a simplified limit order book with two event types: order arrivals (exponential interarrival time, mean 2 seconds) and cancellations of resting orders (exponential, mean 30 seconds per resting order). At t=0t=0 the book has 3 resting orders, each independently scheduled to cancel. The event list might read: order arrival at t=1.3t=1.3s, cancellation of order #2 at t=8.7t=8.7s, order arrival at t=9.9t=9.9s, cancellation of order #1 at t=22.4t=22.4s. The simulation jumps directly to t=1.3t=1.3s, processes the new arrival (say it matches against the book, updating the state and possibly removing a resting order and its scheduled cancellation from the event list), then jumps directly to the next event at t=8.7t=8.7s, and so on — never simulating the "quiet" seconds between 1.3 and 8.7 where literally nothing in the book changed.

Worked example: measuring average queue length

Suppose you run the order-book simulation above for a full trading day and want the average number of resting orders in the book. With DES, you don't sample the book's state at fixed intervals — instead, you compute a time-weighted average: each time the book's order count changes (from nn to n±1n\pm1 orders) at some event timestamp, you record how long the book stayed at count nn before the next event, and weight nn by that duration. If the book held 3 orders for 8.7 seconds, then 4 orders for 1.2 seconds, then 3 orders again for 12.7 seconds (before the next state change), the time-weighted average over that 22.6-second stretch is (3×8.7+4×1.2+3×12.7)/22.63.13(3 \times 8.7 + 4 \times 1.2 + 3 \times 12.7) / 22.6 \approx 3.13 orders — an exact calculation using only the event timestamps actually recorded, with no discretization error from choosing a tick size.

fixed-tick simulation checks every tick, most find nothing discrete-event simulation jumps directly to each real event, skipping dead time
Fixed-tick simulation wastes checks on empty intervals; discrete-event simulation advances the clock directly to each scheduled event, so simulated effort matches actual activity.

What this means in practice

DES is the standard architecture behind limit order book simulators, agent-based market models (see agent-based market simulation), and queueing-network simulations of trading infrastructure like matching engine latency or order-routing systems. It's preferred over fixed-tick simulation whenever event timing is irregular or bursty — which is essentially always true of real markets, where quiet periods and bursts of activity coexist — because fixed-tick simulation either wastes huge amounts of compute on tiny tick sizes to avoid missing fast bursts, or misses fine detail with large tick sizes. Building a correct DES requires careful bookkeeping of the future event list (usually a priority queue/heap for efficiency) and correct handling of events that cancel or reschedule other pending events, such as an order cancellation removing that order's previously scheduled fill event.

Discrete-event simulation advances the simulated clock directly from one scheduled event to the next, updating state and scheduling new events as it goes, rather than checking a fixed grid of time steps — making it exact and efficient for systems where activity is irregular, like order books and queues.

A common mistake when porting fixed-tick intuition to DES is computing time-averaged statistics (like average queue length) by simply averaging the state value observed at each event, rather than weighting each state by how long it actually persisted before the next event. Events are not evenly spaced in time — a state that persisted for 12 seconds and one that lasted 0.01 seconds count equally in an unweighted average of event snapshots, badly distorting any statistic that should reflect the passage of real time. Always use time-weighted averages when reporting quantities like average queue length or average spread from a DES run.

Related concepts

Practice in interviews

Further reading

  • Law, Kelton, Simulation Modeling and Analysis, ch. 1-2
  • Ross, Simulation, ch. 1
ShareTwitterLinkedIn