Option Greeks in C++: Delta Calculation Explained

by Clement Daubrenet
Delta Greek Calculation

Delta is one of the most important Greeks in options pricing. It measures how sensitive an option’s price is to changes in the price of the underlying asset. How to perform a delta calculation? Let’s derive and it and calculate it in C++.

1. Derive the Delta Formula for a Call Option

Delta is defined as the rate of change of an option’s price with respect to changes in the underlying asset price. In mathematical terms, it’s the first partial derivative of the option value V with respect to the underlying asset price S:

[math] \Large{\Delta = \frac{\partial V}{\partial S}} [/math]

Under the Black-Scholes framework, the price of a European call option is given by:

[math]\Large{C = S N(d_1) – K e^{-rT} N(d_2)}[/math]

Where:

  • S is the current spot price of the underlying
  • K is the strike price
  • r is the risk-free interest rate
  • T is the time to maturity
  • N(⋅) is the cumulative distribution function of the standard normal distribution
  • [math]d_1 = \frac{\ln(S/K) + \left(r + \frac{\sigma^2}{2} \right) T}{\sigma \sqrt{T}}[/math]
  • [math]d_2 = d_1 – \sigma \sqrt{T}[/math]

To compute the Delta of a call option, we differentiate the Black-Scholes formula with respect to S:

[math]\Large \frac{\partial C}{\partial S} = \frac{\partial}{\partial S} \left[ S N(d_1) – K e^{-rT} N(d_2) \right][/math]

Only the first term depends on S directly. The derivative of the first term requires the chain rule, since d1​ is a function of S as well. Thus:

[math]\Large \frac{\partial C}{\partial S} = N(d_1)[/math]

Therefore, the Delta of a European call option is:

[math]\Large \Delta_{\text{call}} = N(d_1)[/math]

2. Derive the Delta Formula For a Put Option

For a put option, we apply the same steps to the Black-Scholes formula for puts:

[math]\Large P = K e^{-rT} N(-d_2) – S N(-d_1)[/math]

Where:

  • S is the current spot price of the underlying
  • K is the strike price
  • r is the risk-free interest rate
  • T is the time to maturity
  • N(⋅) is the cumulative distribution function of the standard normal distribution
  • [math]d_1 = \frac{\ln(S/K) + \left(r + \frac{\sigma^2}{2} \right) T}{\sigma \sqrt{T}}[/math]
  • [math]d_2 = d_1 – \sigma \sqrt{T}[/math]

Differentiating:

[math]\Large \frac{\partial P}{\partial S} = -N(-d_1) = N(d_1) – 1[/math]

Hence, the Delta of a European put option is:

[math]\Large \Delta_{\text{put}} = N(d_1) – 1[/math]

3. Delta Calculation in C++ Without Library

We can simply implement the recipes above to calculate delta call and delta put:

#include <cmath>
#include <iostream>

// Cumulative normal distribution function
double norm_cdf(double x) {
    return 0.5 * std::erfc(-x / std::sqrt(2));
}

double black_scholes_delta(
    bool is_call,
    double S,     // Spot
    double K,     // Strike
    double T,     // Time to maturity
    double r,     // Risk-free rate
    double sigma  // Volatility
) {
    double d1 = (std::log(S / K) + (r + 0.5 * sigma * sigma) * T)
                / (sigma * std::sqrt(T));

    if (is_call) {
        return norm_cdf(d1);
    } else {
        return norm_cdf(d1) - 1.0;
    }
}


Then:

int main() {
    double S = 100.0;
    double K = 100.0;
    double T = 1.0;
    double r = 0.05;
    double sigma = 0.2;

    double delta_call = black_scholes_delta(true, S, K, T, r, sigma);
    double delta_put  = black_scholes_delta(false, S, K, T, r, sigma);

    std::cout << "Call Delta: " << delta_call << std::endl;
    std::cout << "Put Delta: "  << delta_put  << std::endl;
    return 0;
}

This is implements the analytical formula for Delta explicitly. It’s lightweight and very fast, great for educational or performance-critical code. It assumes flat rates and no dividends.

But what if you want something less generic?

4. Delta Calculation in C++ With Quantlib

Well, we can use the bazooka:

#include <ql/quantlib.hpp>
#include <iostream>

using namespace QuantLib;

int main() {
    Calendar calendar = TARGET();
    Date today(23, June, 2025);
    Settings::instance().evaluationDate() = today;

    // Common option parameters
    Real underlying = 100.0;
    Real strike = 100.0;
    Spread dividendYield = 0.0;
    Rate riskFreeRate = 0.05;
    Volatility volatility = 0.20;
    Date maturity = today + Period(1, Years);
    DayCounter dayCounter = Actual365Fixed();

    // Market data handles
    Handle<Quote> underlyingH(boost::shared_ptr<Quote>(new SimpleQuote(underlying)));
    Handle<YieldTermStructure> flatDividendTS(boost::shared_ptr<YieldTermStructure>(
        new FlatForward(today, dividendYield, dayCounter)));
    Handle<YieldTermStructure> flatRiskFreeTS(boost::shared_ptr<YieldTermStructure>(
        new FlatForward(today, riskFreeRate, dayCounter)));
    Handle<BlackVolTermStructure> flatVolTS(boost::shared_ptr<BlackVolTermStructure>(
        new BlackConstantVol(today, calendar, volatility, dayCounter)));

    boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(
        new BlackScholesMertonProcess(underlyingH, flatDividendTS, flatRiskFreeTS, flatVolTS));

    // Loop over Call and Put options
    for (auto type : {Option::Call, Option::Put}) {
        std::string typeStr = (type == Option::Call ? "Call" : "Put");

        boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff(type, strike));
        boost::shared_ptr<Exercise> exercise(new EuropeanExercise(maturity));
        VanillaOption option(payoff, exercise);

        option.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new AnalyticEuropeanEngine(bsmProcess)));

        std::cout << typeStr << " Delta: " << option.delta() << std::endl;
    }

    return 0;
}

✅ The QuantLib implementation:

  • Wraps the same math, but within a complete pricing engine (AnalyticEuropeanEngine).
  • Uses market objects like Quote, YieldTermStructure, and BlackVolTermStructure, which can evolve over time.
  • Supports dividends, yield curves, non-constant volatility, and more.

In a word, it’s heavier but more flexible and extensible, making it better suited for production systems or derivatives desks.

5. Let’s Run Both and Compare?

Let’s start with the first version, after compiling and running:

➜  ./delta_vanilla                                                              
Call Delta: 0.636831
Put Delta: -0.363169

Now, the Quantlib version:

➜  build ./delta_quantlib 
Call Delta: 0.636831
Put Delta: -0.363169

The exact same!

What about execution time?

For the first version, it’s instant, <<0.01s:

➜  build time ./delta_vanilla 

./delta_vanilla  0.00s user 0.00s

For the Quantlib version, ~0.01s, slightly slower:

➜  build time ./delta_quantlib

./delta_quantlib  0.00s user 0.01s

4. Summarize Both Implementations for Delta Calculation

FeatureVanillaQuantLib
Analytical Delta✅ Yes✅ Yes
Dividend support❌ No✅ Yes
Yield curve support❌ No✅ Yes
Vol surface support❌ No✅ Yes
Performance⚡ Very fast🐢 Slower (but flexible)
Good for learning✅ Absolutely✅ But more complex
Good for real-world desks❌ Not sufficient✅ Industry standard

If you’re writing an educational article or prototyping, the vanilla version is perfect. If you’re integrating with a full market data and pricing system, QuantLib is the go-to.

You may also like