cswork / libraryOpen practice workspace

Interview guides · Jane Street

Jane Street Machine Learning Engineer Internship 2027: Coding, ML Systems, and Onsite Rounds

Prepare for Jane Street ML internship interviews with coding, a worked forecasting split, exact baseline results, leakage checks and ML systems decisions.

Interviewing at Jane Street

  • Practice bank: 9+ questions
  • Rounds: 1
  • Typical prep: 1–2 weeks
  • Interview reports: 1

Interview rounds

RoundQuestions
Technical Screen9

How hard is the Jane Street Machine Learning Engineer interview?

DifficultyShareQuestions
Easy11%1
Medium33%3
Hard56%5

What Jane Street actually tests for

TopicShareQuestions
Coding & Algorithms44%4
ML System Design22%2
System Design22%2
Machine Learning11%1

Jane Street's ML engineering internship preparation has two connected goals: write reliable code with another person, then explain how data, evaluation, and runtime constraints shape an ML system. A model name is a starting point. The useful discussion is what the model can know, how you measure it, and what happens when its assumptions fail.

This guide includes an original 12-point forecasting exercise with exact baseline results, leakage checks, and a coding follow-up. It uses synthetic data, not Jane Street market data or a private assessment. The 2027 title is a preparation label; the current public internship listing does not explicitly identify a calendar-year recruiting cohort.

What does the current public listing confirm?

Jane Street's New York ML Engineer Internship listing describes an initial technical coding interview over Zoom followed by an onsite with 2–4 technical rounds, including 1–2 focused on ML engineering. It seeks practical experience training models, working on an ML library, or optimizing an ML workflow. Finance experience is not required.

Use that description to divide preparation between coding and applied ML reasoning. Confirm your office, cohort, stages, timing, and permitted tools with recruiting. The public listing does not guarantee every 2027 invitation or specify a universal private question set.

How should you approach the coding screen?

Jane Street's general software-engineering guidance emphasizes collaborative coding in a real language and recommends the language you know best. It does not award extra credit for choosing OCaml. Prepare to clarify an operation, implement a small correct slice, test it, and adapt when the interviewer changes a requirement.

Rehearse stateful tasks such as code folding, board simulation, a small language runtime, or marketplace reconciliation. State which invariant each operation preserves. When a test fails, walk through the smallest failing input before making an edit. When offered a hint, explain what changed in your model of the problem.

For this internship, keep the same working style during ML discussion: fix the prediction contract, compute a baseline, examine a failure, and revise the smallest affected part. The exercise below makes that transition concrete.

Forecasting mock: what can the model know at prediction time?

You observe one integer value at the end of each equally spaced time step:

Step123456789101112
Value101211131416151718201921

Prediction contract: at the end of origin t, observe values through t and forecast y[t+1]. The target arrives one step later. The metric is mean absolute error, MAE, in the same units as the target. This is sequential one-step forecasting, not a multi-step forecast issued once at the beginning of a holdout.

SplitForecast originsTarget stepsUse
Training2–53–6Fit a simple drift parameter
Validation6–87–9Compare two candidates and select one
Final test9–1110–12Evaluate the frozen choice

At validation origin 6, target step 6 from the last training example is already observed. At origin 7, the newly observed value from step 7 can become an input for the next prediction. That is permitted by the sequential one-step contract. It would be leakage under a different contract that forbids incorporating observations after origin 6.

Compare a persistence baseline with a fitted drift

Persistence predicts the latest observed value: prediction = y[t]. The second candidate predicts y[t] + drift, where drift is the mean one-step change over training examples only.

Training changes are −1, +2, +1, and +2. Their mean is +1. Freeze that parameter while comparing validation forecasts:

OriginActual next valuePersistenceDrift +1Absolute error: persistence / drift
61516171 / 2
71715162 / 1
81817181 / 0

Validation MAE is 4/3 ≈ 1.333 for persistence and 1.000 for drift. Select drift using validation, then examine the final test once:

OriginActual next valuePersistenceDrift +1Absolute error: persistence / drift
92018192 / 1
101920211 / 2
112119202 / 1

Test MAE is 5/3 ≈ 1.667 for persistence and 4/3 ≈ 1.333 for drift. Keep the selected drift frozen for this reported comparison. The tiny improvement on three test points provides no credible evidence of general financial predictive value. It verifies the exercise's arithmetic and evaluation boundary.

Code that makes label availability explicit

The helper uses one-based forecast origins and exact rational arithmetic. Integer observations are the toy input contract. Offline scoring reads the target to measure error; fitting must reject labels beyond its cutoff.

from fractions import Fraction

def validate(values, origins):
    if not values or any(type(v) is not int for v in values):
        raise ValueError("nonempty integer series required")
    if not origins or len(set(origins)) != len(origins):
        raise ValueError("nonempty unique origins required")
    if any(type(t) is not int or not 1 <= t < len(values) for t in origins):
        raise ValueError("invalid one-based forecast origin")

def fit_drift(values, origins, label_cutoff):
    validate(values, origins)
    if type(label_cutoff) is not int or not 1 <= label_cutoff <= len(values):
        raise ValueError("invalid label cutoff")
    if any(t + 1 > label_cutoff for t in origins):
        raise ValueError("training label not available by cutoff")
    return Fraction(sum(values[t] - values[t - 1] for t in origins), len(origins))

def score(values, origins, drift):
    validate(values, origins)
    if not isinstance(drift, Fraction):
        raise ValueError("use an exact Fraction drift")
    rows = [(t, Fraction(values[t - 1]) + drift, values[t]) for t in origins]
    mae = sum(abs(predicted - actual) for _, predicted, actual in rows) / len(rows)
    return rows, mae

For this fixture, call fit_drift(y, [2,3,4,5], 6), then score origins [6,7,8] and [9,10,11] with the frozen Fraction(1). The validation and test target sets do not overlap. A local check changed all values after step 6 and confirmed the training drift remained unchanged.

Catch leakage before choosing a larger model

A feature called “tomorrow's value” reproduces the target and would report zero error. It is unavailable at prediction time, so that result is meaningless. A centered rolling average can leak more subtly by including y[t+1] in a feature associated with origin t.

Preprocessing can leak too. Training feature values at origins 2–5 have mean 12.5. All 12 observations have mean 15.5. Fitting a normalizer on the full series lets later values influence earlier training. Fit learned transformations on the training slice, then apply the frozen transformation to validation and test.

RiskQuestion to askCorrective action
Future featureWas this value available at origin t?Use an as-of join or trailing-only feature
Delayed labelWas the training target known by the fit cutoff?Exclude examples whose labels had not arrived
Overlapping horizonDoes a training label extend into the next fold?Remove incompatible origins or use an appropriate gap
Full-data preprocessingWhich rows fitted the transform?Fit within each training fold
Repeated test tuningDid the test result influence a choice?Reserve a new untouched evaluation period

If the interviewer changes the horizon to two steps and the fitting cutoff remains step 6, training origin 5 is no longer eligible: its label window ends at step 7. Origins 2–4 remain eligible because their windows end by step 6. Rebuild the target contract and splits rather than reusing the one-step scores.

Scikit-learn's TimeSeriesSplit supports chronological folds and a gap parameter. A chronological index alone does not solve feature availability, revised data, delayed labels, or overlapping target windows. Those remain properties of your dataset construction.

Coding follow-up: maintain a trailing mean

Suppose the partner asks for the mean of the last W observed values at every eligible origin. Start with slicing and summing, which costs O(W) per output. A hint suggests keeping a running sum. Preserve the same output contract and change the update mechanism:

from collections import deque

def trailing_means(values, width):
    if type(width) is not int or width <= 0:
        raise ValueError("positive window width required")
    if any(type(v) is not int for v in values):
        raise ValueError("integer series required")
    window, running, output = deque(), 0, {}
    for t, value in enumerate(values, 1):
        window.append(value); running += value
        if len(window) > width:
            running -= window.popleft()
        if len(window) == width:
            output[t] = Fraction(running, width)
    return output

For W=3, the feature at origin 6 is (13+14+16)/3 = 43/3; at origin 8 it is (16+15+17)/3 = 16. Neither requires a future observation. Say explicitly that this helper supplies a feature; it is not the selected drift model and its output is not an additional reported test result.

The running algorithm takes O(n) time and O(W) window space. This implementation also stores O(n) output entries. A streaming version can emit each output instead of retaining the dictionary. Do not claim total O(W) memory while materializing every output.

The complete local suite passed 1,227 checks, including 1,200 rolling-window comparisons against an independent slice-and-sum oracle, widths 1–12, and seeded integer series of lengths 1–100. Other checks verified the exact forecast results, invalid inputs, label cutoff, future-data independence of fitting, and the two-step eligibility change. No neural-network training or production latency benchmark was run.

Turn the model exercise into an ML-system decision

For an original deployment discussion, assume one CPU worker, a 100 MB feature-memory budget, and a 50 ms p99 response target. These are supplied exercise constraints, not Jane Street requirements or measured performance.

Begin with the simple baseline. Its arithmetic is cheap, but the service still needs timely input, schema validation, versioned transformations, and defined behavior when the latest observation is missing. Measure the end-to-end path before choosing a larger model: fetch, feature construction, inference, serialization, and queue wait.

For a training framework, name the dataset snapshot, cutoff, split definitions, code version, dependency versions, transform artifact, model artifact, and promotion decision. A seed does not reproduce data that has changed. Reject incompatible feature schemas before serving an artifact, and keep a compatible prior model and transform for rollback.

Monitor missing or late inputs, feature distributions, inference failures, latency tails, and prediction error once labels arrive. Avoid retraining on an alert alone: first distinguish a broken data pipeline from a genuine change in the relationship you are modeling. Jane Street's public ML page describes noisy, changing financial data and training/inference infrastructure; it supplies context, not a private assessment specification.

A seven-day preparation plan with concrete outputs

DayWorkOutput
1Confirm the loop and solve a stateful coding taskWorking code, tests, and clarified assumptions
2Define the forecasting contractOrigin/target table and as-of availability rules
3Compute both baselinesExact validation/test results and a frozen choice
4Audit leakage; change the horizonRebuilt eligibility and split boundaries
5Optimize the trailing featureRunning-sum code checked against a simple oracle
6Design training and servingArtifact contracts, monitoring and rollback plan
7Run an interactive mock and project discussionChanged-requirement notes and honest project evidence

Rehearse a project you actually built, including a failed experiment, the evidence that changed your mind, and the part you personally owned. Keep data-science, ML research, and ML engineering role descriptions separate. Use the question bank's forecasting, framework, compiler and stateful-code tasks as transferable practice rather than predictions of your interview.

Sources and scope

Reviewed October 8, 2026. The public listing is current role guidance, not an explicitly dated 2027 schedule. All data, calculations, budgets and code examples here are original synthetic practice material.