Why Transforming a CEV Process Can Break Martingale Simulation
Summary
The document examines Euler simulation of a constant elasticity of variance process, where the diffusion coefficient depends on a power of the process level. When the simulated level becomes negative and the power is below one, the update is undefined. Flooring negative values at zero avoids that numerical problem but can make zero absorbing and distort later paths.
The author then applies an Itô variable transformation to simulate a transformed process and map it back to the original level. In the reported experiment, the sample mean rises sharply instead of staying near its initial value, raising the question of why the martingale property is lost. The excerpt supplies code and simulated means, but no resolution. The transformed drift has a singularity near zero, and a discretized transformed process may cross into invalid values; the displayed results should not be read as proof that the continuous process itself ceases to be a martingale.
Key ideas
- For CEV exponents below one, Euler updates can become undefined after the process turns negative.
- Clipping negative simulated levels at zero can create an absorbing boundary and alter the path distribution.
- An Itô transformation changes the simulation equation, and its drift becomes singular near zero.
- The example reports a rising sample mean but does not establish the cause or resolve the theoretical question.
Tags
Full text
# CEV model effective simulation
# CEV model effective simulation
I want to simulate the following CEV process : $$ dM_t = \sigma_t M_t^{\eta} dW_t $$
Using Euler discretization to $M_t$, if at a given time $t$, $M_t$ takes a negative value then $M_{t+1} = M_t + \sigma_t M_t^{\eta} \sqrt{dt} \epsilon$, where $\epsilon$ follows a standard Gaussian distribution, gives 'NaN's when $\eta < 1$. A first solution might be to take the positive value such as : $M_{t+1} = \max(0,M_t + \sigma_t M_t^{\eta} \sqrt{dt} \epsilon)$. The problem with this method is that I get to set a floor (here at 0) and that affects the impact results. I still get to preserve my martingale property with this method : $E(M_t) = M_0$, but it's not quite good because the Euler tends to give many negative values which are then floored to zero and there is no rebound, the zero becomes "absorbant".
Therefore, I went for a variable change in order to have values justifiable without setting a floor : $$ dM_t = \sigma_t M_t^{\eta} dW_t $$ Let the variable $Q_t$ as : $$ Q_t = \frac{1}{1 - \eta} M_t^{1 - \eta} $$ Applying Itô formula to $Q_t$ gives : $$ dQ_t = \sigma_t dW_t - \frac{\eta}{2(1 - \eta)} \sigma_t^2 Q_t^{-1}dt $$
I can therefore simulate $Q_t$ without having to deal with the negative part and deduce $M_t$ as : $$ M_t = [(1 - \eta) Q_t]^{\frac{1}{1 - \eta}}.$$
My problem with this approach is that I no longer verify the martingale property $E(M_t) = M_0$. Does anybody know why ?
Here is my Python code for this simulation :
```
import numpy as np
np.random.seed(1)
nb_sim = int(1e4)
nb_steps = int(1e2)
z = np.random.normal(size = [nb_sim, nb_steps])
eta = 0.5
vol = 0.2 * np.ones(nb_steps)
m = np.ones(z.shape)
q = np.power(m, 1 - eta)/ (1 - eta)
# $$ dQ_t = \sigma_t dW_t - \frac{\eta}{2(1 - \eta)} \sigma_t^2 Q_t^{-1} dt $$
dt = 1
for t in range(nb_steps-1):
q[:,t+1] = q[:,t] + vol[t] * np.sqrt(dt) * z[:,t] - dt * eta * np.power(vol[t], 2) / (2 * (1 - eta) * q[:,t])
# Deduce $M_t$ from $Q_t$ :
# $$ M_t = [(1 - \eta) Q_t]^{\frac{1}{1 - \eta}} $$
m = np.power((1 - eta) * q, 1 / (1 - eta))
# Martingale test : $E(M_t) = M_0$
E = m.mean(axis=0)
# The expectation E should be values around M_0 = 1 in this specific example, for all t.
print(E)
```
> print(np.round(E))
> [1.000e+00 1.000e+00 1.000e+00 1.000e+00 1.000e+00 1.000e+00 1.000e+00 1.000e+00 1.000e+00 1.000e+00 1.000e+00 1.000e+00 1.000e+00 1.000e+00 1.000e+00 1.000e+00 4.000e+00 4.000e+00 4.000e+00 8.000e+00 8.000e+00 8.000e+00 8.000e+00 8.000e+00 8.000e+00 1.600e+01 1.600e+01 2.200e+01 2.200e+01 2.400e+01 2.400e+01 2.400e+01 2.700e+01 2.800e+01 2.800e+01 2.800e+01 2.800e+01 2.800e+01 2.900e+01 2.900e+01 3.000e+01 3.400e+01 3.600e+01 3.600e+01 5.290e+02 5.320e+02 5.320e+02 5.320e+02 5.320e+02 5.320e+02 5.330e+02 5.360e+02 5.360e+02 5.370e+02 5.370e+02 5.370e+02 5.590e+02 5.590e+02 5.600e+02 5.600e+02 5.660e+02 5.660e+02 5.660e+02 5.660e+02 5.670e+02 5.670e+02 5.670e+02 5.720e+02 5.800e+02 5.800e+02 5.810e+02 5.850e+02 5.850e+02 5.890e+02 5.890e+02 5.890e+02 5.890e+02 5.910e+02 5.910e+02 5.910e+02 5.910e+02 5.930e+02 5.950e+02 5.950e+02 5.970e+02 5.970e+02 5.970e+02 5.970e+02 5.970e+02 5.970e+02 6.000e+02 6.010e+02 6.010e+02 6.020e+02 6.030e+02 1.889e+03 1.894e+03 1.894e+03 1.895e+03 1.896e+03]Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.