libitofin: Port QuantLib ke dalam Rust dan Python
libitofin merupakan port QuantLib ke dalam Rust yang boleh diakses melalui Python. Ketahui kelebihan pustaka penentuan harga berbanding hamparan kerja serta kepentingan versi stabil.
QuantLib dalam Rust ialah deskripsi satu baris bagi libitofin: satu port bagi QuantLib, pustaka C++ yang telah menjadi rujukan sumber terbuka untuk penentuan harga derivatif sejak awal tahun 2000-an, ke dalam Rust, dengan pakej Python bernama itofin di atasnya. Setakat Ogos 2026, projek ini melabelkan dirinya sebagai pra-1.0, dan label tersebut menentukan segala aspek praktikal penggunaannya. Sesebuah pustaka penentuan harga memperoleh nilainya melalui jentera yang membungkus formula tersebut, dan jentera itu merupakan tugas yang sama dalam mana-mana bahasa pengaturcaraan.
Apa yang diberikan oleh pustaka penentuan harga yang tidak diberikan oleh formula hamparan kerja (spreadsheet)
Satu sel Black-Scholes dalam hamparan kerja mengambil lima input dan mengembalikan harga. Formula itu adalah bahagian yang mudah. Empat lapisan melingkupinya, dan lapisan-lapisan itulah yang membentuk pustaka tersebut.
Struktur tempoh (Term structures). Kadar diskaun ialah keluk merentasi tempoh matang, dengan peraturan interpolasi untuk jurang antara titik yang disebut harga oleh sesiapa sahaja. Panel di bawah menunjukkan bahan mentah: tenor Treasury yang disebut harga pada satu tarikh tertentu.
SQL tepat di sebalik setiap nombor
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 iSetakat Aug 10, 2026, keluk yang disebut harga membawa 7 tenor, bermula daripada 3.79% pada 1 month hingga 5.25% pada 30 years. Hamparan kerja memenuhi keperluan ini dengan carian (lookup) dan kadar 4% yang ditetapkan secara kekal (hardcoded). Pustaka pula menanganinya dengan objek keluk yang digunakan oleh setiap instrumen untuk penentuan harga, di bawah interpolasi yang dinyatakan (linear pada kadar sifar, log-linear pada faktor diskaun, monotone splines) dan polisi ekstrapolasi yang dinyatakan selepas titik terakhir. Anjakkan satu objek itu sebanyak satu mata asas (basis point) dan setiap sensitiviti dalam buku tersebut akan bergerak secara konsisten dengannya.
Konvensyen kiraan hari (Day-count conventions). Faedah terakru sepanjang pecahan tahun, dan definisi pecahan itu ialah konvensyen yang dilampirkan pada instrumen tersebut. Actual/360 membahagikan hari yang berlalu dengan 360. Actual/365 membahagikan dengan 365. Keluarga 30/360 mengandaikan setiap bulan mempunyai 30 hari. Business/252 mengira sesi dagangan berbanding tahun 252 hari, yang memerlukan kalendar bursa sebenar dengan cuti yang telah dimuatkan. Ambil contoh hipotetikal satu juta dolar yang dipinjam pada kadar 5% untuk 90 hari: actual/360 mengakru $12,500 dan actual/365 mengakru $12,329 pada dagangan yang sama. Panel di bawah menunjukkan sebab asas hari perniagaan memerlukan kalendar dan bukannya pembahagi.
SQL tepat di sebalik setiap nombor
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 monthSepanjang 12 bulan yang dipaparkan, 2026-07 mempunyai 22 sesi berbanding 31 hari kalendar. Tiada peraturan aritmetik yang menghasilkan nombor pertama itu. Ia datang daripada kalendar cuti, dan setiap bulan mempunyai jawapannya sendiri. Pustaka membekalkan kalendar tersebut mengikut tempat dan negara; hamparan kerja meminta anda untuk menyelenggaranya sendiri.
Jentera penentukuran (Calibration machinery). Parameter model tidak disebut harga di mana-mana. Anda memilihnya dengan memadankan harga model kepada harga pasaran yang diperhatikan merentasi keseluruhan permukaan sebut harga, kemudian memadankannya semula apabila permukaan itu bergerak. Itu merupakan masalah kuasa dua terkecil (least-squares) yang terikat, dan pustaka membekalkan gelung di sekelilingnya: pengoptimum Levenberg-Marquardt, transformasi parameter yang mengekalkan varians positif tanpa kekangan keras, fungsi kos ke atas set sebut harga, dan kriteria penumpuan yang gagal secara nyata dan bukannya senyap-senyap mengembalikan tekaan permulaan.
Lapisan numerik. Di bawah segala-galanya terletak algebra linear dan integrasi. Penguraian QR dan SVD menyelesaikan sistem yang dihasilkan oleh padanan, kuadratur dan integrasi Fourier menentukan harga model yang formulanya merupakan kamiran, dan pencari punca (root finders) mengeluarkan volatiliti tersirat. Lapisan ini membosankan, dan ia merupakan lapisan yang tepat yang sering dilaksanakan semula dengan buruk. Versi klasik ialah penyelesai Newton buatan sendiri yang menumpu pada sebut harga "at-the-money" yang cair tetapi tersasar jauh pada sebut harga "out-of-the-money". Yang kedua ialah songsangan matriks yang kehilangan ketepatan pada padanan yang hampir singular dan memberikan kembali parameter yang kelihatan sangat munasabah. Jika anda sedang membina model mental dari awal, buku dagangan kuantitatif sumber terbuka adalah titik permulaan yang lebih baik daripada rujukan API mana-mana pustaka.
Apakah itu libitofin, dan adakah ia QuantLib dalam Rust?
Ya, dalam erti kata yang penting. Ia adalah port reka bentuk QuantLib ke dalam Rust, dan projek itu menyatakan bahawa ia diuji terhadap suite ujian QuantLib sendiri. Itulah cara yang jujur untuk memindahkan pustaka numerik: keputusan disemak terhadap pelaksanaan rujukan dan bukannya terhadap jangkaan bertulis tentang jawapan yang sepatutnya. Laluan Python ialah pakej bernama itofin, jadi proses Python boleh mencapai enjin Rust tanpa rantaian alat C++ dalam gelung tersebut.
Label yang lebih penting ialah pra-1.0. Di bawah konvensyen penomboran versi Rust, keluaran 0.x tidak membawa janji keserasian antara versi minor: 0.4 kepada 0.5 dibenarkan untuk menamakan semula, memindah atau memadam apa sahaja yang disukainya. Anggap API tersebut sebagai sasaran yang bergerak, dan beberapa tabiat perlu diikuti.
- Sematkan keluaran bertanda yang tepat dalam fail kunci (lockfile) anda dan naik taraf secara sengaja, dengan suite ujian anda sendiri sebagai penapis.
- Simpan pembungkus nipis anda sendiri di sekeliling jenis pustaka tersebut, supaya penamaan semula hanya perlu dilakukan dalam satu fail dan bukannya empat puluh.
- Rekodkan versi pustaka di sebelah nombor yang dihasilkannya, supaya ulangan yang tidak sepadan menunjukkan kepada naik taraf dan bukannya kepada pasaran.
- Simpan margin pengeluaran, cagaran, dan nombor risiko kawal selia pada sesuatu yang membawa janji keserasian sehingga versi 1.0 tiba.
Tiada satu pun daripada perkara di atas merupakan kritikan terhadap projek tersebut. Pra-1.0 ialah deskripsi kendiri yang tepat dan tempat yang betul untuk port muda bagi pustaka yang sangat besar. Mod kegagalan ialah pembaca menganggapnya sebagai pengganti terus QuantLib dan menemui tandatangan yang berubah dalam keluaran minor, di pertengahan suku tahun. Arahan pemasangan juga berubah mengikut versi, dan kedua-dua cargo serta pip memerlukan akses rangkaian untuk menyelesaikan apa-apa, jadi baca README projek itu sendiri pada tag yang anda ingin sematkan dan bukannya petikan yang disalin daripada catatan blog, termasuk yang ini.
Python, enjin yang dikompil, atau Rust?
Dua soalan menyelesaikan perkara ini, dan tiada satu pun berkaitan dengan cita rasa. Berapa kali sesaat anda menentukan harga semula, dan adakah nombor anda perlu sepadan merentasi proses yang berasingan? Saiz rantaian menetapkan skala soalan pertama.
SQL tepat di sebalik setiap nombor
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 DESCPada Aug 11, 2026, SPY mempunyai 5336 kontrak berbeza yang didagangkan dalam satu sesi, berbanding 360 untuk KO. Menentukan harga rantaian yang luas sekali sahaja bukanlah apa-apa. Menentukan harganya dengan lima sensitiviti setiap kontrak, pada setiap kemas kini sebut harga, merentasi buku aset asas, adalah program berbeza dengan kekangan yang berbeza.
Kekal dalam Python dengan pustaka yang mantap apabila gelung diukur dalam ribuan penilaian seminit dan kerja di sekelilingnya adalah penyelidikan, analisis, atau tanda akhir hari. Ikatan Python QuantLib sendiri adalah pilihan yang matang: enjin C++ yang sama, liputan instrumen yang paling luas, dan pengalaman pengeluaran selama bertahun-tahun. Kelajuan jarang menjadi kekangan utama dalam kod penyelidikan; liputan dan ketepatan adalah lebih penting.
Panggil enjin yang dikompil daripada Python apabila gelung tersebut aktif dan kod di sekelilingnya tidak. Kos yang perlu diperhatikan ialah sempadan itu sendiri. Panggilan setiap kontrak daripada Python membayar overhed pada setiap lintasan, dan penyelesaiannya adalah dengan menyerahkan tatasusunan kepada enjin dan mengambil tatasusunan kembali. Ini adalah kedudukan yang disasarkan oleh itofin, di samping QuantLib-Python.
Tulis dalam Rust apabila gelung penentuan harga adalah produk itu sendiri: penentu harga di dalam perkhidmatan sebut harga, risiko yang dijalankan mengikut jadual yang tidak boleh anda terlepas, atau binari yang dihantar ke kotak tanpa Python di dalamnya. Soalan kedua juga tertumpu di sini. Keputusan titik terapung (floating point) bergantung pada urutan operasi, jadi model yang sama yang dilaksanakan dua kali boleh berbeza pada digit terakhir, dan buku nota penyelidikan yang tidak sepadan dengan perkhidmatan pengeluaran adalah seminggu kerja forensik. Satu enjin yang digunakan daripada kedua-dua pihak menghapuskan keseluruhan kategori percanggahan itu, yang merupakan hujah kukuh untuk teras yang dikompil dengan ikatan (bindings) tidak kira apa bahasa ia ditulis. Naluri yang sama terpakai pada kerja strategi, seperti yang ditunjukkan oleh ujian semula yang boleh dihasilkan semula.
Di mana sasaran penentukuran sebenarnya berada
Penentukuran memerlukan sesuatu untuk dipadankan, dan sesuatu itu ialah permukaan volatiliti tersirat pasaran. Bahagian pencarian punca bagi perkara itu diliputi dalam cara volatiliti tersirat dikira. Bentuk di bawah adalah apa yang perlu dipadankan oleh model.
SQL tepat di sebalik setiap nombor
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)Berhampiran harga (near the money), kontrak AAPL dalam baldi 0 to 7 days mencatatkan purata volatiliti tersirat 29.6% merentasi sesi yang dipaparkan, berbanding 29.3% pada 241 days or more. Model yang membawa satu parameter volatiliti tidak boleh berada pada kedua-dua titik serentak, itulah sebabnya model dengan struktur tempoh volatiliti wujud. Memadankan satu kepada permukaan seperti ini adalah langkah penentukuran, dan sensitiviti yang terhasil daripada model yang dipadankan adalah "greeks", yang diliputi dalam penjelasan opsyen greeks.
Cara panel ini dibina
Panel keluk membaca tarikh sebut harga terkini yang paling tunggal dalam siri Treasury dan membentangkan sebelas lajur tenornya ke dalam baris, menggugurkan sebarang tenor tanpa sebut harga pada hari tersebut. Panel sesi mengira tarikh berbeza pada pita SPY setiap bulan, yang merupakan proksi bersih untuk kiraan sesi bursa penuh. Panel rantaian mengira kod kontrak berbeza dengan volum bukan sifar pada sesi terkini yang tersedia, dikumpulkan mengikut aset asas. Panel volatiliti hanya menyimpan penyelesaian yang menumpu dengan volum bukan sifar dan harga strike dalam lingkungan 5% daripada harga penutup aset asas, yang merupakan jalur standard "near-the-money"; baldi hadapan termasuk tarikh luput hari yang sama.
Soalan Lazim (FAQ)
Adakah libitofin pengganti terus untuk QuantLib?
Tidak. Setakat Ogos 2026, ia adalah port pra-1.0 yang meliputi sebahagian daripada permukaan QuantLib dan mengesahkan keputusannya terhadap suite ujian QuantLib sendiri. QuantLib itu sendiri, yang dicapai melalui ikatan Pythonnya, kekal sebagai pilihan yang lebih luas dan stabil untuk kerja pengeluaran.
Apakah maksud pra-1.0 bagi pustaka penentuan harga?
Di bawah konvensyen penomboran versi Rust, keluaran 0.x tidak membuat janji keserasian: versi minor seterusnya bebas untuk menamakan semula atau memadam apa sahaja. Dalam praktiknya, itu bermakna menyematkan keluaran bertanda yang tepat dan menjalankan semula suite ujian anda sendiri pada setiap naik taraf.
Adakah saya perlu menulis dalam Rust untuk menggunakan libitofin?
Tidak. Projek ini menerbitkan pakej Python bernama itofin, jadi enjin tersebut boleh dipanggil daripada proses Python biasa. Menulis dalam Rust menjadi relevan apabila gelung penentuan harga itu sendiri adalah perkara yang anda hantar.
Apa yang diberikan oleh pustaka penentuan harga yang tidak diberikan oleh formula hamparan kerja?
Keluk dan bukannya kadar tunggal, konvensyen kiraan hari dengan kalendar bursa sebenar di belakangnya, gelung penentukuran yang memadankan parameter model kepada harga yang disebut, dan lapisan numerik yang diuji di bawah ketiga-tiganya. Formula bentuk tertutup hanyalah bahagian kecil daripada tugas tersebut.
Adakah bahasa pengaturcaraan mengubah harga opsyen?
Tidak secara matematik. Ia mengubah kebolehhasilan semula: keputusan titik terapung bergantung pada urutan operasi, jadi dua pelaksanaan satu model boleh berbeza pada digit terakhir. Menjalankan penyelidikan dan pengeluaran daripada enjin yang sama menghapuskan jurang itu.
Setiap panel di sini membawa SQL tepatnya di bawah, jadi kembangkan satu untuk melihat bagaimana kiraan itu diambil. Soalan keluk, kalendar, dan rantaian yang sama boleh ditanya dalam bahasa Inggeris biasa pada terminal Strasmore.