Interview guides · Flow
Flow Data Scientist Interview Questions & Guide 2026
Modeling drills for a Flow data scientist interview: baselines, regression interpretation, class imbalance, model defense.
The 60-second brief
At Flow, a leading global financial technology and proprietary trading firm, the Data Scientist role—often aligned with or titled as Quantitative Researcher—is at the absolute core of the business. Unlike traditional tech companies where data science might focus on user growth or product analytics, at Flow, your work directly impacts real-time pricing, risk management, and market-making strategies. You will design, build, and optimize the mathematical algorithms that provide liquidity to financial markets globally, specializing in complex instruments like Exchange Traded Funds (ETFs).
Ask early whether the loop includes an asynchronous take-home or a timed live case, because the two are graded on different things. A take-home is read as an artifact: the question you decided to answer, what you did about missing or malformed records, and a conclusion stated plainly enough for someone to act on. A reviewer who cannot rerun your notebook discounts the result whatever score is printed in it. Hold to the stated time box and write down what you would have done with more of it, since the follow-up round is usually a live defence of the same work.
Focus areas
- Attach uncertainty to every Sharpe claim
- Separate forecast decay from execution cost
- Build point-in-time panels without lookahead
Overview
This role requires a unique blend of high-level statistical modeling, rapid analytical intuition, and software engineering principles. You will collaborate directly with traders and quantitative developers to analyze massive datasets of market microstructure, identify pricing anomalies, and deploy automated trading strategies. The feedback loop is incredibly short; models you design can be actively trading and managing risk within days, or even hours, making this one of the most dynamic and high-impact environments for data professionals.
To succeed in this position, you must possess a deep passion for financial markets, a rigorous academic mindset, and the ability to perform under pressure. The team thrives on intellectual curiosity and mathematical precision. If you are excited by the prospect of solving highly complex, competitive, and fast-paced quantitative problems where the markets grade your work in real time, this role offers an unparalleled professional challenge.
The Flow interview process
Flow candidates report 4 rounds · ≈ 3-5 weeks. The stages below are what candidates describe, not a published process.
Automated Online Assessments
A 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
Recruiter Conversations
A screening call is a matching exercise run by someone who will not evaluate your statistics. They are checking that the work described on your resume is work you personally did, and that its scope matches the level the role is written for. Logistics get settled in the same half hour so nobody spends an interviewer's afternoon on a mismatch. The answer that fails is the one narrated in the plural. If every sentence is 'we built' and 'the team decided', there is nothing specific to write down about you. Name the piece that was yours, the decision you made inside it, and what changed after.
What to demonstrate
- Whether the ownership implied by your resume survives one round of follow-up about who actually did which part
- Whether your described scope (data size, stakeholders, what shipped) matches the seniority the role is written at
- Whether timeline, location and compensation expectations make the rest of the loop worth scheduling
How to prepare
- Rewrite your top three resume bullets in the first person singular, each with the decision you made and what moved afterwards, then say them out loud once so the 'we' does not return under pressure
- Attach one number to each project: the baseline, the change, and the window it was measured over. Where impact was never measured, say that plainly rather than inventing a figure
- Settle your compensation range before the call and give it as a range with a reason behind it, such as current total comp or a competing timeline, instead of deflecting the question twice
Live Technical Interviews
Much 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
Onsite Interview Day
Where a loop ends with a senior leader, that conversation is rarely another skills test. The technical signal already exists by then, so the questions tend to open up: what you would look at first, where a metric you have heard about could mislead, what you would push back on. The decision being made is scope, which in practice means level and how much you would be trusted to own unsupervised. Treating it as a formality is the usual mistake. An open question late in the day is still being scored, and a vague answer reads as someone who has not run anything themselves.
What to demonstrate
- Whether your view of the business has anything specific behind it, given that you are working only from what is public and are expected to say so
- Whether the scope of work you describe owning matches the scope of the role, instead of sitting a level below it
- Whether you can disagree with something concrete and stay useful about it, rather than agreeing with everything said in the room
- Whether your questions are ones only this person could answer, as opposed to ones the recruiter already covered
How to prepare
- Build one view you could defend for two minutes using only public information: what the funnel probably looks like, which metric likely drives decisions, and where that metric could mislead. Being wrong for a stated reason survives this round; having no view does not
- Write down the largest piece of work you have owned from question to decision, who else touched it, and what you decided alone, then check that it reads at the level you are interviewing for
- Prepare one thing you would want changed if you joined and phrase it as a question rather than a verdict, so it opens a conversation instead of closing one
Where candidates lose points
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'.
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.
Defining the cohort on a post-treatment condition
Ask how rows entered the table. Filtering on something that treatment itself influences, such as users who finished onboarding or accounts still active at ninety days, breaks comparability between arms; define the population at an entry point that precedes exposure and keep everyone in it.
Reporting a mean for a heavy-tailed metric without saying what it hides
For spend, session length or items per order, a small fraction of units carries most of the total, so the mean has a wide standard error and one account can move it. Fix the handling before you see the result: cap or winsorise at a pre-declared percentile, and report the median or the share above a threshold next to the mean. Capping changes the estimand, so say which question the capped number answers, and check how much of any difference comes from the top 0.1 percent of units.
Questions & practice
You are presented with a take-home probability puzzle involving a sequence of coin flips. How do you calculate the expected number of flips to reach a specific pattern versus another?
Medium · statistics and probability
Approach
- Say what the estimate is of, and over what population it generalises.
- Sanity-check the answer against a simple bound or a simulated case.
- Translate the result into the decision it informs, in one plain sentence.
Follow-up
- What sample size would you need to detect an effect half this size?
- How would you explain this result to someone who does not know statistics?
Three players must pick a number on a continuous segment $[0, 1]$. A r…
Medium · statistics and probability
Three players must pick a number on a continuous segment $[0, 1]$. A random number is then drawn from a uniform distribution on that same segment, and the player whose chosen number is closest to the drawn number wins. What is the optimal strategy, and where should you place your number?
Approach
- Sanity-check the answer against a simple bound or a simulated case.
- Quantify uncertainty explicitly rather than reporting a point estimate alone.
- Write down the assumption the method needs before you use the method.
Follow-up
- What sample size would you need to detect an effect half this size?
- Which assumption here is most likely to be violated in practice?
A classic brainteaser involving path planning and conditional probability: if a certain event occurs with a known prior, how does a sequence of noisy observations update your posterior belief?
Medium · statistics and probability
Approach
- Write down the assumption the method needs before you use the method.
- Quantify uncertainty explicitly rather than reporting a point estimate alone.
- Sanity-check the answer against a simple bound or a simulated case.
Follow-up
- What sample size would you need to detect an effect half this size?
- How would you explain this result to someone who does not know statistics?
Can we ever obtain a negative $R^2$ (coefficient of determination) in a linear regression model? If so, under what specific conditions does this occur?
Medium · machine learning and modelling
Approach
- 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.
- Pick an evaluation metric that matches the cost of each error type, not a default.
Follow-up
- What would you monitor after launch to know the model is still valid?
- Where could label leakage enter this setup?
Explain how you would price a simple derivative or option using a basic binary tree model when volatility is non-constant.
Medium · machine learning and modelling
Approach
- Say how the offline result would be validated online before it is trusted.
- Pick an evaluation metric that matches the cost of each error type, not a default.
- Frame the prediction: the label, the moment of prediction, and the action it triggers.
Follow-up
- What would you monitor after launch to know the model is still valid?
- How would you choose the decision threshold, and who owns that choice?
Validate a point-in-time signal panel before it is traded
Easy · data quality · point-in-time · pandas
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.
Worked solution (25 min)
- Sort by (instrument_id, as_of_date). Build grain counts with groupby(key).size() and keep keys above 1.
- Express the two timestamp checks as boolean columns, then aggregate per as_of_date with sum for the count and idxmax for the example instrument.
- Per-date moments via groupby('as_of_date')['zscore_xs'].agg(['mean','std','count']), plus a Spearman check of zscore_xs against decile_rank within each date.
- Staleness runs: group by instrument_id, compare raw_value to its shift(1), start a run id with a cumsum over the change flag, and take run lengths.
- Universe churn from consecutive-date sets built with groupby('as_of_date')['instrument_id'].agg(set) and differenced pairwise.
Expected result: A tidy frame where most dates carry zero violations, index reconstitution dates show a churn spike that you explain rather than flag as a defect, and any date spanning a model_version changeover shows both a grain-duplication burst and a moment shift. Those two appearing together identify a rerun that overlapped the live daily job.
Verify it yourself
- Rows in grain violation plus clean rows must sum to the input row count.
- The number of distinct as_of_date values in the report never exceeds the number in the input.
- On a date you have inspected by hand and know to be clean, every check returns zero; a check that never returns zero on any date has a wrong threshold, not bad data.
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?
Explain the bias-variance tradeoff in the context of ridge regression versus LASSO. Which regularization technique would you prefer when trying to select a sparse set of trading signals?
Medium · sql and data manipulation
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
- What breaks if events arrive late or out of order?
- How would you verify this result without re-running the same query?
Continuous holding spells from a daily position panel
Hard · gaps-and-islands · window-functions · calendar · panel-data
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.
Expected result: One row per continuous spell; spells for a given (strategy_id, instrument_id, sign) are disjoint and ordered; lengths are in sessions, not calendar days; a position held across a long weekend produces one spell.
Verify it yourself
- Summed spell length per (strategy_id, instrument_id) equals the count of non-zero rows for that key.
- No two spells for one (instrument_id, sign) have overlapping [start, end] ranges.
- A name known to be held continuously through the sample returns exactly one spell.
- Total spell P&L equals the panel sum of
realized_pnl_base_day + unrealized_pnl_base_dayover non-zero rows.
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?
Ramp new accounts fast or cheap, and defend the exchange rate
Medium · ramp · tradeoffs · impact · guardrails
Newly funded accounts must reach 90 percent of target_gross_exposure_pct within 20 trading days of funded_date; that is today's primary metric. Raising it means ramping faster, which raises implementation shortfall because temporary impact scales roughly with volatility times the square root of participation. You have account_mandate (funded_date, target_gross_exposure_pct, benchmark_id, effective_from, effective_to), position_daily (market_value_base, weight_pct_nav) and parent_order. Pick the primary, pick the guardrail, and state the exchange rate at which you would trade one against the other, in basis points rather than in words.
Approach
- Name the objective both metrics are proxying: an unramped day costs expected active return plus unwanted benchmark-relative risk, and a faster ramp costs one-off impact. Both convert to basis points of account NAV, so the conflict is resolvable by arithmetic rather than by argument.
- Price the slow side. Daily expected active return is annualized expected alpha over 252, multiplied by the exposure shortfall as a fraction of target. A linear ramp averages a 50 percent shortfall over its window, so at 300 basis points of expected annual alpha a 20-day ramp forgoes roughly 12 basis points. Flag the precondition: this is an expectation with a wide error bar, which makes it the uncertain side of the trade.
- Price the fast side correctly, because this is where most answers break. Total ramp notional is fixed, so halving the ramp window doubles participation, raises per-unit impact by about the square root of two, and raises total ramp cost by about 41 percent rather than 100 percent. The window scaling is proportional to one over the square root of the number of days.
- Choose the primary as ramp completion and the guardrail as ramp shortfall in basis points of ramped notional with a hard cap, on the stated reasoning that the impact cost is realized and permanent while the forgone alpha is an estimate. Set the cap where marginal impact per day saved exceeds daily expected active return.
- Do not paper over the conflict with a blended score. Report both, and if a single number is demanded, define total ramp cost as impact paid plus expected alpha forgone, and attach the alpha assumption to the same line so the reader can see whose estimate is carrying it.
Follow-up
- Two accounts funded the same week ramp at different speeds because one carries a restricted list. Should the metric penalise the desk, and how would you separate that in the data?
- How does the exchange rate move for a strategy whose expected alpha is 80 basis points a year rather than 300?
- The impact curve was fitted on the desk's ordinary daily orders. What is wrong with using it for a ramp, and which direction does the error run?
Cut variance in an execution test without touching the effect
Medium · cuped · variance reduction · stratification
The order-level shortfall test you sized needs nine months and the desk will not wait. For every parent order you can compute, before assignment: the impact model's predicted cost in bps from participation_rate_target, adv_20d and trailing volatility; the instrument's gics_sector_code; and the strategy's trailing sixty-day mean shortfall. Predicted and realised cost correlate at 0.55 historically. Propose a variance-reduction plan, state the reduction you expect and the resulting runtime, and draw the line between admissible and inadmissible covariates.
Approach
- Apply CUPED with predicted cost as the covariate: Y_adj = Y - theta * (X - mean(X)), with theta = Cov(Y, X) / Var(X) estimated on the pooled experiment sample. The adjusted estimator targets the same estimand without bias because X is independent of assignment, and its variance falls by the factor 1 - rho^2.
- Put a number on it. At rho = 0.55 the reduction is 1 - 0.3025, so about 30 percent of the variance and therefore 30 percent of the sample size. State that this is a ceiling: rho estimated in-sample overstates the reduction you will realise, so quote the out-of-sample correlation if you have one.
- Draw the admissibility line sharply. A covariate is admissible only if it is fixed before randomisation. Predicted cost, adv_20d, participation_rate_target, order_qty, decision_mid_px, gics_sector_code and the strategy's trailing shortfall all qualify. Realised participation rate, realised fill count, interval_vwap_px, terminal_ts and anything read from execution_fill do not, because the treatment changes them, and conditioning on a post-treatment variable introduces a bias that no amount of additional sample removes.
- Add stratified assignment on the same information, bucketed as participation quintile by adv_20d quintile, so balance is enforced rather than hoped for. Stratification and CUPED compete for the same variance; running both buys a little extra, mostly as insurance against a bad draw inside a thin stratum rather than as a further cut to the standard error.
- Pre-register how theta is estimated and what the strata are. Choosing theta after seeing the treatment effect turns CUPED into a specification search with a respectable name attached to it.
Worked solution (30 min)
- Build a covariate table keyed on order_id containing only pre-assignment fields: predicted cost, adv_20d, participation_rate_target, order_qty, gics_sector_code and trailing sixty-day strategy shortfall.
- On a historical sample that precedes the experiment, regress realised shortfall on predicted cost, confirm rho is near 0.55 out of sample, and record theta-hat = Cov / Var.
- Compute the variance reduction 1 - rho^2 and the revised per-arm sample size and runtime.
- Once the test is running, verify that mean predicted cost is statistically indistinguishable across arms. If it is not, the randomisation is broken and CUPED will quietly paper over it.
- Report the adjusted and unadjusted effects side by side, along with the realised variance reduction.
Expected result: A 30 percent variance reduction at rho = 0.55. Per-arm sample size falls from about 8,550 to about 5,970 and runtime from roughly nine months to a little over six. Adjusted and unadjusted point estimates should differ only by noise.
Verify it yourself
- Adjusted and unadjusted point estimates should sit within roughly one standard error of each other. A large divergence means the covariate is post-treatment or the arms were not balanced on it.
- The variance reduction realised in the experiment should be close to 1 - rho^2 measured out of sample. Materially more means rho was fitted on the same data it is being credited for.
- Theta estimated on the control arm alone and on the pooled sample should be statistically indistinguishable; a difference indicates the treatment is altering the covariate-outcome relationship.
Follow-up
- What goes wrong if theta is estimated separately within each arm rather than pooled?
- Shortfall is heavy tailed. Does winsorising before CUPED help or hurt, and what does it do to the estimand you are reporting?
- Which is worth more here: CUPED at rho = 0.55, or moving the decision from the equal-weighted to the notional-weighted mean?
Backtest IC improved on unchanged history after deployment
Hard · lookahead · point-in-time · release regression · backtest integrity
After a scheduler release, the research backtest for one signal reports mean daily IC of 0.041 over a fixed five-year window, against 0.024 for the same window and the same model_version before the release. Nothing in the model changed. Table: signal_score (signal_id, model_version, instrument_id, as_of_date, knowledge_ts, raw_value, zscore_xs, universe_id, coverage_flag, is_backfilled, computed_at). Explain why this result is disqualifying on its face, then give the ordered checklist that finds the mechanism and the test that proves it. Deliverable: the verdict plus the query you would run first.
Approach
- State the disqualifying argument before investigating anything. A backtest over a frozen past window is a function of data fixed before the release. If the number moved, the data moved. No deployment can improve an estimate of history without rewriting history, so the only live questions are which rows changed and whether their new values were knowable at the time they are dated.
- Diff the panel rather than the metric. Compare row counts and value hashes per as_of_date against a pre-release snapshot. Rows whose zscore_xs changed for a past as_of_date are the population of interest, and is_backfilled should already flag them.
- Compare the distribution of knowledge_ts minus as_of_date before and after. A rerun that stamps knowledge_ts from its own computed_at, or that inherits the original row's knowledge_ts while recomputing raw_value from restated inputs, collapses that lag and admits restated fundamentals, revised index membership and retroactively applied split adjustments into dates that preceded them.
- Recompute IC restricted to is_backfilled = FALSE, and separately restricted to rows whose knowledge_ts lag matches the pre-release distribution. If the lift disappears under either restriction the mechanism is confirmed, and the size of the lift is the size of the leak.
- Turn the finding into an assertion the pipeline enforces: for any as_of_date, knowledge_ts must be at or after the observation time of the latest input, and must never decrease when a row is rewritten. That is a constraint code can check on every write, not a line in a review checklist.
Follow-up
- Which upstream vendor artefacts produce exactly this signature, and which of them would show up in raw_value rather than only in zscore_xs?
- The team argues the reruns fixed genuine bugs in past rows, so the new values are more correct. How do you answer that without conceding the backtest?
- What would you add to the research harness so a backtest physically cannot consume rewritten history?
Suggested practice checklist
Instead of guessing where the week should go, day one measures it under a fixed rubric and allocates the remaining hours in proportion to the gaps. The method is deliberately rigid: the allocation is written down before any studying starts and is not renegotiated when a topic turns out to be unpleasant.
Day 1 — Diagnostic, scored before you study anything
- Sit a 100-minute timed diagnostic in four blocks: 30 minutes of SQL across three prompts, 25 minutes of short-answer statistics, 25 minutes on one modelling or case prompt, and 20 minutes delivering one behavioural story aloud.
- Score each block from 0 to 3 on a fixed rubric where 3 is correct and fluent, 2 is correct but slow or prompted, 1 is partially correct, and 0 is stuck, grading the output rather than how the attempt felt.
- Allocate the hours for days two to five roughly in proportion to 3 minus the score in each block, write the allocation down, and commit to not revising it midweek.
Deliverable: A scored rubric and a fixed hour allocation for the rest of the week.
Day 2 — Largest gap: find the boundary rather than the subject
- Break the weakest area into five named sub-skills (for query work: grain control, window frames, date arithmetic, set logic with NULLs, and reading a query plan) and rate each one, so the rest of the week targets a sub-skill instead of a subject.
- Solve three problems chosen to sit just above where the rating drops off, and for each write the first move you failed to make.
- Re-solve one of them from memory four hours later, on paper, with nothing open.
Deliverable: A five-item sub-skill map with the two blocking sub-skills circled.
Day 3 — Largest gap: drill the blocking sub-skill
- Do eight short repetitions of the same shape rather than eight different problems, so what you practise is the pattern and not the puzzle.
- Write the rule you now hold in one sentence, then test it against a case built to break it: a ranking function over a column with ties, or a two-sample test on observations that are obviously dependent.
- Have someone else read your one-sentence rule and find the precondition you left out.
Deliverable: One rule statement with its preconditions attached and one counterexample that would have caught the incomplete version.
Day 4 — Second gap, plus maintenance on your strongest area
- Run the same sub-skill map and boundary protocol on the second-largest gap, compressed into half the day.
- Spend 25 timed minutes on your strongest area to stop it decaying, choosing the hardest problem you can still finish rather than an easy warm-up.
- Compare how the two areas fail: whether you lose time on recall, on setup, or on arithmetic, because the fix differs for each.
Deliverable: A second sub-skill map plus a one-line diagnosis of how each area fails you.
Day 5 — The gap that is not a skill
- Record yourself answering one technical and one behavioural prompt, then count two things in the playback: how many seconds before your first clarifying question, and how many sentences you started without knowing where they ended.
- Rewrite your three most-used stock phrases into shorter versions, and practise saying "I do not know, here is how I would find out" without softening it into a guess.
- Deliver one answer again with a hard 90-second limit to force structure before detail.
Deliverable: Two recordings with a counted improvement in time-to-first-question.
Day 6 — Retest under day-one conditions
- Sit the same 100-minute diagnostic structure with new prompts of comparable difficulty and score it on the identical rubric.
- Compare block by block, and for any block that did not move, change the method rather than adding hours: a block stuck at 1 usually means the practice was too varied, not too short.
- Write which single block you would still lose the offer on.
Deliverable: A second scored rubric placed next to the first, with one named remaining risk.
Day 7 — Full loop under interview conditions
- Run a 60-minute mock covering the two blocks that moved least, with an interviewer instructed to interrupt and change direction.
- Write your recovery script for the moment you go blank: restate the question, state your assumption, name the first thing you would check.
- Reduce the week to the rule statements you wrote, each with its preconditions attached, then say every one of them out loud without reading it and cut any you cannot state in a single sentence, since a rule you have to reconstruct mid-answer will not survive being interrupted.
Deliverable: A one-page card holding the recovery script and only the rules you could state from memory.
Where your data came from
Data people depend on systems owned by other teams, and much of the job is negotiating for instrumentation, access, or a fix to a broken pipeline. Prepare an example of getting something changed upstream that you did not control. Describe what you asked for, what you traded, and how you worked while you waited.
Why are you interested in relocating to one of our primary trading hubs, such as Amsterdam, Hong Kong, or New York?
Medium · behavioural and stakeholder questions
Approach
- Quantify the outcome, including what you would not claim credit for.
- Close with what you would do differently, concretely.
- Name the disagreement or constraint, and how you resolved it with evidence.
Follow-up
- How did you know the outcome was caused by your change?
- What would you do differently if you ran that project again?
How do you handle highly collinear features in a high-frequency financial dataset without losing predictive power?
Medium · behavioural and stakeholder questions
Approach
- Quantify the outcome, including what you would not claim credit for.
- State the situation in two sentences and spend the rest on your reasoning.
- Pick a story where you drove the decision, not one where you observed it.
Follow-up
- What did you decide not to do, and why?
- How did you know the outcome was caused by your change?
Writing an impact statement that survives a hostile reading
Hard · self-assessment · causal inference · attribution
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?