Installation and a first result¶
Install¶
Install the released package from PyPI:
python -m pip install vanilla-option-pricers
For a source checkout, install the package and the build-only documentation tools separately:
python -m pip install -e ".[docs]"
The package’s runtime dependencies remain NumPy and Numba. Sphinx, MyST Parser, and Furo belong
only to the optional docs extra.
Run the authoritative offline example¶
The repository’s pricing and IV script is the single source for first success. It uses only the installed package, NumPy, Numba, and deterministic generated inputs; it requires no network, credentials, pandas, or SciPy and creates no files.
From a source checkout with the package installed, run:
python examples/getting_started/pricing_and_iv.py
The wheel intentionally excludes repository examples. After installing from PyPI, download or copy the linked script and run it from any directory.
For a zero-local-setup trial, the Colab notebook installs the latest released distribution from the official PyPI index, prints its distribution version and import path, and runs the exact same workflow below. The committed notebook contains no execution output.
1"""Offline first-success workflow for vanilla-option-pricers."""
2
3from enum import Enum
4from importlib.metadata import version
5from pathlib import Path
6from time import perf_counter
7
8import numpy as np
9from numba.typed import List
10
11import vanilla_option_pricers as vop
12
13forward = 100.0
14discfactor = 0.98
15ttm = 0.50
16strikes = np.array([90.0, 100.0, 100.0, 110.0])
17option_types = np.array(["P", "P", "C", "C"])
18solve_types = List(option_types.tolist())
19lognormal_vols = np.full(strikes.shape, 0.20)
20
21
22class Locals(Enum):
23 """Available local pricing and implied-volatility workflows."""
24
25 PRICING_AND_IV = 1
26
27
28def run_bsm_workflow() -> tuple[np.ndarray, np.ndarray]:
29 """Price one aligned BSM slice and recover its implied volatilities."""
30 prices = vop.compute_bsm_vanilla_slice_prices(
31 ttm,
32 forward,
33 strikes,
34 lognormal_vols,
35 option_types,
36 discfactor,
37 )
38 implied_vols = vop.infer_bsm_ivols_from_slice_prices(
39 ttm,
40 forward,
41 discfactor,
42 strikes,
43 solve_types,
44 prices,
45 )
46 return prices, implied_vols
47
48
49def run_local(local: Locals) -> None:
50 """Run the selected pricing and implied-volatility workflow."""
51 if local != Locals.PRICING_AND_IV:
52 raise ValueError(f"Unsupported local case: {local}")
53
54 cold_started = perf_counter()
55 prices, implied_vols = run_bsm_workflow()
56 cold_seconds = perf_counter() - cold_started
57
58 warm_repetitions = 10
59 warm_started = perf_counter()
60 for _ in range(warm_repetitions):
61 warm_prices, warm_implied_vols = run_bsm_workflow()
62 warm_mean_seconds = (perf_counter() - warm_started) / warm_repetitions
63
64 max_iv_error = float(np.max(np.abs(implied_vols - lognormal_vols)))
65 parity_error = float(prices[2] - prices[1] - discfactor * (forward - strikes[1]))
66
67 absolute_normal_vol = 5.0
68 normal_strike = 102.0
69 normal_price = vop.compute_normal_price(
70 forward,
71 normal_strike,
72 ttm,
73 absolute_normal_vol,
74 discfactor,
75 "C",
76 )
77 normal_implied_vol = vop.infer_normal_implied_vol(
78 forward,
79 ttm,
80 normal_strike,
81 normal_price,
82 discfactor,
83 "C",
84 )
85
86 if max_iv_error > 1e-7:
87 raise RuntimeError(f"BSM implied-volatility round trip failed: {max_iv_error}")
88 if abs(parity_error) > 1e-10:
89 raise RuntimeError(f"BSM put-call parity failed: {parity_error}")
90 if abs(normal_implied_vol - absolute_normal_vol) > 1e-7:
91 raise RuntimeError("Bachelier implied-volatility round trip failed")
92 if not (
93 np.array_equal(prices, warm_prices)
94 and np.array_equal(implied_vols, warm_implied_vols)
95 ):
96 raise RuntimeError("Warm BSM workflow changed the deterministic result")
97
98 print(f"distribution_version={version('vanilla-option-pricers')}")
99 print(f"import_path={Path(vop.__file__).resolve()}")
100 print(
101 "array_shapes="
102 f"strikes{strikes.shape} option_types{option_types.shape} "
103 f"prices{prices.shape} implied_vols{implied_vols.shape}"
104 )
105 print("option_types=" + str(option_types.tolist()))
106 print("prices=" + np.array2string(prices, precision=8))
107 print(f"max_iv_error={max_iv_error:.3e} parity_error={parity_error:.3e}")
108 print(
109 f"cold_first_call_seconds={cold_seconds:.6f} "
110 f"warm_mean_seconds={warm_mean_seconds:.6f} "
111 f"warm_repetitions={warm_repetitions}"
112 )
113 print(
114 f"bachelier_absolute_vol={absolute_normal_vol:.6f} "
115 f"price={normal_price:.8f} iv_error="
116 f"{normal_implied_vol - absolute_normal_vol:.3e}"
117 )
118 print("bsm_convention=forward, discount factor, years, annualised lognormal volatility")
119 print("bachelier_convention=annualised absolute normal volatility in forward units")
120 print(
121 "change_first=forward, discfactor, ttm, strikes, option_types, model_convention"
122 )
123
124
125if __name__ == "__main__":
126 run_local(local=Locals.PRICING_AND_IV)
The script prices one aligned BSM slice, recovers all four input volatilities, and checks the same-strike call/put pair against forward put-call parity. It also prices and inverts one Bachelier call with annualised absolute normal volatility in the same units as the forward and strike.
Successful output reports package version and import path; input/output shapes; option codes and prices; maximum IV and parity errors; one cold first-call duration; the mean of ten warm repeats; and the Bachelier result. Timing values are machine-dependent and are not a benchmark. The verified numerical errors are required to remain below the explicit thresholds in the script.
Start adaptation with the final change_first line: forward, discfactor, ttm, strikes,
option_types, and model_convention. Preserve the stated units and alignment contracts when
substituting market inputs.
Next steps and boundaries¶
Use the package-root functions for stable user examples. Array helpers have distinct scalar, aligned-array, grid, and per-expiry contracts; arbitrary broadcasting is not promised. The first call to a Numba-compiled signature includes compilation time.
Continue with pricing and Greeks, implied volatility, Bachelier units, and array/Numba behavior. Use the issue tracker for support.