libitofin: QuantLib port sa Rust at Python integration
Alamin ang libitofin, isang port ng QuantLib sa Rust na magagamit sa Python via itofin. Tuklasin ang bentahe ng pricing library sa spreadsheet at kahalagahan ng tagged release.
Ang QuantLib sa Rust ang maikling paglalarawan sa libitofin: isang port ng QuantLib, ang C++ library na nagsilbing open source reference para sa derivatives pricing mula noong unang bahagi ng 2000s, patungo sa Rust, na may kasamang Python package na itofin. Simula noong Agosto 2026, ang proyekto ay nasa pre-1.0 status pa lamang, at ang label na ito ang nagtatakda sa lahat ng praktikal na aspeto ng paggamit nito. Ang isang pricing library ay nakakakuha ng halaga nito sa pamamagitan ng machinery na nakabalot sa formula, at ang machinery na ito ay parehong trabaho sa anumang programming language.
Ano ang ibinibigay ng isang pricing library na wala sa spreadsheet formula
Ang isang Black-Scholes cell sa isang spreadsheet ay nangangailangan ng limang input at naglalabas ng presyo. Ang formula ang madaling bahagi. May apat na layer sa paligid nito, at ang mga layer na iyon ang bumubuo sa library.
Term structures. Ang discount rate ay isang curve sa iba't ibang maturity, na may interpolation rule para sa mga puwang sa pagitan ng mga puntong aktwal na may quote. Ang panel sa ibaba ay ang raw material: mga quoted Treasury tenor sa isang partikular na petsa.
Ang eksaktong SQL sa likod ng bawat numero
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 iSimula noong Aug 10, 2026, ang quoted curve ay may 7 tenors, mula 3.79% sa 1 month hanggang 5.25% sa 30 years. Sa spreadsheet, ginagawa ito sa pamamagitan ng lookup at hardcoded na 4%. Sa library, ginagawa ito gamit ang isang curve object kung saan nagpe-price ang bawat instrumento, sa ilalim ng isang itinakdang interpolation (linear sa zero rates, log-linear sa discount factors, monotone splines) at isang itinakdang extrapolation policy paglampas sa huling punto. I-shift ang object na iyon ng isang basis point at lahat ng sensitivity sa libro ay gagalaw nang consistent dito.
Day-count conventions. Ang interes ay naiipon (accrue) sa loob ng bahagi ng isang taon, at ang depinisyon ng bahaging iyon ay isang convention na nakakabit sa instrumento. Ang Actual/360 ay hinahati ang lumipas na mga araw sa 360. Ang Actual/365 ay hinahati sa 365. Ang pamilyang 30/360 ay nagpapalagay na ang bawat buwan ay may 30 araw. Ang Business/252 ay nagbibilang ng trading sessions laban sa isang 252-day year, na nangangailangan ng totoong exchange calendar na may nakapaloob na mga holiday. Halimbawa, sa isang milyong dolyar na hiniram sa 5% sa loob ng 90 araw: ang actual/360 ay mag-a-accrue ng $12,500 at ang actual/365 ay mag-a-accrue ng $12,329 sa parehong trade. Ipinapakita ng panel sa ibaba kung bakit kailangan ng calendar ng business-day basis sa halip na divisor lang.
Ang eksaktong SQL sa likod ng bawat numero
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 monthSa loob ng 12 na buwan na nakikita, ang 2026-07 ay may 22 sessions laban sa 31 calendar days. Walang arithmetic rule ang makakagawa ng unang numerong iyon. Nagmumula ito sa isang holiday calendar, at ang bawat buwan ay may sariling sagot. Ang library ay nagbibigay ng mga kalendaryong iyon kada venue at kada bansa; ang spreadsheet ay nag-aatas sa iyo na ikaw ang mag-maintain nito.
Calibration machinery. Ang mga model parameter ay hindi naka-quote kahit saan. Pinipili mo ang mga ito sa pamamagitan ng pag-fit ng mga model price sa mga nakikitang market price sa buong surface ng mga quote, at pagkatapos ay muling pag-fit habang gumagalaw ang surface. Ito ay isang bounded least-squares problem, at ang library ang nagbibigay ng loop sa paligid nito: isang Levenberg-Marquardt optimiser, parameter transforms na nagpapanatili sa variance na positibo nang walang hard constraints, isang cost function sa ibabaw ng quote set, at convergence criteria na nagfe-fail nang malinaw sa halip na tahimik na ibalik ang unang hula.
A numerics layer. Sa ilalim ng lahat ay ang linear algebra at integration. Ang mga QR at SVD decomposition ang lumulutas sa mga system na ginagawa ng isang fit, ang quadrature at Fourier integration ang nagpe-price sa mga model na ang mga formula ay integrals, at ang root finders ang naglalabas ng implied volatility. Ang layer na ito ay nakakabagot, at ito mismo ang layer na madalas na maling naipapatupad. Ang klasikong bersyon ay isang hand-rolled Newton solver na nag-co-converge sa mga liquid at-the-money quotes at naliligaw sa mga deep out-of-the-money. Ang pangalawa ay isang matrix inverse na nawawalan ng precision sa isang near-singular fit at nagbabalik ng mga parameter na mukhang tama naman. Kung binubuo mo ang mental model mula sa simula, ang isang open source quant trading book ay mas mainam na panimulang punto kaysa sa API reference ng anumang library.
Ano ang libitofin, at ito ba ang QuantLib sa Rust?
Oo, sa paraang mahalaga. Ito ay isang port ng disenyo ng QuantLib patungo sa Rust, at sinasabi ng proyekto na ito ay sinubok laban sa sariling test suite ng QuantLib. Iyan ang tapat na paraan ng pag-port ng isang numerics library: ang mga resulta ay sinusuri laban sa reference implementation sa halip na laban sa isang hand-written na ekspektasyon kung ano dapat ang sagot. Ang Python path ay isang package na pinangalanang itofin, kaya ang isang Python process ay makakaabot sa Rust engine nang hindi nangangailangan ng C++ toolchain.
Ang label na mas mahalaga ay pre-1.0. Sa ilalim ng versioning convention ng Rust, ang isang 0.x release ay walang pangakong compatibility sa pagitan ng mga minor version: ang 0.4 hanggang 0.5 ay maaaring mag-rename, maglipat, o magbura ng anumang gusto nito. Ituring ang API bilang isang moving target, at ilang habit ang dapat sundin.
- I-pin ang eksaktong tagged release sa iyong lockfile at mag-upgrade nang sinasadya, gamit ang sarili mong test suite bilang gate.
- Panatilihin ang isang manipis na wrapper ng sarili mong code sa paligid ng mga type ng library, para ang isang rename ay sa isang file lang mapupunta sa halip na apatnapu.
- Itala ang library version sa tabi ng mga numerong ginawa nito, para ang isang rerun na hindi tugma ay ituturo ang upgrade sa halip na ang merkado.
- Panatilihin ang production margin, collateral, at regulatory risk numbers sa isang bagay na may pangakong compatibility hanggang sa dumating ang 1.0.
Hindi ito kritisismo sa proyekto. Ang pre-1.0 ay isang tumpak na self-description at ang tamang lugar para sa isang batang port ng isang napakalaking library. Ang failure mode ay ang pagtrato ng reader dito bilang isang drop-in QuantLib swap at makatagpo ng nagbagong signature sa isang minor release, sa kalagitnaan ng isang quarter. Ang mga instruction sa pag-install ay nagbabago rin kasabay ng version, at parehong kailangan ng cargo at pip ang network access para ma-resolve ang anumang bagay, kaya basahin ang sariling README ng proyekto sa tag na balak mong i-pin sa halip na isang snippet na kinopya mula sa isang blog post, kasama na ang isang ito.
Python, isang compiled engine, o Rust?
Dalawang tanong ang sumasagot dito, at wala rito ang tungkol sa personal na panlasa. Ilang beses sa isang segundo ka nagpe-reprice, at kailangan bang magtugma ang iyong mga numero sa magkakahiwalay na proseso? Ang laki ng chain ang nagtatakda ng scale ng unang tanong.
Ang eksaktong SQL sa likod ng bawat numero
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 DESCNoong Aug 11, 2026, ang SPY ay may 5336 na magkakaibang kontrata na nag-trade sa isang session, laban sa 360 para sa KO. Ang pag-price sa malawak na chain nang isang beses ay walang anuman. Ang pag-price nito nang may limang sensitivity kada kontrata, sa bawat update ng quote, sa buong libro ng mga underlying, ay ibang programa na may ibang constraints.
Manatili sa Python gamit ang isang established library kapag ang loop ay sinusukat sa libu-libong valuation kada minuto at ang nakapaligid na trabaho ay research, analysis, o end-of-day marks. Ang sariling Python bindings ng QuantLib ang mature na pagpipilian: parehong C++ engine, pinakamalawak na instrument coverage, at maraming taon ng production mileage. Ang bilis ay bihirang maging binding constraint sa research code; ang coverage at correctness ang mahalaga.
Tumawag ng compiled engine mula sa Python kapag ang loop ay "hot" at ang code sa paligid nito ay hindi. Ang cost na dapat bantayan ay ang boundary mismo. Ang per-contract call mula sa Python ay nagbabayad ng overhead sa bawat pagtawid, at ang solusyon ay ibigay sa engine ang isang array at kumuha ng array pabalik. Ito ang upuan na target ng itofin, kasabay ng QuantLib-Python.
Sumulat ng Rust kapag ang pricing loop mismo ang produkto: isang pricer sa loob ng isang quoting service, isang risk run sa isang schedule na hindi mo pwedeng palampasin, o isang binary na ipinapadala sa isang box na walang Python. Ang pangalawang tanong ay dito rin papasok. Ang mga floating point result ay nakadepende sa pagkakasunod-sunod ng operasyon, kaya ang parehong model na ipinatupad nang dalawang beses ay maaaring hindi magtugma sa huling mga digit, at ang isang research notebook na hindi tugma sa isang production service ay isang linggong forensics. Ang isang engine na ginagamit mula sa magkabilang panig ay nag-aalis ng buong kategoryang iyon ng discrepancy, na siyang matibay na argumento para sa isang compiled core na may bindings anuman ang language na ginamit. Ang parehong instinct ay nalalapat sa strategy work, gaya ng ipinapakita ng isang reproducible backtest.
Saan talaga nakatira ang calibration target
Ang calibration ay nangangailangan ng pagbabasehan, at iyon ay isang surface ng market-implied volatilities. Ang root-finding side nito ay sakop sa kung paano kinakalkula ang implied volatility. Ang hugis sa ibaba ang kailangang pantayan ng isang model.
Ang eksaktong SQL sa likod ng bawat numero
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)Malapit sa money, ang mga AAPL contract sa 0 to 7 days bucket ay may average na 29.6% implied volatility sa mga session na nakikita, laban sa 29.3% sa 241 days or more. Ang isang model na may isang volatility parameter ay hindi maaaring tumugma sa dalawang punto nang sabay, na siyang dahilan kung bakit may mga model na may volatility term structure. Ang pag-fit ng isa sa isang surface na tulad nito ang calibration step, at ang mga sensitivity na lumalabas mula sa fitted model ang mga greek, na sakop sa pagpapaliwanag sa option greeks.
Paano binuo ang mga panel na ito
Ang curve panel ay nagbabasa ng pinakabagong quoted date sa Treasury series at inilaladlad ang labing-isang tenor column nito sa mga row, na inaalis ang anumang tenor na walang quote sa araw na iyon. Ang session panel ay nagbibilang ng mga natatanging petsa sa SPY tape kada buwan, na isang malinis na proxy para sa bilang ng full exchange session. Ang chain panel ay nagbibilang ng mga natatanging contract code na may non-zero volume sa pinakahuling available na session, na naka-grupo ayon sa underlying. Ang volatility panel ay nagpapanatili lamang ng mga converged solve na may non-zero volume at strike sa loob ng 5% ng underlying close, na siyang standard near-the-money band; ang front bucket ay kasama ang same-day expiries.
FAQ
Ang libitofin ba ay drop-in replacement para sa QuantLib?
Hindi. Simula noong Agosto 2026, ito ay isang pre-1.0 port na sumasakop sa bahagi ng surface ng QuantLib at nagbe-validate ng mga resulta nito laban sa sariling test suite ng QuantLib. Ang QuantLib mismo, na naaabot sa pamamagitan ng Python bindings nito, ang nananatiling mas malawak at mas stable na opsyon para sa production work.
Ano ang ibig sabihin ng pre-1.0 para sa isang pricing library?
Sa ilalim ng versioning convention ng Rust, ang isang 0.x release ay walang pangakong compatibility: ang susunod na minor version ay malayang mag-rename o magbura ng anumang bagay. Sa praktika, nangangahulugan ito ng pag-pin ng eksaktong tagged release at muling pagtakbo ng sarili mong test suite sa bawat upgrade.
Kailangan ko bang sumulat ng Rust para magamit ang libitofin?
Hindi. Ang proyekto ay naglalathala ng isang Python package na pinangalanang itofin, kaya ang engine ay pwedeng tawagin mula sa isang normal na Python process. Ang pagsusulat ng Rust ay nagiging relevant kapag ang pricing loop mismo ang bagay na iyong ipinapadala.
Ano ang ibinibigay ng isang pricing library na wala sa spreadsheet formula?
Mga curve sa halip na single rate, day-count convention na may totoong exchange calendar sa likod nito, isang calibration loop na nag-fi-fit ng model parameter sa mga quoted price, at isang tested numerics layer sa ilalim ng tatlong ito. Ang closed-form formula ang maliit na bahagi lang ng trabaho.
Binabago ba ng programming language ang presyo ng option?
Hindi sa aspetong matematikal. Binabago nito ang reproducibility: ang mga floating point result ay nakadepende sa pagkakasunod-sunod ng operasyon, kaya ang dalawang implementasyon ng isang model ay maaaring hindi magtugma sa huling mga digit. Ang pagpapatakbo ng research at production mula sa parehong engine ay nag-aalis ng puwang na iyon.
Ang bawat panel dito ay may eksaktong SQL sa ilalim nito, kaya i-expand ang isa para makita kung paano kinuha ang bilang. Ang parehong mga tanong tungkol sa curve, calendar, at chain ay maaaring itanong sa simpleng Ingles sa Strasmore terminal.