npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

options-greeks

v1.0.0

Published

Black-Scholes-Merton (with dividend yield) and Black-76 option prices, greeks (delta, gamma, vega, theta, rho, vanna, charm, vomma) and a robust implied-volatility solver. Double-precision normal CDF, zero dependencies.

Readme

options-greeks

European option prices, greeks and implied volatility: Black-Scholes-Merton with a continuous dividend yield (stocks, indices, FX) and Black-76 (futures and forwards), first-order greeks (delta, gamma, vega, theta, rho), the second-order vanna, charm and vomma, and a safeguarded implied-volatility solver that converges from 1-hour to 10-year expiries and from deep in- to deep out-of-the-money. Built on a double-precision normal CDF. Typed, zero dependencies.

npm install options-greeks

Why

The Black-Scholes packages most people still install date from 2014. black-scholes, greeks and implied-volatility take no dividend yield, so they can't price index or FX options. black-scholes computes the normal CDF from a 100-term Taylor series, which loses precision in the tail: Φ(−7) is off by 5e-4 relative, Φ(−7.95) comes out negative, and an out-of-the-money call (S=100, K=150, T=0.1, σ=20%) is off by 8e-4. implied-volatility runs 100 bisection steps on that pricer and never signals failure. Give it a price below intrinsic and it returns 7.9e-32. Give it a price above the no-arbitrage bound and it returns 1.3e29. The newer option-pricing (2022) has a dividend yield but prices only, with no greeks or implied vol, and its CDF is accurate to only ~1e-7. This package does all of it, to double precision, with documented units and explicit failure values.

import { price, greeks, impliedVol } from "options-greeks";

// Hull's textbook example
price({ type: "call", spot: 42, strike: 40, rate: 0.1, vol: 0.2, time: 0.5 }); // 4.7594
price({ type: "put",  spot: 42, strike: 40, rate: 0.1, vol: 0.2, time: 0.5 }); // 0.8086

// An index put with a dividend yield: everything in one pass
const g = greeks({ type: "put", spot: 5000, strike: 4800, rate: 0.045, dividendYield: 0.015, vol: 0.18, time: 30 / 365 });
g.price;        // 28.288
g.delta;        // -0.1934
g.gamma;        // 0.001063
g.vega;         // 393.02  per 1.00 of vol    (g.vegaPerPoint 3.930 per vol point)
g.theta;        // -400.08 per year           (g.thetaPerDay -1.0961 per calendar day)
g.rho;          // -81.80  per 1.00 of rate   (g.rhoPerPoint -0.8180 per 1%)
g.vanna;        // -1.2384
g.charm;        // 1.1938  delta change per year
g.vomma;        // 1534.94

// Black-76: pass `forward` instead of `spot`
price({ type: "call", forward: 72.5, strike: 75, rate: 0.04, vol: 0.35, time: 0.25 }); // 3.9485

// Implied volatility
impliedVol({ type: "call", spot: 42, strike: 40, rate: 0.1, time: 0.5, price: 4.76 });     // 0.20007
impliedVol({ type: "put", spot: 100, strike: 60, rate: 0.05, time: 7 / 365, price: 1e-12 }); // 0.5280
impliedVol({ type: "call", spot: 100, strike: 50, rate: 0.05, time: 1, price: 40 });      // NaN: below intrinsic

API

Every function takes one object. Provide either spot (Black-Scholes-Merton) or forward (Black-76):

{ type: "call" | "put", spot: number, strike: number, rate: number, dividendYield?: number, vol: number, time: number }
{ type: "call" | "put", forward: number, strike: number, rate: number, vol: number, time: number }

rate and dividendYield are continuously compounded decimals (0.05 = 5%; negative values are fine). For FX, pass the foreign rate as dividendYield. vol is a decimal (0.20 = 20%). time is in years; use calendar days / 365 to match the per-day theta.

Pricing and greeks

  • price(o) → the option premium.
  • greeks(o) → { price, delta, gamma, vega, vegaPerPoint, theta, thetaPerDay, rho, rhoPerPoint, vanna, charm, vomma }, all in one pass.
  • delta / gamma / vega / theta / rho / vanna / charm / vomma (alias volga) → each greek on its own.

| Greek | Definition | Units | | --- | --- | --- | | delta | ∂V/∂S (Black-76: ∂V/∂F) | per 1.00 of underlying | | gamma | ∂²V/∂S² | per 1.00 of underlying, squared | | vega | ∂V/∂σ | per 1.00 of vol (100 vol points); vegaPerPoint = vega / 100 | | theta | −∂V/∂T, value lost as time passes | per year; thetaPerDay = theta / 365 (divide by 252 yourself for trading days) | | rho | ∂V/∂r. Spot: dividend yield held fixed. Black-76: forward held fixed, so rho = −T·V | per 1.00 of rate; rhoPerPoint = rho / 100 | | vanna | ∂²V/∂S∂σ = ∂delta/∂σ | per 1.00 of vol | | charm | ∂delta/∂t = −∂²V/∂S∂T | delta change per year | | vomma | ∂²V/∂σ² = ∂vega/∂σ | per 1.00 of vol, squared |

Degenerate inputs. At time = 0 or vol = 0 the price is the (discounted forward) intrinsic value. Delta is the payoff slope (±e^{−qT}, 0, or exactly ½·e^{−qT} at the money), and gamma, vanna and vomma are 0. At the money these are really Dirac spikes, which a number can't represent. Theta keeps its carry term. Vega at vol = 0 exactly at the forward keeps its σ → 0 limit, S·e^{−qT}·√T·φ(0).

Implied volatility

  • impliedVol(o) takes the same object with price in place of vol and returns σ.

    • Returns 0 when the price equals the intrinsic value. This includes far out-of-the-money options whose value has underflowed to 0, and deep in-the-money options whose time value is below the rounding of the price.
    • Returns NaN when the price is outside the no-arbitrage bounds: below intrinsic, or at or above S·e^{−qT} for a call (F·e^{−rT} for Black-76) or K·e^{−rT} for a put. It returns NaN rather than throwing so that a stale quote doesn't abort a loop over a chain.

    The solver reduces every input to the out-of-the-money option via put-call parity and normalises it, b(x, s) with x = ln(F/K) and s = σ√T. From an asymptotic initial guess it runs a safeguarded Newton iteration on ln b below the inflection point s = √(2|x|) and on ln(b_max − b) above it, inside a bracket that tightens every step. Any step that leaves the bracket or fails to reduce the residual becomes a bisection. That takes typically 5–10 iterations, about 1–2 µs.

Utilities

  • normCdf(x), normPdf(x): the standard normal CDF and density. normCdf uses W. J. Cody's rational Chebyshev erfc (1969) and is accurate to ~1e-16 relative in both tails, not the 7-digit Abramowitz–Stegun 26.2.17 approximation.

Malformed input throws RangeError. That covers a non-finite or non-positive spot, forward or strike, a negative vol or time, an unknown type, both or neither of spot/forward, a dividendYield on a forward, a negative price, and time = 0 passed to impliedVol.

Correctness

Fixtures are generated by test/generate-fixtures.py:

  • Published examples:
    • From Hull's Options, Futures, and Other Derivatives: the S=42 / K=40 call and put (4.76 / 0.81), the S=49 / K=50 greek-letters example (delta 0.522, gamma 0.066, theta −4.31/yr, vega 12.1, rho 8.91), the dividend-yield index option (51.83) and the Black-76 crude-oil put (1.12).
    • From Haug's The Complete Guide to Option Pricing Formulas: the Black-Scholes (2.1334), Merton (2.4648), Black-76 (1.7011) and Garman-Kohlhagen (0.0291) prices, and the delta (0.5946 / −0.3566), gamma (0.0278), vega (18.9358), theta (−31.1924) and rho (38.7325) examples.
  • 50-digit reference: 1,400 BSM and Black-76 cases cover strikes from 0.5× to 2× spot, expiries from 1 day to 5 years, vols from 5% to 150%, and negative rates. They are checked against mpmath at 50 digits, with every greek obtained by numerically differentiating the exact price rather than from a second copy of the formulas. All nine outputs agree to 1e-11 relative.
  • QuantLib: 672 cases agree with AnalyticEuropeanEngine on price, delta, gamma, vega, theta and rho. In the far wings, where QuantLib returns prices such as −5.6e-15, this package matches the 50-digit reference instead.
  • Properties: put-call parity holds in prices and greeks. All eight greeks match central finite differences of the price, for spot and Black-76, calls and puts. Black-76 agrees with BSM at q = r.
  • Normal CDF: matches 50-digit values from x = −37 to 8 to 2e-14 relative (2e-13 below −20).
  • Implied vol: the round trip covers 12,960 cases (moneyness 0.5–2, T from 1 day to 5 years, σ from 1% to 300%, calls and puts, with rates and dividend yields), plus a 20,000-case randomised sweep (K/F 0.14–7.4, T from 2.4 hours to 10 years, σ from 0.5% to 500%). Wherever the price determines σ, it is recovered to 1e-12 relative. Where it doesn't, the error stays within the few-ulp-of-price limit, and the result always reprices exactly. Out-of-the-money prices as small as 1e-279 invert to 1e-11.

Out-of-the-money prices keep about 1e-9 relative accuracy even when they are tiny. The closed form subtracts two nearly equal tail probabilities there, so very short-dated, near-the-money wings lose a few digits, still far below any quoting precision.

Related

Pairs with options-expiration (listed expiry dates and time to expiry in years, ready for time), hagan-sabr (SABR smiles) and svi-vol-surface (arbitrage-free surfaces). Part of a markets toolkit: us-equity-market-calendar.

Author

Built by Moshe Malka — engineering leader in New York City. Studio work at Quentin.Code.

MIT © Moshe Malka