Releases: joaquinbejar/OptionStratLib
v0.17.3 — Black-76 + Garman-Kohlhagen Greeks
Closed-form Greeks for the two pricing models added in v0.17.2 (Black-76 and Garman–Kohlhagen). Pricing kernels shipped first; this release closes the analytics surface for futures/forwards and FX options.
Decimal end-to-end via d_mul/d_sub/d_div. tracing::instrument on every entry point. Quantity scales linearly; Side::Short flips delta only — gamma/vega/theta/rho stay sign-agnostic, matching the BSM module convention. Vega ÷ 100 (per 1 % vol), theta ÷ 365 (per calendar day), rho ÷ 100 (per 1 % rate). Only OptionType::European accepted — American / Bermuda / exotic return GreeksError::Pricing(UnsupportedOptionType).
Added
Black-76 Greeks (PR #402, closes #400) — src/greeks/black_76.rs:
delta_b76,gamma_b76,vega_b76,theta_b76,rho_b76pub trait Black76Greeksmirroring theBlack76pricing traitcalculate_d_values_black_76promotedpub(crate)→pub- Formulas follow Hull (10th ed., Ch. 18). Theta keeps the
+ r·F·e^(-rT)·N(d1)term; rho uses the-T · priceidentity (the only placerappears in Black-76 ise^(-rT)). - 21 tests: delta range / parity (
Δ_call − Δ_put = e^(-rT)),Γ > 0,ν > 0,Γ_call = Γ_put,ν_call = ν_put,ρ = -T · price / 100, BSM cross-check underS = F·e^(-rT),q = 0(1e-9), Hull ATM reference (Δ ≈ 0.5132), error paths. examples/examples_pricing/src/bin/black_76_greeks.rs— 6-month crude-oil futures walkthrough.
Garman–Kohlhagen Greeks (PR #403, closes #401) — src/greeks/garman_kohlhagen.rs:
delta_gk,gamma_gk,vega_gk,theta_gk,rho_domestic_gk,rho_foreign_gkpub trait GarmanKohlhagenGreeksmirroring theGarmanKohlhagenpricing trait- FX field mapping:
risk_free_rate → r_d,dividend_yield → r_f,underlying_price → S. - Carry-adjusted
b = r_d − r_find1/d2. Standalone implementation — does not delegate to BSM Greeks because those computed1fromrisk_free_rateonly and then multiply bye^(-qT), mismatching d-values and discount factor whendividend_yield ≠ 0. Pricing kernels are unaffected (they include−qin the drift). Fixing BSM Greeks tracked separately. - 18 tests: delta range
(0, e^(-r_f·T))/(-e^(-r_f·T), 0), spot delta-parityΔ_call − Δ_put = e^(-r_f·T),Γ > 0,ν > 0,Γ_call = Γ_put,ν_call = ν_put, rho signs (long call: +ρ_d, -ρ_f; long put: -ρ_d, +ρ_f), bit-exact BSM equivalence atq = 0, theta vs 1-day numerical bump, Wystup-style FX reference (S=0.98, K=1.00, r_d=5 %, r_f=4 %, T=4/12, σ=10 %) → Δ ≈ 0.3909. examples/examples_pricing/src/bin/garman_kohlhagen_greeks.rs— 6-month EUR/USD walkthrough.
Changed
greeks/utils.rs:calculate_d_values_black_76visibility bumped.greeks/mod.rs: registers the two new modules.lib.rs: doc index updated.
Docs
- README bumped to v0.17.3 with both pricing modules listed;
Forward-PricedandFX / Currencysubgraphs added to the model-selection mermaid. - Garman-Kohlhagen module: review fixes (T=0 short-circuit + checked
d_addin theta), escaped-Markdown link cleanup.
v0.17.2 — Black-76 + Garman–Kohlhagen pricing models
Release adding two new closed-form pricing models:
- Black-76 (Black 1976) for European options on futures and forwards.
- Garman–Kohlhagen (1983) for European FX options.
0.17.0 and 0.17.1 were preparatory iterations of this work
(0.17.0 was never published; 0.17.1 shipped to crates.io with a
partial subset). 0.17.2 is the first version that ships both models
together. PricingEngine is #[non_exhaustive] (semver-major from the
0.16.x line) and the two new variants are appended at the tail of the
enum so existing discriminants are preserved.
Added
Black-76 model (Black 1976):
pricing::black_76: closed-formblack_76(option) -> Result<Decimal, PricingError>
for European options on futures / forwards. Reuses the existingd1
/d2/big_nhelpers;Decimalend-to-end viad_mul/d_sub;
tracing::instrumenton the entry point. OnlyOptionType::European
is supported — American, Bermuda and exotics return
PricingError::UnsupportedOptionType.pricing::Black76trait with defaultcalculate_price_black_76
(mirrorsBlackScholes).pricing::PricingEngine::ClosedFormBlack76variant + dispatch from
price_option.greeks::utils::calculate_d_values_black_76pub(crate)helper.examples/examples_pricing/src/bin/black_76.rs: runnable demo
(Hull canonical example, ITM commodity-futures call, unified-API
dispatch, short-side sign convention).
Garman–Kohlhagen model (Garman & Kohlhagen 1983):
pricing::garman_kohlhagen: closed-form
garman_kohlhagen(option) -> Result<Decimal, PricingError>for
European options on FX spot rates. Structurally identical to BSM
withq = r_f; the implementation delegates toblack_scholes
after type validation, guaranteeing bit-exact equivalence (verified
to1e-9in the tests).pricing::GarmanKohlhagentrait with default
calculate_price_garman_kohlhagen(mirrors theBlackScholes
trait pattern).pricing::PricingEngine::ClosedFormGKvariant + dispatch from
price_option.examples/examples_pricing/src/bin/garman_kohlhagen.rs: runnable
demo (Hull canonical USD/GBP, ITM EUR/USD with FX parity check,
unified-API dispatch, symmetric-rate degenerate case).
Infrastructure updates:
examples/examples_pricing/: new workspace member with binaries for
both models.lib.rsmermaid:Forward-Pricedsubgraph routing
black_76 -> {Future, Forward}; newFX / Currencysubgraph routing
garman_kohlhagen -> FX Spot.
Changed
pricing::PricingEngineis now#[non_exhaustive]so future engine
variants do not require a new major bump.pricing::mod.rsCore Models / Model Selection Guidelines /
Performance Considerations now include both Black-76 and
Garman–Kohlhagen with explicit field mapping documentation.financial_typesbumped to0.2.2(addsUnderlyingAssetType::Future
andUnderlyingAssetType::Forward).PricingErrorandGreeksErrorpass-through in closed-form dispatch
(BS, Black-76, GK) for full error-variant fidelity.
0.17.1 — Garman-Kohlhagen FX Pricing
Add Garman-Kohlhagen closed-form pricing for European FX options. Structurally identical to Black-Scholes-Merton with dividend_yield ↔ r_f (foreign rate) mapping. Includes 21 regression tests (Hull canonical, BSM equivalence to 1e-9, FX parity, symmetric-rate degenerate case). Module-level docs on field mapping and numerical method. Example binary demos ATM/ITM scenarios with parity verification.
OptionStratLib 0.17.0 — Black-76 & Garman-Kohlhagen FX Pricing
Release of two new closed-form pricing models:
Black-76 (Black 1976)
Pricing model for European options on futures and forwards. Reuses existing d1/d2/big_n helpers with Decimal end-to-end arithmetic. Only OptionType::European is supported.
Garman–Kohlhagen (1983)
Pricing model for European FX options. Structurally identical to BSM with q = r_f; delegates to black_scholes for bit-exact equivalence.
Technical Details
- Both models pass comprehensive reference regression tests (Hull, Wystup)
- PricingEngine now #[non_exhaustive] to prevent future major bumps
- Full test coverage with parity checks and edge cases
- PricingError variants now properly propagated (not wrapped)
See CHANGELOG.md for full details.
v0.16.5
0.16.5 — documentation refresh
Documentation-only release. Refreshes the crate-level rustdoc and the README so both describe the 0.16 quality discipline.
Changed
- New sections in `src/lib.rs` / `README.md`:
- Quality & Discipline (0.16.x): checked `Decimal` helpers, `NonFinite` guards, `NonZeroUsize` step counts, `deny(clippy::indexing_slicing)` / `deny(missing_docs)`, `#[tracing::instrument]` hot paths, `utils::deterministic_rng`, pricing-identity regression tests.
- Arithmetic-Error Cascade mermaid.
- Observability mermaid (five instrumented public hot paths).
- Testing section updated to current counts (3760 lib + 205 doctests) with explicit mentions of the seeded-RNG helper and identity tests.
- Examples section rewritten for the shipped sub-crate layout with the correct `--manifest-path=` invocation.
- Prerequisites updated (Rust 1.85 / 2024 edition), feature list documents `plotly`/`static_export`/`async`.
v0.16.4
0.16.4
Changed
- Bump workspace dependencies: `rust_decimal` 1.40 → 1.41, `rayon` 1.11 → 1.12, `uuid` 1.19 → 1.23, `tokio` 1.43 → 1.52.
Fixed
- Repair three doctests broken by the `NonZeroUsize` migration in 0.16.0:
- `src/pricing/mod.rs` — `telegraph(..)` / `monte_carlo_option_pricing(..)` examples now wrap literal step / simulation counts with `nz!(..)`.
- `src/utils/others.rs` — `deterministic_rng` doctest imports `rand::RngExt` for `.random::()`.
205 doctests / 3760 lib tests pass on the bumped deps.
v0.16.3
0.16.3 — example-runtime fixes
See CHANGELOG.md.
Fixed
- #385 / #386 — Simulation-heavy demo binaries (`long_call_strategy_simulation`, `short_put_strategy_simulation`, `position_simulator`, `strategy_simulator`, `random_walk_chain`) now use an hourly grid over the week instead of a minute-level grid (10 080 × 100 steps, 43 200 for the chain walker). They finish in a few seconds in debug mode instead of timing out.
- #386 — `examples_volatility::test` brute-force scan cut from 1 000 000 to 10 000 iterations — demo, not local benchmark.
v0.16.2
0.16.2 — example-run hot-fixes
See CHANGELOG.md.
Fixed
- #387 — Strategy P&L / break-even arithmetic panicked mid-optimizer-scan with `Positive invariant broken` in `CallButterfly`, `LongButterflySpread`, and `BullPutSpread::get_max_loss`. All four sites now lower to `Decimal` and rewrap via `Positive::new_decimal(..)`; invalid candidates are dropped cleanly or surfaced as typed `StrategyError` instead of panicking. Unblocks the `strategy_best{area,ratio}` / `_delta` examples.
- #388 — `examples_chain::async_chain_ops` now writes to a tempdir it creates; `examples_chain::creator` now points at the Germany-40 JSON that actually ships in `examples/Chains/`.
v0.16.1
Fix chain test fixtures and doc link warning
v0.16.0
0.16.0
Breaking release. Focus: panic-free core, arithmetic discipline, typed errors, and a crate-wide discipline pass over attributes, docs, and test hygiene.
See CHANGELOG.md for the full Added / Changed / Fixed / Internal breakdown.
Highlights
- Checked
Decimalhelpers (d_add/d_sub/d_mul/d_div/d_sum/d_sum_iter) route every monetary-path kernel through overflow-tagged arithmetic. NonFinite { context, value }guards on everyf64 → Decimalboundary inside pricing, Greeks, volatility, and simulation.- Step / simulation counts promoted to
NonZeroUsize(breaking). - Crate-level
#![deny(missing_docs, rustdoc::broken_intra_doc_links, clippy::indexing_slicing)]with scoped, documented escapes. #[tracing::instrument]on public hot paths;#[cold] #[inline(never)]on every error constructor.- Deterministic RNG helper (
utils::deterministic_rng) plus put-call parity / CRR convergence / Greek sanity regression tests.
Migration
Most breakage comes from:
- Functions returning
Result<T, concrete_error>where they previously panicked — wrap call sites with?. steps/simulationsarguments now takeNonZeroUsize— useoptionstratlib::nz!(N)orNonZeroUsize::new(N).ok_or(..)at the boundary.unsafeblocks removed in favour of typed guards.