Interview guides · anaxima
anaxima Data Scientist Interview Questions & Guide 2026
Modeling drills for a anaxima data scientist interview: baselines, regression interpretation, class imbalance, model defense.
The 60-second brief
As a Data Scientist at anaxima, you serve as a pivotal bridge between complex data architecture and actionable business strategy. The role is designed to transform raw information into clear, high-impact narratives that drive decision-making for clients. You are not just building models; you are solving critical business problems by identifying patterns, optimizing processes, and delivering insights that shape the future of the organizations you serve.
Learn the economics of the product category before the loop. Marketplaces, subscription products and ad-supported products turn on different core quantities (match rate and liquidity, retention and churn, fill rate and yield) and fail in different characteristic ways.
Focus areas
- Set fraud thresholds by expected cost
- Read vintage curves, not blended portfolio averages
- Decompose expected loss into PD, LGD, EAD
Overview
This position is particularly demanding because it requires a blend of technical rigor and consultant-level communication. You will be expected to thrive in environments where data is often messy or ambiguous, requiring you to define the right metrics and design experiments that produce statistically sound results. Whether you are diagnosing a sudden drop in product performance or architecting a new feature testing framework, your work directly influences the strategic direction of anaxima engagements.
The work environment at anaxima is fast-paced and intellectually stimulating. You will collaborate with cross-functional teams to ensure that your analytical output is not only accurate but also deeply integrated into the broader product lifecycle. Success here requires a proactive mindset, a high degree of intellectual curiosity, and the ability to explain complex statistical concepts to non-technical stakeholders.
The anaxima interview process
anaxima candidates report 4 rounds · ≈ 3-5 weeks. The stages below are what candidates describe, not a published process.
Initial Screen
Whoever runs this call is usually not a practitioner. They take notes, and a hiring manager skims those notes later, so the real question is whether your work survives being written down by someone outside the field. Test every project sentence against that: could a non-specialist repeat it correctly without knowing what a propensity score is? Carry a plain-language version of each project and one reason you want this particular role that you could not copy onto another application. Vagueness at this stage reads as inexperience, even when the underlying work was genuinely deep.
What to demonstrate
- Whether a non-specialist can restate your projects accurately, since their paraphrase is what reaches the hiring manager
- Whether your reason for wanting the role points at the work itself rather than the company's reputation
- Whether your language signals the level being screened for: what you decided yourself versus what you were handed
How to prepare
- Write a two-sentence, jargon-free version of each major project: the question nobody could answer, and the decision your work changed. Read it to someone outside data and have them repeat it back
- Point your 'why this role' answer at something concrete in the job description or the product surface you would be working on, and keep it to two sentences
- Have two questions ready about measurement: which metric the team is held to, and who acts on an analysis once it lands
Technical Assessment
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
Behavioral Interview
This 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.
Final Round
Where a loop includes a partner from outside the data team, that conversation usually carries the same weight as the technical ones and gets the least preparation. The person opposite you will not follow a derivation and does not need to. They are working out whether having you involved would make their decisions better or slower. The failure mode is not being too technical. It is answering a question about a decision with a description of your method, leaving the translation to them. What they carry into the debrief is the sentence you handed them, not the analysis underneath it.
What to demonstrate
- Whether a statistical result arrives as something the partner could act on, with the one caveat that would change their decision kept and the rest left out
- Whether you can state what you need from their side, in their terms: instrumentation that does not exist yet, a definition they own, or a holdout they have to agree to
- Whether uncertainty is given as a range someone can plan against, rather than as hedging that invites them to ignore the result
- Whether you ask what decision is actually on the table before explaining anything
How to prepare
- Take a result you know well and write the version for someone who stops reading after one sentence, then the three-minute version, and check the short one is not the long one with the qualifications stripped out
- For a past project, list everything you asked a non-technical partner for and how you phrased it, then rewrite each ask so it names what goes unmeasured without it
- Practise saying where a result does not apply, out loud, in one sentence that a partner could repeat accurately to someone else
Where candidates lose points
Recalibrating an underwriting cutoff on approved and funded applicants only
Rejected applicants have no repayment outcome, and they were rejected because the incumbent model scored them badly, so the missingness depends directly on the outcome being modelled. Reject inference by augmentation or parcelling fills the gap using the incumbent model's own assumptions, which means it can confirm those assumptions but cannot test them. The only genuinely new information about the reject region comes from bureau performance on rejects who borrowed elsewhere, or from a deliberately randomised approval band around the cutoff.
Counting authorizations instead of weighting them, and summing amounts across currencies
Declines skew toward high-value, cross-border and card-not-present transactions, so an unweighted approval rate can sit flat while approved value falls. Merchant retry logic also turns one declined purchase into several rows, inflating the denominator by an amount that varies by merchant and by decline reason. Amounts are held in the minor unit of the transaction currency and that unit is not always two decimals, since some currencies have none and some have three, so summing amount_minor across currencies produces a figure with no interpretation at all.
Reporting a p-value with no effect size or interval
Give the estimated difference with a confidence interval in the units the business cares about, then say whether that whole interval is worth acting on. A p-value only addresses whether you can rule out exactly zero; it says nothing about magnitude.
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.
Questions & practice
Simulate false alarms in a merchant chargeback monitoring rule
Medium · simulation · rare events · monitoring thresholds
Baseline matured first-chargeback rate is 12 per 10,000 settled transactions. A monitoring rule alerts when a merchant's observed monthly rate exceeds twice baseline. For monthly settled transaction counts of 500, 2,000, 10,000 and 50,000, simulate the false-alarm probability per merchant-month under the baseline, and the power to detect a merchant whose true rate is 30 per 10,000. Then, for a portfolio of 4,000 merchants split 60, 25, 10 and 5 percent across those four counts, give the expected number of false alarms per month.
Approach
- Recognise the rule is a threshold on an integer count, not on a continuous rate. At n = 500, twice baseline is 24 per 10,000, so the first observable value above it is 2 chargebacks, or 40 per 10,000. Derive the trigger count for every n before simulating anything.
- Draw binomial counts with numpy at p = 0.0012 and take the share at or above the trigger for the false-alarm rate, then repeat at p = 0.0030 for power. Use at least 200,000 draws per cell so a probability near 0.001 has a usable standard error.
- Cross-check every simulated cell against the Poisson approximation with lambda = n*p, which is tight here because p is tiny. A mismatch almost always means the trigger count is off by one.
- Weight the per-merchant false-alarm probabilities by the portfolio mix, and report the share of expected alerts contributed by each size band rather than only the total.
- Close on the operating consequence: a fixed multiplicative threshold is not a constant false-alarm rate across merchant sizes, so either the threshold scales with n or small merchants need a minimum volume before the rule applies.
Worked solution (30 min)
- For each n, compute trigger = floor(2 * 0.0012 * n) + 1 and print the four values before simulating.
- Simulate 200,000 binomial draws per n at p = 0.0012 and take the share at or above the trigger.
- Repeat at p = 0.0030 and record power for the same triggers.
- Compute the Poisson tail 1 - CDF(trigger - 1, lambda = n*p) for both p values and confirm agreement within Monte Carlo error.
- Multiply the false-alarm probabilities by 2400, 1000, 400 and 200 merchants and sum.
Expected result: Trigger counts of 2, 5, 25 and 121. False-alarm probability roughly 12 percent at n = 500, roughly 10 percent at n = 2,000, under 0.1 percent at n = 10,000 and effectively zero at n = 50,000. Power against 30 per 10,000 roughly 44, 72, 85 and above 99 percent. Expected false alarms about 390 per month, with over 99 percent of them coming from the two smallest bands.
Verify it yourself
- The four trigger counts are derived, not guessed: each is the smallest integer strictly above 0.0024n, giving 2, 5, 25 and 121. Derive them in exact or integer arithmetic, because 20.0012*10000 evaluates to 23.999999999999996 in binary floating point and floor-plus-one silently returns 24.
- Simulated probabilities match the Poisson tail at lambda = n*p within about two Monte Carlo standard errors.
- Power exceeds the false-alarm rate at every n; if it does not, the null and alternative rates are swapped.
- Doubling the draw count moves each probability by less than its own simulated standard error.
Follow-up
- How would you set a threshold that holds the false-alarm rate roughly constant across merchant size?
- The rule reads the transaction month, but disputes arrive for up to 120 days afterwards. What does that do to the alert and how would you fix it?
- What does a month of these false alarms cost, and how would you decide whether it is worth paying?
Bootstrap a fraud loss rate that clusters within merchant
Medium · bootstrap · clustered resampling · heavy tails
You have a per-transaction frame with auth_id, merchant_id, settled_amount_reporting and net_loss_reporting, both already in one reporting currency. Most rows carry zero loss, a few carry large ones, and losses cluster within merchant. Using only numpy's random generator and no resampling helper from any library, write a bootstrap that returns a 95 percent interval for net fraud loss in basis points of settled volume, resampling merchants with replacement and taking all rows belonging to each drawn merchant. Also produce the naive row-level interval and state which you would report.
Approach
- State the estimator before writing it: total net loss divided by total settled volume, times 10,000. It is a ratio of sums, so each replicate recomputes both sums. Averaging per-transaction loss rates instead would weight a five-unit transaction like a five-thousand-unit one.
- Pre-aggregate loss and volume to merchant level once. For a ratio of sums, drawing merchants and taking all their rows is arithmetically identical to drawing merchant-level (loss_sum, volume_sum) pairs, so a replicate becomes one integer draw plus two vectorised sums rather than a groupby inside the loop.
- Draw B replicates of M merchant indices with replacement, where M is the observed merchant count, compute the ratio per replicate, and take the 2.5th and 97.5th percentiles. Say explicitly that this is a percentile interval and that BCa would correct the skew-induced bias if the decision is close.
- Repeat with independent row draws for the naive interval and compare widths on the same replicate count.
- Report the clustered interval. Rows within a merchant share an acceptance profile, a category code and a fraud exposure, so they are not independent, and the row-level interval understates variance by roughly the design effect.
Follow-up
- Your clustered interval is three times wider. How do you explain that to someone who wanted a tighter number?
- One merchant accounts for 40 percent of losses. What does that do to the interval, and what would you do about it?
- How does this change if the question is whether two months differ rather than what this month's rate is?
Write integrity checks for the authorization and settlement lifecycle
Easy · data quality · minor units · fx reconciliation
You are given fct_payment_authorization as a pandas DataFrame with auth_id, requested_at, amount_minor, transaction_currency, auth_result, decline_reason_code, is_reversal, parent_auth_id, captured_at, captured_amount_minor, settled_at, settlement_amount_minor, settlement_currency and settlement_fx_rate. Write a function returning one row per integrity check with the check name, failing row count, failing share and up to five example auth_id values. Cover at least six checks, one of which reconciles captured_amount_minor against settlement_amount_minor through settlement_fx_rate. Partial capture, zero-amount verification and a decline with no capture are all legitimate and must not be flagged.
Approach
- Separate contract violations from observations before writing any code: an approved row carrying a decline_reason_code is structurally impossible, while a capture two days after requested_at is merely slow and belongs in a different severity tier.
- Express each check as a boolean mask over the whole frame and collect the masks in a dict, so the summary table is one comprehension over mask.sum() rather than a row loop.
- For the reconciliation, leave minor units before comparing: expected = captured_amount_minor / 10exponent[transaction_currency] * settlement_fx_rate * 10exponent[settlement_currency]. Build the exponent table covering zero-decimal and three-decimal currencies instead of assuming two everywhere.
- Guard the legitimate cases explicitly so each mask fires only on the genuine contradiction: captured_amount_minor below amount_minor is partial capture, amount_minor of zero on an approved row is account verification, a null captured_at on a declined row is correct.
- Sort the output by failing share times a stated severity weight, because a check firing on 0.01 percent of rows can still be the one that breaks a ledger reconciliation.
Follow-up
- Which of these would you run as a blocking pipeline assertion and which as a monitored metric, and why?
- The FX check fails on 3 percent of rows, all in one settlement currency. How do you decide between a data bug and a rounding convention?
- How would you detect that a currency's minor-unit exponent is wrong in your reference table, using only the transaction data?
Explain the difference between various joins and when you would use each in a production environment.
Medium · sql and data manipulation
Approach
- Say which table is the grain you start from, and join outward from it.
- 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?
- What breaks if events arrive late or out of order?
How would you handle missing data in a large user activity log?
Medium · sql and data manipulation
Approach
- State the window function and its partition and ordering out loud before writing it.
- 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.
Follow-up
- How does the query change if the join becomes one-to-many?
- What breaks if events arrive late or out of order?
Count-weighted and dollar-weighted approval rates on one currency
Easy · aggregation · denominators · minor units
Using fct_payment_authorization, report the trailing 7-day authorization approval rate two ways for transaction_currency = 'EUR': count-weighted, and dollar-weighted on amount_minor. Exclude is_reversal = true, exclude incremental authorizations (parent_auth_id not null), and exclude zero-amount account verifications. auth_result = 'approved' is the numerator; the four declined_* values make up the rest of the denominator. Return channel, attempts, approved_attempts, approval_rate_count and approval_rate_value. State every exclusion and its reason before you write the SELECT.
Approach
- Say the denominator out loud first: attempts on a single transaction currency, excluding reversals, incremental authorizations and zero-amount verifications, because none of those is a purchase attempt a merchant is trying to get approved.
- Filter requested_at against a half-open interval (>= start AND < end) so the boundary day is neither dropped nor double counted.
- Compute both rates in one pass with FILTER clauses: COUNT() FILTER (WHERE auth_result = 'approved') over COUNT(), and SUM(amount_minor) FILTER (WHERE auth_result = 'approved') over SUM(amount_minor).
- Cast one side of each ratio to numeric before dividing, since amount_minor and the counts are integers and integer division silently truncates to zero.
- Group by channel and sort by the value-weighted rate, then read the gap between the two rates as a statement about where the declines sit rather than as noise.
Worked solution (20 min)
- Write the exclusion list as comments above the query: is_reversal = false, parent_auth_id is null, amount_minor > 0, transaction_currency = 'EUR'.
- Build a single aggregate query over fct_payment_authorization with a half-open requested_at predicate and those four filters.
- Emit attempts, approved_attempts, approval_rate_count and approval_rate_value with FILTER clauses and a numeric cast on the numerator.
- Group by channel, order by approval_rate_value ascending so the worst channel is on top.
Expected result: One row per channel present in the window, with attempts and approved_attempts as integers and both rates as numerics strictly between 0 and 1. approval_rate_value is typically lower than approval_rate_count on ecommerce and moto, because declines concentrate in higher-value card-not-present traffic.
Verify it yourself
- SUM(attempts) across channels equals a separate COUNT(*) run with the same four filters and no GROUP BY.
- Dropping the amount_minor > 0 filter raises attempts and moves approval_rate_count while leaving approval_rate_value unchanged, which confirms the zero-amount rows were only ever affecting the count-weighted figure.
- Both rates are strictly less than 1 unless a channel had no declines at all in the window.
Follow-up
- The two rates diverge by four points on the ecommerce channel but agree on card_present. What does that tell you, and what would you cut next?
- How would you extend this to all currencies without summing amount_minor across them?
- Which of the four decline reasons belong in the denominator of a rate you would put in front of a risk team, and which are really the network's problem?
How would you measure the success of a new feature launch?
Medium · product sense and metrics
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
- How would you detect that the metric is being gamed rather than genuinely improving?
- Which segment would you cut first, and what would that rule out?
How do you balance long-term user retention with short-term monetization goals?
Medium · product sense and metrics
Approach
- Fix the population and the time window before naming any metric.
- 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
- 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?
A key product metric has dropped by 10% overnight. How do you investigate this?
Medium · product sense and metrics
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
- How would you detect that the metric is being gamed rather than genuinely improving?
- What would you do if the primary metric and the guardrail moved in opposite directions?
Design a metric to track the health of a subscription-based service.
Medium · product sense and metrics
Approach
- Name one primary metric, then the guardrail that stops it being gamed.
- Fix the population and the time window before naming any metric.
- 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?
- How would you detect that the metric is being gamed rather than genuinely improving?
What are the risks of peeking at data before an experiment concludes?
Medium · a/b testing and experimentation
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.
- Decide the analysis before seeing data, including how long it runs and when you look.
Follow-up
- What would you do if you could not randomise at all?
- What would you conclude if the result is positive but the test is underpowered?
How do you determine the required sample size for an A/B test?
Medium · a/b testing and experimentation
Approach
- Name the randomisation unit first; it decides the variance and what the test can detect.
- Decide the analysis before seeing data, including how long it runs and when you look.
- Name the guardrails that would stop a launch even on a positive primary result.
Follow-up
- What would you do if you could not randomise at all?
- How would you handle interference between treated and control units?
Size a two-week test on the ecommerce authorization path
Easy · power · mde · ratio metrics · clustering
Your team wants to test a new decline-retry policy on the ecommerce channel. The metric is the dollar-weighted authorization approval rate from fct_payment_authorization: approved amount_minor over attempted amount_minor, after collapsing retry chains within a 15-minute window on (card_token_id, merchant_id, amount_minor) and excluding is_reversal rows and zero-amount verifications, all converted to one reporting currency. Baseline is 87 percent on roughly 900,000 collapsed attempts in two weeks. Randomisation is by customer_id, mean six attempts per customer. Give the minimum detectable effect at 80 percent power, two-sided alpha 0.05, and say what you would change if it is too large.
Approach
- Compute the count-weighted binomial anchor first, because it is the number everyone expects and you need it to show why it is wrong. With n = 450,000 attempts per arm and p = 0.87, MDE = (1.96 + 0.8416) * sqrt(2p(1-p)/n).
- State that the real metric is a ratio of two sums with a random denominator, not a Bernoulli mean, so the binomial standard error is not the right one. Linearise: Var(R) is approximately Var(Y_i - R * D_i) / (n * Dbar^2), where Y_i and D_i are the approved and attempted amount totals for customer i, n is the number of customers, and Dbar is the mean attempted amount per customer.
- Apply the clustering correction, since assignment is by customer and attempts within a customer are correlated. Ask for or estimate the intra-customer correlation; the design effect is 1 + (m - 1) * rho with m = 6, so rho = 0.05 gives 1.25 and inflates the MDE by sqrt(1.25) = 1.118.
- Do not assume the amount-weighted variance; estimate it by bootstrapping customers from the last eight weeks of history and resampling whole customers, which captures both the skew in amount_minor and the within-customer correlation in one step.
- If the MDE exceeds the plausible effect, list the levers in order of cost: extend duration (MDE falls as 1/sqrt(n)), restrict to the segment where the rule can bind at all rather than diluting across all traffic, apply CUPED on the customer's pre-period approved amount, or switch the primary to the count-weighted rate and demote the dollar-weighted rate to a secondary read.
Worked solution (20 min)
- Split 900,000 collapsed attempts into 450,000 per arm and compute the binomial anchor: sqrt(2 * 0.87 * 0.13 / 450000) = sqrt(5.027e-7) = 7.090e-4; multiply by 2.8016 to get 1.99e-3.
- Derive the customer count: 900,000 / 6 = 150,000 customers, 75,000 per arm, and note that this is the true sample size for inference.
- Apply the design effect at rho = 0.05: 1 + 5 * 0.05 = 1.25, so the count-weighted MDE becomes 1.99e-3 * 1.118 = 2.22e-3.
- State that the dollar-weighted MDE requires the linearised variance and cannot be derived from p alone; specify the customer-level bootstrap that would produce it and note it will be larger because amount_minor is right-skewed.
Expected result: Count-weighted MDE is about 0.20 percentage points unclustered and about 0.22 percentage points at a design effect of 1.25, against an 87 percent baseline (roughly 0.26 percent relative). The dollar-weighted MDE is not computable from the stated inputs and must be estimated by a customer-level bootstrap; the candidate should say so rather than quote the binomial figure for it.
Verify it yourself
- z(0.975) + z(0.80) = 1.9600 + 0.8416 = 2.8016; any MDE quoted with a different multiplier is using different power or alpha than stated.
- Doubling the test duration should shrink the MDE by exactly sqrt(2) = 1.414 if the traffic mix is stable; if a candidate's arithmetic does not, the formula is wrong.
- Run the bootstrap on two historical periods split A/A: the bootstrap standard error of the difference times 2.8016 should reproduce the analytic MDE.
- A/A splits of historical data should reject at roughly 5 percent; materially more means the variance model is understated.
Follow-up
- The rule only changes behaviour on declined attempts, which are 13 percent of traffic. How does restricting the analysis population to attempts that could have triggered the rule change both the MDE and the estimand?
- How would your sizing change if the split were 90/10 instead of 50/50, and why is the loss more than proportional?
- Currency: the metric sums amounts converted to one reporting currency. Would you use settlement_fx_rate or a rate table pinned at test start, and what does the choice do to variance?
Settled volume jumps after a new acceptance corridor launches
Medium · minor units · currency conversion · reconciliation
Settled payment volume per active customer rose 12 percent in the month a new acceptance corridor went live. The pipeline sums settlement_amount_minor from fct_payment_authorization and divides by 100 to get major units. Columns available: amount_minor, transaction_currency, captured_amount_minor, settlement_amount_minor, settlement_currency, settlement_fx_rate, settled_at, is_reversal, issuer_country, acquirer_country. Confirm or refute the 12 percent, and specify exactly the conversion the metric should be using.
Approach
- Split the month-over-month increase by settlement_currency. If one currency carries nearly all of it while its transaction count barely moved, the problem is arithmetic rather than demand, and that is a two-minute check.
- Look up each currency's ISO 4217 exponent. Dividing a three-decimal currency by 100 instead of 1000 overstates it tenfold; dividing a zero-decimal currency by 100 understates it hundredfold. Neither is a rounding issue.
- Rewrite the conversion to scale settlement_amount_minor by ten to the power of that currency's exponent, then convert to the reporting currency. Do not reuse settlement_fx_rate for this; it is the rate applied between transaction and settlement currency at settlement time, not a reporting-currency rate.
- Check the other half of the series too. settlement_amount_minor is denominated in settlement_currency while amount_minor is in transaction_currency, so any series that mixes the two is uninterpretable regardless of the exponent fix.
- Exclude reversals and refunds, recompute, then reconcile the corrected total to the settlement ledger for the same period and show the tie-out in the write-up.
- Recompute the per-customer denominator on the corrected month, since a new corridor adds customers as well as volume and the ratio can move either way once the numerator is right.
Follow-up
- Where else in the warehouse does a hardcoded divide-by-100 appear, and how would you find every instance?
- What test would fail the build the next time a currency with a different exponent is onboarded?
- The reporting-currency rate is itself a choice. Which rate, on which date, and why does finance care about the answer?
Suggested practice checklist
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.
Day 1 — Metric 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.
Day 2 — Diagnosing 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.
Day 3 — Should 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.
Day 4 — The 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.
Day 5 — Technical 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.
Day 6 — Turning 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.
Day 7 — Mock 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.
Bring numbers, including the ones you are unsure of
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 cases where your test results are not statistically significant?
Medium · behavioural and stakeholder questions
Approach
- State the situation in two sentences and spend the rest on your reasoning.
- Name the disagreement or constraint, and how you resolved it with evidence.
- Pick a story where you drove the decision, not one where you observed it.
Follow-up
- What would you do differently if you ran that project again?
- How did you know the outcome was caused by your change?
Retract a published number after finding a currency bug
Medium · error disclosure · minor units · process repair
Two weeks ago you published an interchange and fraud analysis that summed amount_minor across fct_payment_authorization without converting currencies. Minor units are not two decimals everywhere: some currencies carry none and some carry three, so the sum has no interpretation. A pricing decision is already in flight on the back of it. You now have corrected figures. Produce the retraction: what you send, to whom, in what order, and what you change in the process so this class of error is caught next time rather than trusted next time.
Approach
- Size the error before announcing it, because saying the number is wrong without a magnitude and a direction forces every reader to assume the worst case.
- Check whether the conclusion actually flips: if the ranking that drove the pricing decision is unchanged, that belongs in the first sentence beside the correction rather than buried at the end.
- Tell the person acting on it first and directly, then the wider distribution, using the same text, so nobody learns about it secondhand.
- Write the correction as four parts: the old number, the cause in one clause, the effect on the pending decision, and the new number. Leave out self-flagellation, which makes the reader do emotional work instead of acting.
- Fix the class rather than the instance: a rule that a sum over amount_minor either groups by transaction_currency or passes through both conversion steps, exponent scaling and then a dated rate into one named reporting currency, plus a standing reconciliation of the settled subset to the settlement ledger inside each settlement_currency.
Follow-up
- The corrected figures do not change the decision. Do you still send the correction, and what does that choice signal?
- What automated check would have caught this, where would it live, and what would it cost in false alarms?
Explain an incomplete dispute chart to a non-technical executive
Easy · dispute maturity · stakeholder communication · right-censoring
A finance lead is looking at first-chargeback rate by transaction month, built from fct_card_dispute joined to fct_payment_authorization on auth_id and attributed to requested_at. The last three months slope sharply down and the lead wants to announce a fraud improvement at tomorrow's review. Consumer dispute rights commonly run around 120 days from the transaction or expected delivery date, so those months are not complete. In five minutes, with no statistics vocabulary, explain why the decline is not yet evidence and say exactly what you would put on the slide instead.
Approach
- Lead with the mechanism in the listener's own terms, not with the statistical name for it: a dispute is attributed to the month the transaction happened, but it can be filed up to roughly 120 days later, so recent months contain only the disputes filed so far.
- Show completeness rather than arguing about the rate: for each transaction month, plot the share of its eventual disputes already filed, estimated from months that are fully matured. The last three months will sit visibly below 100 percent.
- Replace the chart with two artefacts: a matured series that stops 120 days back and is labelled final, and a development-factor estimate for the immature months drawn as a dashed range and labelled an estimate.
- Hand over one sentence the executive can repeat without you in the room: the recent months look better because the disputes have not arrived yet, not because fewer will arrive.
- Offer a weekly signal they can watch instead, such as the risk-score mix of approved volume or the decline-rule hit rate, and state up front what it does and does not predict.
Follow-up
- The deck ships tomorrow regardless. What exactly goes on the slide, and what wording do you insist on?
- How would you estimate the development factors, and how would you notice if they had shifted?