
Top Graviton Quant Interview Questions with Detailed Solutions
In this article, we’ll walk through two popular quant interview questions from Graviton: a thorough time series forecasting case study and a classic probability puzzle. Each question is solved in detail, with concepts explained and solutions justified—just as you would in a real interview.
Quant Interview Questions from Graviton: Solutions and Explanations
1. Time Series Forecasting: 3 Years of Hourly Sensor Data
Interview Question
You are given three years of hourly measurements from a sensor. Your goal is to forecast the next 24 hours. You are given no information about the underlying process. Walk me through your analysis from the moment you receive the data until you are ready to build a forecasting model.
Step 1: Initial Data Exploration and Visualization
The first step with any dataset is to explore and visualize the data to understand its properties and spot any obvious issues.
- Load the data into your analysis environment (Python, R, etc.).
- Check the structure (data types, timestamps, missing values).
- Plot the time series to get a sense of its shape, variability, and any visible patterns.
import pandas as pd
import matplotlib.pyplot as plt
# Load data
data = pd.read_csv('sensor_data.csv', parse_dates=['timestamp'], index_col='timestamp')
# Quick summary
print(data.head())
# Plot the time series
plt.figure(figsize=(15, 5))
plt.plot(data.index, data['measurement'])
plt.title('Hourly Sensor Measurements')
plt.xlabel('Date')
plt.ylabel('Measurement')
plt.show()
What to look for: Trends, abrupt changes, seasonality, outliers, missing data, and overall range/variance.
Step 2: Handling Missing Values and Outliers
Missing values and outliers can distort your analysis and model performance.
- Find missing values: Is data missing at random, or in blocks?
- Handle missing values: Options include forward/backward fill, interpolation, or model-based imputation. For forecasting, a simple linear interpolation is often sufficient, unless missingness is systematic.
- Detect outliers: Use boxplots, z-scores, or rolling statistics to identify points that are far from typical values.
- Handle outliers: Investigate causes (sensor malfunction, real events). You may cap, remove, or replace them, depending on business context.
# Check for missing values
print(data.isna().sum())
# Interpolate missing values
data['measurement'] = data['measurement'].interpolate(method='time')
# Detect outliers (e.g., using z-score)
import numpy as np
z_scores = np.abs((data['measurement'] - data['measurement'].mean()) / data['measurement'].std())
outliers = data[z_scores > 3]
print(f"Number of outliers: {outliers.shape[0]}")
Step 3: Understanding Trend and Seasonality
Before modeling, it’s essential to decompose the series into its components:
- Trend: Is there a long-term increase or decrease?
- Seasonality: Are there recurring patterns (daily, weekly, yearly)?
- Noise: What’s left after removing trend and seasonality?
You can use techniques like STL (Seasonal-Trend decomposition using LOESS) or classical decomposition to visualize these components.
from statsmodels.tsa.seasonal import STL
stl = STL(data['measurement'], period=24*7) # assuming weekly seasonality
result = stl.fit()
result.plot()
plt.show()
This decomposition helps in determining the appropriate modeling approach and in deciding if transformations are needed.
Step 4: Checking for Stationarity
Stationarity is a key assumption in many time series models (ARIMA, etc.). A stationary series has constant mean and variance over time.
- Visual inspection: Does the series look "stable" around a mean?
- Statistical tests: Augmented Dickey-Fuller (ADF) or KPSS test.
from statsmodels.tsa.stattools import adfuller
adf_result = adfuller(data['measurement'].dropna())
print(f'ADF Statistic: {adf_result[0]}')
print(f'p-value: {adf_result[1]}')
- If the p-value is less than 0.05, we reject the null hypothesis (the series is stationary).
- If not, differencing or detrending may be required.
Step 5: Transformations and Differencing
If the series is non-stationary, transformations can help:
- Log transform: Useful for stabilizing variance.
- First differencing: Subtract the previous value to remove trend.
- Seasonal differencing: Subtract the value from a previous period (e.g., 24 hours ago for daily).
# Log transform
data['measurement_log'] = np.log(data['measurement'] + 1e-6)
# First difference
data['measurement_log_diff'] = data['measurement_log'].diff()
# Seasonal difference (e.g., 24 for daily, 168 for weekly)
data['seasonal_diff'] = data['measurement_log'].diff(24)
After each transformation, recheck stationarity using the ADF test.
Step 6: Autocorrelation and Partial Autocorrelation (ACF/PACF)
Analyzing autocorrelation helps to identify the order of AR (autoregressive) and MA (moving average) terms for models like ARIMA.
- ACF (Autocorrelation Function): Measures correlation of current value with its past values.
- PACF (Partial Autocorrelation): Measures correlation of current value with past values, controlling for intermediate lags.
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
plot_acf(data['measurement_log_diff'].dropna(), lags=50)
plt.show()
plot_pacf(data['measurement_log_diff'].dropna(), lags=50)
plt.show()
Interpret peaks in ACF/PACF to tentatively choose AR and MA orders.
Step 7: Creating Lag Features and Other Predictors
Lag features capture dependencies on previous observations, which is vital for time series forecasting.
- Create lags: For hourly data, lags of 1, 24, 168 (weekly), etc., can be useful.
- Seasonal indicators: Hour of day, day of week, month, etc.
- Rolling statistics: Rolling mean, std dev over various windows.
# Lag features
for lag in [1, 24, 168]:
data[f'lag_{lag}'] = data['measurement'].shift(lag)
# Temporal features
data['hour'] = data.index.hour
data['day_of_week'] = data.index.dayofweek
# Rolling mean
data['rolling_mean_24'] = data['measurement'].rolling(window=24).mean()
Such features are especially useful for tree-based models and neural networks.
Step 8: Exploring Relationships with Other Series
If other sensors or exogenous variables are available, check for cross-correlations.
- Cross-correlation plots to see if other series help in forecasting.
- Granger causality tests to determine if one series helps predict another.
# Assuming 'other_sensor' is another column
from statsmodels.tsa.stattools import ccf
cross_corr = ccf(data['measurement'].dropna(), data['other_sensor'].dropna())
plt.plot(cross_corr)
plt.title('Cross-correlation between sensors')
plt.show()
Step 9: Train / Validation Split
For time series, random splits are not suitable. You must split chronologically to ensure that validation data is always after training data.
- Last 7 days/hours: Hold out the last few days/hours for validation/testing.
- Walk-forward validation: Iteratively train and test on expanding/rolling windows.
# Hold out the last 24 hours for validation (since forecasting next 24 hours)
train = data.iloc[:-24]
test = data.iloc[-24:]
This simulates the real-world scenario where you predict future values from past data.
Step 10: Building a Forecasting Model
Now, select and train a suitable forecasting model. Options include:
- ARIMA/SARIMA: For univariate series with autocorrelation and seasonality.
- Exponential Smoothing (ETS): For trend/seasonality, especially when patterns are stable.
- Prophet: Facebook’s model, robust to missing data and outliers.
- Machine Learning Models: Random Forest, XGBoost, LSTM, etc., when using multiple features/series.
from statsmodels.tsa.statespace.sarimax import SARIMAX
# Example: SARIMA model for hourly data with weekly seasonality
model = SARIMAX(train['measurement'], order=(1,1,1), seasonal_order=(1,1,1,24))
model_fit = model.fit()
forecast = model_fit.forecast(steps=24)
Tune hyperparameters using validation set performance (e.g., RMSE, MAE).
Step 11: Residual Diagnostics
After fitting the model, check the residuals (prediction errors) for:
- Normality: Residuals should be approximately normally distributed.
- No autocorrelation: Residuals should show no significant autocorrelation (use ACF plots, Ljung-Box test).
- Homoskedasticity: Constant variance over time.
residuals = test['measurement'] - forecast
plt.hist(residuals, bins=20)
plt.title('Residuals Histogram')
plt.show()
from statsmodels.stats.diagnostic import acorr_ljungbox
lb_test = acorr_ljungbox(residuals, lags=[10])
print(lb_test)
If residuals show structure, revisit feature engineering or try more complex models.
Summary Table: End-to-End Steps
| Step | Description | Purpose |
|---|---|---|
| 1. Visualization | Plot and summarize data | Spot patterns and issues |
| 2. Missing Values/Outliers | Detect and handle anomalies | Data quality, avoid bias |
| 3. Trend/Seasonality | Decompose series | Guide model choice |
| 4. Stationarity | Statistical tests | Model assumptions |
| 5. Transformations | Log/differencing | Stabilize series |
| 6. ACF/PACF | Plot correlations | Select lag orders |
| 7. Lag Features | Feature engineering | Model enhancement |
| 8. Relationships | Cross-series analysis | Leverage external data |
| 9. Train/Validation Split | Chronological split | Reliable evaluation |
| 10. Forecast Model | Model selection and training | Make predictions |
| 11. Residual Diagnostics | Analyze errors | Model validation |
2. Probability Puzzle: Deck of Cards
Interview Question
Given a deck of cards, 10 cards are removed randomly, what is the probability the next card is red?
Understanding the Problem
A standard deck contains 52 cards: 26 red (hearts and diamonds) and 26 black (spades and clubs). We remove 10 cards at random (without looking at their color), and then draw the next card. What is the probability that it is red?
Step 1: Setting Up the Problem
Let’s denote:
- Total cards: 52
- Red cards: 26
- Cards removed: 10 (unknown color)
- Cards remaining: 42
The challenge is that we don't know how many of the removed cards were red. We need to calculate the expected probability that the next card is red, averaging over all possible ways the 10 cards could have been removed.
At first glance, it might seem that the answer depends on how many red cards were actually removed. However, since the 10 cards are removed randomly (with no knowledge of their composition), the situation is symmetric for red and black cards. This is a classic probability scenario where the linearity of expectation and symmetry play a crucial role.
Let’s define a random variable \( X \) as the number of red cards left in the deck after 10 cards are removed. The probability that the next card drawn is red is then:
\[ P(\text{red}) = \frac{\mathbb{E}[X]}{42} \]
Where \( \mathbb{E}[X] \) is the expected number of red cards remaining.
Step 3: Computing the Expected Number of Red Cards Remaining
Let's use the concept of expected value. Initially, there are 26 red cards in a deck of 52. We remove 10 cards at random.
For each red card, the probability that it is not among the 10 cards removed is:
\[ P(\text{a specific red card remains}) = 1 - P(\text{it is among the 10 removed}) \]
The probability that a specific card is among the 10 removed is \( \frac{10}{52} \), so the probability it remains is \( \frac{42}{52} \).
But, more generally, the expected number of red cards remaining is:
\[ \mathbb{E}[X] = 26 \times \frac{\text{number of remaining cards}}{\text{total number of cards}} = 26 \times \frac{42}{52} = 21 \]
Alternatively, you can see this by considering that each card has an equal chance of being removed, so the expected number of red cards removed is \( 10 \times \frac{26}{52} = 5 \), leaving \( 26 - 5 = 21 \) red cards on average.
Step 4: Calculating the Probability
Now, the probability that the next card is red (averaged over all possible compositions of the remaining deck) is:
\[ P(\text{next card is red}) = \frac{\mathbb{E}[\text{Number of red cards remaining}]}{\text{Cards remaining}} = \frac{21}{42} = \frac{1}{2} \]
Therefore, the answer is: 1/2 or 50%.
Step 5: Formal Solution Using Conditional Probability
Let’s formalize the calculation using conditional probability.
Let \( R \) be the number of red cards remaining after 10 random removals. The probability that the next card is red is:
\[ P(\text{red} \mid R) = \frac{R}{42} \]
But since \( R \) is itself a random variable (since we don’t know how many red cards were removed), the overall probability is:
\[ P(\text{red}) = \sum_{r=0}^{26} P(\text{red} \mid R = r) \cdot P(R = r) = \sum_{r=0}^{26} \frac{r}{42} \cdot P(R = r) = \frac{1}{42} \sum_{r=0}^{26} r \cdot P(R = r) = \frac{\mathbb{E}[R]}{42} \]
As shown above, \( \mathbb{E}[R] = 21 \), so \( P(\text{red}) = \frac{21}{42} = \frac{1}{2} \).
Step 6: Intuitive Explanation with Hypergeometric Distribution
For completeness, let's connect this to the hypergeometric distribution:
If we removed \( k \) red cards among the 10 removed, then \( 26 - k \) red cards are left among 42 cards. The probability that we removed exactly \( k \) red cards is:
\[ P(\text{removed } k \text{ red}) = \frac{{26 \choose k} {26 \choose 10 - k}}{{52 \choose 10}} \]
Given \( k \) red cards removed, the chance the next card is red is \( \frac{26 - k}{42} \).
So, the overall probability is:
\[ P(\text{red}) = \sum_{k=0}^{10} \frac{26 - k}{42} \cdot \frac{{26 \choose k} {26 \choose 10 - k}}{{52 \choose 10}} = \frac{1}{42} \sum_{k=0}^{10} (26 - k) {26 \choose k} {26 \choose 10 - k} / {52 \choose 10} \]
But as shown earlier, the expectation works out to 21, so the answer is still \( \frac{21}{42} = \frac{1}{2} \).
Step 7: Generalization
This result is a special case of a general principle: If you remove some cards at random from a deck, the probability that the next card is of a given type is the same as its original proportion in the deck.
If you remove \( n \) cards from a deck with \( N \) cards, \( r \) of which are of a specific type (say, red), the probability the next card is of that type is always \( \frac{r}{N} \).
This is a powerful (and counterintuitive!) result in probability, and is often a favorite in quant interviews for testing both intuition and understanding of expectation.
Conclusion
Graviton's quant interviews are designed to probe not only your mathematical and programming skills, but also your ability to reason logically and explain your decisions under uncertainty. In the time series forecasting question, we saw the importance of disciplined, step-by-step analysis: from visualization and cleaning, through statistical testing and feature engineering, to model selection and diagnostics. In the probability puzzle, we demonstrated how linearity of expectation and symmetry can greatly simplify seemingly complex problems.
Mastering these approaches, and being able to justify every analytical step, will put you in a strong position for quant interviews at top firms like Graviton.
Further Reading and Practice
- Time Series Analysis: "Forecasting: Principles and Practice" by Rob J Hyndman & George Athanasopoulos
- Probability Puzzles: "Fifty Challenging Problems in Probability with Solutions" by Frederick Mosteller
- Python for Data Analysis: "Python for Data Analysis" by Wes McKinney
Frequently Asked Questions
| Question | Answer |
|---|---|
| Does the probability change if I know the colors of the removed cards? | Yes. If you know how many red cards were removed, the probability becomes \(\frac{\text{remaining red}}{\text{remaining cards}}\). |
| What if the deck isn't standard (e.g., includes jokers)? | Adjust the total and red card counts accordingly; the reasoning remains the same. |
| Is the time series procedure the same for financial data? | The principles are the same, but financial data may require additional steps (e.g., volatility modeling, cointegration analysis). |
| What if the time series has gaps? | Impute missing data carefully; if the gaps are systematic, more advanced imputation or model-based approaches may be needed. |
Summary
- For time series forecasting, follow a systematic approach: visualize, clean, analyze, engineer features, choose models, and validate.
- For probability puzzles involving random removals, use symmetry and linearity of expectation to simplify calculations.
- Being able to explain your reasoning is as important as getting the correct answer in quant interviews.
If you're preparing for quant interviews at firms like Graviton, practice these types of questions regularly. Develop the habit of breaking down complex problems, justifying each step, and always checking your assumptions.
Happy problem solving!