1. Promise
One-sentence promise
After this lecture, you can state model assumptions precisely, identify failure regimes, and translate both into controls, monitoring, and safe-usage language.
End tag line
A model is a conditional statement, not a fact.
2. Learning objectives
After reading this lecture, you will be able to:
- Write explicit assumptions that a model relies on (data, time, regime, behaviour).
- Distinguish assumptions from implementation choices.
- Identify what breaks models: regime shifts, liquidity changes, missing data, and operational outages.
- Convert assumptions and limitations into:
- safe usage statements,
- monitoring rules,
- escalation triggers.
3. Conceptual core
3.1 What “assumptions” mean in model risk
An assumption is a condition under which the model’s outputs are meaningful.
Formally, your model produces: but this statement is only useful under a set of conditions :
Assumptions are often implicit. Model risk work makes them explicit.
Validator sentence
If assumptions are implicit, misuse is guaranteed.
3.2 Categories of assumptions (practical taxonomy)
(1) Data assumptions
- timestamps are correct and monotonic,
- no duplicates,
- corporate actions are handled consistently,
- missing data rate is within known bounds,
- vendor restatements are tracked.
(2) Target and horizon assumptions
- label definition matches business decision,
- evaluation horizon matches deployment horizon,
- no leakage in target construction.
(3) Statistical assumptions
- stationarity “enough” for the chosen method,
- correlation structure is stable enough,
- error distribution is not dominated by rare events outside the training coverage.
(4) Market and microstructure assumptions
- liquidity is sufficient for execution at assumed costs,
- spreads and slippage are within bounds,
- market impact is not dominant.
(5) Operational assumptions
- data arrives on time,
- latency budget is met,
- model is refreshed at the assumed cadence,
- fallback logic exists and is tested.
Slide-ready sentence
Assumptions are not academic. They are deployment constraints.
3.3 What breaks models (limitations you must name)
(1) Regime shifts
- volatility regime changes,
- policy shifts,
- structural breaks in correlation,
- behaviour changes in flow/clients.
Symptom - error spikes in specific periods, - unstable feature importance, - fold-by-fold performance divergence.
(2) Liquidity and execution changes
- spreads widen,
- depth disappears,
- fill rates drop,
- slippage jumps.
Symptom - paper alpha does not survive trading.
(3) Missing data and outages
- gaps in market data,
- stale quotes,
- vendor outages,
- partial feed failures.
Symptom - features become NaN or stale, - model uses forward-filled data without noticing, - outputs become overconfident.
(4) Coverage and extrapolation
- using the model on instruments / regimes not in training coverage,
- new product launches,
- changed tick size or trading hours.
Symptom - predictions become systematically biased.
Validator sentence
Most breakages are not “model mistakes”. They are “assumption violations”.
4. Translating assumptions into safe-usage language
A safe-usage statement has three parts:
- Intended scope
- “This model is designed for …”
- Known limitations
- “It may underperform when …”
- Operational controls
- “Do not use when …; fallback is …; escalate when …”
Example:
- Intended scope: “Daily forecasting for liquid large-cap equities.”
- Limitations: “Not reliable in extreme volatility and illiquid conditions.”
- Controls: “Disable when spread > threshold or missingness > threshold.”
5. Controls: what you monitor because of assumptions
Map each assumption to:
- a check (invariant / metric),
- a threshold,
- an action (warn, stop, fallback, retrain).
Examples:
- Assumption: monotonic timestamps
- check:
index.is_monotonic_increasing - action: hard fail
- check:
- Assumption: missing rate below 1%
- check: missingness per feature per day
- action: fallback features or stop
- Assumption: liquidity stable
- check: spread, depth proxy, slippage
- action: reduce exposure or stop trading
6. Control lens
In control, assumptions define the operating envelope: - model validity region, - noise bounds, - actuator limits.
Outside the envelope, you switch mode. Finance is the same: - disable, - hedge, - reduce risk, - retrain.
7. Python lab (assumption checks + “breakage” demonstration)
This lab does two things:
- Implements a minimal assumption checklist.
- Demonstrates a model that looks good in one regime and breaks in another.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
rng = np.random.default_rng(0)
# ---------------------------------------------------------
# 1) Simulate two regimes and a simple forecasting task
# ---------------------------------------------------------
T = 600
t = np.arange(T)
# Regime A: low vol, stable dynamics
sigma = np.ones(T) * 0.7
phi = np.ones(T) * 0.3
# Regime B: high vol, changed dynamics (break assumption of stability)
sigma[T//2:] = 1.6
phi[T//2:] = -0.1
y = np.zeros(T)
for k in range(1, T):
y[k] = phi[k] * y[k-1] + sigma[k] * rng.normal()
idx = pd.date_range("2024-01-01", periods=T, freq="B")
df = pd.DataFrame({"y": y}, index=idx)
# Create features and 1-step ahead target
df["lag1"] = df["y"].shift(1)
df["y_target"] = df["y"].shift(-1)
df = df.dropna()
# ---------------------------------------------------------
# 2) Assumption checklist (minimal)
# ---------------------------------------------------------
def assumption_checks(d: pd.DataFrame) -> dict:
checks = {}
checks["monotonic_index"] = bool(d.index.is_monotonic_increasing)
checks["unique_index"] = bool(d.index.is_unique)
checks["no_nans_in_features"] = bool(~d[["lag1", "y_target"]].isna().any().any())
return checks
checks = assumption_checks(df)
print("Assumption checks:", checks)
# ---------------------------------------------------------
# 3) Fit a simple model on regime A only, test on regime B
# y_{t+1} = a + b * y_t (using lag1)
# ---------------------------------------------------------
split = len(df) // 2
train = df.iloc[:split]
test = df.iloc[split:]
Xtr = np.column_stack([np.ones(len(train)), train["lag1"].values])
ytr = train["y_target"].values
beta = np.linalg.lstsq(Xtr, ytr, rcond=None)[0]
Xte = np.column_stack([np.ones(len(test)), test["lag1"].values])
yhat = Xte @ beta
ytrue = test["y_target"].values
rmse = float(np.sqrt(np.mean((ytrue - yhat)**2)))
# RMSE by rolling window to show breakage
err = (ytrue - yhat)**2
roll_rmse = pd.Series(err, index=test.index).rolling(40).mean().apply(np.sqrt)
plt.figure(figsize=(8, 3.8))
plt.plot(df.index, df["y"], label="y")
plt.axvline(df.index[split], linestyle="--", label="regime change")
plt.title("Two regimes: dynamics and volatility change")
plt.xlabel("date")
plt.ylabel("y")
plt.legend()
plt.tight_layout()
plt.show()
plt.figure(figsize=(8, 3.8))
plt.plot(test.index, roll_rmse.values, label="rolling RMSE (40)")
plt.title(f"Model trained in regime A breaks in regime B (test RMSE={rmse:.2f})")
plt.xlabel("date")
plt.ylabel("RMSE")
plt.legend()
plt.tight_layout()
plt.show()
print("Test RMSE:", rmse)What to say after the lab
- “The model was trained under an implicit stability assumption.”
- “The regime change violated that assumption.”
- “Fold-by-fold or rolling-window error shows the failure clearly.”
- “Controls should detect drift and restrict usage or trigger retraining.”
8. Mini-exercises
- Add a missing data block and make the checklist fail.
- Add a liquidity proxy feature and set a “do not trade” threshold.
- Write a safe-usage statement in three lines for this model.
9. Summary
- Assumptions define when model outputs are meaningful.
- Limitations are the named ways assumptions can fail.
- Regimes, liquidity, and missing data are the primary breakage sources.
- Controls convert assumptions into checks, thresholds, and actions.
- Good model risk work is explicit, operational, and testable.