<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Journey Building Options Trader]]></title><description><![CDATA[Journey Building Options Trader]]></description><link>https://journey-building-options-trader.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Thu, 05 Nov 2026 09:53:52 GMT</lastBuildDate><atom:link href="https://journey-building-options-trader.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Building a High-Performance Options Trading Simulator in C++: My Journey]]></title><description><![CDATA[As someone deeply curious about financial markets and systems engineering, I wanted to better understand the options market while improving my C++ skills…]]></description><link>https://journey-building-options-trader.hashnode.dev/building-a-high-performance-options-trading-simulator-in-c-my-journey</link><guid isPermaLink="true">https://journey-building-options-trader.hashnode.dev/building-a-high-performance-options-trading-simulator-in-c-my-journey</guid><category><![CDATA[options trading]]></category><category><![CDATA[C++]]></category><category><![CDATA[hft]]></category><dc:creator><![CDATA[Xiaohu Cao]]></dc:creator><pubDate>Wed, 28 May 2025 14:10:43 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>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.</p>
<h2 id="heading-getting-started-learning-the-fundamentals">Getting Started: Learning the Fundamentals</h2>
<p>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 <code>price()</code> method.</p>
<p>This worked well initially, but I realized that I needed a more extensible structure—so I used inheritance. I created a base <code>Option</code> class and derived <code>EuropeanOption</code> subclass and anticipated later the <code>AmericanOption</code> subclass. However, this introduced runtime overhead due to virtual function table (vtable) lookups, which I confirmed through benchmarks.</p>
<h2 id="heading-template-based-optimization">Template-Based Optimization</h2>
<p>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 <code>Call</code> and <code>Put</code> options into their own structs with <code>constexpr</code> booleans. While this was extremely fast for uniform batches, it became too rigid for mixed-type use cases.</p>
<p>So I restructured again—this time into a single <code>Option</code> struct that held all the parameters (<code>S</code>, <code>K</code>, <code>r</code>, <code>sigma</code>, <code>T</code>, etc.) along with enum types for <code>OptionType</code> and <code>OptionStyle</code>. This allowed for flexible batch processing without vtables, and the speed was comparable to the highly specialized template version—within ~2%.</p>
<p>The code of previous implementations remain in my codebase in the directory <code>backend/src/legacy</code>.</p>
<h2 id="heading-american-options-amp-binomial-tree">American Options &amp; Binomial Tree</h2>
<p>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.</p>
<p>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 <code>Option</code> objects and route them to the correct pricing method depending on style and type.</p>
<h2 id="heading-simulating-market-conditions">Simulating Market Conditions</h2>
<p>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.</p>
<h2 id="heading-parallelization-simd-amp-memory-reuse">Parallelization, SIMD, &amp; Memory Reuse</h2>
<p>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.</p>
<p>For American options, I experimented with memory reuse using a <code>BinomialWorkspace</code> 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.</p>
<h2 id="heading-benchmarking-results">Benchmarking Results</h2>
<p>The improvements were significant:</p>
<ul>
<li><p><strong>Before parallelization</strong>: Pricing 10,000 American and 1,000,000 European options took <strong>~63,615 ms</strong>.</p>
</li>
<li><p><strong>With OpenMP</strong>: Mixed batches dropped to <strong>~3,183 ms</strong>.</p>
</li>
<li><p><strong>Fully optimized</strong>:</p>
<ul>
<li><p><strong>1,000,000 European (SIMD + Parallel)</strong>: <strong>15.81 ms</strong></p>
</li>
<li><p><strong>10,000 American (Parallel)</strong>: <strong>404 ms</strong></p>
</li>
<li><p><strong>Mixed Dispatcher (Parallel)</strong>: <strong>~405 ms</strong></p>
</li>
</ul>
</li>
</ul>
<p>This reflects over <strong>150x speedup</strong> from restructuring, parallelization, and SIMD.</p>
<h2 id="heading-whats-next">What’s Next</h2>
<ul>
<li><p>Implementing <strong>Greeks for American options</strong></p>
</li>
<li><p>Adding <strong>Barone-Adesi-Whaley</strong> and <strong>Ju-Zhong</strong> models for faster American approximation</p>
</li>
<li><p>Exploring <strong>GPU acceleration</strong> for batch pricing</p>
</li>
<li><p>Possibly integrating <strong>Monte Carlo simulation</strong> for exotic options</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>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.</p>
]]></content:encoded></item></channel></rss>