34inline constexpr double kMinVol = 1e-4;
40[[nodiscard]]
inline double norm_pdf(
double x)
noexcept {
41 return 0.398942280401432677939946 * std::exp(-0.5 * x * x);
43[[nodiscard]]
inline double norm_cdf(
double x)
noexcept {
44 return 0.5 * std::erfc(-x * 0.707106781186547524400844);
48[[nodiscard]]
constexpr double year_fraction(std::int64_t expiry_ns, std::int64_t now_ns)
noexcept {
68 double rate = 0.0) noexcept {
70 if (!(forward > 0.0) || !(strike > 0.0))
return g;
71 const double df = std::exp(-rate * (t_years > 0.0 ? t_years : 0.0));
73 if (!(t_years > 0.0) || !(sigma > 0.0)) {
74 const double intrinsic = call ? forward - strike : strike - forward;
75 if (intrinsic > 0.0) {
76 g.price = df * intrinsic;
77 g.delta = call ? df : -df;
81 const double sqrt_t = std::sqrt(t_years);
82 const double sd = sigma * sqrt_t;
83 const double d1 = (std::log(forward / strike) + 0.5 * sd * sd) / sd;
84 const double d2 = d1 - sd;
93 g.gamma = df * pdf / (forward * sd);
94 g.vega = df * forward * pdf * sqrt_t;
95 g.theta = -df * forward * pdf * sigma / (2.0 * sqrt_t) + rate * g.price;
96 g.rho = -t_years * g.price;
105 double rate = 0.0) noexcept {
106 return black76(cp, forward, strike, t_years, sigma, rate).
price;
132 double price_tol = 1e-12,
133 int max_iterations = 100) noexcept {
135 if (!(forward > 0.0) || !(strike > 0.0) || !(t_years > 0.0) || !std::isfinite(price) ||
136 !std::isfinite(rate))
140 const double p = price * std::exp(rate * t_years);
141 const double intrinsic = call ? std::max(forward - strike, 0.0) : std::max(strike - forward, 0.0);
142 const double upper = call ? forward : strike;
143 const double tol = price_tol > 0.0 ? price_tol : 1e-12;
144 if (p < intrinsic - tol || p >= upper) {
150 if (p <=
black76_price(cp, forward, strike, t_years, lo) + tol) {
160 std::sqrt(2.0 * std::numbers::pi / t_years) * (p - intrinsic) / (0.5 * (forward + strike));
161 if (!(sigma > lo && sigma < hi)) sigma = 0.5;
162 const double sqrt_t = std::sqrt(t_years);
163 for (
int i = 1; i <= max_iterations; ++i) {
165 const Greeks g =
black76(cp, forward, strike, t_years, sigma);
166 const double diff = g.price - p;
167 if (std::fabs(diff) <= tol) {
177 if (hi - lo <= 1e-15 * hi) {
178 r.vol = 0.5 * (lo + hi);
183 forward *
norm_pdf(std::log(forward / strike) / (sigma * sqrt_t) + 0.5 * sigma * sqrt_t) *
185 double next = vega > 1e-300 ? sigma - diff / vega : 0.0;
187 if (!(next > lo && next < hi))
188 next = 0.5 * (lo + hi);
191 r.vol = 0.5 * (lo + hi);
199[[nodiscard]]
inline double to_coin_price(
double quote_value,
double forward)
noexcept {
200 return forward > 0.0 ? quote_value / forward : 0.0;
204[[nodiscard]]
constexpr double coin_delta(
double delta,
double coin_price)
noexcept {
205 return delta - coin_price;
Definition black76.hpp:33
Greeks black76(CallPut cp, double forward, double strike, double t_years, double sigma, double rate=0.0) noexcept
Price and greeks.
Definition black76.hpp:65
double to_coin_price(double quote_value, double forward) noexcept
Quote-currency value -> price in the base coin (Deribit BTC options: USD / underlying price).
Definition black76.hpp:200
constexpr double year_fraction(std::int64_t expiry_ns, std::int64_t now_ns) noexcept
Year fraction between two epoch-ns timestamps (ACT/365); negative once expired.
Definition black76.hpp:50
constexpr double kMinVol
0.01 % annualised
Definition black76.hpp:36
double norm_pdf(double x) noexcept
Standard normal density and distribution. erfc keeps the far tail accurate (no 1 - N(x)).
Definition black76.hpp:42
IvResult implied_vol(CallPut cp, double price, double forward, double strike, double t_years, double rate=0.0, double price_tol=1e-12, int max_iterations=100) noexcept
Implied volatility of a Black-76 price.
Definition black76.hpp:128
constexpr double coin_delta(double delta, double coin_price) noexcept
Delta of a coin-quoted option in coin units.
Definition black76.hpp:205
constexpr double kMaxVol
1000 % annualised
Definition black76.hpp:37
double black76_price(CallPut cp, double forward, double strike, double t_years, double sigma, double rate=0.0) noexcept
Definition black76.hpp:102
CallPut
Definition black76.hpp:39
double norm_cdf(double x) noexcept
Definition black76.hpp:45
constexpr double kSecondsPerYear
ACT/365, as Deribit's theta.
Definition black76.hpp:35
IvStatus
Definition black76.hpp:111
@ AtIntrinsic
price at (or within tolerance of) the no-arbitrage lower bound: vol 0
@ OutOfBounds
below intrinsic, or above what kMaxVol can produce
@ NoConvergence
iteration bound hit; vol is the best bracket midpoint
@ BadInput
non-positive forward/strike/time or non-finite price
Definition black76.hpp:54
double price
Definition black76.hpp:55
double rho
Definition black76.hpp:60
double theta
Definition black76.hpp:59
double vega
Definition black76.hpp:58
double gamma
Definition black76.hpp:57
double delta
Definition black76.hpp:56
Definition black76.hpp:119
bool ok() const noexcept
Definition black76.hpp:123
IvStatus status
Definition black76.hpp:121
int iterations
Definition black76.hpp:122
double vol
Definition black76.hpp:120