Skip to content

Releases: joaquinbejar/OptionStratLib

v0.17.3 — Black-76 + Garman-Kohlhagen Greeks

27 Apr 11:46
b46c958

Choose a tag to compare

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_b76
  • pub trait Black76Greeks mirroring the Black76 pricing trait
  • calculate_d_values_black_76 promoted pub(crate)pub
  • Formulas follow Hull (10th ed., Ch. 18). Theta keeps the + r·F·e^(-rT)·N(d1) term; rho uses the -T · price identity (the only place r appears in Black-76 is e^(-rT)).
  • 21 tests: delta range / parity (Δ_call − Δ_put = e^(-rT)), Γ > 0, ν > 0, Γ_call = Γ_put, ν_call = ν_put, ρ = -T · price / 100, BSM cross-check under S = 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_gk
  • pub trait GarmanKohlhagenGreeks mirroring the GarmanKohlhagen pricing trait
  • FX field mapping: risk_free_rate → r_d, dividend_yield → r_f, underlying_price → S.
  • Carry-adjusted b = r_d − r_f in d1/d2. Standalone implementation — does not delegate to BSM Greeks because those compute d1 from risk_free_rate only and then multiply by e^(-qT), mismatching d-values and discount factor when dividend_yield ≠ 0. Pricing kernels are unaffected (they include −q in 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 at q = 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_76 visibility 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-Priced and FX / Currency subgraphs added to the model-selection mermaid.
  • Garman-Kohlhagen module: review fixes (T=0 short-circuit + checked d_add in theta), escaped-Markdown link cleanup.

v0.17.2 — Black-76 + Garman–Kohlhagen pricing models

26 Apr 09:27
6cc3226

Choose a tag to compare

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-form black_76(option) -> Result<Decimal, PricingError>
    for European options on futures / forwards. Reuses the existing d1
    / d2 / big_n helpers; Decimal end-to-end via d_mul / d_sub;
    tracing::instrument on the entry point. Only OptionType::European
    is supported — American, Bermuda and exotics return
    PricingError::UnsupportedOptionType.
  • pricing::Black76 trait with default calculate_price_black_76
    (mirrors BlackScholes).
  • pricing::PricingEngine::ClosedFormBlack76 variant + dispatch from
    price_option.
  • greeks::utils::calculate_d_values_black_76 pub(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
    with q = r_f; the implementation delegates to black_scholes
    after type validation, guaranteeing bit-exact equivalence (verified
    to 1e-9 in the tests).
  • pricing::GarmanKohlhagen trait with default
    calculate_price_garman_kohlhagen (mirrors the BlackScholes
    trait pattern).
  • pricing::PricingEngine::ClosedFormGK variant + 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.rs mermaid: Forward-Priced subgraph routing
    black_76 -> {Future, Forward}; new FX / Currency subgraph routing
    garman_kohlhagen -> FX Spot.

Changed

  • pricing::PricingEngine is now #[non_exhaustive] so future engine
    variants do not require a new major bump.
  • pricing::mod.rs Core Models / Model Selection Guidelines /
    Performance Considerations now include both Black-76 and
    Garman–Kohlhagen with explicit field mapping documentation.
  • financial_types bumped to 0.2.2 (adds UnderlyingAssetType::Future
    and UnderlyingAssetType::Forward).
  • PricingError and GreeksError pass-through in closed-form dispatch
    (BS, Black-76, GK) for full error-variant fidelity.

0.17.1 — Garman-Kohlhagen FX Pricing

26 Apr 08:38
0c26f7c

Choose a tag to compare

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

26 Apr 08:51
e680532

Choose a tag to compare

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

20 Apr 07:04
c7cfd85

Choose a tag to compare

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

20 Apr 06:36
123981c

Choose a tag to compare

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

20 Apr 06:05
3ba1dcb

Choose a tag to compare

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

19 Apr 22:00
28d14d2

Choose a tag to compare

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

19 Apr 21:32
594164b

Choose a tag to compare

Fix chain test fixtures and doc link warning

v0.16.0

19 Apr 20:47
a901eb0

Choose a tag to compare

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 Decimal helpers (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 every f64 → Decimal boundary 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:

  1. Functions returning Result<T, concrete_error> where they previously panicked — wrap call sites with ?.
  2. steps / simulations arguments now take NonZeroUsize — use optionstratlib::nz!(N) or NonZeroUsize::new(N).ok_or(..) at the boundary.
  3. unsafe blocks removed in favour of typed guards.