Reported July 2023
Optiverhash table

Worst Trade Reporter

Reported by candidates from Optiver's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.

Get StealthCoderRuns invisibly during the live Optiver OA. Under 2s to a working solution.
Founder's read

The Optiver OA reported in July 2023 looks like a parsing exercise, but one detail wrecks the obvious approach: the true price changes after trades are recorded, so every stored loss goes stale. If you're taking this OA soon, the question is how to answer WORST_TRADE fast across up to 10^6 instructions. It's a hash-table plus ordered-structure problem dressed as a trading log. StealthCoder sits as a safety net during the live OA if you blank on the data structure, but the idea below is small enough to hold in your head.

The problem

Process a stream of price updates, trades, and worst-trade queries.
PRICE instrument price sets the latest true price for an instrument.
TRADE tradeId instrument BUY|SELL price volume records a unique trade.
WORST_TRADE instrument asks for the recorded trade with the greatest loss per lot at the latest true price.
For a buy, profit per lot is truePrice - tradePrice. For a sell, profit per lot is tradePrice - truePrice. A trade is bad only when this value is negative. If several trades have the same greatest loss per lot, choose the one that appeared latest in the instruction stream. If no trade is bad, return NO BAD TRADES.
Return one string for every query, in query order.

Function
worstTrades(instructions: String[]) → String[]

Examples
Example 1
instructions = ["PRICE Facebook 80","PRICE Apple 120","TRADE 100 Apple SELL 90 2","TRADE 10 Facebook BUY 100 4","WORST_TRADE Facebook","WORST_TRADE Apple"]
return = ["10","100"]
The Facebook buy loses 20 per lot, while the Apple sell loses 30 per lot.
Example 2
instructions = ["PRICE Google 100","TRADE 1 Google BUY 100 10","WORST_TRADE Google","TRADE 2 Google SELL 102 5","TRADE 3 Google SELL 103 5","PRICE Google 98","WORST_TRADE Google","TRADE 4 Google BUY 101 10","TRADE 5 Google BUY 100 10","WORST_TRADE Google"]
return = ["NO BAD TRADES","1","4"]
The first query has no loss. At price 98, trade 1 loses 2 per lot; after two more buys, trade 4 loses 3 per lot.

Constraints
1 <= instructions.length <= 10^6
1 <= tradeId, price, volume <= 10^6
Every trade ID is unique.
A price update for an instrument appears before its first trade or query.
Instrument identifiers contain no spaces.

Reported by candidates. Source: FastPrep

Pattern and pitfall

The naive move is to scan every trade for the instrument on each WORST_TRADE query. With 10^6 instructions that's quadratic and dies. The trick is to rewrite the loss. For a buy, loss is tradePrice - truePrice. For a sell, loss is truePrice - tradePrice. Each side is a constant minus or plus the current price, so the price shift is the same for every trade on that side. That means you only need the best candidate per side. Per instrument, keep the buy with the highest tradePrice and the sell with the lowest tradePrice, breaking ties by latest position. Then at query time compute both losses at the latest price, drop non-negative ones, and compare. The pitfall is the tie-break: equal loss across a buy and a sell must go to the later instruction. Track an instruction index. StealthCoder is your hedge if the tie rule slips under pressure.

If you see this problem in your OA tomorrow, the play is to recognize the pattern in 30 seconds. StealthCoder buys you that recognition.

If this hits your live OA

You can drill Worst Trade Reporter cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. Built by an Amazon engineer who passed his OA cold and still thinks the filter is broken.

Get StealthCoder

Related leaked OAs

⏵ The honest play

You've seen the question. Make sure you actually pass Optiver's OA.

Optiver reuses patterns across OAs. Built by an Amazon engineer who passed his OA cold and still thinks the filter is broken. Works on HackerRank, CodeSignal, CoderPad, and Karat.

Worst Trade Reporter FAQ

What's the trick in Worst Trade Reporter?+

Loss per lot depends on the current price only through a shared offset per side. So you don't rescan trades. Per instrument, store the best buy (highest price) and best sell (lowest price), and evaluate just those two at query time.

How do I handle ties on loss?+

If several trades share the greatest loss, pick the one that appeared latest in the stream. Store an instruction index with each candidate. Within a side, replace on equal price using the newer trade. Across sides, compare indexes when losses match.

When do I return NO BAD TRADES?+

Only when no trade has a negative profit per lot at the latest price. Zero profit isn't bad. Check each side's candidate, discard any with profit of zero or more, and return the string if both are gone or no trades exist.

How hard is this one really?+

Medium. The logic is short once you spot the per-side reduction. The difficulty is input size and the tie rule. Brute force passes the examples but fails the 10^6 constraint, so aim for O(1) per instruction using a hash map.

How do I prepare in 48 hours?+

Practice parsing string commands into a hash map of per-key state. Write the two-candidate approach from memory, then test price drops and rises, equal-loss ties, and instruments with no trades. Return values as strings, including trade IDs.

Problem reported by candidates from a real Online Assessment. Sourced from a publicly-available candidate-aggregated repository. Not affiliated with Optiver.

OA at Optiver?
Invisible during screen share
Get it