QuantLib in Rust: libitofin en Python integratie
Ontdek libitofin, een Rust port van QuantLib voor derivaten. Leer waarom een pricing library superieur is aan spreadsheets en waarom u voor productie altijd een tagged release kiest.
QuantLib in Rust: een overzicht
QuantLib in Rust is de kernomschrijving van libitofin: een port naar Rust van QuantLib, de C++ library die sinds het begin van de jaren tweeduizend de open-source standaard is voor de prijsbepaling van derivaten, inclusief een Python-pakket genaamd itofin. Per augustus 1 month 2026 kwalificeert het project zichzelf als pre-1.0, en dit label is bepalend voor elk praktisch aspect van het gebruik ervan. Een pricing library verdient zijn plek door het mechanisme dat rondom de formule is gebouwd, en dat mechanisme is in elke programmeertaal dezelfde taak.
De status van het project
Het label pre-1.0 betekent dat de API nog aan verandering onderhevig is en dat de stabiliteit van de code nog niet volledig is gegarandeerd. Voor professionele toepassingen in een productieomgeving is voorzichtigheid geboden. Gebruikers moeten rekening houden met mogelijke wijzigingen in de structuur van de library die toekomstige updates kunnen bemoeilijken.
Functionele aspecten
De kracht van QuantLib ligt in de uitgebreide set aan instrumenten voor risicobeheer en waardering. Bij het porten naar Rust ligt de uitdaging in het behouden van de rekenkundige precisie en de efficiëntie van de oorspronkelijke C++ implementatie, terwijl de voordelen van het Rust-ecosysteem, zoals geheugenveiligheid en concurrency, worden benut. De integratie met Python via itofin maakt de functionaliteit toegankelijk voor analisten die de voorkeur geven aan een snellere ontwikkelcyclus voor hun modellen.
Toekomstperspectief
Hoewel de library zich nog in een vroege fase bevindt, biedt de overstap naar Rust aanzienlijke voordelen voor de prestaties van complexe berekeningen. Ontwikkelaars die bijdragen aan libitofin richten zich op het repliceren van de robuuste architectuur van de originele library, waarbij de focus ligt op het waarborgen van de correctheid van de financiële modellen. Gebruikers worden aangemoedigd om de voortgang van het project nauwgezet te volgen via de officiële kanalen.
Wat een pricing library biedt wat een spreadsheetformule niet kan
Een Black-Scholes-cel in een spreadsheet vereist vijf inputs en geeft een prijs terug. De formule is het eenvoudige gedeelte. Daaromheen bevinden zich vier lagen, en die lagen vormen de library.
Termstructuren. Een discount rate is een curve over verschillende looptijden, met een interpolatieregel voor de hiaten tussen de punten die daadwerkelijk worden geciteerd. Het onderstaande paneel toont het basismateriaal: de geciteerde Treasury-looptijden op één specifieke datum.
De exacte SQL achter elk getal
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 iPer Aug 10, 2026 bevatte de geciteerde curve 7 looptijden, variërend van 3.79% op 1 month tot 5.25% op 30 years. Een spreadsheet lost dit op met een lookup-functie en een hardcoded percentage van vier procent. Een library pakt dit aan met een curve-object waar elk instrument op prijst, onder een vastgestelde interpolatie (lineair op zero rates, log-lineair op discount factors, monotone splines) en een vastgesteld extrapolatiebeleid voorbij het laatste punt. Verschuif dat ene object met één basis point en elke gevoeligheid in het boek beweegt daar consistent mee.
Day-count conventions. Rente loopt op over een fractie van een jaar, en de definitie van die fractie is een conventie die bij het instrument hoort. Actual/360 deelt het aantal verstreken dagen door 360. Actual/365 deelt door 365. De 30/360-familie gaat ervan uit dat elke maand dertig dagen heeft. Business/252 telt handelsdagen tegen een jaar van 252 dagen, waarvoor een echte beurskalender met reeds ingeladen feestdagen nodig is. Neem een hypothetische lening van een miljoen dollar tegen vijf procent voor 90 dagen: actual/360 levert 12.500 dollar op en actual/365 levert 12.329 dollar op voor dezelfde transactie. Het onderstaande paneel laat zien waarom de business-day-basis een kalender vereist in plaats van een deler.
De exacte SQL achter elk getal
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 de 12 maanden in beeld, telde 2026-07 22 sessies tegenover 31 kalenderdagen. Geen enkele rekenkundige regel levert dat eerste getal op. Het is afkomstig uit een vakantiekalender, en elke maand heeft een eigen uitkomst. Een library levert die kalenders per locatie en per land; een spreadsheet vereist dat u deze zelf bijhoudt.
Calibratiemechanismen. Modelparameters worden nergens geciteerd. U kiest deze door modelprijzen te fitten aan geobserveerde marktprijzen over een volledig oppervlak aan koersen, en vervolgens opnieuw te fitten naarmate het oppervlak beweegt. Dat is een begrensd kleinste-kwadratenprobleem, en de library levert de lus daaromheen: een Levenberg-Marquardt-optimizer, parametertransformaties die een variantie positief houden zonder harde restricties, een kostenfunctie over de koersenset, en convergentiecriteria die luidruchtig falen in plaats van stilletjes de startwaarde terug te geven.
Een numerieke laag. Onder alles liggen lineaire algebra en integratie. QR- en SVD-decomposities lossen de systemen op die een fit produceert, kwadratuur en Fourier-integratie prijzen de modellen waarvan de formules integralen zijn, en root-finders berekenen de implied volatility. Deze laag is saai, en het is precies de laag die vaak slecht opnieuw wordt geïmplementeerd. De klassieke versie is een zelfgebouwde Newton-solver die convergeert op liquide at-the-money koersen en afdwaalt bij deep out-of-the-money koersen. Een goede tweede is een matrix-inverse die precisie verliest bij een bijna-singuliere fit en parameters teruggeeft die er volkomen plausibel uitzien. Als u het mentale model vanaf nul opbouwt, is een open source quant trading boek een beter startpunt dan de API-referentie van welke library dan ook.
Wat is libitofin en is het QuantLib in Rust?
Ja, in de zin die ertoe doet. Het is een port van het ontwerp van QuantLib naar Rust, en het project geeft aan dat het wordt getest tegen de eigen testsuite van QuantLib. Dat is de eerlijke manier om een numerieke bibliotheek te porten: resultaten worden gecontroleerd tegen de referentie-implementatie in plaats van tegen een handgeschreven verwachting van wat het antwoord zou moeten zijn. Het Python-pad is een pakket genaamd itofin, waardoor een Python-proces de Rust-engine kan bereiken zonder dat er een C++ toolchain in de lus zit.
Het label dat er meer toe doet, is pre-1.0. Volgens de versieconventie van Rust biedt een 0.x-release geen compatibiliteitsgarantie tussen minor-versies: van 0.4 naar 0.5 mag alles worden hernoemd, verplaatst of verwijderd. Beschouw de API als een bewegend doelwit, en daaruit volgen enkele gewoonten.
- Pin een exacte getagde release in uw lockfile en voer upgrades bewust uit, met uw eigen testsuite als controlepunt.
- Houd een dunne eigen wrapper rond de types van de bibliotheek, zodat een hernoeming in één bestand terechtkomt in plaats van in veertig.
- Noteer de bibliotheekversie naast de cijfers die deze heeft geproduceerd, zodat een herberekening die afwijkt naar de upgrade wijst in plaats van naar de markt.
- Houd cijfers voor productiemarge, onderpand en regelgevend risico op iets dat een compatibiliteitsgarantie biedt totdat een 1.0-versie verschijnt.
Niets hiervan is kritiek op het project. Pre-1.0 is een nauwkeurige zelfbeschrijving en de juiste plek voor een jonge port van een zeer grote bibliotheek. De foutieve werkwijze is wanneer een gebruiker het behandelt als een drop-in QuantLib-swap en halverwege een kwartaal geconfronteerd wordt met een gewijzigde signature in een minor-release. Installatie-instructies veranderen ook met de versie, en zowel cargo als pip hebben netwerktoegang nodig om alles op te lossen. Lees daarom de eigen README van het project bij de tag die u wilt pinnen, in plaats van een fragment dat uit een blogpost is gekopieerd, inclusief deze.
Python, een gecompileerde engine of Rust?
Twee vragen bepalen dit, en geen van beide gaat over smaak. Hoe vaak per seconde herprijst u, en moeten uw cijfers overeenkomen tussen afzonderlijke processen? De omvang van de chain bepaalt de schaal van de eerste vraag.
De exacte SQL achter elk getal
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 DESCOp Aug 11, 2026 werden in SPY 5336 verschillende contracten verhandeld in één sessie, tegenover 360 voor KO. Het één keer prijzen van een brede chain stelt niets voor. Het prijzen ervan met vijf gevoeligheden per contract, bij elke quote-update, over een boek aan onderliggende waarden, is een ander programma met andere beperkingen.
Blijf bij Python met een gevestigde bibliotheek wanneer de loop wordt gemeten in duizenden waarderingen per minuut en het omliggende werk bestaat uit onderzoek, analyse of end-of-day marks. De Python-bindings van QuantLib zelf zijn de volwassen keuze: dezelfde C++ engine, de breedste dekking van instrumenten en jarenlange ervaring in productieomgevingen. Snelheid is zelden de beperkende factor in onderzoekscode; dekking en correctheid zijn dat wel.
Roep een gecompileerde engine aan vanuit Python wanneer de loop intensief is en de code eromheen niet. De kosten waar u op moet letten, bevinden zich bij de grens zelf. Een aanroep per contract vanuit Python brengt overhead met zich mee bij elke overgang, en de oplossing is om de engine een array te geven en een array terug te ontvangen. Dit is de positie waar itofin zich op richt, naast QuantLib-Python.
Schrijf in Rust wanneer de pricing loop het product is: een pricer binnen een quoting service, een risicoberekening volgens een schema dat u niet mag missen, of een binary die wordt verzonden naar een server zonder Python. De tweede vraag komt hier ook aan de orde. Resultaten met drijvende-kommagetallen hangen af van de volgorde van bewerkingen, waardoor hetzelfde model dat twee keer is geïmplementeerd in de laatste cijfers kan verschillen. Een onderzoeksnotitie die niet overeenkomt met een productieservice betekent een week aan forensisch onderzoek. Eén engine die vanaf beide kanten wordt gebruikt, elimineert die hele categorie van discrepanties, wat het duurzame argument is voor een gecompileerde kern met bindings, ongeacht de taal waarin deze is geschreven. Hetzelfde instinct is van toepassing op strategiewerk, zoals een reproduceerbare backtest aantoont.
Waar het kalibratiedoel zich daadwerkelijk bevindt
Voor kalibratie is een referentiepunt nodig, en dat punt is een oppervlak van door de markt geïmpliceerde volatiliteiten. Het proces van wortelzoeken hiervoor wordt behandeld in hoe implied volatility wordt berekend. De onderstaande vorm is wat een model moet zien te benaderen.
De exacte SQL achter elk getal
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)Nabij de money noteerden AAPL-contracten in de 0 to 7 days-bucket gemiddeld 29.6% implied volatility over de bekeken sessies, tegenover 29.3% op 241 days or more. Een model met slechts één volatiliteitsparameter kan niet op beide punten tegelijkertijd liggen; dit is precies de reden waarom modellen met een volatiliteitstermstructuur bestaan. Het fitten van een model aan een dergelijk oppervlak is de kalibratiestap, en de gevoeligheden die uit het gefitte model voortvloeien zijn de greeks, die worden behandeld in de option greeks uitgelegd.
Hoe deze panelen zijn opgebouwd
Het curve-paneel leest de meest recente genoteerde datum in de Treasury-reeks en rolt de elf tenor-kolommen uit naar rijen, waarbij elke tenor zonder koersnotering op die dag wordt weggelaten. Het sessie-paneel telt het aantal unieke data op de SPY-tape per maand, wat een zuivere proxy is voor het volledige aantal beurssessies. Het chain-paneel telt het aantal unieke contractcodes met een volume groter dan nul op de laatst beschikbare sessie, gegroepeerd per underlying. Het volatiliteitspaneel behoudt alleen geconvergeerde berekeningen met een volume groter dan nul en uitoefenprijzen binnen vijf procent van de slotkoers van de underlying; dit is de standaardbandbreedte voor near-the-money. De front-bucket bevat expiries die op dezelfde dag aflopen.
Veelgestelde vragen
Is libitofin een directe vervanging voor QuantLib?
Nee. Per augustus 2026 is het een pre-1.0 port die een deel van het oppervlak van QuantLib dekt en de resultaten valideert aan de hand van de eigen testsuite van QuantLib. QuantLib zelf, benaderbaar via de Python-bindings, blijft de bredere en stabielere optie voor productiewerkzaamheden.
Wat betekent pre-1.0 voor een pricing library?
Volgens de versieconventie van Rust biedt een 0.x-release geen enkele garantie op compatibiliteit: de volgende minor-versie mag naar believen onderdelen hernoemen of verwijderen. In de praktijk betekent dit dat u een specifieke tagged release moet vastzetten en bij elke upgrade uw eigen testsuite opnieuw moet draaien.
Moet ik Rust schrijven om libitofin te gebruiken?
Nee. Het project publiceert een Python-pakket genaamd itofin, waardoor de engine aanroepbaar is vanuit een standaard Python-proces. Het schrijven van Rust wordt relevant wanneer de pricing loop zelf het product is dat u levert.
Wat biedt een pricing library mij wat een spreadsheetformule niet biedt?
Curves in plaats van enkelvoudige rentestanden, day-count conventions met werkelijke beurskalenders erachter, een kalibratieloop die modelparameters aanpast aan quoted prices, en een geteste numerieke laag onder alle drie. De closed-form formule is slechts een klein onderdeel van het werk.
Verandert de programmeertaal de option price?
Wiskundig gezien niet. Het verandert de reproduceerbaarheid: floating point-resultaten hangen af van de volgorde van bewerkingen, waardoor twee implementaties van hetzelfde model in de laatste decimalen kunnen verschillen. Door research en productie op dezelfde engine te draaien, wordt dat verschil weggenomen.
Elk paneel hier bevat de bijbehorende SQL; vouw een paneel uit om te zien hoe de telling tot stand is gekomen. Dezelfde vragen over curves, kalenders en chains kunnen in gewoon Engels worden gesteld op de Strasmore-terminal.