Random Walks Have Never Been Funnier: Drifted Brownian Motion in Python

5 minute read

We are not in power to predict the outcome of everything that surrounds us. For instance, we do not know the exact number of people that will attend an event or the exact noise that is going to occur in a signal or electric circuit. Rather than that, we can think of rough estimates and compute the likelihood of the possible scenarios. Thus, it is not surprising at all that the answers for many phenomena lie in the realm of randomness.

The stochastic processes play a major role in the modeling of many time-dependent systems. One particular and well-studied process is the Brownian Motion that we already covered in the previous blog post. This process has fascinating properties and is very handy in quite different and interdisciplinary areas including quantum physics, economics, or chemistry.

Having only a bare Brownian Motion is of no use and can be considered as a jitter. For this reason, in this blog post, we drill more and attach some properties to the standard Brownian Motion. These properties include the drift (also called bias) which drives the process in a particular direction and the volatility which increases the fluctuation of the process. We leverage Python's numerical capabilities to simulate such a process. On top of everything, we enhance the visual experience with multiple animations using the Matplotlib's Animation API.

Having said that, let us begin and stay tuned!

Towards more inclusive Brownian Motion

The standard Brownian Motion has an interesting set of features making its pattern recognizable in plentiful domains. The standard, non-avoidable pattern that we all know is the price of some stock over the course of time. For example let's take a look at the S&P 500 stock market index from 1950 until 2018, depicted in the figure below.

Line plot over a time period from 1950 until 2018
Fig. 1: S&P 500 index level every 2 years from 1950 until 2018

At first glance, we can instantly recognize the random Brownian pattern. However, it is clear that there are other components hidden inside, it is not just plain randomness. We can notice that the process has a tendency to grow over time with some local drops and fluctuations. Thus, we must account for these observations.

In order to reason about the directional tendency of the process, we can think of an additive component resembling a slope growing over time. In mathematical terms it means we have some constant, let's say \( \mu \) multiplying the time variable \( t \). In this case of modeling a stock price, we interpret \( \mu \) as a mean of returns.

We can easily see that the fluctuations appear randomly, thus they must be directly tied with the random component. Moreover, some of the drops are more severe while others are milder. That indicates only one thing, as the process randomly ascends or descends, we magnify these relative changes by multiplying with some constant, let's say \( \sigma \). This is how we incorporate the diffusion factor or vvolatility.

Having said all of this, we come to a formal definition of a drifted Brownian Motion with volatility, which is:

math equation for drifted Brownian Motion

In the next few sections, we will analyze separately and visually illustrate with meaningful animations these two properties.

Drifted Brownian Motion in Python

To simulate the drifted Brownian Motion with volatility, we basically extend the work from the previous blog post where we defined only a bare Brownian Motion. Having this component ready-to-use, the Python implementation of this extended process is given below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import numpy as np

def drifted_brownian_motion(mu, sigma, N, T, seed=42):
    """Simulates a Brownian Motion with drift.
    
    :param float mu: drift coefficient
    :param float sigma: volatility coefficient
    :param int N : number of discrete steps
    :param int T: number of continuous time steps
    :param int seed: initial seed of the random generator
    :returns list: drifted Brownian motion
    """
    # set the seed
    np.random.seed(seed)
    # standard brownian motion
    W, _ = brownian_motion(N, T ,1.0)
    # the normalizing constant
    dt = 1. * T/N
    # generate the time steps
    time_steps = np.linspace(0.0, N*dt, N+1)
    # calculate the Brownian Motion with drift
    X = mu * time_steps + sigma * W
    return X

A picture is worth a thousand words, an animation even more. Using the Matplotlib's Animation API we analyze and illustrate the effect of these two components separately. The visual way of thinking helps us to actually comprehend the concepts in a striking and captivating manner, or in other words citing the popular cognitive psychologist Steven Pinker:

For us to go from “I think I understand” to “I understand,” we need to see the sights and feel the motions.

Animated illustration of the drift

By setting the diffusion coefficient \( \sigma \) to 1, and varying the drift coefficient, we can observe the difference between a process with and without drift (colored with orange and blue respectively). In the animation below, as time passes by, the gap between the processes becomes larger and larger.

Animation of the Brownian Motion only with drift
Animation: The impact of the drift

This is a perfect demonstration that a Brownian Motion without bias is just a jitter, which means it is an important property.

Animated illustration of the volatility

On the other hand, by fixing the drift coefficient \( \mu \) to 0 and varying the diffusion coefficient, we can examine the volatile behavior of the process. As depicted in the animation below, the two processes, one with volatility (in orange) and another one without (in blue), have exactly the same tendency over time. However, the fluctuations of the volatile motion are severe, dropping instantly from high to low values and vice-versa.

Animation of the Brownian Motion only with volatility
Animation: The impact of the volatility

We confirm that the volatility completely changes the pace of random processes, which implies that it is a key component to consider.

The full source code behind this simulation and animations can be found on my GitHub repo, called Amusive Blogging and Coding (ABC).

If you liked what you just saw, it would be really helpful to subscribe to the mailing list below. You will not get spammed that's a promise! You will get updates for the newest blog posts and visualizations from time to time.

Conclusion

In this blog post, we extended the bare Brownian Motion with two important properties: drift and volatility. Through the animated visualizations, we observed the impact of these key components. We saw that without drift, the motion is a pure noise without any trend. On the other side, the volatility makes the process to keep the same trend but within a wider span of possible values.

This process has additional ingredients which make it more inclusive and aligned with the reality. However, it still exhibits an additive behavior which is not a natural way of expressing growth. For this reason we need another trick, to switch from additive to multiplicative changes and think in terms of rates of changes. One such process is the Geometric Brownian Motion which we will cover next time.

References

[1] Peter Olofsson, Mikael Andersson, "Probability, Statistics, and Stochastic Processes"

Leave a comment