8  Chapter 5. Martingales in Discrete Time

8.1 Learning Goals

By the end of this chapter, students should be able to:

  • describe information flow using a filtration \((\mathcal F_n)_{n\ge 0}\);
  • compute conditional expectations in finite probability spaces;
  • define martingales, submartingales, and supermartingales in discrete time;
  • explain why discounted asset prices are martingales under a risk-neutral measure;
  • use the martingale property to price contingent claims by conditional expectation;
  • connect dynamic replication in a binomial tree with martingale pricing;
  • state and apply the optional stopping principle in simple bounded settings;
  • interpret Doob decomposition as predictable drift plus martingale noise;
  • implement discrete-time martingale checks and pricing recursions in Python;
  • use AI tools to audit conditional-expectation calculations, assumptions, and code.

The central mathematical idea of risk-neutral pricing is simple to state:

\[ \mathbb E^{\mathbb Q}\left[\widetilde S_{n+1}\mid \mathcal F_n\right]=\widetilde S_n. \]

The discounted price \(\widetilde S_n=S_n/B_n\) has no predictable drift under the pricing measure \(\mathbb Q\). This does not say that investors are risk-neutral in the real world. It says that after changing from the physical probability \(\mathbb P\) to a pricing probability \(\mathbb Q\), no-arbitrage prices can be computed by conditional expectations.

8.2 5.1 Why Martingales Appear in Finance

In Chapters 3 and 4, we priced contingent claims in one-period and multi-period binomial models. The formulas looked like discounted expectations under a special probability measure:

\[ V_0=\frac{1}{R^N}\mathbb E^{\mathbb Q}[H]. \]

For a claim \(H\) paid at time \(N\), this formula is correct at time \(0\). But financial pricing is not only a time-zero problem. At each intermediate date \(n\), a trader observes some information and must update the value of the claim. Therefore the correct dynamic formula is

\[ V_n=R^{-(N-n)}\mathbb E^{\mathbb Q}[H\mid \mathcal F_n]. \]

Equivalently, if \(B_n=R^n\) is the bank account and \(\widetilde V_n=V_n/B_n\) is the discounted derivative value, then

\[ \widetilde V_n=\mathbb E^{\mathbb Q}\left[\widetilde H\mid \mathcal F_n\right], \qquad \widetilde H=\frac{H}{B_N}. \]

The process \((\widetilde V_n)_{n=0}^N\) is a martingale. This is the mathematical form of the statement:

A fairly priced discounted asset has no predictable gain.

This chapter develops the discrete-time martingale language carefully. We will work mostly in finite probability spaces, where every conditional expectation can be computed as an average over states. This keeps the measure-theoretic ideas clean while still preparing for Brownian motion, stochastic integration, and continuous-time martingale pricing later in the book.

8.3 5.2 Probability Space and Information

A discrete-time financial model begins with a probability space

\[ (\Omega,\mathcal F,\mathbb P), \]

where:

  • \(\Omega\) is the set of possible scenarios;
  • \(\mathcal F\) is the collection of events whose probabilities are defined;
  • \(\mathbb P\) is the physical probability measure.

In a finite model, \(\Omega=\{\omega_1,\ldots,\omega_m\}\) and probabilities are simply positive weights \(p_i=\mathbb P(\{\omega_i\})\) satisfying

\[ \sum_{i=1}^m p_i=1. \]

A random variable is a function

\[ X:\Omega\to \mathbb R. \]

The expectation of \(X\) is

\[ \mathbb E[X]=\sum_{\omega\in\Omega}X(\omega)\mathbb P(\omega). \]

In finance, what matters is not only what can happen, but also when information is revealed.

8.3.1 Definition 5.1: Filtration

A filtration is an increasing sequence of sigma-algebras

\[ \mathcal F_0\subseteq \mathcal F_1\subseteq\cdots\subseteq \mathcal F_N\subseteq \mathcal F. \]

The sigma-algebra \(\mathcal F_n\) represents the information available at time \(n\).

In a finite tree model, \(\mathcal F_n\) tells us which node of the tree has been reached by time \(n\). At time \(0\), there is no uncertainty resolved, so \(\mathcal F_0\) usually contains only the trivial events \(\varnothing\) and \(\Omega\). At maturity \(N\), all relevant uncertainty may be revealed, so \(\mathcal F_N\) may be the full sigma-algebra.

8.3.2 Example 5.1: Two-step binomial information

Let \(\Omega=\{UU,UD,DU,DD\}\) be the four possible two-step paths of a binomial stock model. At time \(0\), the investor cannot distinguish any paths:

\[ \mathcal F_0=\{\varnothing,\Omega\}. \]

At time \(1\), the investor knows whether the first move was up or down. Thus \(\Omega\) is partitioned into two information cells:

\[ \{UU,UD\},\qquad \{DU,DD\}. \]

At time \(2\), the investor knows the full path. The information cells are singletons:

\[ \{UU\},\{UD\},\{DU\},\{DD\}. \]

8.4 5.3 Adapted Processes

A stochastic process is a sequence of random variables

\[ X_0,X_1,\ldots,X_N. \]

In financial applications, \(X_n\) may represent a stock price, portfolio value, discounted price, cumulative gain, trading strategy, or derivative value.

8.4.1 Definition 5.2: Adapted process

A process \((X_n)_{n=0}^N\) is adapted to the filtration \((\mathcal F_n)_{n=0}^N\) if \(X_n\) is \(\mathcal F_n\)-measurable for every \(n\).

The phrase “\(X_n\) is \(\mathcal F_n\)-measurable” means that the value of \(X_n\) is known using the information available at time \(n\). In a tree model, this means that \(X_n\) is constant on every node at time \(n\).

8.4.2 Example 5.2: Stock price is adapted

In a two-step binomial model, suppose

\[ S_0=100, \qquad u=1.2, \qquad d=0.8. \]

At time \(1\), the stock price is \(120\) on paths \(UU,UD\) and \(80\) on paths \(DU,DD\). Since these values are constant on the time-\(1\) information cells, \(S_1\) is \(\mathcal F_1\)-measurable.

At time \(2\), each path has its own final value. Therefore \(S_2\) is \(\mathcal F_2\)-measurable.

A trading strategy must also be adapted or predictable, depending on convention. A trader cannot choose today’s position using tomorrow’s information. This simple restriction is one of the most important modeling assumptions in no-arbitrage theory.

8.5 5.4 Conditional Expectation in Finite Models

Conditional expectation is the mathematical tool for updating fair values when information changes.

8.5.1 Definition 5.3: Conditional expectation in a finite partition

Suppose \(\mathcal G\) corresponds to a finite partition

\[ A_1,\ldots,A_k \]

of \(\Omega\), where each \(A_j\) has positive probability. The conditional expectation \(\mathbb E[X\mid\mathcal G]\) is the random variable that is constant on each cell \(A_j\) and satisfies

\[ \mathbb E[X\mid\mathcal G](\omega) = \frac{\sum_{\eta\in A_j}X(\eta)\mathbb P(\eta)}{\mathbb P(A_j)}, \qquad \omega\in A_j. \]

Thus conditional expectation is obtained by averaging only over the scenarios that remain possible given the current information.

8.5.2 Example 5.3: Conditional expectation on a two-step tree

Let \(\Omega=\{UU,UD,DU,DD\}\) with probabilities

\[ \mathbb P(UU)=0.36, \quad \mathbb P(UD)=0.24, \quad \mathbb P(DU)=0.24, \quad \mathbb P(DD)=0.16. \]

Let \(X\) be a payoff with values

\[ X(UU)=44, \quad X(UD)=0, \quad X(DU)=0, \quad X(DD)=0. \]

At time \(1\), the information cells are

\[ A_U=\{UU,UD\}, \qquad A_D=\{DU,DD\}. \]

Then

\[ \mathbb E[X\mid\mathcal F_1](UU) = \mathbb E[X\mid\mathcal F_1](UD) = \frac{44(0.36)+0(0.24)}{0.36+0.24}=26.4. \]

On the down cell,

\[ \mathbb E[X\mid\mathcal F_1](DU) = \mathbb E[X\mid\mathcal F_1](DD)=0. \]

Conditional expectation satisfies several identities that are essential in mathematical finance.

8.5.3 Theorem 5.1: Basic properties of conditional expectation

Let \(X,Y\) be integrable random variables and let \(\mathcal G\subseteq \mathcal F\) be a sigma-algebra. Then:

  1. Linearity:

    \[ \mathbb E[aX+bY\mid\mathcal G] =a\mathbb E[X\mid\mathcal G]+b\mathbb E[Y\mid\mathcal G]. \]

  2. Taking out what is known: if \(Z\) is \(\mathcal G\)-measurable, then

    \[ \mathbb E[ZX\mid\mathcal G]=Z\mathbb E[X\mid\mathcal G]. \]

  3. Tower property: if \(\mathcal H\subseteq\mathcal G\), then

    \[ \mathbb E[\mathbb E[X\mid\mathcal G]\mid\mathcal H] =\mathbb E[X\mid\mathcal H]. \]

  4. Total expectation:

    \[ \mathbb E[\mathbb E[X\mid\mathcal G]]=\mathbb E[X]. \]

The tower property is especially important. It says that updating in two steps is consistent with updating directly. In asset pricing, this means that today’s price obtained through tomorrow’s price must agree with today’s price obtained directly from the terminal payoff.

8.6 5.5 Martingales, Submartingales, and Supermartingales

We can now define the central object.

8.6.1 Definition 5.4: Discrete-time martingale

Let \((X_n)_{n=0}^N\) be an adapted process with \(\mathbb E[|X_n|]<\infty\) for every \(n\). The process is a martingale with respect to \((\mathcal F_n)\) and probability measure \(\mathbb P\) if

\[ \mathbb E[X_{n+1}\mid\mathcal F_n]=X_n, \qquad n=0,1,\ldots,N-1. \]

A martingale is a fair game in the following precise sense: given the information available now, the expected next value equals the current value.

8.6.2 Definition 5.5: Submartingale and supermartingale

An adapted integrable process \((X_n)\) is a submartingale if

\[ \mathbb E[X_{n+1}\mid\mathcal F_n]\ge X_n, \]

and a supermartingale if

\[ \mathbb E[X_{n+1}\mid\mathcal F_n]\le X_n. \]

A submartingale has nonnegative conditional drift. A supermartingale has nonpositive conditional drift. Martingales are the zero-drift boundary case.

8.6.3 Example 5.4: Random walk martingale

Let \(\xi_1,\xi_2,\ldots\) be independent random variables with

\[ \mathbb P(\xi_k=1)=\mathbb P(\xi_k=-1)=\frac12. \]

Define

\[ X_n=\sum_{k=1}^n\xi_k, \qquad X_0=0. \]

Let \(\mathcal F_n\) be the information generated by \(\xi_1,\ldots,\xi_n\). Then

\[ \mathbb E[X_{n+1}\mid\mathcal F_n] = \mathbb E[X_n+\xi_{n+1}\mid\mathcal F_n] =X_n+\mathbb E[\xi_{n+1}] =X_n. \]

Therefore \((X_n)\) is a martingale.

A martingale does not mean that paths are constant. A martingale can move up and down randomly. The condition is about the conditional expectation of the next value, not about deterministic equality from one time to the next.

8.7 5.6 Discounted Prices and Risk-Neutral Martingales

Let \(S_n\) be a stock price and let \(B_n\) be the bank account. If the risk-free gross return is constant \(R=1+r\), then

\[ B_n=R^n. \]

The discounted stock price is

\[ \widetilde S_n=\frac{S_n}{B_n}=\frac{S_n}{R^n}. \]

In a no-arbitrage model, there exists a probability measure \(\mathbb Q\) such that discounted traded asset prices are martingales:

\[ \mathbb E^{\mathbb Q}[\widetilde S_{n+1}\mid \mathcal F_n] =\widetilde S_n. \]

This measure \(\mathbb Q\) is called a risk-neutral measure or an equivalent martingale measure.

8.7.1 Theorem 5.2: Binomial discounted stock is a martingale under \(\mathbb Q\)

Consider a binomial model with stock dynamics

\[ S_{n+1}=\begin{cases} u S_n, & \text{up},\\ dS_n, & \text{down},\end{cases} \]

and bank account \(B_n=R^n\). Assume

\[ d<R<\nu. \]

Define

\[ q=\frac{R-d}{\nu-d}. \]

If each next up move has conditional probability \(q\) under \(\mathbb Q\), then the discounted stock price \(\widetilde S_n=S_n/R^n\) is a \(\mathbb Q\)-martingale.

Proof. At time \(n\), the stock price \(S_n\) is known. Therefore

\[ \mathbb E^{\mathbb Q}[S_{n+1}\mid\mathcal F_n] =q\nu S_n+(1-q)dS_n =S_n\left(q\nu+(1-q)d\right). \]

By the definition of \(q\),

\[ q\nu+(1-q)d=R. \]

Thus

\[ \mathbb E^{\mathbb Q}[S_{n+1}\mid\mathcal F_n]=RS_n. \]

Dividing by \(B_{n+1}=R^{n+1}\) gives

\[ \mathbb E^{\mathbb Q}\left[\frac{S_{n+1}}{R^{n+1}}\mid\mathcal F_n\right] = \frac{RS_n}{R^{n+1}} = \frac{S_n}{R^n} =\widetilde S_n. \]

Therefore \(\widetilde S\) is a martingale under \(\mathbb Q\).

The physical probability \(p\) determines real-world statistical behavior. The risk-neutral probability \(q\) determines no-arbitrage prices. They are generally not equal.

8.8 5.7 Pricing Claims by Martingales

Let \(H\) be a contingent claim paid at time \(N\). For example, for a European call option,

\[ H=(S_N-K)^+. \]

If the bank account is \(B_n=R^n\), the discounted payoff is

\[ \widetilde H=\frac{H}{B_N}. \]

The no-arbitrage value process is

\[ V_n =B_n\mathbb E^{\mathbb Q}\left[\frac{H}{B_N}\mid\mathcal F_n\right]. \]

Equivalently,

\[ \widetilde V_n =\frac{V_n}{B_n} = \mathbb E^{\mathbb Q}[\widetilde H\mid\mathcal F_n]. \]

8.8.1 Theorem 5.3: Discounted derivative prices are martingales

Let

\[ \widetilde V_n=\mathbb E^{\mathbb Q}[\widetilde H\mid\mathcal F_n], \qquad n=0,1,\ldots,N. \]

Then \((\widetilde V_n)\) is a \(\mathbb Q\)-martingale.

Proof. Using the tower property,

\[ \mathbb E^{\mathbb Q}[\widetilde V_{n+1}\mid\mathcal F_n] = \mathbb E^{\mathbb Q}\left[ \mathbb E^{\mathbb Q}[\widetilde H\mid\mathcal F_{n+1}] \mid\mathcal F_n \right] = \mathbb E^{\mathbb Q}[\widetilde H\mid\mathcal F_n] =\widetilde V_n. \]

Hence the discounted value process is a martingale.

This theorem explains why pricing is naturally recursive. If a claim is fairly priced at all future nodes, then today’s discounted value is the conditional average of tomorrow’s discounted value.

8.9 5.8 Worked Example: Two-Step European Call

Consider a two-step binomial model with

\[ S_0=100, \qquad u=1.2, \qquad d=0.8, \qquad R=1.05, \qquad K=100. \]

The risk-neutral probability is

\[ q=\frac{R-d}{\nu-d}=\frac{1.05-0.8}{1.2-0.8}=0.625. \]

The terminal stock prices are

\[ S_2(UU)=144, \qquad S_2(UD)=S_2(DU)=96, \qquad S_2(DD)=64. \]

The European call payoff is

\[ H=(S_2-K)^+, \]

so

\[ H(UU)=44, \qquad H(UD)=H(DU)=H(DD)=0. \]

At time \(1\), the option value after an up move is

\[ V_1(U) =\frac{1}{R}\left(q\cdot 44+(1-q)\cdot 0\right) =\frac{0.625\cdot 44}{1.05} \approx 26.1905. \]

After a down move,

\[ V_1(D)=0. \]

At time \(0\),

\[ V_0 =\frac{1}{R}\left(qV_1(U)+(1-q)V_1(D)\right) \approx \frac{0.625\cdot 26.1905}{1.05} \approx 15.5896. \]

Equivalently,

\[ V_0 =\frac{1}{R^2}\mathbb E^{\mathbb Q}[H] = \frac{1}{1.05^2}\left(44q^2\right) \approx 15.5896. \]

The equality of these two calculations is an example of the tower property.

8.10 5.9 Interactive Demo: Martingale Versus Drift

The next activity compares three processes on a binomial tree:

  1. the stock price \(S_n\) under the physical probability \(p\);
  2. the discounted stock price \(\widetilde S_n=S_n/R^n\) under \(\mathbb P\);
  3. the discounted stock price under the risk-neutral probability \(q\).

Only the third process is guaranteed to have zero conditional drift.

8.10.1 Explore conditional drift in a one-step binomial model

Move the sliders and compare the physical probability \(p\) with the risk-neutral probability \(q=(R-d)/(u-d)\). The plot shows the one-step conditional expected change of the discounted stock price.

8.11 5.10 Python Example: Conditional Expectation on a Tree

The following code computes conditional expectations in the two-step example directly from path probabilities.

import numpy as np
import pandas as pd

# Two-step path space
paths = ["UU", "UD", "DU", "DD"]
q = 0.625
prob_Q = {
    "UU": q * q,
    "UD": q * (1 - q),
    "DU": (1 - q) * q,
    "DD": (1 - q) * (1 - q),
}

# Terminal payoff of a European call in the example
H = {"UU": 44.0, "UD": 0.0, "DU": 0.0, "DD": 0.0}

# Time-1 information cells
cells_F1 = {
    "U": ["UU", "UD"],
    "D": ["DU", "DD"],
}

def conditional_expectation_on_cells(X, probs, cells):
    values = {}
    for cell_name, states in cells.items():
        total_prob = sum(probs[s] for s in states)
        avg = sum(X[s] * probs[s] for s in states) / total_prob
        for s in states:
            values[s] = avg
    return values

EH_F1 = conditional_expectation_on_cells(H, prob_Q, cells_F1)

pd.DataFrame({
    "path": paths,
    "Q probability": [prob_Q[p] for p in paths],
    "payoff H": [H[p] for p in paths],
    "E_Q[H | F1]": [EH_F1[p] for p in paths],
})
path Q probability payoff H E_Q[H | F1]
0 UU 0.390625 44.0 27.5
1 UD 0.234375 0.0 27.5
2 DU 0.234375 0.0 0.0
3 DD 0.140625 0.0 0.0

Because the payoff is positive only after two up moves, the time-\(1\) conditional expectation is positive after an up move and zero after a down move.

8.12 5.11 Python Example: Checking the Martingale Property

A process is a martingale if the conditional expectation of the next value equals the current value at every node. The following code checks this property for the discounted stock in a binomial model.

S0 = 100.0
u = 1.2
d = 0.8
R = 1.05
q = (R - d) / (u - d)
N = 4

rows = []
for n in range(N):
    for j in range(n + 1):
        S_n = S0 * (u ** j) * (d ** (n - j))
        discounted_now = S_n / (R ** n)
        S_up = u * S_n
        S_down = d * S_n
        discounted_next_expectation = (
            q * S_up / (R ** (n + 1))
            + (1 - q) * S_down / (R ** (n + 1))
        )
        rows.append({
            "time n": n,
            "up moves j": j,
            "discounted current": discounted_now,
            "conditional expected discounted next": discounted_next_expectation,
            "difference": discounted_next_expectation - discounted_now,
        })

pd.DataFrame(rows)
time n up moves j discounted current conditional expected discounted next difference
0 0 0 100.000000 100.000000 0.000000e+00
1 1 0 76.190476 76.190476 0.000000e+00
2 1 1 114.285714 114.285714 0.000000e+00
3 2 0 58.049887 58.049887 -7.105427e-15
4 2 1 87.074830 87.074830 -1.421085e-14
5 2 2 130.612245 130.612245 0.000000e+00
6 3 0 44.228485 44.228485 0.000000e+00
7 3 1 66.342728 66.342728 0.000000e+00
8 3 2 99.514091 99.514091 0.000000e+00
9 3 3 149.271137 149.271137 0.000000e+00

The difference column should be essentially zero, up to floating-point rounding.

8.13 5.12 Martingales and Self-Financing Strategies

A portfolio strategy is called self-financing if all changes in portfolio value come from gains and losses on assets already held, not from adding or withdrawing cash.

In a simple one-stock, one-bank-account model, let \(\Delta_n\) be the number of shares held over the interval from \(n\) to \(n+1\), and let \(\beta_n\) be the number of bank-account units. The portfolio value at time \(n\) is

\[ V_n=\Delta_n S_n+\beta_n B_n. \]

The discounted value is

\[ \widetilde V_n=\frac{V_n}{B_n} =\Delta_n\widetilde S_n+\beta_n. \]

If the strategy is self-financing, then the discounted gains satisfy

\[ \widetilde V_{n+1}-\widetilde V_n =\Delta_n(\widetilde S_{n+1}-\widetilde S_n). \]

Under a risk-neutral measure, \(\widetilde S\) is a martingale. Since \(\Delta_n\) is known at time \(n\),

\[ \mathbb E^{\mathbb Q}[\widetilde V_{n+1}-\widetilde V_n\mid\mathcal F_n] = \Delta_n\mathbb E^{\mathbb Q}[\widetilde S_{n+1}-\widetilde S_n\mid\mathcal F_n] =0. \]

Therefore a self-financing discounted portfolio value is also a martingale, provided the strategy is admissible and integrable.

8.13.1 Theorem 5.4: Self-financing portfolios preserve martingales

Suppose \(\widetilde S\) is a martingale under \(\mathbb Q\). Let \((\Delta_n)\) be a predictable trading strategy, meaning \(\Delta_n\) is known at time \(n\). If the discounted self-financing portfolio satisfies

\[ \widetilde V_{n+1}-\widetilde V_n =\Delta_n(\widetilde S_{n+1}-\widetilde S_n), \]

then \((\widetilde V_n)\) is a martingale under suitable integrability assumptions.

This theorem is the martingale version of the no-free-lunch idea. If discounted asset prices have no predictable drift, then predictable self-financing trading cannot create predictable discounted profit.

8.14 5.13 Optional Stopping: Why Doubling Strategies Do Not Create Arbitrage

A common misunderstanding is that a martingale can be beaten by stopping at the right time. For example, in a fair coin-tossing game, one might try to keep playing until the first win. This can appear to guarantee profit, but it usually requires unbounded losses, unbounded capital, or an unbounded stopping time.

8.14.1 Definition 5.6: Stopping time

A random time \(\tau\) taking values in \(\{0,1,\ldots,N\}\) is a stopping time with respect to \((\mathcal F_n)\) if the event

\[ \{\tau\le n\} \]

belongs to \(\mathcal F_n\) for every \(n\).

The event \(\{\tau\le n\}\) must be decidable using the information available by time \(n\). For example, the first time a stock price exceeds a barrier is a stopping time. The last time before maturity that a stock reaches its maximum is generally not a stopping time, because knowing it requires future information.

8.14.2 Theorem 5.5: Optional stopping in a bounded discrete-time setting

Let \((X_n)_{n=0}^N\) be a martingale and let \(\tau\) be a stopping time taking values in \(\{0,1,\ldots,N\}\). Then

\[ \mathbb E[X_\tau]=\mathbb E[X_0]. \]

The boundedness of the time horizon is important. More general optional stopping theorems require additional assumptions.

Proof. For each \(k\), define

\[ I_k=\mathbf 1_{\{\tau\ge k\}}. \]

Since \(\{\tau\ge k\}\) is known at time \(k-1\), \(I_k\) is \(\mathcal F_{k-1}\)-measurable. We can write the stopped increment sum as

\[ X_\tau-X_0=\sum_{k=1}^N I_k(X_k-X_{k-1}). \]

Taking expectations and using the martingale property,

\[ \mathbb E[I_k(X_k-X_{k-1})] = \mathbb E\left[I_k\mathbb E[X_k-X_{k-1}\mid\mathcal F_{k-1}]\right] =0. \]

Summing over \(k\) gives

\[ \mathbb E[X_\tau-X_0]=0. \]

Therefore \(\mathbb E[X_\tau]=\mathbb E[X_0]\).

In finance, optional stopping supports the idea that a predictable rule for when to stop trading cannot create arbitrage if prices are properly discounted martingales and strategies satisfy admissibility conditions.

8.15 5.14 Interactive Demo: Stopping a Fair Game

The next simulation shows a simple symmetric random walk. We stop the process the first time it reaches an upper barrier, a lower barrier, or a fixed maximum time. With a bounded stopping rule, the average stopped value remains close to the initial value.

8.15.1 Simulate optional stopping for a bounded random walk

8.16 5.15 Python Example: Optional Stopping Simulation

rng = np.random.default_rng(7243)

def stopped_random_walk(upper=5, lower=-5, max_steps=100, rng=None):
    if rng is None:
        rng = np.random.default_rng()
    x = 0
    for n in range(1, max_steps + 1):
        x += 1 if rng.random() < 0.5 else -1
        if x >= upper or x <= lower:
            return x, n
    return x, max_steps

num_sims = 20_000
upper = 5
lower = -5
max_steps = 100

results = np.array([
    stopped_random_walk(upper, lower, max_steps, rng)
    for _ in range(num_sims)
])

stopped_values = results[:, 0]
stopping_times = results[:, 1]

pd.DataFrame({
    "quantity": ["mean stopped value", "standard error", "mean stopping time"],
    "estimate": [
        stopped_values.mean(),
        stopped_values.std(ddof=1) / np.sqrt(num_sims),
        stopping_times.mean(),
    ]
})
quantity estimate
0 mean stopped value 0.016350
1 standard error 0.035226
2 mean stopping time 24.887750

The simulated mean stopped value should be close to zero. The exact value changes with the random seed, but the standard error gives a sense of the Monte Carlo uncertainty.

8.17 5.16 Doob Decomposition: Drift Plus Martingale Noise

Many stochastic processes are not martingales. However, in discrete time, an adapted integrable process can be decomposed into a predictable finite-variation part and a martingale part.

For an adapted process \((X_n)\), define the predictable drift increments

\[ A_{n+1}-A_n = \mathbb E[X_{n+1}-X_n\mid\mathcal F_n], \qquad A_0=0. \]

Then define

\[ M_n=X_n-A_n. \]

The process \(M_n\) is a martingale. Indeed,

\[ \begin{aligned} \mathbb E[M_{n+1}-M_n\mid\mathcal F_n] &=\mathbb E[X_{n+1}-X_n\mid\mathcal F_n] -\mathbb E[A_{n+1}-A_n\mid\mathcal F_n]\\ &=\mathbb E[X_{n+1}-X_n\mid\mathcal F_n] -(A_{n+1}-A_n)\\ &=0. \end{aligned} \]

Therefore

\[ X_n=X_0+M_n+A_n \]

is a decomposition into martingale noise and predictable drift.

8.17.1 Example 5.5: Stock under physical probability

In a binomial model under the physical probability \(p\), the discounted stock satisfies

\[ \mathbb E^{\mathbb P}[\widetilde S_{n+1}-\widetilde S_n\mid\mathcal F_n] =\widetilde S_n\left(\frac{p\nu+(1-p)d}{R}-1\right). \]

Unless

\[ p\nu+(1-p)d=R, \]

this drift is not zero. The Doob decomposition separates this predictable physical drift from the martingale innovation.

8.18 5.17 Python Example: Decomposing a Process

The following simulation decomposes a random walk with drift into predictable drift plus martingale residual.

rng = np.random.default_rng(5110)
num_paths = 5_000
N = 50
p_up = 0.56

# increments are +1 with probability p_up and -1 otherwise
increments = np.where(rng.random((num_paths, N)) < p_up, 1.0, -1.0)
X = np.column_stack([np.zeros(num_paths), increments.cumsum(axis=1)])

# predictable drift per step
mean_increment = 2 * p_up - 1
A = np.arange(N + 1) * mean_increment
M = X - A

summary = pd.DataFrame({
    "time": np.arange(N + 1),
    "E[X_n] empirical": X.mean(axis=0),
    "A_n predictable drift": A,
    "E[M_n] empirical": M.mean(axis=0),
})
summary.tail()
time E[X_n] empirical A_n predictable drift E[M_n] empirical
46 46 5.5712 5.52 0.0512
47 47 5.6716 5.64 0.0316
48 48 5.7884 5.76 0.0284
49 49 5.9180 5.88 0.0380
50 50 6.0376 6.00 0.0376

The empirical mean of \(M_n\) should remain close to zero, while \(A_n\) captures the linear drift.

8.19 5.18 Martingale Pricing and Backward Induction

In a binomial tree, the martingale pricing formula and backward induction are the same method written in two languages.

Suppose a derivative has value \(V_{n+1}^u\) at the up successor node and \(V_{n+1}^d\) at the down successor node. Then the time-\(n\) value is

\[ V_n =\frac{1}{R}\left(qV_{n+1}^u+(1-q)V_{n+1}^d\right). \]

This is exactly the conditional-expectation formula

\[ V_n =\frac{1}{R}\mathbb E^{\mathbb Q}[V_{n+1}\mid\mathcal F_n]. \]

Equivalently,

\[ \frac{V_n}{B_n} =\mathbb E^{\mathbb Q}\left[\frac{V_{n+1}}{B_{n+1}}\mid\mathcal F_n\right]. \]

Thus the discounted derivative value is a martingale.

8.20 5.19 Python Example: Martingale Option-Value Process

The following code computes the full binomial value tree for a European call and verifies the discounted martingale recursion at every node.

def binomial_call_value_tree(S0, K, u, d, R, N):
    q = (R - d) / (u - d)
    stock = []
    value = []

    for n in range(N + 1):
        stock.append(np.array([S0 * (u ** j) * (d ** (n - j)) for j in range(n + 1)]))

    terminal = np.maximum(stock[N] - K, 0.0)
    value = [None] * (N + 1)
    value[N] = terminal

    for n in range(N - 1, -1, -1):
        value[n] = (q * value[n + 1][1:] + (1 - q) * value[n + 1][:-1]) / R

    return stock, value, q

S0 = 100
K = 100
u = 1.2
d = 0.8
R = 1.05
N = 4

stock, value, q = binomial_call_value_tree(S0, K, u, d, R, N)

checks = []
for n in range(N):
    for j in range(n + 1):
        discounted_now = value[n][j] / (R ** n)
        discounted_next_conditional = (
            q * value[n + 1][j + 1] / (R ** (n + 1))
            + (1 - q) * value[n + 1][j] / (R ** (n + 1))
        )
        checks.append({
            "time": n,
            "node j": j,
            "discounted value now": discounted_now,
            "conditional expected discounted next": discounted_next_conditional,
            "difference": discounted_next_conditional - discounted_now,
        })

pd.DataFrame(checks)
time node j discounted value now conditional expected discounted next difference
0 0 0 24.998425 24.998425 0.000000e+00
1 1 0 7.680699 7.680699 8.881784e-16
2 1 1 35.389061 35.389061 7.105427e-15
3 2 0 0.000000 0.000000 0.000000e+00
4 2 1 12.289118 12.289118 0.000000e+00
5 2 2 49.249027 49.249027 0.000000e+00
6 3 0 0.000000 0.000000 0.000000e+00
7 3 1 0.000000 0.000000 0.000000e+00
8 3 2 19.662589 19.662589 0.000000e+00
9 3 3 67.000890 67.000890 0.000000e+00

This computation should show that the discounted derivative value process is a martingale under \(\mathbb Q\).

8.21 5.20 AI-Assisted Learning Components

8.21.1 AI Prompt 5.1: Explain conditional expectation on a tree

Use an AI assistant to explain the following statement in three levels: intuitive, finite-state mathematical, and financial.

\(\mathbb E[X\mid\mathcal F_n]\) is the best estimate of \(X\) using the information available at time \(n\).

Then check whether the explanation clearly distinguishes unconditional expectation from conditional expectation.

8.21.2 AI Prompt 5.2: Audit a martingale proof

Give an AI assistant the proof of Theorem 5.2 and ask:

  1. Where is the no-arbitrage condition \(d<R<u\) used?
  2. Where is the risk-neutral probability \(q=(R-d)/(u-d)\) used?
  3. Why is it important that \(S_n\) is known at time \(n\)?
  4. Does the proof still work under the physical probability \(p\)?

A correct answer should identify that \(d<R<u\) guarantees \(0<q<1\), and that the martingale property generally fails under \(p\).

8.21.3 AI Prompt 5.3: Find the bug in martingale-checking code

Ask an AI assistant to review Python code that checks

\[ \mathbb E^{\mathbb Q}[\widetilde S_{n+1}\mid\mathcal F_n]=\widetilde S_n. \]

Tell it to look specifically for:

  • using \(p\) instead of \(q\);
  • forgetting to divide by \(R^{n+1}\);
  • reversing the order of up and down children in the tree;
  • checking unconditional expectation only instead of nodewise conditional expectation.

8.21.4 AI Prompt 5.4: Generate a counterexample

Ask an AI assistant to construct a one-step model where the undiscounted stock price is not a martingale but the discounted stock price is a martingale under \(\mathbb Q\). Then verify the example by hand.

8.22 5.21 Common Mistakes

  1. Confusing \(\mathbb P\) and \(\mathbb Q\). The physical probability \(\mathbb P\) describes real-world frequencies. The risk-neutral probability \(\mathbb Q\) prices assets under no arbitrage.

  2. Forgetting the filtration. Conditional expectation is always conditional on a specific information set. A statement such as \(\mathbb E[X_{n+1}]=X_n\) is not the martingale property.

  3. Forgetting discounting. Stock prices are usually not martingales under \(\mathbb Q\). Discounted stock prices are martingales under \(\mathbb Q\).

  4. Using future information in a trading strategy. A trading strategy must be predictable or adapted in the appropriate sense. Strategies that see the future are not admissible.

  5. Misusing optional stopping. Optional stopping requires assumptions. Unbounded doubling strategies are not valid arbitrage arguments.

  6. Checking only averages across all paths. A martingale condition is nodewise and conditional. The correct check must be performed at each information cell.

8.23 5.22 Exercises

8.23.1 Conceptual Exercises

  1. Explain in your own words why a filtration is needed in mathematical finance.

  2. Give an example of a random variable that is \(\mathcal F_2\)-measurable but not \(\mathcal F_1\)-measurable in a two-step binomial tree.

  3. Explain why the martingale property is a conditional statement, not merely an unconditional statement.

  4. In a risk-neutral binomial model, is the undiscounted stock price usually a martingale? Explain.

  5. Why does the risk-neutral probability generally differ from the physical probability?

8.23.2 Computational Exercises

  1. Consider a one-step binomial model with

    \[ S_0=50, \qquad \nu=1.3, \qquad d=0.7, \qquad R=1.04. \]

    Compute the risk-neutral probability \(q\) and verify the discounted martingale condition.

  2. In the same model, price a European call with strike \(K=55\) by risk-neutral expectation.

  3. In a two-step tree with \(S_0=100\), \(\nu=1.1\), \(d=0.9\), \(R=1.02\), and \(K=100\), compute the value process of a European put at every node.

  4. For Exercise 8, verify explicitly that the discounted put-value process is a martingale under \(\mathbb Q\).

  5. Construct a three-state one-period model and compute a conditional expectation with respect to a nontrivial partition of the state space.

8.23.3 Proof Exercises

  1. Prove the tower property directly in a finite probability space using partitions.

  2. Prove that if \(X_n=\mathbb E[Y\mid\mathcal F_n]\), then \((X_n)\) is a martingale.

  3. Prove that the sum of two martingales is a martingale.

  4. Let \((X_n)\) be a martingale and let \(a,b\) be constants. Prove that \((aX_n+b)\) is a martingale.

  5. Let \((X_n)\) be a martingale and define the stopped process

\[ X_n^\tau=X_{n\wedge \tau}. \]

Prove that \((X_n^\tau)\) is a martingale when \(\tau\) is a bounded stopping time.

8.23.4 Python Exercises

  1. Write a Python function that takes a finite probability space, a random variable, and a partition, and returns the conditional expectation on each state.

  2. Write a Python function that checks the discounted martingale property at every node of a binomial stock tree.

  3. Simulate a biased random walk and numerically construct its Doob decomposition.

  4. Simulate stopped symmetric random walks for several upper and lower barriers. Compare the sample mean of the stopped value with the optional stopping prediction.

  5. Price a European call using backward induction and then independently verify the time-zero value using the binomial distribution formula.

8.23.5 AI-Assisted Exercises

  1. Ask an AI assistant to explain why discounting is necessary in martingale pricing. Critique whether it correctly distinguishes prices from discounted prices.

  2. Ask an AI assistant to produce an example of a non-martingale process. Then compute the conditional drift yourself and check the answer.

  3. Give an AI assistant a flawed optional stopping argument based on a doubling strategy. Ask it to identify the missing assumptions.

  4. Ask an AI assistant to generate Python code for binomial martingale verification. Test the code on at least two parameter choices and identify any errors.

  5. Ask an AI assistant to compare the martingale property with the Markov property. Write a short correction if it confuses the two.

8.24 5.23 Chapter Summary

This chapter introduced the discrete-time martingale framework that underlies no-arbitrage pricing.

The main ideas are:

  • a filtration \((\mathcal F_n)\) models information available over time;
  • conditional expectation averages over states consistent with current information;
  • a martingale has zero conditional drift;
  • under a risk-neutral measure \(\mathbb Q\), discounted traded asset prices are martingales;
  • derivative prices can be written as conditional expectations of discounted terminal payoffs;
  • backward induction in a binomial tree is a concrete form of martingale pricing;
  • self-financing strategies preserve the martingale property of discounted wealth;
  • optional stopping prevents bounded fair games from being turned into arbitrage by stopping rules;
  • Doob decomposition separates predictable drift from martingale noise.

The next chapter uses these ideas to state the discrete-time Fundamental Theorem of Asset Pricing more systematically. In that theorem, no arbitrage, equivalent martingale measures, and market completeness become one unified mathematical structure.