As a Data Scientist at Wolverine Trading, you play a pivotal role in transforming complex data into actionable insights that drive strategic decision-making and enhance trading performance. Your contributions will impact various areas, including algorithmic trading, risk management, and market analysis, ensuring that the company remains competitive in a rapidly evolving financial landscape. The insights you provide will not only optimize trading strategies but also enhance the overall user experience by making data-driven recommendations that resonate with market dynamics.
This role is critical because it combines advanced analytical skills with a deep understanding of financial markets. You will work closely with cross-functional teams, including traders, engineers, and product managers, to solve complex problems and identify opportunities for innovation. The complexity of the datasets you’ll handle, coupled with the high-stakes environment of trading, makes this role both challenging and rewarding. Expect to engage with cutting-edge tools and technologies while contributing to projects that have a significant impact on the business.
Online Assessment
reportedThis round decides whether someone can hand you a schema and a question and trust the number that comes back. Correctness under a clock is the bar, not clever syntax. The habit that separates strong from weak answers is checking the grain: after every join, know how many rows you expect and whether the count moved. Most wrong answers in this format are not wrong logic, they are a fan-out from a key that turned out not to be unique, or a filter applied before an aggregate when it belonged after. Say what you expect before you run it.
What to demonstrate
- Whether your row counts survive each join, and whether you notice on your own when they do not
- Deliberate handling of rows that fail to match, including whether the question needs an inner join or a left join with the non-matches kept and counted
- Whether NULLs are treated on purpose, given that a NULL compares equal to nothing and that COUNT of a column skips it
- Reaching a defensible answer inside the window instead of a refined one after it
How to prepare
- Take a two-table schema, write a join that fans out on purpose, then fix it by collapsing the many-side to one row per key before joining. Repeat until the fix is reflex rather than recall.
- Write a funnel as one query and print the distinct user count at each stage, then confirm each stage is a subset of the one above it rather than assuming it
- Do a few timed runs in a plain text box with no autocomplete and no formatter, since assessment editors often have neither
Technical Interviews
reportedThis round decides whether someone can hand you a schema and a question and trust the number that comes back. Correctness under a clock is the bar, not clever syntax. The habit that separates strong from weak answers is checking the grain: after every join, know how many rows you expect and whether the count moved. Most wrong answers in this format are not wrong logic, they are a fan-out from a key that turned out not to be unique, or a filter applied before an aggregate when it belonged after. Say what you expect before you run it.
What to demonstrate
- Whether your row counts survive each join, and whether you notice on your own when they do not
- Deliberate handling of rows that fail to match, including whether the question needs an inner join or a left join with the non-matches kept and counted
- Whether NULLs are treated on purpose, given that a NULL compares equal to nothing and that COUNT of a column skips it
- Reaching a defensible answer inside the window instead of a refined one after it
How to prepare
- Take a two-table schema, write a join that fans out on purpose, then fix it by collapsing the many-side to one row per key before joining. Repeat until the fix is reflex rather than recall.
- Write a funnel as one query and print the distinct user count at each stage, then confirm each stage is a subset of the one above it rather than assuming it
- Do a few timed runs in a plain text box with no autocomplete and no formatter, since assessment editors often have neither
Behavioral Interviews
reportedThis round decides whether you owned a decision or watched one happen nearby. Interviewers for data roles listen for the point where the analysis stopped being a report and started changing what someone did, so build each story around that hinge: what was going to happen by default, what you found, and what happened instead. The most common weakness is a story that ends at delivery. If you can name the decision your work changed and the number that moved because of it, most follow-ups become easy.
What to demonstrate
- Whether the decision was yours to influence, or whether you are narrating a team outcome in the first person
- The counterfactual: what would have been done without your analysis, and why that default was worse
- How far your involvement ran past the handoff, and whether you checked that the change did what you predicted
How to prepare
- Pick three projects and write one sentence for each naming the decision-maker, the choice in front of them, and what they chose after seeing your work. If you cannot name a person and a choice, the story is not ready for this round.
- Reconstruct the baseline for your strongest project from the original query or dashboard rather than memory, so the before-number survives a follow-up asking where it came from.
- Prepare an honest version of a project where your recommendation was overruled, including what you did with the analysis afterwards.
3 candidate reports. Individual accounts describe a particular role and hiring cycle.
Wolverine Trading Software Engineer interview: CoderByte trading assessment
An early conversation led quickly to a CoderByte assessment built around trading concepts. The coding was lighter than the systems-style prompts I had seen elsewhere, but it depended on using the right trading vocabulary and mapping it to simple logic. Timing and execution made the difference, and the platform's format pushed me to be precise. The live coding interview gave me more room to explai…
Read full experienceWolverine Trading Software Engineer interview experience
After applying, I was sent to an online OA on CoderByte. It involved object-oriented coding and trading-flavored logic, including registering and monitoring stock pairs and reporting when their price relationship moved beyond a tolerance. The specification was long, so careful reading mattered more than finding a trick algorithm. I spent most of my time translating requirements into code. The nex…
Read full experienceWolverine Trading Software Engineer interview: OOP clarification with a helpful interviewer
My process felt straightforward end to end. After an initial recruiter-style conversation, I had a quick early exchange where I introduced myself and answered an OOP-oriented question. The process felt professional. The interviewer was clear about the specification and helped me work through what they expected, so it felt more like collaborative clarification than a gotcha. It was what I expected…
Read full experiencePracHub editorial advice for the preparation topics above.
Filtering on as_of_date rather than knowledge_ts, so restated fundamentals, revised index constituents and retroactively applied split and dividend adjustments enter the backtest before they were knowable.
Vendors overwrite history in place. A quarterly figure filed 45 days after period end is stored against period end, an index addition announced five business days before it takes effect is stored against the effective date, and a split applied tonight rewrites every prior close in the adjusted series. Each of those gives the strategy information it could not have had, and the resulting lift is concentrated in the highest-turnover, highest-apparent-alpha names. The signal_score table separates the two timestamps precisely so this filter can be written correctly.
Joining research panels to the current instrument master instead of its effective-dated version, so delisted, merged and bankrupt names silently disappear from the historical universe.
The names that leave a universe leave disproportionately after bad returns, so removing them raises backtested return and lowers backtested volatility at the same time. The bias is largest exactly where the strategy claims to add value, in the tails, and it is invisible in the output: the query succeeds, the row count looks plausible, and the equity curve simply looks better than it should. The fix is to resolve universe membership with a predicate on effective_from and effective_to, never on status = 'active'.
Over-explaining the method and under-explaining the implication
Lead with the answer and what you would do about it, then give the approach when asked. Roughly one sentence of method per three of implication is the right ratio for a stakeholder-facing answer; the interviewer already knows what a regression is.
Reading a dozen metrics with no multiplicity control
Nominate one primary metric before launch and treat the rest as guardrails or exploratory, with Bonferroni or Benjamini-Hochberg applied when you intend to make claims from them. Twenty independent tests at 0.05 under the null produce at least one false positive about 64 percent of the time.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Describe a project where you implemented a machine learning model.
Describe a project where you implemented a machine learning model.
Approach
- Set a baseline first, so any model has something honest to beat.
- Frame the prediction: the label, the moment of prediction, and the action it triggers.
- Say how the offline result would be validated online before it is trusted.
Follow-up
- How would you choose the decision threshold, and who owns that choice?
- Where could label leakage enter this setup?
Validate a point-in-time signal panel before it is traded
signal_score arrives as a DataFrame with signal_id, model_version, instrument_id, as_of_date, knowledge_ts (UTC), raw_value, zscore_xs, decile_rank, universe_id, coverage_flag, is_backfilled and computed_at: one signal, six years, about 2.4M rows. Write a checker returning a tidy frame of (check_name, as_of_date, n_violations, example_instrument_id) covering grain duplication, knowledge_ts ordering, the cross-sectional moments of zscore_xs, effective coverage, and day-over-day universe churn. Choose your own thresholds and state each one in the output.
Approach
- Start with the grain. The declared key is (signal_id, model_version, instrument_id, as_of_date). Count rows per key rather than calling duplicated(), which with keep='first' reports k-1 for k copies and tells you nothing about whether the copies disagree. Compare raw_value across the duplicates to separate a harmless double-load from two model outputs colliding.
- Check the two timestamp orderings, both of which are silent lookahead: knowledge_ts earlier than the close of as_of_date means the row claims to know a day's value before the day ended, and knowledge_ts later than computed_at is impossible, since inputs cannot become observable after the job that read them ran.
- Per as_of_date, take the moments of zscore_xs. It is winsorized at +/- 3 within universe_id, so the mean should sit near zero and the standard deviation a little under one; flag |mean| > 0.05 or std outside [0.85, 1.15]. Separately verify decile_rank is monotone in zscore_xs within the date and that each decile holds n/10 plus or minus one name.
- Measure effective coverage, not row coverage: put only coverage_flag = 'computed' in the numerator, and additionally flag instruments whose raw_value is unchanged for more than ten consecutive as_of_dates, which catches a feed that stopped updating without emitting a single null.
- Compute universe churn as the symmetric difference of the instrument sets on consecutive as_of_dates over the mean of the two sizes. Outside index reconstitution this should sit well under 1% a day, so flag above 5%. Report the is_backfilled share on the same frame: a spike is a rerun that rewrote history in place.
Follow-up
- A date shows 4% of rows with knowledge_ts before the as_of_date close. How do you decide between dropping those rows, shifting their knowledge_ts, and quarantining the whole date?
- Which of these checks belongs in the daily job as a blocking gate and which as a report, and what does a false positive cost in each case?
- How would the thresholds change for a signal whose eligible universe is 120 names rather than 1,500?
Sessionise a corrected fill stream into trading bursts
One trading day of execution_fill: fill_id, order_id, instrument_id, exec_ts (microsecond UTC venue time), received_ts, fill_qty, fill_px, venue_mic, liquidity_flag, is_correction, corrects_fill_id. About 9.4M rows, delivered in received_ts order, with roughly 0.3% corrections including chains and zero-quantity busts. Produce one row per (order_id, burst), where a burst is a maximal run of surviving fills whose consecutive exec_ts gap is at most 90 seconds, carrying start_ts, end_ts, n_fills, qty, quantity-weighted price and the added-liquidity share. No per-order Python loop.
Approach
- Resolve corrections with set arithmetic rather than iteration: any fill_id appearing in corrects_fill_id has been superseded, so drop those rows, then drop rows with fill_qty = 0 to remove busts, including a bust that supersedes a real fill. Chains need no special case, because every intermediate row is itself somebody's target.
- Sort by (order_id, exec_ts, fill_id). The file arrives in received_ts order and venue timestamps are not monotone in arrival, so sorting is load-bearing rather than tidy; tie-break on fill_id because exec_ts collides at microsecond resolution on active names.
- gap = df.groupby('order_id')['exec_ts'].diff(); new_burst = gap.isna() | (gap > Timedelta('90s')); burst_seq = new_burst.groupby(df.order_id).cumsum(). Two passes over an already-sorted frame, no Python-level iteration.
- Aggregate in one groupby([order_id, burst_seq]): min and max of exec_ts, size, sum of fill_qty, sum of fill_qty*fill_px, and sum of fill_qty where liquidity_flag == 'added'. Derive the weighted price after aggregation as notional over quantity, never as a mean of fill_px.
- Then the concentration flag: join each burst's quantity against the order's surviving total and the order's working span (last exec_ts minus first), and mark bursts holding over 40% of quantity in under 5% of the span. Those are the auction prints and the blocks, and they are the orders whose shortfall is driven by one decision rather than by the algo.
Worked solution 40 min
- superseded = set(f.corrects_fill_id.dropna().astype('int64')); f = f[~f.fill_id.isin(superseded)]; f = f[f.fill_qty > 0].
- f = f.sort_values(['order_id','exec_ts','fill_id'], kind='mergesort').
- Build gap, new_burst and burst_seq as above, then assert burst_seq is 1 on each order's first surviving fill (gap.isna() makes new_burst True there, so the grouped cumsum is 1-based) and increases by exactly 1 at every boundary, with no gaps in the sequence.
- g = f.groupby(['order_id','burst_seq'], sort=False); build the aggregate frame, then wavg_px = notional_sum/qty_sum.
- Reconcile against parent_order.filled_qty and hand-check the three orders with the most bursts.
Follow-up
- Two bursts on one order are separated by 91 seconds. What does a 90-second threshold do to the distribution of bursts per order, and how would you pick the threshold from the data instead of by hand?
- How would you sessionise across orders instead, over all fills in one instrument in one account, and what breaks when two strategies trade the same name in opposite directions?
- One venue reports exec_ts in local time rather than UTC. What would that look like in the burst output, and which check catches it?
Write a function to calculate the Fibonacci sequence.
Write a function to calculate the Fibonacci sequence.
Approach
- Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
- Compute rates by summing numerator and denominator separately, never by averaging rates.
- Say which table is the grain you start from, and join outward from it.
Follow-up
- How does the query change if the join becomes one-to-many?
- What breaks if events arrive late or out of order?
Solve a problem involving SQL queries to extract relevant insights fro…
Solve a problem involving SQL queries to extract relevant insights from a database.
Approach
- Say which table is the grain you start from, and join outward from it.
- Check whether any join is one-to-many before aggregating, or the sums inflate.
- State the window function and its partition and ordering out loud before writing it.
Follow-up
- How would you verify this result without re-running the same query?
- How does the query change if the join becomes one-to-many?
Continuous holding spells from a daily position panel
position_daily holds one row per (business_date, account_id, strategy_id, instrument_id) with signed quantity, weight_pct_nav, realized_pnl_base_day and unrealized_pnl_base_day. Rows exist only for business dates, and a flat day may appear as quantity = 0 or not at all. For one account_id, return every continuous holding spell — consecutive business dates with non-zero quantity and unchanged sign — as one row: instrument_id, strategy_id, side, start date, end date, length in trading days, peak absolute weight and total P&L. Weekends and exchange holidays must not split a spell.
Approach
- Build a trading-day index before anything else:
DENSE_RANK() OVER (ORDER BY business_date)across the distinct business dates in the panel, or against a calendar table if the panel itself can have gaps. Differencing raw dates counts calendar days and breaks every spell at a weekend; differencing the index counts sessions, which is the definition in play. - Restrict to
quantity <> 0and deriveSIGN(quantity). A long that flips to short is two spells, so sign belongs in the island's partition key, not in the aggregate — otherwise a reversal is reported as one continuous position with a misleading average. - Apply the islands construction on the index:
day_idx - ROW_NUMBER() OVER (PARTITION BY account_id, strategy_id, instrument_id, qty_sign ORDER BY day_idx)is constant within a run of consecutive sessions, so grouping by it collapses each run to one row. - Aggregate per island: MIN and MAX of
business_date,COUNT(*)as the session length,MAX(ABS(weight_pct_nav))for peak size, andSUM(realized_pnl_base_day + unrealized_pnl_base_day)for spell P&L. - Fix the gap policy before writing the predicate and state it: a single flat session that splits a spell into two is a different answer from one that is tolerated. If tolerated, merge adjacent islands separated by one session in a second pass, rather than loosening the non-zero filter, which would also swallow genuine exits.
Worked solution 40 min
- Create the session index CTE with DENSE_RANK over business_date across the account's panel.
- Filter to non-zero quantity, add
SIGN(quantity), and compute the island key with ROW_NUMBER. - Group by (strategy_id, instrument_id, qty_sign, island key) and aggregate the five output measures.
- Check for overlap: self-join spells of one (instrument, sign) and assert no pair has intersecting date ranges.
- Reconcile: summed spell lengths per (strategy, instrument) must equal that key's non-zero row count.
Follow-up
- A corporate action changes
instrument_idmid-spell. How do you keep the spell whole, and which table establishes that the two ids are the same economic position? - Some rows inside a spell carry
recon_status = 'break_quantity'. Include or exclude them, and what does each choice do to the length distribution? - How would you extend this to report the P&L contribution of the first five sessions of each spell separately from the rest?
How would you optimize a piece of code for better performance?
How would you optimize a piece of code for better performance?
Approach
- Name one primary metric, then the guardrail that stops it being gamed.
- Decompose the metric into the rates that drive it, and say which one you would check first.
- State what result would change your recommendation, so the answer is falsifiable.
Follow-up
- Which segment would you cut first, and what would that rule out?
- What would you do if the primary metric and the guardrail moved in opposite directions?
Given a scenario where trading performance is declining, how would you…
Given a scenario where trading performance is declining, how would you analyze the situation?
Approach
- Restate the decision this analysis has to support, and who acts on the answer.
- Decompose the metric into the rates that drive it, and say which one you would check first.
- Fix the population and the time window before naming any metric.
Follow-up
- Which segment would you cut first, and what would that rule out?
- How would you detect that the metric is being gamed rather than genuinely improving?
Provide a framework for evaluating the success of a new product featur…
Provide a framework for evaluating the success of a new product feature based on user data.
Approach
- Name one primary metric, then the guardrail that stops it being gamed.
- State what result would change your recommendation, so the answer is falsifiable.
- Decompose the metric into the rates that drive it, and say which one you would check first.
Follow-up
- What would you do if the primary metric and the guardrail moved in opposite directions?
- Which segment would you cut first, and what would that rule out?
How would you approach a new dataset to derive actionable insights?
How would you approach a new dataset to derive actionable insights?
Approach
- Fix the population and the time window before naming any metric.
- State what result would change your recommendation, so the answer is falsifiable.
- Name one primary metric, then the guardrail that stops it being gamed.
Follow-up
- What would you do if the primary metric and the guardrail moved in opposite directions?
- Which segment would you cut first, and what would that rule out?
Discuss your methodology for conducting A/B testing in a trading envir…
Discuss your methodology for conducting A/B testing in a trading environment.
Approach
- Name the guardrails that would stop a launch even on a positive primary result.
- State the primary metric and the minimum effect worth shipping, then size the test.
- Say whether units interfere with each other, and switch design if they do.
Follow-up
- What would you do if you could not randomise at all?
- How would you handle interference between treated and control units?
How do you ensure the validity of your data analysis?
How do you ensure the validity of your data analysis?
Approach
- Clarify what is being asked and what a complete answer would contain.
- Say what you would check first and why it is the highest-information step.
- Work from the decision backwards to the evidence you would need.
Follow-up
- What assumption would you test first?
- How would you know your answer was wrong?
Decide whether a nine-month drawdown means the edge is gone
A live strategy with a three-year Sharpe of 1.0 has returned roughly zero over nine months. The portfolio manager wants to keep it; risk wants it cut. Design the metric set for the keep-or-cut decision and state what each metric can and cannot settle. You have daily active returns derived from position_daily, signal_score with zscore_xs and knowledge_ts, and monthly shortfall by participation bucket from the TCA pipeline. Include the power of the test you propose: how long a flat run would have to be before it counts as evidence rather than noise.
Approach
- Do the arithmetic before taking a side, and get the units right. For i.i.d. normal returns the asymptotic standard error of a Sharpe estimate is the square root of (1 plus SR squared over 2) divided by T, where SR is the PER-PERIOD Sharpe and T is the number of those same periods. On a daily grid an annualized SR of 1.0 is a daily SR of 1.0 over the square root of 252, about 0.063, so the SR squared over 2 term is about 0.002 and contributes nothing; nine months is 189 daily observations, giving a daily standard error near 0.0728, which annualizes by the square root of 252 to about 1.15. Equivalently the whole thing collapses to the square root of 252 over T in days, or 1 over the square root of T in years, and 1 over the square root of 0.75 is 1.15. A realized nine-month Sharpe of zero therefore sits inside one standard error of the prior estimate. The P&L series excludes nothing, and saying so plainly is most of the answer.
- Do not feed the annualized Sharpe into that formula with T in years. Doing so returns the square root of 1.5 over 0.75, or 1.41, overstating the error bar by about 22 percent. The SR squared over 2 correction only bites when the per-period Sharpe approaches 1, which no daily return series has; at daily frequency it is a rounding error, and quoting it as though it were doing work is the tell that two different period units were mixed.
- Reach for a measurement with more observations per unit of time: mean daily IC of the underlying signal over the drawdown window against the prior 252 days, since IC is measured across hundreds of names every day. Then actually compute its power rather than assuming it is enough, because at nine months it usually is not either.
- Build guardrails that separate the three candidate causes, since the decision depends on which one holds. Forecast decay shows as IC down and half-life down. Cost shows as shortfall up at matched participation buckets, or capacity utilisation up after an AUM increase. Neither shows as intact IC and intact costs, which points to factor exposure or ordinary noise and is checkable against the risk model's attribution.
- Pre-register the cut rule together with its power, so the threshold is not chosen after seeing the series. If the honest number is that several more years would be needed to distinguish the hypotheses, write that number down and make the decision on risk and capacity grounds instead of dressing a judgement call as evidence.
- State what the standard-error formula assumes and how the assumption fails here: i.i.d. normal returns. A strategy in drawdown frequently has autocorrelated and negatively skewed returns, which widens the true error bar rather than narrowing it, so the calculation above is the optimistic case.
Worked solution 30 min
- Compute realized Sharpe and its standard error for the drawdown window and the prior period with SR and T on the same daily grid, the square root of (1 plus daily SR squared over 2) over T in days, then scale that standard error by the square root of 252 to report it annualized; at daily frequency it reduces to 1 over the square root of T in years. Write both with their error bars rather than as point estimates.
- Compute mean daily IC and its Newey-West standard error in both windows, then compute the standard error of the difference and the minimum detectable difference at 80 percent power.
- Compute shortfall in basis points at matched participation buckets in both windows, and average gross exposure against modelled capacity.
- Run factor attribution over the drawdown window to split realized active return into systematic exposure and residual alpha.
- Write the decision with the power statement attached to it, naming which evidence is carrying it.
Follow-up
- Mean IC over the drawdown window is 0.018 against 0.031 before. Is that a real degradation, and what is the minimum drop your test could have detected?
- AUM tripled ten months ago. Which metric in your set distinguishes alpha decay from capacity exhaustion, and how quickly can it?
- If nothing in your set can settle the question, what do you actually recommend, and how do you say it to a portfolio manager whose book is at stake?
Return dispersion widened inside one strategy composite
Trailing-12-month net returns for accounts running one strategy used to sit within about 40 bps of each other. This quarter the cross-sectional standard deviation is 210 bps and the AUM-weighted mandate success rate fell. The investment team insists the model is identical across accounts. You have position_daily (business_date, account_id, strategy_id, instrument_id, market_value_base, weight_pct_nav, is_restricted, fx_rate_to_base) and account_mandate (account_id, funded_date, inception_date, status, target_gross_exposure_pct, max_single_name_weight_pct, base_currency, mgmt_fee_bps, effective_from, effective_to). Explain the dispersion with an ordered checklist and say which part is a problem.
Approach
- Rank accounts by trailing-12-month net return and inspect the tail before averaging anything. A standard deviation is a distribution statistic and two accounts out of forty can produce it; the number alone does not say whether the cause is systemic or concentrated.
- Cut by months since funded_date and by status. An account in 'ramping' holds cash and sits below target_gross_exposure_pct, so it earns a diluted version of the strategy's return. In a rising market that reads as underperformance and in a falling one as outperformance, and both are mechanical rather than informative.
- Compute realized gross exposure per account-day from position_daily, as the sum of absolute market_value_base over NAV, and compare it with target_gross_exposure_pct from the account_mandate version valid on that business_date. Join on the effective_from and effective_to range, not on the current row, because mandate terms change mid-life and the current row would apply today's target to last year's book.
- Sort the remaining explanations into expected and not expected. Names excluded by is_restricted, base_currency differences moving through fx_rate_to_base, and mgmt_fee_bps differences on a net-of-fee metric are all expected. A weight breaching max_single_name_weight_pct, or an account holding instruments the others do not, is not.
- Report dispersion decomposed by cause with dollars attached. The client question is never why sigma is 210 bps; it is why this account returned less than the one on the last page.
Follow-up
- Two accounts funded the same day diverge by 90 bps and both reached target exposure inside 20 trading days. Where do you look next?
- The AUM-weighted success rate only counts accounts with 36 months of history. How does that interact with what you just found, and does it flatter the number or penalise it?
- How would you present cash drag to a client so it reads as a fact about funding rather than an excuse?
Roughly 90 minutes a night on weekdays with one longer weekend block. The plan deliberately cuts scope rather than compressing everything, on the assumption that finishing one thing a night beats half-starting four.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Fix the scope and set a baseline
- Read the role description and write the three things the loop will almost certainly test, then write an explicit not-doing list for everything else and keep it visible all week.
- Take one 20-minute SQL prompt and one 10-minute metric question cold, and write the single sentence that says what blocked each attempt, since that sentence is what decides which two topics get the most evenings.
- Set the week's one rule: one problem finished to completion every night, including the night you only have 40 minutes.
Deliverable: A one-page scope with an explicit not-doing list and two cold attempts, each carrying one sentence on what blocked it.
Practice prompt ↗Practice prompt ↗Practice prompt ↗Worked solution ↗02One query pattern, written three times
- Choose the single pattern most likely to appear (a cohort retention grid, or a funnel counted by user) and write it three times from a blank file rather than editing the previous attempt.
- On the third attempt, write the grain of every CTE as a comment before writing its body.
- Stop at 90 minutes even if the third version is imperfect, and write the one thing you would fix with another hour.
Deliverable: Three independent versions of the same query plus a note on what changed between them.
Practice prompt ↗Practice prompt ↗Practice prompt ↗03Only the statistics you will be asked to defend
- Write, in under 200 words, how you would decide whether a difference between two groups is real: the test, its assumptions, and what you would switch to when an assumption fails.
- Compute a 95 percent confidence interval for a difference in proportions by hand on realistic numbers, then write in one sentence what changes if the two samples are paired rather than independent.
- Write your answer to "what does a p-value mean", check it against a definition, and delete the version that describes it as the probability the hypothesis is true.
Deliverable: A 200-word written answer and one hand-computed interval you can reproduce under pressure.
Practice prompt ↗Practice prompt ↗Practice prompt ↗04One case, and the assumptions holding it up
- Answer one product case aloud in 20 minutes with a recording running, then listen back with a pen and mark every claim you asserted without saying what it rested on: an assumed user behaviour, an assumed data source, an assumed baseline rate, an assumed grain.
- Pick the three assumptions the recommendation actually depends on, write how you would check each one against data, and say which one being wrong would flip the recommendation rather than merely weaken it.
- Write the four-step structure you used onto a card small enough to hold in working memory when you are nervous.
Deliverable: One recording, three load-bearing assumptions each with a written check, and a four-step structure card.
Practice prompt ↗Practice prompt ↗Worked solution ↗05Your own work, timed
- Write a 90-second version and a four-minute version of your main project, and time both out loud rather than reading them.
- Prepare answers to the two follow-ups that always come: what you would do differently, and how you knew it worked.
- Put one number in the first sentence and be able to say exactly where that number came from and what it excludes.
Deliverable: Two timed narratives with one defensible number in the opening line.
Practice prompt ↗Practice prompt ↗06The one full rehearsal, in a longer weekend block
- Run a 60-minute mock covering query work, a case and a behavioural question in a single sitting with no breaks, because sustained attention is the thing evenings have not trained.
- Immediately afterwards, and before hearing any feedback, write the three moments you lost the thread.
- Spend the rest of the block only on those three moments, and on nothing you merely feel shaky about.
Deliverable: Mock notes naming three failure moments with a specific fix written under each.
Practice prompt ↗Practice prompt ↗07Taper
- Write the 20-minute warm-up you will actually do on the morning of the interview: one query you can already write from a blank file, one metric you can define out loud, and nothing you have never seen before.
- Re-read only your own notes from this week, and open no new material.
- Write down the logistics: the tool you will be asked to work in, whether lookups are allowed, and the sentence you will use when you do not know something.
Deliverable: A one-page card holding the case structure, the project numbers, and the logistics.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
An answer without a quantity is hard to interrogate, so interviewers keep probing until they find one. Come with the baseline, the change, the window it was measured over, and how confident you were. If the effect never got measured, say so and say what you would have measured. Fabricated precision is worse than an honest gap.
How do you handle missing data in a dataset?
How do you handle missing data in a dataset?
Approach
- Name the disagreement or constraint, and how you resolved it with evidence.
- Quantify the outcome, including what you would not claim credit for.
- Close with what you would do differently, concretely.
Follow-up
- What would you do differently if you ran that project again?
- What did you decide not to do, and why?
Writing an impact statement that survives a hostile reading
Write your own annual impact statement. Your work: a market-impact recalibration the desk adopted in March; a signal you researched that a portfolio manager sized and traded; and a rewrite of the nightly position reconciliation that reduced unreconciled rows in position_daily. Realized implementation shortfall fell from 21 bps to 14 bps after March. Market volatility also fell over the same period. State what you added, in basis points where the attribution supports it, and be explicit about where it does not.
Approach
- What is probed: whether you can separate correlation from contribution when the correlation favours you, which is the one place almost everyone's standards slip.
- Build a counterfactual for the shortfall claim instead of a before-and-after. Shortfall scales with volatility, so a pre and post comparison across a regime change partly measures the market. Use orders that kept the old routing or the old parameters as a control over the same window, matched on participation bucket (order_qty over adv_20d) and side, and report the difference-in-differences rather than the raw 7 bps.
- State the part you cannot claim before anyone asks. The signal was sized by the portfolio manager, so its P and L is a joint product. Claim the research decision itself: what you tested, what you rejected, the number of configurations tried, and the standard error you attached. Volunteering the boundary is what makes the claims inside it credible.
- Give the reconciliation work a number that is not basis points. Report unreconciled and break rows in position_daily before and after, plus the downstream consequence: marks that fell back to stale_prior_day, and client reports restated. Inventing a basis-point figure for operational work costs you the basis-point figures that are real.
- Write a falsifier next to each claim, naming the evidence that would show you added nothing. A reviewer who watches you name your own weakest claim stops auditing the strong ones.
Follow-up
- Your control group is 8 percent of order flow. Is the difference-in-differences credible at that size, and what would you need to make it so?
- The signal lost money this year. Does it appear in the statement, and in what form?
- What did you get wrong this year, and what did it cost?
Defending a backtest correction that removes an allocated strategy
A colleague's cross-sectional equity signal received capital last month on a backtest showing annualized Sharpe 1.6 over three years. Reproducing it, you find the panel filters signal_score on as_of_date rather than knowledge_ts. Rerunning with the knowledge_ts predicate, holding universe_id, date range, cost model and rebalance schedule fixed, gives Sharpe 0.5 and moves mean daily IC from 0.041 to 0.012. The colleague is senior and presented the original result. You have one meeting with the research lead and the portfolio manager. Deliver a recommendation on whether the allocation stands, and the evidence behind it.
Approach
- What is probed: whether a quantitative objection survives social cost. Lead with the defect and the single-variable reproduction, never with a judgement about the colleague. The claim under test is one predicate, not a person's competence.
- Rerun both versions from one code path with one line changed, and say so explicitly. Holding universe_id, date range, cost model and rebalance schedule fixed leaves the 1.1 Sharpe gap exactly one candidate cause, which is what makes the result arguable on its merits instead of on whose code is trusted.
- Pair the comparison before quoting any error bar. For modest Sharpe ratios the annualized standard error of a Sharpe estimate is approximately 1 over the square root of the number of years, so three years of daily data gives roughly 0.58 and two marginal estimates 1.1 apart are only about two standard errors apart. But the two runs are the same returns except where the leak bites, so test the daily difference series directly: its standard error is far smaller, and the pairing is what turns a marginal result into a decisive one.
- Exhibit the mechanism, not just the size. Rank instrument-days by their contribution to the return difference between the two runs and show that the top contributors carry is_backfilled TRUE or coverage_flag 'stale', with knowledge_ts postdating as_of_date by the vendor's restatement lag. A named mechanism is falsifiable; a Sharpe delta alone becomes an argument about your code.
- Bring a decision rather than only a finding: the position size the corrected Sharpe supports, and an untouched out-of-sample window that would settle it either way. Being right with no path forward is how a correct objection gets overruled.
Follow-up
- Your colleague reruns it and gets 0.9 rather than 0.5. What do you do with the discrepancy before the meeting?
- The strategy is up since funding. Does live P and L change your recommendation, and how much of it would?
- What would have caught this before the allocation, and why did the existing review not catch it?
- 01
How do you handle missing data in a dataset?
- 02
Write your own annual impact statement. Your work: a market-impact recalibration the desk adopted in March; a signal you researched that a portfolio manager sized and traded; and a rewrite of the nightly position reconciliation that reduced unreconciled rows in position_daily. Realized implementation shortfall fell from 21 bps to 14 bps after March. Market volatility also fell over the same period. State what you added, in basis points where the attribution supports it, and be explicit about where it does not.
- 03
A colleague's cross-sectional equity signal received capital last month on a backtest showing annualized Sharpe 1.6 over three years. Reproducing it, you find the panel filters signal_score on as_of_date rather than knowledge_ts. Rerunning with the knowledge_ts predicate, holding universe_id, date range, cost model and rebalance schedule fixed, gives Sharpe 0.5 and moves mean daily IC from 0.041 to 0.012. The colleague is senior and presented the original result. You have one meeting with the research lead and the portfolio manager. Deliver a recommendation on whether the allocation stands, and the evidence behind it.
Is this an official Wolverine Trading interview guide?
No. It is PracHub's own research and practice material for the Data Scientist role at Wolverine Trading. Rounds and questions reflect what candidates have reported, not a process Wolverine Trading has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗How difficult are the interviews, and how much preparation time is typical?
The interviews at Wolverine Trading can be challenging, especially the technical assessments. Candidates typically spend several weeks preparing, focusing on coding skills, statistical knowledge, and behavioral interview techniques.
PracHub interview research ↗What differentiates successful candidates?
Successful candidates demonstrate a strong technical foundation, effective problem-solving skills, and the ability to communicate complex ideas clearly. They also align with the company culture, showing collaboration and innovation.
PracHub interview research ↗What is the culture and working style at Wolverine Trading?
The work culture emphasizes teamwork, agility, and a results-oriented approach. There is a strong focus on leveraging data to inform decisions, and employees are encouraged to be proactive in their roles.
PracHub interview research ↗What is the typical timeline from the initial screen to an offer?
The timeline can vary, but candidates can expect a response within a few weeks following the initial interview. The process includes multiple stages, which may take 4-6 weeks in total.
PracHub interview research ↗Sources & methodology 3 sources ↗
Official role evidence, timestamped platform data and clearly labeled preparation advice.
- 01PracHub interview research ↗
PracHub editorial research into this company and role, maintained with this guide. Candidate-reported, not an employer publication.
platform · Accessed 2026-09-22 - 02PracHub Data Scientist practice ↗
Cross-company practice questions for this role.
platform · Accessed 2026-09-22 - 03PracHub interview preparation framework ↗
The framework the preparation plan follows.
platform · Accessed 2026-09-22