Skip to content
All library documents

Simulating Poisson and Compound Poisson Processes with Exponential Waiting Times

Article Quant Q&A · Author: Math122

Summary

The document describes simulating a Poisson counting process by drawing independent exponential waiting times with rate equal to the Poisson intensity, then cumulatively summing those times to obtain event times. It also addresses plotting the path, which is zero before the first event, and demonstrates a check based on the distribution of event counts over a fixed interval. The example compares many simulated counts with direct Poisson draws and reports that their histogram match is good, though no quantitative fit statistic is given.

A compound Poisson process extends the construction by assigning a random jump size to each event and accumulating those sizes. The example uses binomially distributed jumps, while the method allows another secondary distribution if its samples can be generated. The discussion provides a basic simulation recipe and a distributional sanity check, not a proof of correctness or a study of model fit. It does not explore parameter estimation, dependence between jumps, or more advanced process models.

Key ideas

  • Poisson event times can be generated by cumulatively summing exponential waiting times.
  • The rate parameter controls the waiting-time distribution and the expected event count over an interval.
  • A counting process path remains at zero until the first event and increases at event times.
  • A simulated Poisson process can be checked by comparing interval counts with Poisson-distributed draws.
  • A compound Poisson process accumulates random jump sizes at Poisson event times.

Tags

Full text
# How to simulate Poisson and Compound Poisson process


# How to simulate Poisson and Compound Poisson process












someone knows, maybe websites / blogs where I can find tips (preferably ready codes) to simulate the trajectory of processes? So far I only need the Poisson process and the compound Poisson process but I would like to learn to simulate more advanced processes as well so I will be grateful for every source

EDIT: I edit code from anserws a little bit:

```
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.stats import poisson

mu = 3
num_events_simulated = 5

def generate_poisson_process(mu, num_events):
    time_intervals = -np.log(np.random.random(num_events)) / mu
    total_events = time_intervals.cumsum()
    events = pd.DataFrame(np.ones(num_events), index=total_events)
    events[0] = events[0].cumsum()

    return events

plt.plot(generate_poisson_process(mu, num_events_simulated), marker='o', drawstyle='steps-post')
plt.title("Sample Poisson Process")
plt.xlabel("time")
plt.ylabel("events")
```

but the trajectory starts from the first jump. How to add to the graph this fragment in which the trajectory starts from zero and is 0 until 1 jump?

## Answer by StackG (score 2, accepted)

https://quant.stackexchange.com/a/57228

The time between two events in a poisson distribution has an exponential distribution, so the easiest thing to do is simulate a sequence of exponentially distributed variables and use these as the times between events, as discussed in this primer.

To simulate variables given a uniform RNG, we need the reverse CDF of the distribution, which maps uniform distributions to our distribution of choice

For the exponential distribution this is just \begin{align} F^{-1}(x) = {\frac {-\log(1-x)} {\lambda}} \end{align} where $\lambda$ is the poisson parameter

We can simulate that using `numpy` as follows

```
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.stats import poisson

mu = 15
num_events_simulated = 50

def generate_poisson_process(mu, num_events):
    time_intervals = -np.log(np.random.random(num_events)) / mu
    total_events = time_intervals.cumsum()
    events = pd.DataFrame(np.ones(num_events), index=total_events)
    events[0] = events[0].cumsum()

    return events

plt.plot(generate_poisson_process(mu, num_events_simulated), marker='o', linestyle='none')
plt.title("Sample Poisson Process")
plt.xlabel("time")
plt.ylabel("events")
plt.legend()
```

which generates

So far, so good, but how can we demonstrate that this is a poisson process? Well, for a poisson process, the number of events in a period of time $\tau$ is distributed as $Poi(\tau\lambda)$, and `numpy` can generate these directly for us to compare.

Here, we generate 100,000 processes and compare the number of events in $\tau = 1$ to the results of the variables generated directly:

```
results = []
for x in range(100000):
    process = generate_poisson_process(mu, num_events_simulated)
    results.append(process[:1][0].iloc[-1])

plt.hist(results, bins=np.linspace(0, 35, 36), alpha=0.5, label='simulated poisson', ec='black')

r = poisson.rvs(mu, size=100000)
plt.hist(r, bins=np.linspace(0, 35, 36), alpha=0.5, label='counting process', ec='black')

plt.title("Poisson-Distributed Variables")
plt.ylabel("Count")
plt.xlabel("X")
plt.legend()
```

which generates

Match is very good, so we're happy with the path generation process!

The compound poisson process is a simple extension of this as long as you know which secondary distribution you want to use, and can generate variables distributed according to it. Here is an example of a compound poisson process generated using binomial $X ~ B(10,0.5)$ as the seocndary distribution:

```
def binomial_generator(num_events):
    return np.random.binomial(10, 0.5, num_events)

def generate_compound_poisson_process(mu, num_events, generator):
    time_intervals = -np.log(np.random.random(num_events)) / mu
    total_events = time_intervals.cumsum()
    events = pd.DataFrame(generator(num_events), index=total_events)
    events[0] = events[0].cumsum()

    return events

plt.plot(generate_compound_poisson_process(mu, num_events_simulated, binomial_generator), marker='o', linestyle='none')
plt.title("Sample Compound Poisson Process (Binomial)")
plt.xlabel("time")
plt.ylabel("events")
plt.legend()
```

which generates

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.