As a Data Scientist at Quantiphi, you sit at the intersection of advanced machine learning research and high-impact business application. You are not merely building models in a vacuum; you are solving complex, real-world challenges for enterprise clients by transforming raw data into actionable insights and scalable AI solutions. Your work directly influences how businesses optimize operations, enhance customer experiences, and leverage emerging technologies to stay competitive.
The role demands a rigorous analytical mindset coupled with the ability to communicate technical complexity to non-technical stakeholders. You will be expected to own the end-to-end lifecycle of data products—from hypothesis generation and feature engineering to model deployment and performance monitoring. Success in this role requires a balance of deep theoretical knowledge in statistics and machine learning with the pragmatic engineering skills needed to deploy solutions in production environments.
Online Assessment
reportedA handful of shapes account for most of what gets asked in this format: a ranking or deduplication inside groups, a running or rolling total, a period-over-period comparison, and a cohort tracked forward over time. Recognising the shape quickly is most of the speed here; deriving it from scratch while a clock runs is where the time goes. Know that a window function keeps every row while a GROUP BY collapses them, and know which one the question needs. If the exercise is in Python instead of SQL, the same shapes arrive as groupby with transform, shift and merge, and the same grain mistakes are available.
What to demonstrate
- Whether you reach the right construct without a detour, such as ROW_NUMBER over a partition to deduplicate instead of a self-join against a MAX subquery
- Whether you know what your window frame actually is, since adding ORDER BY inside OVER changes the default frame and silently changes a running total
- Whether the thing runs. A near-miss that throws an error scores below a plainer query that returns the right rows.
How to prepare
- Write each of the four shapes once from memory against a small schema and keep the working version somewhere you will reread it: dedupe with ROW_NUMBER, a running total, a month-over-month change with LAG, and a retention table
- Compute one running total twice on data with tied timestamps, once on the default frame and once with ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, and look at where the two disagree
- If Python is on the table, rebuild the dedupe and the running total with groupby and cumsum, then assert the two implementations return identical rows
Technical Discussions
reportedBefore anything else, this round is a reading test. You are given a small schema and a question phrased in business language, and most of the difficulty sits in the gap between them. Who counts as an active user, does a refunded order still count as an order, is that date column an event time or a load time. Weak answers start typing immediately and compute something precise about the wrong population. Strong ones pin the definition in one sentence, name the column that encodes it, then write the query. On a timed assessment with nobody to tell, write the definition in a comment anyway.
What to demonstrate
- Whether an ambiguous term becomes a specific column and filter before any computation happens
- Whether you read the schema for keys and cardinality rather than only for column names
- Whether the result answers the question at the grain it was asked at, per user or per session or per day
How to prepare
- Take three metrics you already use and write down the exact filter and exact grain behind each, then practise stating one of them in a single sentence out loud
- On a schema you have never seen, spend the first minute writing what one row of each table means and which key it is unique on, then predict which joins can duplicate rows
- Rehearse a version where the definition changes halfway through, and edit the query you have instead of starting over
Project-Based Evaluations
reportedMuch of what gets scored here happens out loud while you type. Nobody can see your reasoning inside a half-written query, so five silent minutes read as being stuck even when they are not. State the plan in plain language first: which tables, what grain you are aggregating to, and the one filter that defines the population. Then write it. The narration doubles as insurance, because a wrong plan gets caught early and cheaply while a wrong query gets caught at the end with no time left to redo it. A timed statistics section, where one exists, is a separate test with its own clock.
What to demonstrate
- Whether the query you write matches the plan you just described
- What you do with a hint, meaning whether the correction gets absorbed or the first approach gets defended
- Whether you can debug your own wrong output by reading the result set and naming which part of the query produced the anomaly
How to prepare
- Solve three problems while screen-sharing into a recording, then watch it back and mark every stretch longer than thirty seconds where you said nothing
- Practise compressing the plan into one sentence before typing, then check afterwards whether the finished query actually matched it
- Time yourself on statistics questions that carry a business reading, such as what a confidence interval does and does not claim, rather than re-reading notes without a clock
PracHub editorial advice for the preparation topics above.
Judging execution quality against interval VWAP and treating a favourable number as proof of good trading.
Interval VWAP is a benchmark the trader partly determines: trading in line with volume tracks VWAP almost by construction, and stretching an order over a longer interval makes the benchmark easier while exposing the position to price drift that the benchmark never charges. Arrival price is the benchmark aligned with the decision, because it charges both the spread and the drift between decision and completion, including the unfilled remainder. Reporting both, and reporting the opportunity cost of unfilled quantity, is what separates a real TCA from a flattering one.
Modelling transaction cost as a constant number of basis points, independent of order size and volatility.
Temporary market impact scales approximately with volatility times the square root of participation, that is, of order quantity divided by average daily volume, so cost per share rises as size rises rather than staying flat. A constant-bps assumption is roughly right for the small orders used to calibrate it and badly wrong for the size the strategy would actually run, which is how a book that backtests well at modest notional loses money at ten times the size. It also makes capacity unmeasurable, because capacity is exactly the notional at which marginal impact equals marginal alpha.
Ignoring interference between units in a marketplace experiment
Ask whether one unit's treatment can change another unit's outcome through shared inventory, a matching pool, a social graph or a common budget. Where it can, randomise at a level that contains the spillover, such as region or time slice, and say explicitly what that costs you in statistical power.
Interpreting a change before checking data quality and logging
Spend the first pass on row volume by day, null rates, duplicate keys, and whether the step change lands on a release or tracking-migration date. A discontinuity that coincides with a deploy is an instrumentation hypothesis before it is a behavioural one.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
What are the common challenges when moving a model from a notebook to …
What are the common challenges when moving a model from a notebook to a production environment?
Approach
- Pick an evaluation metric that matches the cost of each error type, not a default.
- Check what information would not exist at prediction time, and exclude it.
- 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?
- What would you monitor after launch to know the model is still valid?
Explain the intuition behind Random Forest and how it differs from Gra…
Explain the intuition behind Random Forest and how it differs from Gradient Boosting.
Approach
- Set a baseline first, so any model has something honest to beat.
- Say how the offline result would be validated online before it is trusted.
- Check what information would not exist at prediction time, and exclude it.
Follow-up
- How would you choose the decision threshold, and who owns that choice?
- Where could label leakage enter this setup?
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?
Implement a solution involving Vectors, Arrays, or Hash Maps to solve …
Implement a solution involving Vectors, Arrays, or Hash Maps to solve a data processing problem.
Approach
- Check whether any join is one-to-many before aggregating, or the sums inflate.
- Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
- 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?
Write a function to clean a provided dataset, handling missing values …
Write a function to clean a provided dataset, handling missing values and outliers.
Approach
- 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.
- State the window function and its partition and ordering out loud before writing it.
Follow-up
- What breaks if events arrive late or out of order?
- How does the query change if the join becomes one-to-many?
Given an array, how would you find the most frequent element or perfor…
Given an array, how would you find the most frequent element or perform specific transformations?
Approach
- Check whether any join is one-to-many before aggregating, or the sums inflate.
- Say which table is the grain you start from, and join outward from it.
- 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?
- What breaks if events arrive late or out of order?
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 do you optimize a piece of code that is performing slowly on a lar…
How do you optimize a piece of code that is performing slowly on a large dataset?
Approach
- Fix the population and the time window before naming any metric.
- Name one primary metric, then the guardrail that stops it being gamed.
- Restate the decision this analysis has to support, and who acts on the answer.
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?
Walk me through your most challenging data science project: what was t…
Walk me through your most challenging data science project: what was the business impact?
Approach
- State your assumptions explicitly before working the problem.
- Say what you would check first and why it is the highest-information step.
- Clarify what is being asked and what a complete answer would contain.
Follow-up
- What assumption would you test first?
- How would you know your answer was wrong?
Size an execution algorithm test on implementation shortfall
Per-order implementation shortfall against arrival price, computed from parent_order (order_qty, filled_qty, arrival_mid_px, avg_fill_px, adv_20d) and execution_fill (commission_amt, exchange_fee_amt, rebate_amt), has averaged 12.4 bps with a standard deviation of 35 bps over the trailing twelve months. The desk releases roughly 1,900 parent orders a month. An execution team proposes a new child-order scheduler and claims a 1.5 bps improvement. Size a two-arm, order-level randomised test at 80 percent power and a two-sided 5 percent level, and say how long it has to run.
Approach
- Pin the response variable to the exact metric definition before touching the arithmetic: shortfall in bps versus arrival_mid_px, with commission, exchange fee and rebate included and the unfilled remainder (order_qty minus filled_qty) charged at the terminal mid. The sigma you plug in has to be the standard deviation of that quantity, not of a convenient proxy.
- Estimate sigma from the trailing twelve months of the same order population rather than from a remembered number. Shortfall is heavy tailed, so also compute a winsorised sigma and quote the sample size both ways, because the difference tells you how much of your power calculation rests on a handful of orders.
- Apply the two-sample difference-in-means formula, n per arm = 2 * sigma^2 * (z_{0.975} + z_{0.80})^2 / delta^2, which under equal allocation reduces to 15.7 * sigma^2 / delta^2.
- Decide whether the shipping decision is made on the equal-weighted per-order mean or the notional-weighted mean, because they have different variances. For a weighted mean the effective sample size is (sum of weights)^2 / (sum of squared weights), and notional weights in a book with a long tail of large orders can cut that well below the row count.
- Convert to calendar time at realised flow and check the answer against the business horizon. If nine months is unacceptable, the legitimate levers are a larger delta, lower power accepted explicitly, or variance reduction; shortening the test while keeping the same stopping rule is not one of them.
Worked solution 20 min
- Compute per-order shortfall for the trailing twelve months from parent_order joined to execution_fill, charging the unfilled remainder at the terminal mid, and confirm sigma is about 35 bps.
- Record the notional-weighted effective sample size (sum of weights)^2 / (sum of squared weights) on the same population, so you know the discount before you commit to an estimator.
- Evaluate n per arm = 2 * 35^2 * (1.96 + 0.8416)^2 / 1.5^2.
- Divide the two-arm total by 1,900 orders a month to get calendar time.
- Recompute at delta = 3.0 bps to demonstrate the quadratic sensitivity to the claimed effect.
Follow-up
- What happens to the required sample size if the committee decides on the notional-weighted mean instead of the equal-weighted mean?
- At 1,900 orders a month, what effect size can you detect in a single month, and would you run that test at all?
- If the real goal is 'no worse than the incumbent', how do you set the non-inferiority margin and what changes in the test?
Turnover doubled in a week with unchanged positions
Annualized one-way turnover for a strategy reads 368 percent this month against 180 percent last month. Position_daily shows end-of-day quantities and market_value_base following their usual pattern, and neither the signal nor portfolio construction was touched. Tables: execution_fill (fill_id, order_id, side, fill_qty, fill_px, is_correction, corrects_fill_id, exec_ts, currency) and position_daily (business_date, account_id, instrument_id, quantity, market_value_base). The catalogue definition is: monthly sum of min(total buy notional, total sell notional), over average end-of-day gross market value, times 12. Find the cause and prove it.
Approach
- Split the ratio and chart the numerator and the denominator as separate monthly series before interpreting either. A ratio that moved tells you nothing about which side moved, and the two sides have unrelated failure modes.
- Read the magnitude as evidence. A jump close to a factor of two, in a book whose buy and sell notional are nearly balanced, is the signature of min(buy, sell) having become buy plus sell. No strategy change produces a suspiciously round multiple in a week.
- Reconstruct the numerator yourself from the catalogue definition and compare it with the reported figure for both months. If your recomputation matches last month and not this month, the expression changed, and the scheduled job's query or its version history says when.
- Rule out the competing mechanism before closing. Correction rows arrive as new rows referencing corrects_fill_id, so a naive SUM(fill_qty) counts the correction and never removes the original. Size the corrected notional separately instead of assuming it is small.
- Reconcile to the book of record. Day-over-day change in position_daily.quantity per instrument must equal that day's net signed fills, which bounds true traded quantity independently of whichever expression the report used.
Follow-up
- Correction rows turn out to be 0.8 percent of notional. Write the numerator expression that handles them correctly in one pass.
- Your reconciliation against position_daily leaves a residual on two instruments. Which legitimate causes would you rule out before calling it a data bug?
- What would you add to the pipeline so a metric definition cannot change without the change being visible in the report itself?
For someone who can already write the query and train the model but stalls when asked what to measure or whether a change is worth making. Metric definition and case structure come first; the technical work is kept as maintenance rather than the centre of the week.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Metric anatomy
- For three products you use daily, write one primary metric, two input metrics that plausibly move it, and one guardrail that would catch a cheap way of moving the primary at the cost of the product.
- For one of them, specify the metric precisely enough that two analysts would return the same number: numerator, denominator, unit of observation, time window, and how returning and deleted accounts are treated.
- Pick a ratio metric and write what happens to it when the denominator shrinks for reasons unrelated to the numerator, with a concrete example of that happening.
Deliverable: A one-page metric tree for one product, with the primary metric written as an unambiguous spec.
Practice prompt ↗Practice prompt ↗Worked solution ↗02Diagnosing a drop without guessing
- Take the prompt "weekly active users fell 8 percent week over week" and write the segmentation plan before proposing any cause: platform, region, tenure cohort, acquisition channel, and whether the movement sits in the numerator or in a changed denominator.
- List the instrumentation failures that manufacture fake drops (a client release that stopped firing an event, a bot filter change, a shifted date boundary or timezone) and write the query that rules out each one.
- Rehearse stating the boring explanations first, seasonality and day-of-week composition, before reaching for a product cause.
Deliverable: A drop-diagnosis checklist short enough to recite from memory in under a minute.
Practice prompt ↗Practice prompt ↗03Should we build it
- Take a feature idea and write it as a bet: what you believe is true, what would have to be true for it to pay off, the metric that would confirm it, and the effect size that would justify the engineering cost.
- Size the opportunity top-down and bottom-up, then reconcile the two numbers in writing instead of quoting whichever is friendlier.
- Write the counter-metric that would make you kill the feature even if it wins on the primary metric.
Deliverable: A one-page product memo ending in a decision rather than a list of considerations.
Practice prompt ↗Practice prompt ↗04The places aggregate numbers lie
- Construct a Simpson's paradox numerically: two segments where the treatment wins within each segment yet loses overall, and identify the shift in segment weights that causes it.
- Take a heavy right-tailed quantity such as revenue per user and write why the mean is the wrong summary, which percentile you would report instead, and what a moving mean with a stable median tells you.
- Write your definition of a session for the product from day one, then name two real behaviours it misclassifies.
Deliverable: One page holding a worked Simpson's paradox table and a session definition with its two known failure cases.
Practice prompt ↗Practice prompt ↗Worked solution ↗05Technical maintenance, aimed at metrics
- Solve four timed SQL prompts that all end in a ratio metric, so the question of grain stays live in every answer.
- Compute a 95 percent confidence interval for a proportion on a small sample, and state why the normal approximation is unreliable when either np or n(1 minus p) falls below roughly 10, along with which interval you would use instead.
- Take one metric from your day-one tree, write the query that computes it correctly, then write the query that computes it wrong in the most plausible way and explain how you would notice.
Deliverable: Four solved prompts plus a matched correct and plausible-wrong query for one metric.
Practice prompt ↗Practice prompt ↗06Turning engineering work into data science stories
- Write three project stories as situation, decision, trade-off, outcome, each carrying one number and one thing you got wrong.
- For the story you will lead with, prepare an answer to "what would you do differently" that names a decision you made, not a constraint you were handed.
- Practise the sentence that reframes a systems project as a question project: the question the work answered, ahead of the pipeline it shipped.
Deliverable: Three written stories with the lead story delivered aloud and timed under four minutes.
Practice prompt ↗Practice prompt ↗07Mock case and gap list
- Run a 40-minute mock case with someone playing a product manager who pushes back on your metric choice, and record it.
- Listen back and mark every moment you proposed a solution before the success metric existed.
- Rewrite those moments as the question you should have asked, and rehearse the first 90 seconds of the case until scoping comes before solving.
Deliverable: A recorded case plus a rewritten opening 90 seconds.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
Half of this section is about translation. Be ready to describe how you explained a result to someone who did not want the method, only the implication, and what you did when the simplified version started being repeated in a way that overstated it. Correcting your own simplification is a strong beat.
How do you handle imbalanced datasets in a classification task?
How do you handle imbalanced datasets in a classification task?
Approach
- Name the disagreement or constraint, and how you resolved it with evidence.
- Close with what you would do differently, concretely.
- State the situation in two sentences and spend the rest on your reasoning.
Follow-up
- How did you know the outcome was caused by your change?
- What would you do differently if you ran that project again?
Answering whether a six-week-old signal is working yet
A new signal has been live six weeks: 30 trading days of realized cross-sectional IC against a 5-day forward return, mean 0.030, standard deviation across days 0.12. An executive with no statistics background asks in a Monday meeting whether it is working and wants a yes or a no. You have the daily IC series and nothing else. Give an answer in three sentences plus one number the executive can hold onto, and say when the question becomes answerable.
Approach
- What is probed: whether you can be honest about statistical power without hiding behind the word significant and without giving a yes that gets quoted back at you in three months.
- Compute the interval before you speak. The standard error of the mean daily IC is 0.12 divided by the square root of 30, which is 0.022, so a mean of 0.030 sits about 1.4 standard errors from zero. That is the optimistic bound and it is already not a yes.
- Adjust for overlap and say that you did. A 5-day forward return sampled every day shares four of five days with its neighbour, so the honest standard error uses a Newey-West estimator with at least 4 lags and lands materially above 0.022. Presenting the naive figure without that caveat is the same error as the signal's own author would make.
- Convert power into a date rather than a verdict. Detecting a true mean IC of 0.03 at two standard errors needs roughly (2 x 0.12 / 0.03)^2 = 64 independent days, and with the overlap inflation of a 5-day horizon that is on the order of 300 trading days, so the question becomes answerable around fifteen months in, not six weeks.
- Give one number and one decision, because wait is useless on its own. Offer a tripwire that makes waiting active: a pre-committed stop if the trailing 60-day mean IC turns negative, and a named review date.
Follow-up
- Another desk called their signal working after four weeks. What do you say when the executive raises that?
- What single observation before the review date would make you stop the signal early?
- The six-week mean is minus 0.03 instead. Does your answer change in substance or only in sign?
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?
- 01
How do you handle imbalanced datasets in a classification task?
- 02
A new signal has been live six weeks: 30 trading days of realized cross-sectional IC against a 5-day forward return, mean 0.030, standard deviation across days 0.12. An executive with no statistics background asks in a Monday meeting whether it is working and wants a yes or a no. You have the daily IC series and nothing else. Give an answer in three sentences plus one number the executive can hold onto, and say when the question becomes answerable.
- 03
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.
Is this an official Quantiphi interview guide?
No. It is PracHub's own research and practice material for the Data Scientist role at Quantiphi. Rounds and questions reflect what candidates have reported, not a process Quantiphi has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗Is the interview process mostly theoretical or practical?
It is a balanced mix. Expect the early rounds to test your theoretical foundation and coding skills, while later rounds focus heavily on how you apply that knowledge to solve real-world, messy data problems.
PracHub interview research ↗How do I handle a "one-way" interview environment?
If you feel the conversation is one-sided, try to guide it by asking for feedback on your approach or asking clarifying questions about the interviewer’s specific project challenges. Use this to pivot the conversation toward a dialogue.
PracHub interview research ↗What is the best way to prepare for the "presentation" round?
If you are asked to present a topic, focus on clarity, structure, and the "so-what" factor. Ensure your slides or talk track clearly define the problem, your methodology, the results, and the business impact.
PracHub interview research ↗Sources & methodology 3 sources ↗
No official company page is cited. Rounds and questions come from candidate reports and PracHub editorial material; each source shows the date it was read.
- 01PracHub interview research ↗
PracHub editorial research into this company and role, maintained with this guide. Candidate-reported, not an employer publication.
PracHub page · Accessed 2026-09-22 - 02PracHub Data Scientist practice ↗
Cross-company practice questions for this role.
PracHub page · Accessed 2026-09-22 - 03PracHub interview preparation framework ↗
The framework the preparation plan follows.
PracHub page · Accessed 2026-09-22