This post will just be a quick example of how to use OpenCL to generate some simulated stock prices’ “trajectories”. Using CUDA could have been possible as well, and indeed the code could be ported with minimal changes, but then it would have been able to run only on NVidia GPUs while OpenCL runs even on CPUs.

A consideration, before we get into the code, is that this is a simplistic model which is **not very useful** at all. This post, in fact, is not about how to properly model stocks, but rather just a quick self-contained reference to get up and running with the topic. In this example we will compute 10k different possible trajectories for the price of some stock and generate a histogram with the results.

Without further ado, here is the link to the code.

Right off the bat we should say that we are using the C++ bindings for openCL; you can find them in the repo in the 3rdParties directory. The Cmake file will look for them automatically if you clone the entire repository. Other than that, the README will get you up and running.

Starting with the boilerplate code, at the top there is a couple of macros that we need to change if we want to use our GPU instead of the CPU like I do here:

#define PLATFORM 0 #define DEVICE 0

Besides that the rest of the main.cpp is fairly uninteresting until line [56-60] where I hardcoded some values that will drive the price increase (or decrease). These values are the common parameters described better that I could in many other places [1] [2] [3].

The main thing we need to know is the following iterative formula:

which becomes in the kernel

share_val += share_val * (dt * rate + variance * epsilon * sqrt(dt));

So we are going to need some *Gaussian* random variable epsilon, which in C++ would just mean we’d use std::normal_distribution, but in OpenCL we don’t have anything like that. To create random variables in a Kernel we’ll use a library called RandomCL, which you can checkout into the “../3rdParties” directory (see README). To turn the random variable into a Gaussian variable we will employ the good ol’ Box-Muller transform, which we can use to generate 2 numbers at a time:

// Compute gauss random number using box muller const float rand1 = msws_float(state); const float rand2 = msws_float(state); const float rand1_log = -2 * log(rand1); float cos_rand2; const float sin_rand2 = sincos(rand2 * two_pi, &cos_rand2); const float epsilon1 = sqrt(rand1_log) * cos_rand2; const float epsilon2 = sqrt(rand1_log) * sin_rand2;

That’s it. Run it and plot it, here is what you get with the current hard-coded parameters:

#### References

[1] https://en.wikipedia.org/wiki/Geometric_Brownian_motion

[2] http://sfb649.wiwi.hu-berlin.de/fedc_homepage/xplore/tutorials/sfehtmlnode27.html

[3] https://beta.vu.nl/nl/Images/werkstuk-dmouj_tcm235-91341.pdf