Boutquin.OptionPricing.Examples.Shared 1.0.0

dotnet add package Boutquin.OptionPricing.Examples.Shared --version 1.0.0
                    
NuGet\Install-Package Boutquin.OptionPricing.Examples.Shared -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Boutquin.OptionPricing.Examples.Shared" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Boutquin.OptionPricing.Examples.Shared" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Boutquin.OptionPricing.Examples.Shared" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Boutquin.OptionPricing.Examples.Shared --version 1.0.0
                    
#r "nuget: Boutquin.OptionPricing.Examples.Shared, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Boutquin.OptionPricing.Examples.Shared@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Boutquin.OptionPricing.Examples.Shared&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Boutquin.OptionPricing.Examples.Shared&version=1.0.0
                    
Install as a Cake Tool

Boutquin.OptionPricing

NuGet License Build

Boutquin.OptionPricing is a concept-first, model-oriented C# library that maps the full conceptual arc of Black-Scholes and Beyond: Option Pricing Models into a clean, testable, modular codebase. It is designed as a companion to your reading of the book — every package corresponds to a chapter group, every model carries the assumptions stated in the text, and every example traces the progression from closed-form pricing through tree methods to calibrated implied surfaces.

The library depends on Boutquin.Analytics for all curve infrastructure: discount factors, forward rates, dividend curves, and carry. This keeps the option-pricing layer free from data-fetching and bootstrapping concerns. A flat-curve helper is provided for quick exploration; a bootstrapped curve from the NY Fed or Bank of Canada fixtures is one call away for production-grade discounting.

The design is production-grade in engineering terms — strict code quality, full test coverage, documented XML API surface — while remaining concept-first in scope. This is not a trading system or a brokerage integration. It is a reference implementation: the kind you study alongside a textbook and then use as the starting point for your own pricing work.

What You Will Learn

Working through this codebase alongside Black-Scholes and Beyond gives practical exposure to:

  • why risk-neutral pricing works and how the discount curve enters the Black-Scholes formula via OptionMarketData rather than a scalar rate,
  • how binomial trees converge to Black-Scholes as steps increase, and where American exercise breaks that convergence,
  • how to invert a model price to recover implied volatility — and why bisection, Newton-Raphson, and secant solvers behave differently near the boundary,
  • how a smile surface is constructed from market quotes and what butterfly/calendar arbitrage constraints enforce,
  • how implied binomial trees (Rubinstein) and implied volatility trees (Derman-Kani) fit a calibrated surface and price path-dependent instruments like barriers.

Book-To-Code Map

Book chapter group Package
Instruments, arbitrage, parity Domain, Analytics
Probability and distributions Numerics
Geometric Brownian motion, Black-Scholes derivation Analytics
Hedging interpretation Analytics
Binomial trees Trees
American exercise and tree pricing Trees
Implied volatility and smile Calibration
Implied volatility trees (Derman-Kani) Calibration
Implied binomial trees (Rubinstein) Calibration
Barrier options in the presence of the smile Exotics

Packages

Packages are organized in dependency order, from foundational contracts through advanced models.

Contracts

The foundational contracts all other packages depend on. Downstream code that only consumes prices and Greeks will typically reference only this group.

Package Description
Boutquin.OptionPricing.Abstractions Generic pricing, Greek, calibration, and diagnostic interfaces
Boutquin.OptionPricing.Domain Option contracts (EuropeanOption, AmericanOption, BarrierOption), OptionMarketData, result types (PriceResult, GreekSet)

Vanilla Pricing Models

Closed-form and tree-based pricing for European and American options.

Package Description
Boutquin.OptionPricing.Analytics BlackScholesPricer, BlackScholesGreeks, BlackScholesDividendPricer, DeltaHedgeSimulator, put-call parity and risk-neutral valuation
Boutquin.OptionPricing.Trees CRR, Jarrow-Rudd, and flexible binomial tree builders; EuropeanTreePricer, AmericanTreePricer; Arrow-Debreu state prices

Smile, Calibration, And Exotics

Surface fitting, implied tree calibration, and barrier pricing.

Package Description
Boutquin.OptionPricing.Calibration ImpliedVolatilitySolver, smile slice and surface builders, QuoteArbitrageValidator, Rubinstein ImpliedBinomialTreeCalibrator, Derman-Kani ImpliedVolatilityTreeCalibrator, calibration diagnostics
Boutquin.OptionPricing.Exotics BarrierTreePricer (flat vol), SmileAwareBarrierPricer (surface), barrier parity, Broadie-Glasserman-Kou monitoring adjustments

Examples And Delivery

Package Description
Boutquin.OptionPricing.BlackScholesAndBeyond Book-aligned executable tracing all eleven chapter groups in Black-Scholes and Beyond (Chriss). CLI: --chapter <n> runs a single chapter; default runs all.
Boutquin.OptionPricing.Examples Infrastructure-focused executable for six examples covering bootstrapped curves, term-structure Greeks, multi-curve borrow cost, diagnostic gating, and live market data pricing. CLI: --example <id> runs a single example.
Boutquin.OptionPricing.Examples.Shared Shared class library consumed by both executables: MarketHelpers (flat and bootstrapped market construction) and SimulationHelpers (normal sampling for hedging simulation).
Boutquin.OptionPricing.Benchmarks BenchmarkDotNet performance suite

Model Assumptions

Black-Scholes

  • lognormal underlying with constant volatility
  • risk-free rate, dividend yield, and borrow cost derived from OptionMarketData curves
  • cost-of-carry includes borrow rate: effective yield = q + b, so the forward is F = S × exp(−(q+b)T) / exp(−rT)
  • European exercise only
  • zero-time-to-expiry returns intrinsic value with a Success status

CRR binomial tree

  • recombining tree with flat volatility and flat discount rate
  • optional flat continuous dividend yield
  • American exercise evaluated at each node via early-exercise comparison
  • converges to Black-Scholes as step count increases

Implied binomial tree (Rubinstein)

  • fits to a market volatility surface via Arrow-Debreu state prices
  • recombining tree with state-dependent risk-neutral probabilities
  • single flat discount curve for time value

Implied volatility tree (Derman-Kani)

  • fits to a market volatility surface via implied local volatilities
  • forward induction to build tree; backward induction to price
  • single flat discount curve for time value

Validation Invariants

Tests enforce the following relationships across model families:

  • put-call parity holds to within tolerance for all European pricers
  • American put value is always ≥ European put value at the same inputs
  • CRR tree price converges toward Black-Scholes as step count increases
  • implied volatility round-trip: invert model price, re-price, recover original price to tolerance
  • butterfly and calendar arbitrage are absent from valid smile surface inputs

Quick Start

Installation

dotnet add package Boutquin.OptionPricing.Domain
dotnet add package Boutquin.OptionPricing.Analytics
dotnet add package Boutquin.OptionPricing.Trees

Price a European Call (flat-curve market)

OptionMarketData requires a discount curve. For exploration, wrap a constant rate in FlatDiscountCurve from Boutquin.Analytics.Curves:

using Boutquin.Analytics.Abstractions.Identifiers;
using Boutquin.Analytics.Curves.Discounting;
using Boutquin.OptionPricing.Analytics.BlackScholes;
using Boutquin.OptionPricing.Domain.Contracts;
using Boutquin.OptionPricing.Domain.Enums;
using Boutquin.OptionPricing.Domain.Market;

DateOnly valuationDate = DateOnly.FromDateTime(DateTime.Today);
var discountCurve = new FlatDiscountCurve(
    new CurveName("USD-OIS"), valuationDate, CurrencyCode.USD, riskFreeRate: 0.03);
var dividendCurve = new FlatDiscountCurve(
    new CurveName("DIVIDEND"), valuationDate, CurrencyCode.USD, riskFreeRate: 0.01);

var market = new OptionMarketData(valuationDate, spot: 100m, flatVolatility: 0.20, discountCurve, dividendCurve);
var option = new EuropeanOption(CallPut.Call, strike: 100m, valuationDate.AddMonths(6));

var result = new BlackScholesPricer().Price(option, market);
Console.WriteLine($"Call price: {result.Price:F4}");

Price with a Bootstrapped Curve (Fixture Data)

For deterministic testing, use FixtureData.CreatePipeline() — pre-built market data for USD, CAD, GBP, EUR with no network calls:

using Boutquin.Analytics.Abstractions.Identifiers;
using Boutquin.Analytics.Recipes;
using Boutquin.Analytics.Recipes.Testing;
using Microsoft.Extensions.DependencyInjection;

var services = new ServiceCollection();
services.AddAnalytics();                                    // registers CurveBuilder, calibrator, conventions
services.AddSingleton<IDataPipeline>(FixtureData.CreatePipeline());  // deterministic fixture data
services.AddLogging();
var sp = services.BuildServiceProvider();

var builder = sp.GetRequiredService<CurveBuilder>();
var recipe = StandardCurveRecipes.UsdSofrDiscount();
var snapshot = await builder.BuildAsync(recipe, new DateOnly(2026, 4, 9));

// Verify bootstrap quality before pricing
double maxError = snapshot.Diagnostics.Repricing.Max(r => r.AbsoluteError);
if (maxError > 1e-6)
    throw new InvalidOperationException($"Curve failed quality gate: {maxError:E2}");

var market = OptionMarketData.FromCurveGroup(
    snapshot.CurveGroup, new CurrencyCode("USD"), spot: 100m, flatVolatility: 0.20);

Price with Real Market Data

For live data from public sources, replace FixtureData.CreatePipeline() with the real Boutquin.MarketData pipeline. Source adapters from Boutquin.MarketData.Adapter fetch EOD data from free public APIs:

Source Data Adapter Package
NY Fed SOFR fixings MarketData.Adapter.NewYorkFed
US Treasury Par yields (2Y-30Y) MarketData.Adapter.UsTreasury
Bank of Canada CORRA fixings, zero curves MarketData.Adapter.BankOfCanada
Bank of England SONIA fixings MarketData.Adapter.BankOfEngland
ECB ESTR fixings MarketData.Adapter.Ecb
CME SOFR futures settlements MarketData.Adapter.Cme
using Boutquin.Analytics.Abstractions.Curves;
using Boutquin.Analytics.Abstractions.Identifiers;
using Boutquin.Analytics.Recipes;
using Boutquin.MarketData.Abstractions.Calendars;
using Boutquin.MarketData.Adapter.NewYorkFed;
using Boutquin.MarketData.Adapter.UsTreasury;
using Boutquin.MarketData.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

var services = new ServiceCollection();
services.AddAnalytics();                // CurveBuilder, calibrator, reference data
services.AddMarketDataKernel();         // IDataPipeline with transport, L1/L2 caching, normalization
services.AddMarketDataNewYorkFed();     // SOFR overnight fixings from NY Fed Markets API
services.AddMarketDataUsTreasury();     // Treasury par yields (2Y-30Y)
services.AddLogging(b => b.AddConsole().SetMinimumLevel(LogLevel.Warning));

var sp = services.BuildServiceProvider();
var builder = sp.GetRequiredService<CurveBuilder>();
var calendar = sp.GetRequiredService<IBusinessCalendar>();

// EOD data is published after market close — use previous business day
DateOnly valuationDate = calendar.Advance(DateOnly.FromDateTime(DateTime.Today), -1);
var snapshot = await builder.BuildAsync(StandardCurveRecipes.UsdSofrDiscount(), valuationDate);

// Verify bootstrap quality before pricing
double maxError = snapshot.Diagnostics.Repricing.Max(r => r.AbsoluteError);
if (maxError > 1e-4)
    throw new InvalidOperationException($"Curve failed quality gate: {maxError:E2}");

var market = OptionMarketData.FromCurveGroup(
    snapshot.CurveGroup, new CurrencyCode("USD"), 100m, 0.20d, new BenchmarkName("SOFR"));
// Now price with the latest available real discount curve

// Provenance shows data source and actual business date
foreach (var prov in snapshot.Provenance.DistinctBy(p => p.Dataset))
    Console.WriteLine($"{prov.Dataset}: {prov.RetrievalMode} via {prov.Provider} [{prov.Freshness} {prov.DataDate}]");

// DATE_ROLLBACK warnings surface when data date != valuation date
foreach (var issue in snapshot.DataIssues.Where(i => i.Code == "DATE_ROLLBACK"))
    Console.WriteLine($"[{issue.Severity}] {issue.Message}");

This is Example 15 in the Examples project. The data flow is: StandardCurveRecipes defines which data to fetch → CurveBuilder calls IDataPipeline → adapters fetch from NY Fed and Treasury APIs → rates are extracted and passed to the bootstrap calibrator → calibrated curves are returned in a CurveSnapshot with full provenance and data-quality issues.

Each DataProvenance record indicates whether data was retrieved via "api" (live fetch), "snapshot" (L2 disk cache), or "cache" (L1 memory), along with the actual DataDate of the underlying data. When the data date differs from the requested valuation date (e.g., requesting Monday's data before EOD publication), adapter and node layers emit DATE_ROLLBACK warnings. Issues are persisted through the L2 cache so they are visible on cached replays. Consecutive runs hit the L2 disk cache and skip HTTP calls.

Architecture

Boutquin.OptionPricing is organized in four dependency tiers:

  • ContractsAbstractions, Domain: stable contracts, option types, and result objects. The only tier downstream pricing consumers need to reference directly. Numerical primitives (root-finding, interpolation, distributions) are provided by Boutquin.Numerics.
  • Vanilla Pricing ModelsAnalytics, Trees: closed-form Black-Scholes, full Greeks, put-call parity, CRR/JR/flexible binomial trees, American exercise.
  • Smile, Calibration, And ExoticsCalibration, Exotics: implied volatility inversion, smile surface construction, Rubinstein and Derman-Kani implied tree calibration, barrier pricing with flat-vol and smile-aware pricers.
  • Examples And DeliveryBlackScholesAndBeyond, Examples, Examples.Shared, Benchmarks: book-aligned chapter walkthroughs, infrastructure-focused examples, shared helpers, and performance benchmarks.

Dependencies flow in one direction: Exotics and Calibration depend on Trees and Analytics; all depend on Contracts and Numerics. Boutquin.OptionPricing depends on Boutquin.Analytics for curve abstractions — the dependency never flows in reverse.

See docs/curve-layer.md for the Analytics dependency design and docs/repository-map.md for per-package navigation guidance.

Directory Structure

Boutquin.OptionPricing/
├── src/                                    # Source projects (9)
│   ├── Boutquin.OptionPricing.Abstractions/        # Core interfaces and payoff contracts
│   ├── Boutquin.OptionPricing.Domain/              # Option contracts, market data, result types
│   ├── Boutquin.OptionPricing.Analytics/           # Black-Scholes pricer, Greeks, hedging
│   ├── Boutquin.OptionPricing.Trees/               # Binomial tree pricing (CRR, JR, flexible)
│   ├── Boutquin.OptionPricing.Calibration/         # Implied vol, smile surface, implied trees
│   ├── Boutquin.OptionPricing.Exotics/             # Barrier and exotic options
│   ├── Boutquin.OptionPricing.BlackScholesAndBeyond/ # Book-aligned chapter examples
│   ├── Boutquin.OptionPricing.Examples/            # Infrastructure-focused examples
│   └── Boutquin.OptionPricing.Examples.Shared/    # Shared market construction helpers
├── tests/                                  # Test projects (10)
│   ├── Boutquin.OptionPricing.Domain.Tests/        # Domain contracts and market data
│   ├── Boutquin.OptionPricing.Analytics.Tests/     # Black-Scholes and Greeks
│   ├── Boutquin.OptionPricing.Trees.Tests/         # Binomial tree pricing
│   ├── Boutquin.OptionPricing.Calibration.Tests/   # Implied vol and calibration
│   ├── Boutquin.OptionPricing.Exotics.Tests/       # Barrier option tests
│   ├── Boutquin.OptionPricing.PropertyTests/       # Property-based tests (put-call parity, convergence)
│   ├── Boutquin.OptionPricing.IntegrationTests/    # End-to-end integration
│   ├── Boutquin.OptionPricing.Tests.Verification/  # Cross-language reference vectors
│   └── Boutquin.OptionPricing.ArchitectureTests/   # Dependency enforcement
├── benchmarks/
│   └── Boutquin.OptionPricing.Benchmarks/  # BenchmarkDotNet suite
├── docs/                                   # Architecture and usage documentation
└── .github/                                # CI/CD workflows

Documentation

Document Description
docs/repository-map.md Per-package descriptions with external dependency and test structure
docs/curve-layer.md Market curve integration design: why OptionMarketData uses curve objects

Contributing

Contributions are welcome! Please read the contributing guidelines first.

Reporting Bugs

If you find a bug, please report it by opening an issue on the Issues page with:

  • A clear and descriptive title
  • Steps to reproduce the issue
  • Expected and actual behavior
  • Screenshots or code snippets, if applicable

Contributing Code

  1. Fork the repository and clone locally
  2. Create a feature branch: git checkout -b feature-name
  3. Make your changes following the style guides
  4. Commit with clear messages: git commit -m "Add feature X"
  5. Push and open a pull request

Disclaimer

Boutquin.OptionPricing is open-source software provided under the Apache 2.0 License. It is a general-purpose library intended for educational and research purposes.

This software does not constitute financial advice. The option pricing, volatility, and risk analysis tools are provided as-is for research and development. Before using any financial calculations in production, consult with qualified professionals who understand your specific requirements and regulatory obligations.

License

This project is licensed under the Apache 2.0 License -- see the LICENSE file for details.

Contact

For inquiries, please open an issue or reach out via GitHub Discussions.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Boutquin.OptionPricing.Examples.Shared:

Package Downloads
Boutquin.OptionPricing.Examples

Package Description

Boutquin.OptionPricing.BlackScholesAndBeyond

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 122 4/17/2026