TICKETS 03 OF 3 RUNS LEFTACC --
OUTCRY

← Guide BookPlay it

Mock Screens

Quant Developer Online Assessment

Four auto-graded coding problems against hidden tests and a performance gate, plus a ten-item concurrency and complexity code-review section.

Quant Developer Online Assessment in play on Outcry
Quant Developer Online Assessment, in play.

What is a Hudson River Trading-style quant developer online assessment?

Low-latency trading firms hire software engineers through algorithmic coding OAs hosted on platforms like HackerRank or CodeSignal, in the same general genre as a typical big-tech coding screen - implement a function, submit it, and hidden test cases grade it automatically. What distinguishes the quant-dev flavor of this genre is an added performance gate: on select problems, a correct solution that is too slow is graded as a failure, not a partial success.

That gate exists because it mirrors the actual job. A market-making or low-latency engineering role is not just about producing the right output eventually - the whole point of the system is that it produces the right output fast enough to matter, on a live feed, under load. An OA that only checked correctness would pass a candidate whose instinct is to reach for the simplest correct data structure rather than the one that scales, which is exactly the instinct a production low-latency codebase cannot tolerate.

A companion code-review section - reading snippets and identifying the defect rather than writing new code - tests a related but distinct skill: recognizing concurrency bugs (data races, missing memory-ordering semantics) and cache-unfriendly access patterns by inspection. This maps onto real code review at this kind of firm, where a subtle data race or a relaxed-ordering bug in a lock-free structure is exactly the kind of defect that a review has to catch before it reaches production, because it will not reliably show up in ordinary testing.

Together, the two sections screen for a specific profile: an engineer who writes efficient code under time pressure and who can also read someone else's code critically for the failure modes that are unique to concurrent, performance-sensitive systems - as opposed to a generalist who can pass a standard algorithms interview but has never had to reason about memory ordering or amortized cost at all.

How it works

The sitting has two sections. Coding problems runs 100 minutes for 4 items, each a kind: "code" item - implement a named JavaScript function or factory, then run it against hidden test cases you cannot see. The pool includes an LRU cache (get/put in O(1)), a running median over a stream (two-heap technique), a best-single-trade maximum-profit scan, and a shortest-cost graph search (Dijkstra with unreachable nodes reported as -1).

Two of those four - the LRU cache and the streaming median - carry a PerfSpec: after every hidden test case passes, the candidate's function is timed against a reference implementation running the identical workload in the same sandboxed worker, and it must land within a fixed multiple of that reference time to pass.

Code review follows: 15 minutes for 10 multiple-choice items on complexity, data-structure selection, and concurrency defects - constant-time order cancellation, running-median structure choice, the real-world cost of O(n²) scaling, what amortized O(1) actually means for a dynamic array, a data race from a non-atomic shared counter, a missing memory-ordering barrier in a lock-free ring buffer, and cache-friendly iteration order.

Per the sitting's own rules, you may re-run a submission as many times as you like before time runs out, but only the last run for each problem counts, and there is no negative marking on either section.

How scoring works

Both sections have penalty 0 (no negative marking) and allowBack false (no return pass to an earlier item once you have moved on).

For a code item, runAssessmentCode.ts runs your submission inside a Web Worker against every hidden CodeTest first. A test with a script (like the LRU cache's put/get sequence) fails at the first call whose return value does not match the expected value; a plain args/expected test compares the return value directly. Any case that fails, or that throws, marks that case as failed - and a submission that never resolves is cut off after a 12-second timeout and reported as timed out.

Only if every hidden test passes does the performance gate run for a problem that has one (LRU cache and streaming median). The worker warms up both the candidate's function and a reference implementation, then times the median of 5 runs of each on an identical workload. The ratio of candidate time to reference time must fall at or under the problem's budget (5x for both gated problems here) for perfPassed to be true.

A code item counts as solved only when every hidden test passes and, where a performance gate exists, perfPassed is also true - passing all tests with an approach the gate is built to catch (for example, an O(n) array scan against the LRU cache's O(1) reference) is graded as unsolved.

The 10 code-review items are ordinary multiple choice with no marks override, so each is worth one raw mark, scored the same way as any other choice item on the site.

Coding problems

Notice which two problems carry the performance note in their description (LRU cache, streaming median) - those are the ones where the starter's naive approach will pass every test and still fail the item. Treat the performance note as a spec requirement, not a bonus objective.

For the LRU cache, the fix is structural: a JavaScript Map already preserves insertion order, so deleting and re-inserting a key on every get or put moves it to the 'most recent' end for free, and the least-recently-used key is always whatever keys().next().value returns.

For the streaming median, two balanced heaps (a max-heap of the lower half, a min-heap of the upper half) turn every add into an O(log n) heap push and every median() into an O(1) peek - re-sorting the whole buffer on each query is the trap the gate is tuned to catch.

The two ungated problems (best single trade, cheapest routes) reward getting the standard technique right the first time - a single pass tracking the running minimum for the trade problem, Dijkstra with a settled-node relaxation for the routes problem - since there is no partial credit for an approach that is merely close.

Run your code against the visible examples in the description before you consider a problem done, but budget your last run carefully - only the final run per problem is what gets graded, so do not leave a debugging change unrun.

Code review

For the concurrency items, look specifically for read-modify-write on shared state without synchronization (a lost increment) and for a relaxed atomic store publishing an index before the data it points to is actually visible to another thread - both are named defects in this pool, not generic 'add a lock' answers.

For the complexity items, be ready to reason about scaling directly: an O(n squared) routine run at 10x the input does about 100x the work, and amortized O(1) for a growing array means most operations are cheap while occasional reallocation is spread thin across many calls - not that every single call is equally fast.

For data-structure-choice items, match the operation to its native complexity: O(1) cancel-by-id needs a hash map plus a doubly linked list, and a running median needs two balanced heaps - both are the same techniques the coding section rewards, so recognizing them here is free reuse of what you just built (or should have).

At roughly 1.5 minutes per item, these are meant to be answered on recognition - if you are working out big-O from first principles during this section, that is worth a post-sitting review, not more time spent on this one item.

Pacing across the whole sitting

100 minutes for 4 coding problems is 25 minutes each on average, but the two ungated problems are typically faster to get fully correct than the two gated ones are to get both correct and fast - bank the ungated pair early if you can, and leave more of the 100 minutes for the LRU cache and streaming median.

Do not spend the coding section's remaining time squeezing extra margin out of a problem that is already comfortably under its performance budget - the gate is pass/fail at the stated multiple, not a leaderboard, so time beyond clearing it is better spent elsewhere.

The 15-minute code-review section is worth protecting on its own clock: 10 quick-recognition items at roughly 1.5 minutes each is a lot of raw marks to leave unattempted because the coding section ran long.

A worked example

  1. Restate the requirement precisely: get(key) and put(key, value) must each run in O(1), and once the cache is at capacity, a new key must evict the least-recently-used entry.

  2. Pick a structure whose native ordering already tracks recency instead of bolting recency-tracking on top of an array: a JavaScript Map preserves insertion order, so removing and re-inserting a key moves it to the end with no extra bookkeeping.

  3. get(key): if the map does not have the key, return -1. Otherwise read the value, delete the key, then set it again - the delete-then-set round trip is what moves it to the most-recently-used end, and both operations are O(1) on a Map.

  4. put(key, value): if the key already exists, delete it first so the reinsertion below moves it to the end rather than leaving it at its old position. If the cache is full and the key is new, evict the current oldest entry - map.keys().next().value - before inserting, since Map iteration order is insertion order.

  5. Trace the logic against one of the hidden scripts: with capacity 2, put(1,1) then put(2,2) leaves order [1, 2]. get(1) returns 1 and moves 1 to the end, giving [2, 1]. put(3,3) evicts the oldest entry, 2, and inserts 3, giving [1, 3]. get(2) now correctly returns -1, exactly as the hidden test expects.

  6. See why the naive array starter fails the performance gate even though it passes every test: store.findIndex scans every entry to locate a key, and splice shifts the array to remove or reposition one - both O(n) per call. It returns correct answers on all 5 hidden tests, but the benchmark runs 25,000 operations against a 15,000-entry cache; against the reference's O(1) implementation, the array version lands at roughly 12x the reference time, well past the 5x budget - so perfPassed is false and the item is not solved despite every test passing.

Common mistakes

Passing every hidden test with an O(n) approach (array scans and splices) and assuming that means the problem is solved - the performance gate on the LRU cache and streaming median problems fails a correct-but-slow solution outright.

Returning Infinity for an unreachable node in the shortest-cost routes problem instead of -1 - the tests compare JSON.stringify output directly, and Infinity serializes to null, not -1.

In the LRU cache, overwriting an existing key's value with put() but forgetting to also move it to the most-recently-used position, so a just-updated key gets evicted as if it were stale.

In the streaming median, letting the two heaps drift more than one element apart in size instead of rebalancing after every insert, which produces the wrong element - or the wrong average of two elements - once the count is even.

Spending the last minutes of the 100-minute coding budget shaving further margin off a problem that already clears its performance gate, instead of banking the separately-timed code-review section's 10 items.

Why interviews test this

The performance gate is the mechanism that most distinguishes this OA from a generic algorithms screen, and it exists because it mirrors the actual failure mode a low-latency shop cares about: code that is correct in every test case but was written with the wrong complexity in mind will not survive contact with a real feed at real volume. Grading 'solved' as tests-pass AND perf-pass, rather than tests-pass alone, forces exactly the discipline the job requires - notice the scale of the workload before picking a data structure, not after.

The code-review section tests a complementary and equally job-relevant skill: reading someone else's code for concurrency and cache-behavior defects that unit tests routinely miss, because a data race or a missing memory-ordering barrier can pass every test run and still be wrong under real interleaving. Firms building low-latency, multi-threaded systems need engineers who catch that class of bug by inspection during review, since by the time it reproduces in production it is usually already expensive.

Play Quant Developer Online Assessment · All game guides · The arcade