Building a High-Performance Options Trading Simulator in C++: My Journey

Introduction
As someone deeply curious about financial markets and systems engineering, I wanted to better understand the options market while improving my C++ skills. This led me to build an options trading simulator from scratch—a project that taught me not only the fundamentals of options pricing but also advanced C++ design patterns, numerical methods, and performance optimization techniques.
Getting Started: Learning the Fundamentals
I began by learning what options are and how they’re priced. Naturally, this led me to the Black-Scholes model. I spent time learning the math behind it—stochastic calculus, log-normal distributions, and the derivation of the formula. Once I had a grip on the theory, I implemented European option pricing as a simple class with a price()
method.
This worked well initially, but I realized that I needed a more extensible structure—so I used inheritance. I created a base Option
class and derived EuropeanOption
subclass and anticipated later the AmericanOption
subclass. However, this introduced runtime overhead due to virtual function table (vtable) lookups, which I confirmed through benchmarks.
Template-Based Optimization
To eliminate the vtable overhead, I ventured to template-based design. I templated the pricing and Greeks functions, and immediately saw a speedup. To further exploit branch prediction, I tried separating Call
and Put
options into their own structs with constexpr
booleans. While this was extremely fast for uniform batches, it became too rigid for mixed-type use cases.
So I restructured again—this time into a single Option
struct that held all the parameters (S
, K
, r
, sigma
, T
, etc.) along with enum types for OptionType
and OptionStyle
. This allowed for flexible batch processing without vtables, and the speed was comparable to the highly specialized template version—within ~2%.
The code of previous implementations remain in my codebase in the directory backend/src/legacy
.
American Options & Binomial Tree
Next, I tackled American options, which can be exercised before expiration. I studied the binomial tree method through YouTube lectures. My implementation used two arrays: one for terminal payoffs and one for backward induction. This approach used more memory but was significantly faster than a recursive implementation.
Unsurprisingly, pricing American options was much slower than European options. To handle this at scale, I built a pricing dispatcher that could take a vector of Option
objects and route them to the correct pricing method depending on style and type.
Simulating Market Conditions
To test the simulator, I generated randomized market conditions using a high-quality random number generator. I deliberately mixed the order of options to test how branch prediction would impact performance. No significant slowdowns were observed.
Parallelization, SIMD, & Memory Reuse
To improve performance, I enabled parallelization using OpenMP. This led to a major speedup in batch processing. Then I optimized further using SIMD for Black-Scholes: I converted input vectors to Structure of Arrays (SoA) format and enabled compiler vectorization directives.
For American options, I experimented with memory reuse using a BinomialWorkspace
object to avoid repeated memory allocation. While this helped in pure American batches, it didn’t yield major improvements for mixed-style batches—so I decided to limit its use to pure American batch pricing.
Benchmarking Results
The improvements were significant:
Before parallelization: Pricing 10,000 American and 1,000,000 European options took ~63,615 ms.
With OpenMP: Mixed batches dropped to ~3,183 ms.
Fully optimized:
1,000,000 European (SIMD + Parallel): 15.81 ms
10,000 American (Parallel): 404 ms
Mixed Dispatcher (Parallel): ~405 ms
This reflects over 150x speedup from restructuring, parallelization, and SIMD.
What’s Next
Implementing Greeks for American options
Adding Barone-Adesi-Whaley and Ju-Zhong models for faster American approximation
Exploring GPU acceleration for batch pricing
Possibly integrating Monte Carlo simulation for exotic options
Conclusion
This project has been an incredible learning experience. I dove deep into financial mathematics, numerical methods, and high-performance C++. Each challenge forced me to reconsider design decisions and explore more efficient approaches. I’m excited to continue building, optimizing, and eventually turning this into a full-featured educational or trading simulation platform.
Subscribe to my newsletter
Read articles from Xiaohu Cao directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
