@Sanjay's answer is correct but there is an important consideration from a practical perspective.
Closed form theta in BS is the change per unit time (the change after one year). In other words, mathematically the result of the formula for theta is expressed in value per year. Many professional pricing engines actually display it as 1 day theta (computed as BS_Theta / 365).
More often though, finite difference (FD) theta is actually computed as a true 1 day bump and reprice theta (shifting the evaluation date one day forward and repricing). A complete replication of Bloomberg's OVML and Quantlib can be found in this answer. Using FD theta has at least two advantages:
- BS theta can exceed actual market value of an option if the time to expiry is short (see below for an example)
- Holidays and weekends can easily be included in the computation (Friday will be a 3 day theta, provided Monday is a working day)
In any case, the value from the calculator that Sanjay provided is a 1 year theta, which is easy to show with the following Julia code:
using Distributions, DataFrames
N(x) = cdf(Normal(0,1),x)
n(x) = pdf(Normal(0,1),x)
function BSM(S,K,t,r,d,σ, cp)
d1 = ( log(S/K) + (r - d + 1/2*σ^2)*t ) / (σ*sqrt(t))
d2 = d1 - σ*sqrt(t)
opt = cp*exp(-d*t)S*N(cp*d1) - cp*exp(-r*t)*K*N(cp*d2)
theta_c = (-(S * exp(-d*t)*n(d1)* σ )/ (2 * sqrt(t)) - r * K * exp(-r*t) * N(d2) + d * S * exp(-d*t)*N(d1))
theta_p = (-(S * exp(-d*t)*n(d1)* σ )/ (2 * sqrt(t)) + r * K * exp(-r*t) * N(-d2) - d * S * exp(-d*t)*N(-d1))
return opt, theta_c, theta_p
S, K, r, t, σ = 50, 50, 0.12, 0.25, 0.3
res = BSM(S, K, t, r, 0, σ, 1)
DataFrame(Call = res, Theta = res )
This theta value is in line with the calculator used by Sanjay (this is assuming rates are continuous).
However, it is rather useless from a practical perspective. What one would usually do is to look at what happens to the option price with one less day to expiry. You get this value by dividing BS theta by 365. FD theta is the result of repricing the model with one less day to expiry, keeping all else equal and simply looking at the price difference between the two option values.
res2 = BSM(S, K, t - 1/365, r, 0, σ, 1)
day_theta = res/365
fd_theta = res2- res
DataFrame(Symbol("Call") => res, Symbol("Call -1 day") => res2, Symbol("Theta") => res, Symbol("1 Day Theta") => day_theta, Symbol("FD Theta") => fd_theta)
We can use the below example, which prices a OTM option with 5 days to expiry and 1 million notional, to show why FD theta is often preferred. BS theta would actually result in a negative option value in this case.
r1 = BSM(45, 50, 5/365, r, 0, σ, 1) .* 1000000
r2 = BSM(45, 50, 4/365, r, 0, σ, 1) .* 1000000
DataFrame(Symbol("Call") => r1, Symbol("Call -1 day") => r2, Symbol("1 Day Theta") => r1/365, Symbol("FD Theta") => r2 - r1)