Quant interview preparation
Prop market making and quantitative research, weighted the way the interviews actually are: probability and expected value, statistics and machine learning, market making logic, programming and options. Every question is either traced to a named firm from a public candidate report, or tagged at desk level when we could not trace it, and every probability answer shows the reasoning path rather than just the number.
100 questions, mapped to the firms that asked them
- Questions
- 100
- Traced to a firm
- 53
- Firms
- 15
- Updated
- September 2026
078Given a stream of numbers, return the median after each element arrives.Old Mission CapitalEquities · Boston · 2024
Say this
Two heaps. A max heap for the lower half and a min heap for the upper half, kept balanced so their sizes differ by at most one. The median is the top of the larger heap, or the average of the two tops. Insert is O(log n), query is O(1).
Then walk it
- Insert rule: if the new value is at most the max of the lower heap, push it there, otherwise push to the upper heap. Then rebalance by moving one element across if the sizes differ by more than one.
- Query: if the sizes are equal, the median is the average of the two tops. Otherwise it is the top of the larger heap. Constant time either way.
- Total cost for n elements is n log n, and memory is O(n) because you must retain everything. That memory cost is the honest limitation, and it is the first thing an interviewer will probe.
- If the median must be over a sliding window rather than the whole prefix, the two-heap approach needs deletions from the middle. Use an indexed multiset or two heaps with lazy deletion and a hash of pending removals. That is the version that comes up in practice on a tick stream.
- And if approximate is acceptable, which on a trading system it usually is, the right answer is a streaming quantile sketch: t-digest or the Greenwald-Khanna algorithm, giving you any quantile in bounded memory rather than O(n). Naming that unprompted is what turns a correct interview answer into a practical one.
Where candidates lose it
Sorting on every element, which is O(n squared log n) overall, or maintaining a sorted list with insertion, which is O(n) per element because of the shifting even though the binary search is fast. Say two heaps immediately, then volunteer the sliding-window and bounded-memory variants, because that is where the conversation is heading.
Expect next
- Now do it over a sliding window of the last thousand values.
- What if you cannot store all the data?
- How would you get the 99th percentile instead of the median?
Reported by candidates at Old Mission Capital (Equities, Boston, 2024). Source: Wall Street Oasis.
081Write me an unordered_map class. What is actually inside a hash map?Old Mission CapitalTrading · Chicago · 2021
Say this
An array of buckets, a hash function mapping keys to bucket indices, a collision resolution strategy, and a resize policy driven by load factor. The three decisions that define the implementation are the hash, the collision handling, and when you grow.
Then walk it
- Core operations: index equals hash of key modulo bucket count, then search within that bucket comparing keys for equality. Insert, find and erase all follow that pattern, and all are O(1) expected under a good hash.
- Collision resolution, and this is the main design choice. Separate chaining stores a list per bucket, which is simple and is what the C++ standard effectively mandates for unordered_map because of its iterator and reference stability guarantees. Open addressing stores entries inline and probes forward, which is far more cache-friendly but complicates erase, since you need tombstones or backward shifting.
- Resize: track load factor as elements over buckets, and when it exceeds a threshold, typically 0.75 for chaining or 0.5 to 0.7 for open addressing, allocate a bigger array and rehash everything. Use a power-of-two bucket count so the modulo is a bitmask, but then your hash must mix the high bits or a weak hash collides badly.
- The correctness details an interviewer will probe: key equality is separate from the hash, two equal keys must hash the same, iterator invalidation on rehash, and what happens when the key type has a bad hash. A hash that is the identity on integers plus power-of-two buckets means sequential keys with a stride collide catastrophically.
- If I were writing this for a trading system I would use open addressing with linear probing over a pre-allocated power-of-two array, reserve capacity up front so no rehash ever happens in the hot path, and store keys and values in separate arrays if the values are large. The reason is tail latency: one rehash mid-session is a millisecond spike, and a millisecond is forever.
Where candidates lose it
Describing the interface rather than the internals. The question is about buckets, hashing, collisions and resizing. Also be ready for why is std::unordered_map slow, whose answer is node-per-element allocation and the standard's stability guarantees forcing chaining. And never forget that erase under open addressing needs tombstones, which is the bug candidates ship.
Expect next
- How does erase work under open addressing?
- What load factor would you choose and why?
- What makes a good hash function, and what happens with a bad one?
Reported by candidates at Old Mission Capital (Trading, Chicago, 2021). Source: Wall Street Oasis.
082Something in your C++ program is overwriting memory it should not. How do you find it?Tower Research CapitalForeign Exchange · London · 2019
Say this
Reach for the sanitisers first. AddressSanitizer catches out-of-bounds writes and use-after-free with roughly a two times slowdown and tells you both the write site and the allocation site. If the corruption is timing-dependent, add ThreadSanitizer for data races.
Then walk it
- Order of tools: compile with -fsanitize=address,undefined and run the failing case. That resolves most buffer overruns and use-after-free immediately. Valgrind memcheck is slower but needs no recompile and catches uninitialised reads that ASan misses.
- If the corrupted location is known but the writer is not, set a hardware watchpoint in gdb on that address with watch, and let it break when something writes. Four watchpoints on x86, which is usually enough.
- If the corruption is not reproducible, make it reproducible before anything else. Record the inputs, pin the threads, disable randomisation, and consider record-and-replay with rr. A bug you cannot reproduce cannot be fixed, only guessed at.
- Common causes to check by inspection while the tools run: writing past the end of a fixed buffer, a dangling reference into a vector that reallocated, a stale pointer into an object that moved, a struct written with memcpy at the wrong size, and two threads writing the same cache line without synchronisation.
- And the systems answer for a production trading process where you cannot run ASan in the hot path: build with sanitisers in a test environment and in a canary, add canary values or guard pages around suspect buffers, and turn on the allocator's own debug checks. I would also say plainly that the fastest fix for a class of these bugs is to stop using raw buffers, because bounds-checked containers and spans eliminate the whole category.
Where candidates lose it
Answering add print statements. That is the answer of someone who has never used a sanitiser, and at a firm running C++ in production it is disqualifying. Name ASan specifically, name the gdb watchpoint technique for a known address, and say how you would make an intermittent bug reproducible before you try to find it.
Expect next
- What does AddressSanitizer not catch?
- How would you debug this in production where you cannot run sanitisers?
- What is a data race and why is it undefined behaviour?
Reported by candidates at Tower Research Capital (Foreign Exchange, London, 2019). Source: Wall Street Oasis.
084How would you design a system to troubleshoot latency in a trading stack?CitadelProp Trading · New York · 2026
Say this
Timestamp at every hop with one clock, measure distributions not averages, and make the whole path attributable so you can say which segment consumed the microseconds. The design principle is that you cannot fix what you cannot decompose.
Then walk it
- Instrumentation: hardware timestamps at the network card for packet in and packet out, plus software timestamps at each stage, market data decode, book update, strategy decision, order encode, and kernel bypass send. Carry a correlation id through the whole chain so a single event can be reconstructed end to end.
- Clocks are the hard part. Use PTP with hardware timestamping across hosts, not NTP, and record clock offset and drift as first-class data. Two hosts disagreeing by fifty microseconds will invent latency that does not exist and hide latency that does.
- Statistics: report the median, the 99th, the 99.9th and the maximum. Averages are useless here because the distribution is heavily right-tailed and the tail is exactly what costs money. Track per-segment histograms, ideally with HDR histograms so the tail resolution survives.
- Storage and analysis: stream the records off the critical path into a time-series store, then build the two views that actually get used, a per-segment breakdown over time and a drill-down into the slowest individual events. Alert on percentile regressions against a rolling baseline rather than on fixed thresholds.
- Then the causes to design for, because the system exists to distinguish them: garbage collection or allocation pauses, page faults, context switches and CPU migration, interrupt coalescing settings, cache misses and false sharing, queueing at the exchange gateway, and simple network congestion. And I would say the measurement must not itself be on the hot path, so lock-free ring buffers with a separate reader thread, because an observability system that adds ten microseconds has destroyed what it measures.
Where candidates lose it
Describing logging and monitoring generically. This is a specific systems question and the differentiators are clock synchronisation, percentile rather than mean reporting, and keeping instrumentation off the critical path. Talk in microseconds, and be able to name concrete causes of a tail latency spike.
Expect next
- How do you synchronise clocks across hosts, and to what accuracy?
- Why report the 99.9th percentile rather than the average?
- Walk me through diagnosing a spike that happens once a day.
Reported by candidates at Citadel (Prop Trading, New York, 2026). Source: Wall Street Oasis.
Firm tags come from public, anonymous candidate reports on Wall Street Oasis: strong signal, not sworn testimony. Firms are named as the places a question was reported, not as partners of Fin Maverick. Answers are written for this page to show how to think out loud; they are not scripts to recite.

