Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Orderbook Trade Query Processor

A small Rust CLI that answers trade queries over a local dataset (trades.csv).

The interesting part is the caching: queries are at most 1 hour wide, so the program caches trades per-hour in an LRU to avoid repeating the same "expensive" fetch.

Note: get_fills_api in src/server.rs simulates an expensive API call (sleep + filter over the CSV-backed dataset). There's no HTTP server here.

Quickstart

Files expected in the repo root:

  • trades.csv (trade data)
  • a query file like test_input.txt or input.txt

Run:

cargo run --quiet < test_input.txt

Or:

cargo run --quiet < input.txt

Input format

Each line on stdin is:

<TYPE> <START_TIME> <END_TIME>
  • START_TIME / END_TIME: Unix timestamps (seconds)
  • Time window semantics: trades with time > START_TIME and time <= END_TIME

Example:

C 1700000000 1700003600
V 1700000000 1700003600

Output is one line per query (a number for C/B/S, a Decimal for V).

Query types

  • C: count of taker trades (unique by sequence number)
  • B: count of market buys (direction 1)
  • S: count of market sells (direction -1)
  • V: total traded volume in USD (quantity * price summed over fills)

Constraints

  • END_TIME - START_TIME must be <= 3600 seconds
  • Input timestamps are assumed to be within the dataset's time range
  • A "taker trade" is uniquely identified by sequence_number (duplicate sequence numbers are treated as the same taker trade for C/B/S)

How it works

  • Rounds START_TIME and END_TIME down to hour boundaries.
  • Fetches fills for the start hour, and (if different) the end hour.
  • Uses an LRU cache keyed by hour timestamp (seconds) with capacity 168 hours.
  • Filters fills to the exact (> start, <= end) window and answers the query.

Implementation entry point: src/main.rs.

Logging

Uses env_logger. Set RUST_LOG to control verbosity:

RUST_LOG=info cargo run --quiet < test_input.txt
RUST_LOG=debug cargo run --quiet < test_input.txt

At the end it prints cache stats + hit rate.

Performance + design notes

Cache design

  • Cache capacity: 168 hours (one week)
  • Key: hour timestamp (rounded down to hour boundary)
  • Value: Vec<Fill> (all fills for that hour)

Data flow (per query)

  1. Round timestamps to hour boundaries.
  2. Read required hours from cache, fetching missing hours via get_fills_api and inserting into cache.
  3. Merge hour buckets (at most 2 hours given the <= 3600s constraint).
  4. Filter to the exact (> start, <= end) range.
  5. Answer the query.

Benchmarks (local)

  • Environment: MacBook Pro (16GB RAM, M2 Pro)
  • Dataset: 235,834 trades over ~165 hours
  • Query Set: 1000 random queries
  • Results:
    • Memory usage: 13.2MB (normal), ~47MB (worst case estimate)
    • API calls: reduced by 83.6% (from 1000 to 164)
    • Total processing time: reduced by 64% (from 31.8s to 11.5s)

Assumptions

  • Trade volume varies; average ~1,438 trades/hour, peak 4,211 trades/hour.
  • Dataset is static during execution.
  • Each fill has direction 1 (buy) or -1 (sell).
  • Single-threaded is sufficient.

RAM estimate (why ~50MB is enough here)

  • Total fills in dataset: 235,834
  • Cache size if it held the entire dataset: 13,212,016 bytes (~13.2MB)
  • Approx bytes/fill: 13,212,016 / 235,834 ~= 56 bytes
  • Peak-hour assumption: 5,000 fills/hour
  • One-week peak cache: 5000 * 56 * 168 ~= 47MB

Tradeoffs

  • Cache raw Fill vs. cache precomputed aggregates:
    • raw keeps query flexibility; costs memory and per-query processing.
  • Cache full hours vs. cache exact ranges:
    • hours simplify cache keys and improve hit rate; may store unused fills.
  • LRU cache vs. HashMap:
    • LRU gives a fixed cap + eviction; slightly more overhead.

Other choices

  • rust_decimal::Decimal instead of f64 to avoid floating point surprises for money.
  • anyhow for error messages and ergonomics.

About

Optimizing queries on hourly trade data using an LRU cache mechanism

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages