Options Greeks are a set of quantities representing an option’s price sensitivity to its underlying parameters. Each of them measures a different dimension of the risk in an option position.
They fall out elegantly from derivatives of the Black-Scholes options pricing formula.
This tutorial will go through the Options Greeks, and how to derive them from derivatives of the Black-Scholes option pricing formula for call and put options.
Then we will go through how to create functions to calculate the Options Greeks in Python, C++, and R with code examples.
Table of contents
What is the Black-Scholes Options Pricing Formula
The Black-Scholes or Black-Scholes-Merton model is a financial mathematical equation for pricing options contracts and other derivatives.
Using the Black-Scholes model, the price of a European call option is calculated using the formula:
$$C= S_{0}N(d_{1})~- Xe^{-r\tau}N(d_{2}) $$
and for the price of a European put option:
$$P= ~- Xe^{-r\tau}N(d_{2}) ~- S_{0}N(-d_{1})$$
With:
$$d_{1} = \frac{\text{ln}\frac{S_{0}}{X} + (r + \sigma^{2}/2)*\tau}{\sigma\sqrt{\tau}}, \qquad d_{2} = \frac{\text{ln}\frac{S_{0}}{X} + (r – \sigma^{2}/2)*\tau}{\sigma\sqrt{\tau}} = d_{1} – \sigma\sqrt{\tau}$$
Where:
- C = price of the call option
- S0 = price of the underlying stock
- X = option exercise price or strike price
- r = risk-free interest rate
- π = time until expiration (maturity)
- π = the volatility of the underlying asset.
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”.
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 Option Greeks Explained
Option Greeks are a set of quantities representing an option’s price sensitivity to its underlying parameters. Each of them measures a different dimension of the risk in an option position.
Delta (Ξ)
Delta measures the rate of change of option value with respect to changes in the underlying asset’s price
$$\Delta = \frac{\partial V}{\partial S_{0}} $$
Gamma (Ξ)
Gamma measures the rate of change in Delta with respect to changes in the underlying price.
$$\Gamma = \frac{\partial \Delta}{\partial S_{0}} $$
Theta (Ο΄)
Theta measures the sensitivity of the option value to the passage of time.
$$\Theta = -\frac{\partial V}{\partial \tau} $$
Vega (V)
Vega is the rate of change of the option price with respect to the underlying stock’s volatility.
$$\nu = \frac{\partial V}{\partial \sigma} $$
For further reading on how volatility is found, go to the article: How to Calculate Implied Volatility in Python.
Rho (Ο)
Rho is the rate of change of the option price with respect to the interest rate.
$$\rho = \frac{\partial V}{\partial r} $$
Where V denotes the option’s value, either C for the call option or P for the put option.
Options Greeks Expressions
Taking the Black-Scholes Formulae for call and put option pricing as follows:
$$ C= S_{0}N(d_{1}) ~- Xe^{-rt}N(d_{2}), \qquad P= -S_{0}N(-d_{1}) ~- Xe^{-rt}N(d_{2})$$
The expressions for the Options Greeks can be derived as follows:
Call option (C): $$ \Delta = \frac{\partial C}{\partial S_{0}} = N(d_{1})$$ $$ \Theta = -\frac{\partial C}{\partial \tau} = -rXe^{-r\tau}N(d_{2}) ~- \frac{\sigma}{2\sqrt{\tau}}S_{0}n(d_{1})$$ $$ \Gamma = \frac{\partial \Delta}{\partial S_{0}} = \frac{1}{S_{0}\sigma\sqrt{\tau}}n(d_{1})$$ $$ \nu = \frac{\partial C}{\partial \sigma} = \sqrt{\tau}S_{0}n(d_{1}) $$ $$ \rho = \frac{\partial C}{\partial r} = \tau Xe^{-r\tau}N(d_{2}) $$ Put option (C): $$ \Delta = \frac{\partial P}{\partial S_{0}} = N(d_{1}) ~- 1$$ $$ \Theta = ~-\frac{\partial P}{\partial \tau} = ~- \frac{\sigma}{2\sqrt{\tau}}S_{0}n(d_{1}) + rXe^{-r\tau}N(-d_{2}) $$ $$ \Gamma = \frac{\partial \Delta}{\partial S_{0}} = \frac{1}{S_{0}\sigma\sqrt{\tau}}n(d_{1})$$ $$ \nu = \frac{\partial P}{\partial \sigma} = \sqrt{\tau}S_{0}n(d_{1}) $$ $$ \rho = \frac{\partial P}{\partial r} = -\tau Xe^{-r\tau}N(-d_{2}) $$
Calculate Options Greeks using Black-Scholes Formula in Python
Let’s go through how to calculate the Options Greeks in Python. First, we will import the necessary mathematical and statistical functions from math and scipy.stats. Then, we will define functions for the d1 and d2 variables, and the call and put options pricing.
from math import log, sqrt, pi, exp
from scipy.stats import norm
# Function for d1 variable
def d1(S,K,T,r,sigma):
return(log(S/K)+(r+sigma**2/2.)*T)/(sigma*sqrt(T))
# Function for d2 variable
def d2(S,K,T,r,sigma):
return d1(S,K,T,r,sigma)-sigma*sqrt(T)
# Function for Call option pricing using Black-Scholes
def bs_call(S,K,T,r,sigma):
return S*norm.cdf(d1(S,K,T,r,sigma))-K*exp(-r*T)*norm.cdf(d2(S,K,T,r,sigma))
# Function for Put option pricing using Black-Scholes
def bs_put(S,K,T,r,sigma):
return K*exp(-r*T)*norm.cdf(-1 * d2(S,K,T,r,sigma)) - S*norm.cdf(-1*d1(S,K,T,r,sigma))
Next, we will define the call Option Greeks using the expressions in the Options Greeks Expressions section.
# Function for Call Delta function
def call_delta(S, K, T, r, sigma):
return norm.cdf(d1(S,K,T,r,sigma))
# Function for Call Theta function
def call_theta(S,K,T,r,sigma):
theta_1 = -r*K*exp(-r*T)*norm.cdf(d2(S,K,T,r,sigma))
theta_2 = sigma*S*norm.pdf(d1(S,K,T,r,sigma))/(2*sqrt(T))
# Divide by 365 to get the change in option price per one calendar day, otherwise change would be per one year
theta = (theta_1 - theta_2) / 365
return theta
# Function for Call Gamma function
def call_gamma(S, K, T, r, sigma):
return norm.pdf(d1(S,K,T,r,sigma))/(S*sigma*sqrt(T))
# Function for Call Vega function
def call_vega(S, K, T, r, sigma):
return 0.01 * (sqrt(T)*S*norm.pdf(d1(S, K, T, r, sigma)))
# Function for Call Rho function
def call_rho(S, K, T, r, sigma):
return 0.01 * (T*K*exp(-r*T)*norm.cdf(d2(S, K, T, r, sigma)))
Next, we will define the put Option Greeks using the expressions in the Options Greeks Expressions section.
# Function for Put Delta function
def put_delta(S, K, T, r, sigma):
return norm.cdf(d1(S,K,T,r,sigma)) - 1
# Function for Put Theta function
def put_theta(S, K, T, r, sigma):
theta_1 = -1*sigma*S*norm.pdf(d1(S,K,T,r,sigma))/(2*sqrt(T))
theta_2 = r*K*exp(-r*T)*norm.cdf(-1*d2(S,K,T,r,sigma))
# Divide by 365 to get the change in option price per one calendar day, otherwise change would be per one year
theta = (theta_1 + theta_2) / 365
return theta
# Function for Put Gamma function
def put_gamma(S, K, T, r, sigma):
return norm.pdf(d1(S,K,T,r,sigma))/(S*sigma*sqrt(T))
# Function for Put Vega function
def put_vega(S, K, T, r, sigma):
return 0.01 * (sqrt(T)*S*norm.pdf(d1(S, K, T, r, sigma)))
# Function for Put Rho function
def put_rho(S, K, T, r, sigma):
return 0.01 * -1* (T*K*exp(-r*T)*norm.cdf(-1*d2(S, K, T, r, sigma)))
Now, we can define our main function, and set values for the price of the underlying stock, the strike price, the risk-free interest rate, volatility, and the time until expiration. We can then price the call and put options and calculate the Options Greeks.
if __name__ == '__main__':
S = 110
K = 100
T = 1
r = 0.04
sigma = 0.2
call = bs_call(S, K, T, r, sigma)
delta = call_delta(S,K,T,r,sigma)
gamma = call_gamma(S,K,T,r,sigma)
theta = call_theta(S,K,T,r,sigma)
rho = call_rho(S,K,T,r,sigma)
vega = call_vega(S,K,T,r,sigma)
put = bs_put(S, K, T, r, sigma)
put_delta = put_delta(S,K,T,r,sigma)
put_gamma = put_gamma(S,K,T,r,sigma)
put_theta = put_theta(S,K,T,r,sigma)
put_rho = put_rho(S,K,T,r,sigma)
put_vega = put_vega(S,K,T,r,sigma)
print('Call option price:', round(call,2))
print('Call Delta: ', round(delta,3))
print('Call Gamma: ', round(gamma,3))
print('Call Theta: ', round(theta,3))
print('Call Rho: ', round(rho,3))
print('Call Vega: ', round(vega,3))
print('===================================')
print('Put option price:', round(put,2))
print('Put Delta: ', round(put_delta,3))
print('Put Gamma: ', round(put_gamma,3))
print('Put Theta: ', round(put_theta,3))
print('Put Rho: ', round(put_rho,3))
print('Put Vega: ', round(put_vega,3))
Let’s run the code to see the result:
Call option price: 16.97 Call Delta: 0.781 Call Gamma: 0.013 Call Theta: -0.016 Call Rho: 0.69 Call Vega: 0.325 =================================== Put option price: 3.05 Put Delta: -0.219 Put Gamma: 0.013 Put Theta: -0.006 Put Rho: -0.271 Put Vega: 0.325
Calculate Options Greeks using Black-Scholes Formula in C++
Let’s go through how to calculate the Options Greeks in C++. First, we will define the Standard normal probability density function, cumulative distribution function, the d1,d2 variables, and the call and put option pricing formulae.
#include <iostream>
#include <cmath>
// Standard normal probability density function
double norm_pdf(const double& x) {
return (1.0/(pow(2*M_PI,0.5)))*exp(-0.5*x*x);
}
// Standard normal cumulative distribution function
double normalCDF(double x) // Phi(-β, x) aka N(x){
return std::erfc(-x/std::sqrt(2))/2;
}
// d1 variable
double d_1(const double& S, const double& K, const double& r, const double& T, const double& sig){
return (log(S/K) + (r + pow(sig,2)/2)*T) / (sig*(pow(T,0.5)));
}
// d1 variable
double d_2(const double& S, const double& K, const double& r, const double& T, const double& sig) {
return (log(S/K) + (r - pow(sig,2)/2)*T) / (sig*(pow(T,0.5)));
}
// Function for Call option pricing using Black-Scholes
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));
}
// Function for Put option pricing using Black-Scholes
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));
}
Next, let’s define functions for the call and put Option Greeks using the expressions in the Options Greeks Expressions section.
// Function for Call Delta
double call_delta(const double& S, const double& K, const double& r, const double& T, const double& sig) {
return normalCDF(d_1(S,K,r,T,sig));
}
// Function for Call Gamma
double call_gamma(const double& S, const double& K, const double& r, const double& T, const double& sig) {
return norm_pdf(d_1(S,K,r,T,sig))/(S*sig*pow(T,0.5));
}
// Function for Call Theta
double call_theta(const double& S, const double& K, const double& r, const double& T, const double& sig) {
double theta_1 = -r*K*exp(-r*T)* normalCDF(d_2(S,K,r,T,sig));
double theta_2 = sig*S* norm_pdf(d_1(S,K,r,T,sig))/(2*pow(T,0.5));
// Divide by 365 to get the change in option price per one calendar day, otherwise change would be per one year
double theta = (theta_1 - theta_2) / 365;
return theta;
}
// Function for Call Rho
double call_rho(const double& S, const double& K, const double& r, const double& T, const double& sig) {
return 0.01 * (T * K * exp(-r * T)* normalCDF(d_2(S,K,r,T,sig)));
}
// Function for Call Vega
double call_vega(const double& S, const double& K, const double& r, const double& T, const double& sig) {
return 0.01 * (pow(T,0.5) * S * norm_pdf(d_1(S,K,r,T,sig)));
}
// Function for Put Delta
double put_delta(const double& S, const double& K, const double& r, const double& T, const double& sig) {
return normalCDF(d_1(S,K,r,T,sig)) - 1;
}
// Function for Put Gamma
double put_gamma(const double& S, const double& K, const double& r, const double& T, const double& sig) {
return norm_pdf(d_1(S,K,r,T,sig))/(S*sig*pow(T,0.5));
}
// Function for Put Theta
double put_theta(const double& S, const double& K, const double& r, const double& T, const double& sig) {
double theta_1 = -1*sig*S* norm_pdf(d_1(S,K,r,T,sig))/(2*pow(T,0.5));
double theta_2 = r*K*exp(-r*T)* normalCDF(-1*d_2(S,K,r,T,sig));
// Divide by 365 to get the change in option price per one calendar day, otherwise change would be per one year
double theta = (theta_1 + theta_2) / 365;
return theta;
}
// Function for Put Rho
double put_rho(const double& S, const double& K, const double& r, const double& T, const double& sig) {
return 0.01 * -1 *(T * K * exp(-r * T)* normalCDF(-1* d_2(S,K,r,T,sig)));
}
// Function for Put Vega
double put_vega(const double& S, const double& K, const double& r, const double& T, const double& sig) {
return 0.01 * (pow(T,0.5) * S * norm_pdf(d_1(S,K,r,T,sig)));
}
Now, we can define our main function, and set values for the price of the underlying stock, the strike price, the risk-free interest rate, the volatility, and the time until expiration. We can then price the call and put options and calculate the Options Greeks.
int main() {
// 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
// Then we calculate the call/put values
// double call = call_price(S, K, r, T, sig);
// double put = put_price(S, K, r, T, sig);
// Then we calculate the call/put values
double call = call_price(S, K, r, T, sig);
double put = put_price(S, K, r, T, sig);
double delta = call_delta(S, K, r, T, sig);
double theta = call_theta(S, K, r, T, sig);
double gamma = call_gamma(S, K, r, T, sig);
double vega = call_vega(S, K, r, T, sig);
double rho = call_rho(S, K, r, T, sig);
double p_delta = put_delta(S, K, r, T, sig);
double p_theta = put_theta(S, K, r, T, sig);
double p_gamma = put_gamma(S, K, r, T, sig);
double p_vega = put_vega(S, K, r, T, sig);
double p_rho = put_rho(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;
std::cout << "Call Delta: " << delta << std::endl;
std::cout << "Call Gamma: " << gamma << std::endl;
std::cout << "Call Theta: " << theta << std::endl;
std::cout << "Call Rho: " << rho << std::endl;
std::cout << "Call Vega: " << vega << std::endl;
std::cout << "Put Delta: " << p_delta << std::endl;
std::cout << "Put Gamma: " << p_gamma << std::endl;
std::cout << "Put Theta: " << p_theta << std::endl;
std::cout << "Put Rho: " << p_rho << std::endl;
std::cout << "Put Vega: " << p_vega << std::endl;
return 0;
}
Let’s run the code to see the result:
Underlying: 110 Strike: 100 Risk-Free Rate: 0.04 Volatility: 0.2 Maturity: 1 Call Price: 16.9687 Put Price: 3.04762 Call Delta: 0.781288 Call Gamma: 0.0134135 Call Theta: -0.016452 Call Vega: 0.324606 Call Rho: 0.68973 Put Delta: -0.218712 Put Gamma: 0.0134135 Put Theta: -0.00592279 Put Vega: 0.324606 Put Rho: -0.271059
Calculate Options Greeks using Black-Scholes Formula in R
Let’s go through how to calculate the Options Greeks in R. First, we will define functions for the d1, d2 variables and the call and put option pricing.
# d1 variable
d1 <- function(S, K, r, T, sig){
(log(S/K) + (r+sig^2/2)*T)/(sig*sqrt(T))
}
# d2 variable
d2 <- function(S, K, r, T, sig){
(log(S/K) + (r-sig^2/2)*T)/(sig*sqrt(T))
}
# Function for Call option pricing using Black-Scholes
call_price <- function(S, K, r, T, sig){
call <- S*pnorm(d1(S,K,r,T,sig)) - K*exp(-r*T)*pnorm(d2(S,K,r,T,sig))
return (call)
}
# Function for Put option pricing using Black-Scholes
put_price <- function(S, K, r, T, sig){
put <- K*exp(-r*T)*pnorm(-d2(S,K,r,T,sig)) - S*pnorm(-d1(S,K,r,T,sig))
return (put)
}
Let’s define the call and put Option Greeks using the expressions in the Options Greeks Expressions section.
# Function for Call Delta
call_delta <- function(S,K,r,T,sig){
delta <- pnorm(d1(S,K,r,T,sig))
return(delta)
}
# Function for Call Gamma
call_gamma <- function(S,K,r,T,sig){
gamma <- dnorm(d1(S,K,r,T,sig))/(S*sig*sqrt(T))
return(gamma)
}
# Function for Call Theta
call_theta <- function(S,K,r,T,sig){
theta_1 = -1* r * K * exp(-r*T)*pnorm(d2(S,K,r,T,sig))
theta_2 = sig * S * dnorm(d1(S,K,r,T,sig))/(2*sqrt(T))
# Divide by 365 to get the change in option price per one calendar day, otherwise change would be per one year
theta = (theta_1-theta_2)/365
return (theta)
}
# Function for Call Rho
call_rho <- function(S,K,r,T,sig){
rho <- 0.01 * (T * K * exp(-r*T)*pnorm(d2(S,K,r,T,sig)))
return(rho)
}
# Function for Call Vega
call_vega <- function(S,K,r,T,sig){
vega <- 0.01 * (sqrt(T) * S * dnorm(d1(S,K,r,T,sig)))
return(vega)
}
# Function for Put Delta
put_delta <- function(S,K,r,T,sig){
delta <- pnorm(d1(S,K,r,T,sig)) - 1
return(delta)
}
# Function for Put Gamma
put_gamma <- function(S,K,r,T,sig){
gamma <- dnorm(d1(S,K,r,T,sig))/(S*sig*sqrt(T))
}
# Function for Put Theta
put_theta <- function(S,K,r,T,sig){
theta_1 = -1*sig * S * dnorm(d1(S,K,r,T,sig))/(2*sqrt(T))
theta_2 = r * K * exp(-r*T)*pnorm(-1* d2(S,K,r,T,sig))
theta = (theta_1+theta_2)/365
return (theta)
}
# Function for Put Rho
put_rho <- function(S,K,r,T,sig){
rho <- 0.01 * -1* (T * K * exp(-r*T)*pnorm(-1*d2(S,K,r,T,sig)))
}
# Function for Put Vega
put_vega <- function(S,K,r,T,sig){
vega <- 0.01 * (sqrt(T) * S * dnorm(d1(S,K,r,T,sig)))
}
Next, we will call the defined functions to get the call and put options prices and the Options Greeks, then assign them to variables.
call <- call_price(110, 100, 0.04, 1, 0.2) put <- put_price(110, 100, 0.04, 1, 0.2) c_delta <- call_delta(110, 100, 0.04, 1, 0.2) c_gamma <- call_gamma(110, 100, 0.04, 1, 0.2) c_theta <- call_theta(110, 100, 0.04, 1, 0.2) c_rho <- call_rho(110, 100, 0.04, 1, 0.2) c_vega <- call_vega(110, 100, 0.04, 1, 0.2) p_delta <- put_delta(110, 100, 0.04, 1, 0.2) p_gamma <- put_gamma(110, 100, 0.04, 1, 0.2) p_theta <- put_theta(110, 100, 0.04, 1, 0.2) p_rho <- put_rho(110, 100, 0.04, 1, 0.2) p_vega <- put_vega(110, 100, 0.04, 1, 0.2)
Next, we will use the cat function to print all of the values to the console:
cat("Call price=", call,
"\nPut price=", put,
"\nCall Delta=",c_delta,
"\nCall Gamma=",c_gamma,
"\nCall Theta=",c_theta,
"\nCall Rho=",c_rho,
"\nCall Vega=",c_vega,
"\n\nPut Delta=",p_delta,
"\nPut Gamma=",p_gamma,
"\nPut Theta=",p_theta,
"\nPut Rho=",p_rho,
"\nPut Vega=",p_vega
)
Let’s run the code to get the result:
Call price= 16.96868 Put price= 3.047622 Call Delta= 0.7812881 Call Gamma= 0.01341346 Call Theta= -0.01645199 Call Rho= 0.6897301 Call Vega= 0.3246057 Put Delta= -0.2187119 Put Gamma= 0.01341346 Put Theta= -0.005922795 Put Rho= -0.2710593 Put Vega= 0.3246057
Summary
Congratulations on reading to the end of this tutorial!
For further reading on the Black-Scholes Option Pricing model and how to use it in R, Python, and C++, go to the articles:
- Black-Scholes Option Pricing in R
- Black-Scholes Option Pricing in Python
- Black-Scholes Option Pricing in C++
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.
For a detailed implementation of the Black-Scholes model in a production environment, explore our C++ options pricing calculator on The Research Scientist Pod’s GitHub repository. The project includes complete Greeks calculations and a user-friendly interface. Don’t forget to star the repository and follow us for more quantitative finance implementations!
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.
