The Black-Scholes or Black-Scholes-Merton model is a financial mathematical equation for pricing options contracts and other derivatives.
Fischer Black and Myron Scholes published the formula in their 1973 paper “The Pricing of Options and Corporate Liabilities“. Robert C. Merton published a paper expanding on the mathematical understanding of the options pricing model and devised the term “Black-Scholes options pricing model”.
This tutorial will go through how to write the Black-Scholes options pricing formula from scratch in C++ and how to use the formula to price an option.
You can use our free Black-Scholes option pricing calculator to estimate the fair value of a European call or put option.
Formula
Using the Black-Scholes model, the price of a European call option (only one time you can exercise the option) is calculated using the formula:
C = S0N(d1) – Xe-rtN(d2)
Where:
- C = price of the call option
- S0 = price of the underlying stock
- X = option exercise price
- r = risk-free interest rate
- t = time until expiration (maturity)
N represents the cumulative distribution function for a normal (Gaussian) distribution, which we can understand as “the probability that a random variable is less or equal to its input for a normal distribution”.
d1 = (ln(S0/X) + (r + π2 / 2 )*T) / (πβT)
d2 = (ln(S0/X) + (r – π2 / 2 )*T) / (πβT)
Where π is the volatility of the underlying asset.
We can think of the two terms in the sum as the current price in the stock weighted by the probability of exercising the option to buy the stock minus the discounted price of exercising the option weighted by the probability of exercising the option. In other words, what you will pay minus what you will receive (Introduction to the Black-Scholes formula, Khan Academy 2013).
The price of a put option is:
P = Xe-rtN(-d2) – S0N(-d1)
You can use our free Black-Scholes option pricing calculator to estimate the fair value of a European call or put option.
Black-Scholes Assumptions
The Black-Scholes model holds the following assumptions:
- The option is European and can only be exercised at expiration
- The returns of the underlying asset are normally distributed
- Markets are random, in that market movements cannot be predicted
- No dividends are paid out during the life of the option
- No transaction costs for buying the option
- Risk-free interest rate and volatility of the underlying asset are known and constant
The original model does not account for dividends paid during the lifetime of the option, but there are versions of the model that account for dividends by determining the ex-dividend date value of the underlying asset. The model has also been adapted for the effect of options that can be exercised before expiration.
Black-Scholes Using C++ From Scratch
We can write a function to calculate the option price once we have the values for the parameters:
- S = price of the underlying stock
- K = option exercise price
- r = risk-free interest rate
- t = time until expiration (maturity)
- sig = volatility of the underlying asset
First, we need to import iostream for std::cout and the cmath libraries for the mathematical functions sqrt, exp, pow, and sqrt. Then, we can define the normal cumulative distribution function.
#include <iostream> #include <cmath> double normalCDF(double x) // Phi(-β, x) aka N(x) { return std::erfc(-x/std::sqrt(2))/2; }
Next, we will define the d1 and d2 variables:
// Define functions for d_1 and d_2 double d_1(const double& S, const double& K, const double& r, const double& T, const double& sig){ double d1 = (log(S/K) + (r + pow(sig,2)/2)*T) / (sig*(pow(T,0.5))); return d1; } double d_2(const double& S, const double& K, const double& r, const double& T, const double& sig) { double d2 = (log(S/K) + (r - pow(sig,2)/2)*T) / (sig*(pow(T,0.5))); return d2; }
Next, we can price a European call and put option with the following functions:
// Calculate the European vanilla call price based on // underlying S, strike K, risk-free rate r, volatility of // underlying sigma and time to maturity T double call_price(const double& S, const double& K, const double& r, const double& T, const double& sig) { return S * normalCDF((d_1(S, K, r, T, sig))) - K*exp(-r*T)* normalCDF(d_2(S,K, r, T, sig)); } double put_price(const double& S, const double& K, const double& r, const double& T, const double& sig) { return -S * normalCDF(-d_1(S, K, r, T, sig)) + K*exp(-r*T)* normalCDF(-d_2(S,K, r, T, sig)); }
Once, we have all of the functions defined we can write the main program, which assigns values to the required parameters, calculates the call and put prices and print them to the console.
int main(int argc, char **argv) { // First we create the parameter list double S = 110.0; // Option price double K = 100.0; // Strike price double r = 0.04; // Risk-free rate (5%) double sig = 0.2; // Volatility of the underlying (20%) double T = 1.0; // One year until expiry // Calculate the call/put values double call = call_price(S, K, r, T, sig); double put = put_price(S, K, r, T, sig); // Output the parameters and prices std::cout << "Underlying: " << S << std::endl; std::cout << "Strike: " << K << std::endl; std::cout << "Risk-Free Rate: " << r << std::endl; std::cout << "Volatility: " << sig << std::endl; std::cout << "Maturity: " << T << std::endl; std::cout << "Call Price: " << call << std::endl; std::cout << "Put Price: " << put << std::endl; return 0; }
Let’s run the code to get the call and put prices:
Underlying: 110 Strike: 100 Risk-Free Rate: 0.04 Volatility: 0.2 Maturity: 1 Call Price: 16.9687 Put Price: 3.04762
Summary
Congratulations on reading to the end of this tutorial!
To learn how to use Black-Scholes in R and Python, go to the articles:
For further reading on the Options Greeks, go to the article:
You can use our free Black-Scholes option pricing calculator to estimate the fair value of a European call or put option.
You can use our free Implied Volatility calculator to estimate the Implied Volatility of a priced option.
Have fun and happy researching!
Suf is a senior advisor in data science with deep expertise in Natural Language Processing, Complex Networks, and Anomaly Detection. Formerly a postdoctoral research fellow, he applied advanced physics techniques to tackle real-world, data-heavy industry challenges. Before that, he was a particle physicist at the ATLAS Experiment of the Large Hadron Collider. Now, heβs focused on bringing more fun and curiosity to the world of science and research online.