libitofin: QuantLib port for Rust wey you need
libitofin na QuantLib port for Rust wey you fit use for Python via itofin. See wetin pricing library get wey spreadsheet no get plus why you must pin your tagged release.
QuantLib for Rust na wetin dem dey use describe libitofin: e bi port of QuantLib, the C++ library wey don bi the open source reference for derivatives pricing since early 2000s, enter Rust, come get Python package wey dem call itofin on top. As of August 2026, the project dey describe imsef as pre-1.0, and that label dey control everything wey concern how you go take use am. Pricing library dey earn im place through the machinery wey surround the formula, and that machinery na the same work for any language.
Wetin pricing library give you wey spreadsheet formula no get
Black-Scholes cell for spreadsheet dey take five inputs come return price. The formula na the easy part. Four layers dey surround am, and those layers na the library.
Term structures. Discount rate na curve across maturities, with interpolation rule for the gaps between points wey person actually quote. The panel wey dey down so na the raw material: quoted Treasury tenors on one date.
The exact SQL behind every number
SELECT
arrayElement(tenors, i) AS tenor,
round(arrayElement(rates, i), 2) AS yield_pct,
formatDateTime(curve_date, '%b %e, %Y') AS as_of
FROM
(
SELECT
date AS curve_date,
['1 month', '3 months', '6 months', '1 year', '2 years', '3 years',
'5 years', '7 years', '10 years', '20 years', '30 years'] AS tenors,
[toFloat64(yield_1_month), toFloat64(yield_3_month), toFloat64(yield_6_month),
toFloat64(yield_1_year), toFloat64(yield_2_year), toFloat64(yield_3_year),
toFloat64(yield_5_year), toFloat64(yield_7_year), toFloat64(yield_10_year),
toFloat64(yield_20_year), toFloat64(yield_30_year)] AS rates,
arrayJoin(range(1, 12)) AS i
FROM global_markets.treasury_yields
WHERE date = (SELECT max(date) FROM global_markets.treasury_yields)
)
WHERE yield_pct > 0
ORDER BY iAs of Aug 10, 2026 the quoted curve carry 7 tenors, wey start from 3.79% at 1 month go reach 5.25% at 30 years. Spreadsheet dey meet this one with lookup and hardcoded 4%. Library dey meet am with curve object wey every instrument dey price off, under stated interpolation (linear on zero rates, log-linear on discount factors, monotone splines) and stated extrapolation policy past the last point. Shift that one object by one basis point and every sensitivity for the book go move join am.
Day-count conventions. Interest dey accrue over fraction of one year, and the definition of that fraction na convention wey dey attached to the instrument. Actual/360 dey divide elapsed days by 360. Actual/365 dey divide by 365. The 30/360 family dey pretend say every month get 30 days. Business/252 dey count trading sessions against 252-day year, wey require real exchange calendar with holidays wey dem don load. Take hypothetical million dollars wey you borrow at 5% for 90 days: actual/360 go accrue $12,500 and actual/365 go accrue $12,329 on the same trade. The panel wey dey down so show why business-day basis need calendar instead of divisor.
The exact SQL behind every number
SELECT
formatDateTime(toStartOfMonth(date), '%Y-%m') AS month,
countDistinct(date) AS trading_days,
toUInt8(toDayOfMonth(toLastDayOfMonth(max(date)))) AS calendar_days
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= toStartOfMonth(today() - 365)
AND date < toStartOfMonth(today())
GROUP BY month
ORDER BY monthOver the 12 months wey we dey look, 2026-07 get 22 sessions against 31 calendar days. No arithmetic rule dey produce that first number. E dey come from holiday calendar, and every month get im own answer. Library dey ship those calendars per venue and per country; spreadsheet dey ask you make you maintain dem.
Calibration machinery. Model parameters no dey quoted anywhere. You go pick dem by fitting model prices to observed market prices across whole surface of quotes, then you go refit as the surface move. That one na bounded least-squares problem, and the library dey supply the loop around am: Levenberg-Marquardt optimiser, parameter transforms wey dey keep variance positive without hard constraints, cost function over the quote set, and convergence criteria wey go fail loudly instead of just returning the starting guess.
Numerics layer. Underneath everything, linear algebra and integration dey. QR and SVD decompositions dey solve the systems wey fit dey produce, quadrature and Fourier integration dey price the models wey their formulas na integrals, and root finders dey back out implied volatility. This layer dey dull, and na exactly the layer wey dem dey reimplement badly. The classic version na hand-rolled Newton solver wey dey converge on liquid at-the-money quotes and dey wander off on deep out-of-the-money ones. Close second na matrix inverse wey dey lose precision on near-singular fit and dey hand back parameters wey look entirely plausible. If you dey assemble the mental model from scratch, an open source quant trading book na better starting point pass any library API reference.
Wetin be libitofin, and e be QuantLib for Rust?
Yes, for the sense wey matter. E bi port of QuantLib design enter Rust, and the project state say dem test am against QuantLib own test suite. That one na the honest way to port numerics library: results dey checked against reference implementation instead of against hand-written expectation of wetin the answer suppose be. The Python path na package wey dem call itofin, so Python process fit reach the Rust engine without C++ toolchain for the loop.
The label wey matter pass na pre-1.0. Under Rust versioning convention, 0.x release no get compatibility promise between minor versions: 0.4 to 0.5 fit rename, move, or delete anything wey e like. Treat the API as moving target, and some habits go follow.
- Pin exact tagged release for your lockfile and upgrade on purpose, with your own test suite as gate.
- Keep thin wrapper of your own around the library types, so rename go land for one file instead of forty.
- Record the library version next to the numbers wey e produce, so rerun wey disagree go point at the upgrade instead of the market.
- Keep production margin, collateral, and regulatory risk numbers on something wey carry compatibility promise until 1.0 arrive.
None of that na criticism of the project. Pre-1.0 na accurate self-description and the right place for young port of very large library to sit. The failure mode na reader wey dey treat am as drop-in QuantLib swap and meet changed signature for minor release, halfway through quarter. Install instructions also dey move with version, and both cargo and pip need network access to resolve anything, so read the project own README at the tag wey you intend to pin instead of snippet wey you copy from blog post, this one included.
Python, compiled engine, or Rust?
Two questions settle this, and none of dem concern taste. How many times per second you dey reprice, and your numbers must match across separate processes? Chain size dey set the scale of the first question.
The exact SQL behind every number
WITH (SELECT max(date) FROM global_markets.options_greeks) AS last_session
SELECT
underlying_symbol AS symbol,
countDistinct(ticker) AS contracts_priced,
formatDateTime(max(date), '%b %e, %Y') AS as_of
FROM global_markets.options_greeks
WHERE date = last_session
AND underlying_symbol IN ('SPY', 'AAPL', 'NVDA', 'MSFT', 'KO')
AND volume > 0
GROUP BY symbol
ORDER BY contracts_priced DESCOn Aug 11, 2026, SPY get 5336 distinct contracts trade for single session, against 360 for KO. Pricing the wide chain once no be anything. Pricing am with five sensitivities per contract, on every quote update, across book of underlyings, na different program with different constraints.
Stay for Python with established library when the loop dey measured in thousands of valuations per minute and the surrounding work na research, analysis, or end-of-day marks. QuantLib own Python bindings na the mature choice: the same C++ engine, the widest instrument coverage, and years of production mileage. Speed rarely dey the binding constraint for research code; coverage and correctness na the main thing.
Call compiled engine from Python when the loop dey hot and the code around am no be. The cost wey you go watch na the boundary itself. Per-contract call from Python dey pay overhead on every crossing, and the fix na to hand the engine array and take array back. This na the seat wey itofin dey aim at, alongside QuantLib-Python.
Write Rust when the pricing loop na the product: pricer inside quoting service, risk run on schedule wey you no fit miss, or binary wey dem ship to box wey no get Python. The second question land here too. Floating point results dey depend on order of operations, so the same model wey dem implement twice fit disagree for the last digits, and research notebook wey disagree with production service na one week of forensics. One engine wey dem use from both sides dey remove that whole category of discrepancy, wey be the durable argument for compiled core with bindings whatever language e dey written in. The same instinct apply to strategy work, as a reproducible backtest show.
Where the calibration target actually dey live
Calibration need something to fit against, and that something na surface of market-implied volatilities. The root-finding side of that dey covered for how implied volatility is calculated. The shape wey dey down so na wetin model must match.
The exact SQL behind every number
SELECT
multiIf(days_to_expiry <= 7, '0 to 7 days',
days_to_expiry <= 30, '8 to 30 days',
days_to_expiry <= 60, '31 to 60 days',
days_to_expiry <= 120, '61 to 120 days',
days_to_expiry <= 240, '121 to 240 days',
'241 days or more') AS dte_bucket,
round(avg(implied_volatility) * 100, 1) AS iv_pct,
countDistinct(ticker) AS contracts
FROM global_markets.options_greeks
WHERE underlying_symbol = 'AAPL'
AND date >= today() - 10
AND days_to_expiry >= 0
AND iv_converged = 1
AND volume > 0
AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) < 0.05
GROUP BY dte_bucket
ORDER BY min(days_to_expiry)Near the money, AAPL contracts for the 0 to 7 days bucket average 29.6% implied volatility across the sessions wey we dey look, against 29.3% at 241 days or more. Model wey carry one volatility parameter no fit sit on both points at once, wey be the whole reason why models with volatility term structure dey exist. Fitting one to surface like this na the calibration step, and the sensitivities wey dey fall out of the fitted model na the greeks, wey dey covered for the option greeks explained.
How dem build these panels
The curve panel dey read the single most recent quoted date for Treasury series and dey unroll im eleven tenor columns into rows, e dey drop any tenor wey no get quote that day. The session panel dey count distinct dates on SPY tape per month, wey be clean proxy for full exchange session count. The chain panel dey count distinct contract codes with non-zero volume on the latest available session, grouped by underlying. The volatility panel dey keep only converged solves with non-zero volume and strikes within 5% of the underlying close, wey be the standard near-the-money band; the front bucket include same-day expiries.
FAQ
Libitofin be drop-in replacement for QuantLib?
No. As of August 2026, e bi pre-1.0 port wey cover part of QuantLib surface and validate im results against QuantLib own test suite. QuantLib itself, wey you go reach through im Python bindings, remain the broader and more stable option for production work.
Wetin pre-1.0 mean for pricing library?
Under Rust versioning convention, 0.x release no get compatibility promise: the next minor version fit rename or remove anything. For practice, that one mean say you go pin exact tagged release and rerun your own test suite on every upgrade.
I need to write Rust to use libitofin?
No. The project dey publish Python package wey dem call itofin, so the engine dey callable from normal Python process. Writing Rust dey relevant when the pricing loop itself na the thing wey you dey ship.
Wetin pricing library give me wey spreadsheet formula no get?
Curves instead of single rates, day-count conventions with real exchange calendars behind dem, calibration loop wey dey fit model parameters to quoted prices, and tested numerics layer underneath all three. The closed-form formula na the small part of the work.
The programming language dey change option price?
No be mathematically. E dey change reproducibility: floating point results dey depend on order of operations, so two implementations of one model fit disagree for the final digits. Running research and production off the same engine dey remove that gap.
Every panel here carry im exact SQL underneath, so expand one to see how dem take the count. The same curve, calendar, and chain questions fit be asked in plain English on the Strasmore terminal.