← Point72 Asset Management Interview Insights

Point72 Asset Management·Software Engineer·Online Assessment (OA)·Intermediate

IntermediatePrefer not to say
May 2026Remote

Summary

SQL-heavy online assessment for a Data Engineer role at Point72, one problem but it had enough edge cases to keep me busy for a while. The problem was framed as fraud detection on a crypto exchange and the output formatting requirements were brutal.

Questions Asked (1)

Q1

Given a transactions table on a cryptocurrency exchange, write a PostgreSQL query to detect potentially fraudulent activity: find all sender-recipient pairs with 2 or more transactions, then produce one row per sender showing their wallet address, a formatted time range from first to last transaction, and a concatenated string of transaction amounts sorted descending. For senders with 3 or fewer transactions just list them all with a sum; for more than 3, show the top 3 and collapse the rest into a '+ .. X more = Sum' suffix. Order final output by total amount descending.

Algorithms & Data StructuresData ModelingTechnical Trade-offs
Author's notes

The core logic, CTEs for filtering pairs then joining back to detail rows, wasn't the hard part.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Break the problem into stages: first filter sender-recipient pairs with at least 2 transactions using a HAVING clause, then aggregate per sender to compute total amount, first/last timestamps, and a sorted array of amounts. Use window functions or array aggregation to rank amounts and conditionally format the output string, then order by total amount descending.

Pro tip: Mention that you would clarify edge cases upfront—like how to handle ties in amount ordering, timezone for timestamps, and whether 'transaction amount' is in a specific currency—and note that using a CTE with array_agg and unnest can make the conditional formatting both readable and performant.

1. Filter qualifying sender-recipient pairs

Use a subquery or CTE to group by sender and recipient, apply HAVING COUNT(*) >= 2, and return only those pairs. This reduces the dataset before further aggregation.

2. Aggregate per sender

Join back to the transactions table for qualifying pairs, then group by sender to compute total amount, MIN(transaction_time), MAX(transaction_time), and collect all amounts into an array sorted descending.

3. Format the amount string conditionally

If count <= 3, concatenate all amounts; otherwise, take the top 3 amounts and append a suffix like '+ .. X more = Sum' where X is the remaining count and Sum is the sum of those remaining amounts.

4. Format the time range and final output

Use to_char or similar to format the first and last timestamps into a readable range string. Select sender, time range, and amount string, then order by total amount descending.

Key Points to Mention

  • Use of HAVING COUNT(*) >= 2 to filter sender-recipient pairs with multiple transactions.
  • Array aggregation (array_agg) with ORDER BY to sort amounts descending, and array slicing to get top 3.
  • Conditional logic (CASE WHEN) to handle the two formatting scenarios based on transaction count.
  • Window functions or subqueries to compute the sum of remaining amounts for the '+ .. X more = Sum' suffix.
  • Proper timestamp formatting (e.g., to_char) and consideration of timezone.
  • Final ORDER BY total_amount DESC and ensuring the output is one row per sender.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.