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

Xiaohu CaoXiaohu Cao
3 min read

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.

3
Subscribe to my newsletter

Read articles from Xiaohu Cao directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Xiaohu Cao
Xiaohu Cao