As a Data Scientist at Tower Research Capital, you are at the intersection of high-frequency trading, statistical modeling, and large-scale data engineering. Your work directly influences the firm’s ability to identify market inefficiencies and develop robust alpha-generating strategies. You will not be working on peripheral projects; instead, you will be deeply embedded in the technical engine of the firm, building models that must perform with extreme precision and low latency.
The role demands a rare combination of theoretical rigor and practical coding ability. You will be expected to transform raw, noisy financial signals into actionable insights, requiring a deep understanding of probability, machine learning, and computer science fundamentals. Because Tower Research Capital operates in a highly competitive and fast-paced environment, your contributions will be evaluated by their direct impact on the firm’s trading performance and your ability to solve complex, open-ended problems under pressure.
The interview process at Tower is highly decentralized; expect the focus to shift significantly depending on the specific trading team you are interviewing with.
Online Assessment
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
Technical Interviews
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
1 candidate reports. Individual accounts describe a particular role and hiring cycle.
Tower Research Capital Quantitative Analyst interview experience: five rounds across systems and probability
I went through a high-friction process with five rounds that tested breadth as well as depth. The subjects ranged across probability, puzzle-style questions, computer architecture, networks, and operating systems. Most prompts were open ended, with more emphasis on how I reasoned than on one correct answer. The lack of a clear right path was mentally exhausting at times. I had to keep my logic or…
Read full experiencePracHub editorial advice for the preparation topics above.
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.
Computing a t-statistic on daily observations of an h-day forward return as if the observations were independent.
Sampling an h-day forward return every day means consecutive observations share h-1 days of the same return, which induces strong positive autocorrelation. The naive standard error is too small by a factor on the order of sqrt(h), so a 5-day-horizon signal with a genuine t of 1.3 can present as 2.9. Either use non-overlapping samples, which costs power, or use a Newey-West or Hansen-Hodrick covariance with at least h-1 lags, and state which one was used.
Reading experiment results before checking the arm split
Compare observed arm counts against the intended allocation ratio, not an assumed even split, and set the alarm far below the conventional 0.05: at 0.05 roughly one healthy experiment in twenty trips it, which is why sample-ratio checks usually run at p < 0.001 or stricter. The test's power scales with sample size, so it misses a real diversion on a small experiment and fires on an imbalance too small to move the estimate on a very large one. A flag means go find the assignment or logging fault before reading any outcome, not report a mismatch.
Reading an observational correlation as a causal effect
Name the confounder you are most worried about and the design that would remove it: an experiment, a difference-in-differences with a checked pre-period trend, an instrument, or a regression discontinuity. When none is available, state which direction the bias likely runs and bound the claim accordingly.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Solve a brain teaser involving probability or combinatorics (often wit…
Solve a brain teaser involving probability or combinatorics (often with a follow-up advanced version).
Approach
- Write down the assumption the method needs before you use the method.
- Say what the estimate is of, and over what population it generalises.
- 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?
- Which assumption here is most likely to be violated in practice?
Discuss the properties of consistency and unbiasedness in estimators.
Discuss the properties of consistency and unbiasedness in estimators.
Approach
- Say what the estimate is of, and over what population it generalises.
- Translate the result into the decision it informs, in one plain sentence.
- Write down the assumption the method needs before you use the method.
Follow-up
- Which assumption here is most likely to be violated in practice?
- How would you explain this result to someone who does not know statistics?
Derive the OLS estimator and discuss its properties.
Derive the OLS estimator and discuss its properties.
Approach
- Write down the assumption the method needs before you use the method.
- Quantify uncertainty explicitly rather than reporting a point estimate alone.
- Translate the result into the decision it informs, in one plain sentence.
Follow-up
- How would you explain this result to someone who does not know statistics?
- What sample size would you need to detect an effect half this size?
Explain the mechanics and use cases for Lasso versus Ridge regularizat…
Explain the mechanics and use cases for Lasso versus Ridge regularization.
Approach
- Say how the offline result would be validated online before it is trusted.
- Frame the prediction: the label, the moment of prediction, and the action it triggers.
- Check what information would not exist at prediction time, and exclude it.
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?
Compare and contrast Random Forest and Gradient Boosting machines.
Compare and contrast Random Forest and Gradient Boosting machines.
Approach
- Set a baseline first, so any model has something honest to beat.
- 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
- 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?
Annualized information ratio with an honest standard error
You are given active, one row per (account_id, business_date) with active_return: the daily arithmetic portfolio-minus-benchmark return, net of all costs, as a decimal. Three accounts, roughly 750 business days each. Rows are absent on exchange holidays and on days before an account's funded_date. Per account, compute the annualized information ratio (mean times 252, divided by standard deviation times sqrt(252)) and an approximate standard error for that ratio, then report a 95% interval. Do not reindex onto a calendar. State what T you used and why.
Approach
- Drop null active_return per account rather than filling it. T must be the number of days the account actually traded: holidays and pre-funding days are not evidence, and treating them as such changes both the point estimate and the interval.
- Compute the daily mean m and the daily standard deviation s with ddof=1. The annualized IR is (m/s)*sqrt(252), because the 252 in the numerator and the sqrt(252) in the denominator collapse to a single sqrt(252) factor. Say that out loud instead of writing two separate annualizations that can drift apart.
- Take the standard error at the frequency the statistic is estimated at: SE(SR_daily) is approximately sqrt((1 + SR_daily^2/2)/T) for i.i.d. normal returns, then scale it by sqrt(252), the same factor as the point estimate. At daily frequency SR_daily^2/2 is of order 1e-3, so the SE is effectively sqrt(252/T) and depends only on elapsed years.
- Report IR plus or minus 1.96*SE per account, and check the lag-1 autocorrelation of active_return. The i.i.d. assumption behind that SE is the same assumption that justifies the sqrt(252) scaling, so if the series is autocorrelated both numbers need widening and you should say by how much.
Worked solution 20 min
- groupby('account_id'), dropna on active_return, and record n per account before anything else.
- Per account compute m = mean, s = std(ddof=1), ir = m/s*sqrt(252).
- sr_d = m/s; se_ann = sqrt((1 + sr_d**2/2)/n)sqrt(252); interval = ir +/- 1.96se_ann.
- Compute lag-1 autocorrelation of active_return per account and print it in the same table as the interval.
Follow-up
- The shortest account has 14 months of history. How much of the spread between the best and worst account IR is explainable by sampling noise alone?
- One account carries mark_source = 'vendor_eval' on 30% of days. What does that do to the denominator, and to the independence assumption behind the standard error?
- How many years of daily data would you need to distinguish an IR of 0.8 from an IR of 1.1 at 95% confidence?
Explain the performance implications of different data structures in P…
Explain the performance implications of different data structures in Python.
Approach
- State the window function and its partition and ordering out loud before writing it.
- Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
- Check whether any join is one-to-many before aggregating, or the sums inflate.
Follow-up
- What breaks if events arrive late or out of order?
- How does the query change if the join becomes one-to-many?
Write a bash script or perform basic data engineering tasks to clean a…
Write a bash script or perform basic data engineering tasks to clean and process a dataset.
Approach
- State the window function and its partition and ordering out loud before writing it.
- Compute rates by summing numerator and denominator separately, never by averaging rates.
- Say which table is the grain you start from, and join outward from it.
Follow-up
- How would you verify this result without re-running the same query?
- What breaks if events arrive late or out of order?
Implement a specific data manipulation task using Pandas or NumPy.
Implement a specific data manipulation task using Pandas or NumPy.
Approach
- Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
- 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?
List fills that were never corrected, and survive the NULL
execution_fill records a cancel/correct as a new row with is_correction = TRUE and corrects_fill_id referencing the original; an ordinary fill has is_correction = FALSE and corrects_fill_id IS NULL. Return every original fill for a given settle_date that was never corrected, with fill_id, order_id, fill_qty, fill_px and commission_amt. A colleague's version filters WHERE fill_id NOT IN (SELECT corrects_fill_id FROM execution_fill) and returns zero rows on a day with thousands of fills. Explain why, then write the correct query.
Approach
- Name the mechanism precisely.
x NOT IN (...)expands tox <> v1 AND x <> v2 AND .... Against a NULL element the comparison is UNKNOWN, so the conjunction is either FALSE (when x matches some value) or UNKNOWN, never TRUE. Every probe row is filtered out. It is not an error, which is why it survives review. - Rewrite as
NOT EXISTS (SELECT 1 FROM execution_fill c WHERE c.is_correction AND c.corrects_fill_id = f.fill_id). This uses plain equality, is immune to NULLs in the inner column, and is the form the planner turns into a hash anti-join. - If
NOT INhas to stay for some reason, addWHERE corrects_fill_id IS NOT NULLto the subquery. It is correct, and it is fragile: the next nullable column someone probes reintroduces the identical bug with no new symptom. - Scope the correction lookup by time, not by the same
settle_date. A correction commonly arrives a day or more after the fill it amends, so restricting the inner query to the report date reports already-corrected fills as clean. - Close with arithmetic: originals on the date, minus distinct originals referenced by any correction row, must equal the returned count. If it does not, a correction references a fill_id that does not exist, which is a feed integrity issue worth raising.
Worked solution 15 min
- Run
SELECT COUNT(*) FROM execution_fill WHERE corrects_fill_id IS NULLto confirm the subquery contains NULLs. - Rewrite the filter as NOT EXISTS with the
is_correctionpredicate inside. - Remove the settle_date restriction from the inner query so late corrections are still seen.
- Count originals on the date and count distinct corrected originals, and check the difference equals the result size.
- Re-run the original NOT IN with
IS NOT NULLadded and confirm the two forms now agree.
Follow-up
- Would
LEFT JOIN ... WHERE c.fill_id IS NULLgive the same answer here? What changes if a single fill is corrected twice? - A correction lands three days after the TCA report went out. How do you make the report reproducible as-of its publication date rather than silently restating it?
Design a firm-level client-outcome metric that survives audit
The firm wants one number reported monthly to the board for whether clients are getting what they were sold. The proposal is: AUM held in accounts whose trailing 36-month net-of-fee return beats their own benchmark_id, divided by AUM in accounts with at least 36 months of history. Using account_mandate (benchmark_id, inception_date, funded_date, close_date, status, mgmt_fee_bps, perf_fee_rate, high_water_mark_base, effective_from, effective_to) and position_daily, critique it, name three ways it rises without any client being better off, and specify the guardrails and the exact denominator you would publish.
Approach
- Attack the denominator first, because that is where this metric is won or lost. Requiring 36 months of history excludes accounts that closed during the window, and accounts close disproportionately after bad performance. Fix it by including accounts whose close_date falls inside the window, measured to their close, and carrying them for 36 months afterwards, so the series cannot be improved by attrition.
- Name the three inflation paths concretely. First, survivorship through the close_date exclusion. Second, benchmark choice: benchmark_id is per account and amendable, and account_mandate is SCD2, so an amendment silently restates history unless the metric evaluates each date against the benchmark in force via effective_from and effective_to, with a count of amendments published beside the ratio. Third, AUM-weight concentration: one large mandate can carry the number, so publish the effective number of accounts as the inverse Herfindahl of AUM weights next to it.
- Set the guardrails from the spine: cross-sectional dispersion of trailing 12-month net return within each strategy composite, and trailing 12-month dollar redemption rate. Dispersion catches the case where the headline is met by a favoured subset, and the redemption rate catches the attrition path from the client's side of the relationship.
- Fix the numerator's arithmetic. Net of fee means management fee accrued plus performance fee crystallised, and under a high-water mark with a hurdle two accounts in one strategy legitimately pay different fees, so compute per account from its own terms rather than deducting a composite fee. Then decide the return convention deliberately: time-weighted answers whether the manager delivered, money-weighted answers whether the client made money, and publishing only one answers only one question.
- State the residual honestly. Even a clean version measures relative return, not whether the product matched the client's purpose. Pair it with a small set of hard flags from the same tables, such as breaches of max_tracking_error_bps or max_single_name_weight_pct and recon_status values other than 'matched', rather than pretending one ratio covers the question.
Worked solution 45 min
- Build the account-month panel from account_mandate with SCD2 ranges resolved, tagging each account-month with the benchmark_id in force that month rather than the current one.
- Compute per-account trailing 36-month net-of-fee time-weighted return and the matching benchmark return over the same dates, including accounts closed inside the window up to their close_date.
- Compute the headline ratio under three denominators, surviving accounts only, surviving plus closed-to-date, and surviving plus closed with a 36-month tail, and tabulate the gaps.
- Compute the guardrails: within-composite standard deviation of trailing 12-month net return, trailing 12-month dollar redemption rate, and the effective number of accounts as one over the sum of squared AUM weights.
- Recompute the headline as of a month six months in the past and compare it to what was published then; any drift is a restatement and needs a named cause.
Follow-up
- An account funded 20 months ago has beaten its benchmark throughout and is excluded by the 36-month rule. Is that the right treatment, and what would including it cost you?
- Two accounts in the same composite differ by 180 basis points over 12 months. List the legitimate causes before calling it an error.
- How does the published ratio behave in a month when the firm funds one very large new mandate, and what should the board see alongside it?
Ramp new accounts fast or cheap, and defend the exchange rate
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?
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 has spent the last year in notebooks, dashboards or modelling work and has not written raw SQL under time pressure. The first four days rebuild query fluency against a fixture you control and can verify by hand; the last three attach that fluency to the rest of the loop.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Build a fixture you can check answers against
- Create a local Postgres or SQLite database with four tables (users, sessions, events, orders) holding roughly 200 rows you generated yourself, so you know the contents well enough to predict every result.
- Deliberately seed the cases that break queries: a user with no sessions, a session with no events, two orders sharing a timestamp, a NULL in one join key, and one duplicated user row.
- Before writing any SQL, hand-compute five answers on paper (how many users placed at least one order, median orders per ordering user, and three others) and save them as the ground truth for the week.
Deliverable: A one-command seed script plus a text file of five hand-computed answers to grade every later query against.
Practice prompt ↗Practice prompt ↗Practice prompt ↗Worked solution ↗02Joins, filters and NULL semantics
- Answer "which users have no orders" three ways (LEFT JOIN with IS NULL, NOT EXISTS, NOT IN) and confirm that the NOT IN version returns zero rows once the subquery contains a NULL, because the comparison is never TRUE.
- Reproduce the LEFT JOIN that silently collapses to an inner join by putting a right-table predicate in WHERE, then fix it by moving the predicate into the ON clause, and record both row counts.
- Create a fan-out bug on purpose by joining orders to order_items and summing the order total, then correct it with a pre-aggregated subquery and explain in one line which table changed the grain.
Deliverable: One annotated .sql file holding the three join traps, each with the wrong result and the corrected result side by side.
Practice prompt ↗Practice prompt ↗Practice prompt ↗03Window functions and frames
- Write three window queries against the fixture: a running order total per user, the rank of each order within its user by value, and the day gap to that user's previous order, then check each against the day-one ground truth.
- Run ROW_NUMBER, RANK and DENSE_RANK over a column containing ties, print all three side by side, and write one sentence on when each is the correct choice.
- Switch one query from the default frame (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, which is what you get when ORDER BY is present and no frame is written) to ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, and explain why the output differs only when the ORDER BY column has duplicates.
Deliverable: Three verified window queries plus a short note explaining the RANGE versus ROWS difference in your own words.
Practice prompt ↗Practice prompt ↗04The four analytical query patterns
- Write a monthly retention grid: first order month per user, then months-since-first as the column, and verify that month zero equals the cohort size exactly.
- Sessionize the events table under a 30-minute inactivity rule using LAG plus a cumulative sum over a new-session flag.
- Build a four-step funnel that counts distinct users rather than events at each step, and state the rule you applied to a user who reaches step three without ever logging step two.
Deliverable: One file with the retention, sessionization and funnel patterns, each carrying a one-line note on the assumption it bakes in.
Practice prompt ↗Practice prompt ↗Worked solution ↗05Write SQL the way you will have to write it live
- Set a 12-minute timer and solve three medium prompts in a plain editor with no execution and no autocomplete, then run them and tally syntax errors separately from logic errors.
- Narrate one solution aloud while writing it, stating the grain of each intermediate result (one row per user, one row per user-day) before you type its body.
- Rewrite your slowest solution as a CTE chain where every CTE name states its grain, and time yourself re-solving it from blank.
Deliverable: A recording of one narrated solution plus an error tally that separates syntax from logic.
Practice prompt ↗Practice prompt ↗06One day for everything that is not SQL
- Write the preconditions of the two-sample t-test from memory, then check them: independent observations, and a difference in means whose sampling distribution is approximately normal, which at large sample sizes follows from the central limit theorem rather than from normality of the raw values.
- Write the difference between an odds ratio from logistic regression and a relative risk, and state the condition under which the two are close (low outcome prevalence).
- Prepare a 90-second answer to "how would you know this model is any good" that names the metric, the baseline you would beat, and the cost of the errors you care about.
Deliverable: One page of notes covering test preconditions, the odds-ratio caveat and the model-quality answer.
Practice prompt ↗Practice prompt ↗07Full loop rehearsal
- Run a 45-minute mock with someone willing to interrupt: 20 minutes of SQL, 15 minutes defining a metric, 10 minutes on a past project.
- Re-solve from blank the two queries you were slowest on this week and compare the times against day five.
- Write a five-line answer to "walk me through a project" that puts a number in the first sentence and names the decision the work changed.
Deliverable: Mock feedback notes plus a timed project narrative you can deliver without reading it.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
Sometimes the honest read is that the initiative did not work, and the person who commissioned the analysis was hoping otherwise. Interviewers want to know whether you softened it. Prepare the case where you delivered an unwelcome result, how you presented the uncertainty without hiding behind it, and what the team did next.
Discuss your experience with NLP or Deep Learning architectures in the…
Discuss your experience with NLP or Deep Learning architectures in the context of time-series data.
Approach
- Pick a story where you drove the decision, not one where you observed it.
- Name the disagreement or constraint, and how you resolved it with evidence.
- Quantify the outcome, including what you would not claim credit for.
Follow-up
- How did you know the outcome was caused by your change?
- What did you decide not to do, and why?
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?
Correcting a published TCA note that dropped cancelled orders
Three months ago you published a monthly transaction cost note concluding that algo A beat algo B by 12 bps of implementation shortfall, and the desk moved flow to A. You have since found that your query filtered parent_order to status = 'filled', so cancelled and expired orders never entered the numerator or the denominator. A cancels more often than B. Write the correction: what you tell the desk, in what order, and what changes so this class of error is caught rather than found.
Approach
- What is probed: whether you report your own error at the speed and specificity you would demand from someone else. The clock starts when you know, not when the rework is finished.
- Size the error before describing it. Recompute both algos with cancelled and expired parent orders included and opportunity cost charged on order_qty minus filled_qty at the terminal mid, as the shortfall definition requires. The gap may shrink, vanish or reverse, and I do not yet know the sign is a legitimate first message only if it arrives within hours.
- Name the mechanism that makes the bias directional rather than noisy. Orders get cancelled disproportionately when price runs away from the decision, so excluding them removes the worst outcomes, and it removes more of them from the algo that cancels more. That is why the filter flattered A specifically.
- Tell the desk head in person before the corrected note circulates, and lead with the operational consequence rather than the methodology: flow moved on a wrong number, and here is what to do with it today.
- Make the fix structural rather than a promise to be careful. Add an assertion to the TCA job that the count and notional of parent orders in the report equal the count and notional in parent_order over the window, grouped by status, so a silent population drop fails the job instead of shipping.
Follow-up
- The corrected numbers still favour A, by 3 bps. Does the desk need to hear from you at all, and why?
- Who else built on that note, and how do you find out rather than guess?
- Your review process passed a status filter. What specifically in it was supposed to catch a population change?
- 01
Discuss your experience with NLP or Deep Learning architectures in the context of time-series data.
- 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
Three months ago you published a monthly transaction cost note concluding that algo A beat algo B by 12 bps of implementation shortfall, and the desk moved flow to A. You have since found that your query filtered parent_order to status = 'filled', so cancelled and expired orders never entered the numerator or the denominator. A cancels more often than B. Write the correction: what you tell the desk, in what order, and what changes so this class of error is caught rather than found.
Is this an official Tower Research Capital interview guide?
No. It is PracHub's own research and practice material for the Data Scientist role at Tower Research Capital. Rounds and questions reflect what candidates have reported, not a process Tower Research Capital has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗Is the interview process strictly standardized?
A: No. Because Tower Research Capital allows its trading teams to operate somewhat independently, the interview style and specific technical focus can vary significantly between teams.
PracHub interview research ↗Should I expect brain teasers?
A: Yes, particularly in early rounds. These are used to test your logical reasoning and how you handle ambiguity, rather than your ability to memorize a riddle.
PracHub interview research ↗How much weight is placed on my past work?
A: A significant amount. Be prepared for interviewers to dive deep into your previous projects, asking why you chose specific features, how you validated your models, and what you would do differently today.
PracHub interview research ↗What is the best way to prepare for the technical rounds?
A: Focus on building a "mental library" of your past projects and refreshing your core knowledge of probability, statistics, and algorithm complexity. Practice coding on a whiteboard or a shared editor without relying on IDE autocompletion.
PracHub interview research ↗Sources & methodology 3 sources ↗
Official role evidence, timestamped platform data and clearly labeled preparation advice.
- 01PracHub interview research ↗
PracHub editorial research into this company and role, maintained with this guide. Candidate-reported, not an employer publication.
platform · Accessed 2026-09-22 - 02PracHub Data Scientist practice ↗
Cross-company practice questions for this role.
platform · Accessed 2026-09-22 - 03PracHub interview preparation framework ↗
The framework the preparation plan follows.
platform · Accessed 2026-09-22