Skip to content

selimozten/volt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

volt

A limit order book achieving 50M+ operations per second with O(1) complexity for all core operations. Built in Zig.

Performance

Operation       Throughput        Latency    Complexity
────────────────────────────────────────────────────────
Insert          54.91M ops/sec    18ns       O(1)
Cancel          53.11M ops/sec    18ns       O(1)
Best Price      211.82M ops/sec   4ns        O(1)
Match           119.05M ops/sec   8ns        O(1) per fill

Measured on Apple M3 Max.

The Ladder Algorithm

volt replaces the traditional red-black tree with fixed-size arrays and hierarchical bitsets. Every operation is constant-time.

Price to index mapping:

index = (price - base_tick) / tick_size

Best price discovery uses CPU intrinsics (@clz, @ctz) on the bitset — no tree traversal needed.

Operation RB-tree volt
Insert O(log M) O(1)
Cancel O(log M) O(1)
Best Price O(1) cached O(1) bitset
Match O(log M) + O(K) O(1) + O(K)

Memory Layout

Per side:
  Price levels  — 1M slots x 32 bytes = 32MB (cache-aligned)
  Order pool    — 100K pre-allocated orders
  HashMap       — OrderID -> index, no rehashing
  Bitset        — 2-level hierarchy for O(1) price discovery

Total: ~64MB per symbol. Pre-allocated, zero allocations in the hot path.

Why Pre-allocation

Dynamic allocation introduces latency spikes (malloc can block), cache pollution, and unpredictable HashMap rehashing. Pre-allocation gives deterministic 18ns latency on every operation.

Usage

const MatchingEngine = @import("matching_engine");

var engine = try MatchingEngine.init(allocator, .{
    .n_ticks = 1_000_000,
    .max_orders = 100_000,
    .tick_size = 1,
});
defer engine.deinit();

// Insert limit order
const order_id = try engine.insertLimit(.{
    .id = unique_id,
    .side = .buy,
    .price = 45000,
    .quantity = 100,
    .type = .limit,
    .time_in_force = .good_till_cancel,
});

// Cancel
engine.cancel(order_id, .buy);

// Match market order
var events = std.ArrayList(Event).init(allocator);
try engine.matchMarket(.{
    .side = .sell,
    .quantity = 50,
    .events_out = &events,
});

Build

Requires Zig 0.14.0+. No external dependencies.

zig build -Doptimize=ReleaseFast        # Build
zig build test                           # Run all tests
zig build bench-ladder-micro             # Operation benchmarks
zig build bench-compare                  # Ladder vs RB-tree comparison

Architecture

Domain Layer        LadderBook (array-based O(1))
                    OrderBook (RB-tree baseline for comparison)

Application Layer   MatchingEngine -> Command Processor -> Event Emitter

Adapter Layer       HTTP Server, WebSocket, Binary Protocol
                    Journal Persistence, Snapshot Store

Testing: unit tests, parity tests (ladder vs RB-tree produce identical results), invariant validation, and performance benchmarks.

Why Zig

No hidden allocations. Comptime metaprogramming for zero-cost abstractions. Direct access to CPU intrinsics. No GC pauses. Simple, readable code.

License

MIT

About

High-performance limit order book with O(1) operations, 50M+ ops/sec. Zig.

Resources

Stars

Watchers

Forks

Contributors