Strasmore Research
Học tập Matt ConnorBởi Matt Connor · data as of August 12, 2026 · refreshed weekly

Tìm hiểu libitofin: Thư viện định giá QuantLib cho Rust

Khám phá libitofin, dự án chuyển đổi QuantLib sang ngôn ngữ Rust. Bài viết phân tích lý do cần sử dụng thư viện định giá thay vì bảng tính và tầm quan trọng của việc ghim phiên bản.

QuantLib trong Rust là mô tả ngắn gọn về libitofin: một bản chuyển đổi (port) từ QuantLib, thư viện C++ vốn là tài liệu tham khảo mã nguồn mở cho định giá phái sinh từ đầu những năm 2000, sang Rust, đi kèm với một gói Python có tên là itofin. Tính đến tháng 8 năm 2026, dự án này tự mô tả là đang ở giai đoạn tiền 1.0 (pre-1.0), và nhãn này chi phối mọi khía cạnh thực tế khi sử dụng. Một thư viện định giá khẳng định vị thế thông qua các cơ chế bao quanh công thức, và cơ chế đó là công việc tương tự trong bất kỳ ngôn ngữ nào.

Thư viện định giá mang lại những gì mà công thức bảng tính không có

Một ô Black-Scholes trong bảng tính nhận năm đầu vào và trả về một mức giá. Công thức chỉ là phần dễ. Bốn lớp bao quanh nó, và những lớp đó chính là thư viện.

Cấu trúc kỳ hạn (Term structures). Lãi suất chiết khấu là một đường cong theo các kỳ hạn, với quy tắc nội suy cho các khoảng trống giữa các điểm mà thị trường thực tế niêm yết. Bảng dưới đây là dữ liệu thô: các kỳ hạn trái phiếu Kho bạc được niêm yết vào một ngày cụ thể.

Truy vấnĐường cong lợi suất trái phiếu Chính phủ tại ngày niêm yết gần nhất
Câu lệnh SQL chính xác đằng sau mỗi con số
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 i
Run this yourself

Tính đến Aug 10, 2026, đường cong niêm yết có 7 kỳ hạn, chạy từ 3.79% ở mức 1 month đến 5.25% ở mức 30 years. Bảng tính giải quyết việc này bằng hàm tìm kiếm và một con số cố định 4%. Một thư viện giải quyết bằng một đối tượng đường cong mà mọi công cụ đều sử dụng để định giá, theo một quy tắc nội suy đã định (tuyến tính trên lãi suất zero, log-tuyến tính trên hệ số chiết khấu, spline đơn điệu) và chính sách ngoại suy sau điểm cuối cùng. Chỉ cần dịch chuyển đối tượng đó một điểm cơ bản (basis point), mọi độ nhạy (sensitivity) trong sổ sách sẽ thay đổi nhất quán theo.

Quy ước đếm ngày (Day-count conventions). Lãi suất tích lũy theo một phần của năm, và định nghĩa của phần đó là một quy ước gắn liền với công cụ. Actual/360 chia số ngày thực tế cho 360. Actual/365 chia cho 365. Nhóm 30/360 giả định mỗi tháng có 30 ngày. Business/252 đếm các phiên giao dịch so với một năm 252 ngày, đòi hỏi một lịch giao dịch thực tế đã nạp sẵn các ngày nghỉ lễ. Giả sử vay một triệu đô la với lãi suất 5% trong 90 ngày: Actual/360 tích lũy 12.500 đô la và Actual/365 tích lũy 12.329 đô la trên cùng một giao dịch. Bảng dưới đây cho thấy lý do tại sao cơ sở ngày làm việc cần một lịch thay vì một số chia.

Truy vấnSố phiên giao dịch so với ngày dương lịch, theo tháng
Câu lệnh SQL chính xác đằng sau mỗi con số
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 month
Run this yourself

Trong 12 tháng được xem xét, 2026-0722 phiên so với 31 ngày dương lịch. Không có quy tắc số học nào tạo ra con số đầu tiên đó. Nó đến từ lịch nghỉ lễ, và mỗi tháng có câu trả lời riêng. Một thư viện cung cấp các lịch đó theo từng địa điểm và quốc gia; bảng tính yêu cầu bạn phải tự duy trì chúng.

Cơ chế hiệu chỉnh (Calibration machinery). Các tham số mô hình không được niêm yết ở bất kỳ đâu. Bạn chọn chúng bằng cách khớp giá mô hình với giá thị trường quan sát được trên toàn bộ bề mặt niêm yết, sau đó khớp lại khi bề mặt thay đổi. Đó là một bài toán bình phương tối thiểu có giới hạn, và thư viện cung cấp vòng lặp xung quanh nó: bộ tối ưu hóa Levenberg-Marquardt, các phép biến đổi tham số giữ cho phương sai dương mà không cần ràng buộc cứng, hàm chi phí trên tập hợp niêm yết, và các tiêu chí hội tụ báo lỗi thay vì âm thầm trả về kết quả dự đoán ban đầu.

Lớp số học (Numerics layer). Bên dưới mọi thứ là đại số tuyến tính và tích phân. Các phân rã QR và SVD giải quyết các hệ thống mà quá trình khớp tạo ra, tích phân cầu phương và tích phân Fourier định giá các mô hình có công thức là tích phân, và các bộ tìm nghiệm (root finders) tính ngược ra độ biến động ngụ ý (implied volatility). Lớp này rất tẻ nhạt, và chính xác là lớp thường bị triển khai lại một cách tồi tệ. Phiên bản kinh điển là bộ giải Newton tự viết hội tụ trên các mức giá tại tiền (at-the-money) có tính thanh khoản cao và đi chệch hướng trên các mức giá xa tiền (out-of-the-money). Một lỗi phổ biến khác là nghịch đảo ma trận mất độ chính xác trên một phép khớp gần suy biến và trả về các tham số trông hoàn toàn hợp lý. Nếu bạn đang xây dựng mô hình tư duy từ đầu, một cuốn sách giao dịch định lượng mã nguồn mở là điểm khởi đầu tốt hơn bất kỳ tài liệu tham khảo API nào của thư viện.

libitofin là gì, và nó có phải là QuantLib trong Rust không?

Có, theo nghĩa quan trọng nhất. Nó là bản chuyển đổi thiết kế của QuantLib sang Rust, và dự án tuyên bố rằng nó được kiểm thử dựa trên bộ kiểm thử của chính QuantLib. Đó là cách trung thực để chuyển đổi một thư viện số học: kết quả được kiểm tra dựa trên bản triển khai tham chiếu thay vì dựa trên kỳ vọng tự viết về câu trả lời nên là gì. Đường dẫn Python là một gói có tên itofin, vì vậy một tiến trình Python có thể tiếp cận công cụ Rust mà không cần chuỗi công cụ C++ đi kèm.

Nhãn quan trọng hơn là tiền 1.0. Theo quy ước phiên bản của Rust, bản phát hành 0.x không mang lại cam kết tương thích giữa các phiên bản phụ: 0.4 lên 0.5 được phép đổi tên, di chuyển hoặc xóa bất cứ thứ gì. Hãy coi API là một mục tiêu di động, và một vài thói quen sau đây sẽ hữu ích.

  • Ghim một bản phát hành có gắn thẻ (tagged release) chính xác trong tệp lockfile và nâng cấp có chủ đích, với bộ kiểm thử của riêng bạn làm cổng kiểm soát.
  • Giữ một lớp bao bọc (wrapper) mỏng của riêng bạn xung quanh các kiểu dữ liệu của thư viện, để việc đổi tên chỉ cần thực hiện trong một tệp thay vì bốn mươi tệp.
  • Ghi lại phiên bản thư viện bên cạnh các con số mà nó tạo ra, để một lần chạy lại cho kết quả khác biệt sẽ chỉ ra bản nâng cấp thay vì thị trường.
  • Giữ các con số về ký quỹ sản xuất, tài sản thế chấp và rủi ro pháp lý trên một thứ gì đó mang cam kết tương thích cho đến khi phiên bản 1.0 ra đời.

Không điều nào trong số này là chỉ trích dự án. Tiền 1.0 là một mô tả tự thân chính xác và là vị trí phù hợp cho một bản chuyển đổi trẻ của một thư viện rất lớn. Chế độ thất bại là khi người đọc coi nó như một bản thay thế trực tiếp cho QuantLib và gặp phải chữ ký hàm thay đổi trong một bản phát hành phụ, ngay giữa quý. Hướng dẫn cài đặt cũng thay đổi theo phiên bản, và cả cargo lẫn pip đều cần truy cập mạng để giải quyết các phụ thuộc, vì vậy hãy đọc tệp README của chính dự án tại thẻ bạn định ghim thay vì một đoạn mã sao chép từ bài đăng trên blog, bao gồm cả bài này.

Python, một công cụ biên dịch, hay Rust?

Hai câu hỏi quyết định điều này, và không câu nào liên quan đến sở thích. Bạn định giá lại bao nhiêu lần mỗi giây, và các con số của bạn có cần khớp nhau giữa các tiến trình riêng biệt không? Kích thước chuỗi (chain size) đặt ra quy mô cho câu hỏi đầu tiên.

Truy vấnSố lượng hợp đồng quyền chọn riêng biệt giao dịch trong một phiên
Câu lệnh SQL chính xác đằng sau mỗi con số
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 DESC
Run this yourself

Vào ngày Aug 11, 2026, SPY đã có 5336 hợp đồng riêng biệt giao dịch trong một phiên, so với 360 cho KO. Định giá chuỗi rộng một lần không là gì cả. Định giá nó với năm độ nhạy cho mỗi hợp đồng, trên mỗi lần cập nhật giá, trên toàn bộ sổ sách các tài sản cơ sở, là một chương trình khác với các ràng buộc khác.

Hãy ở lại với Python cùng một thư viện đã được thiết lập khi vòng lặp được đo bằng hàng nghìn định giá mỗi phút và công việc xung quanh là nghiên cứu, phân tích hoặc đánh dấu cuối ngày. Các liên kết Python của chính QuantLib là lựa chọn trưởng thành: cùng một công cụ C++, độ bao phủ công cụ rộng nhất và nhiều năm kinh nghiệm thực tế. Tốc độ hiếm khi là ràng buộc chính trong mã nghiên cứu; độ bao phủ và tính chính xác mới là quan trọng.

Gọi một công cụ biên dịch từ Python khi vòng lặp yêu cầu hiệu năng cao và mã xung quanh thì không. Chi phí cần theo dõi chính là ranh giới giữa chúng. Một lệnh gọi từ Python cho mỗi hợp đồng phải trả phí overhead trên mỗi lần chuyển đổi, và cách khắc phục là truyền cho công cụ một mảng và nhận lại một mảng. Đây là vị trí mà itofin đang nhắm tới, cùng với QuantLib-Python.

Viết Rust khi vòng lặp định giá chính là sản phẩm: một bộ định giá bên trong dịch vụ báo giá, một lần chạy rủi ro theo lịch trình bạn không thể bỏ lỡ, hoặc một tệp nhị phân được gửi đến một máy không có Python. Câu hỏi thứ hai cũng dẫn đến đây. Kết quả dấu phẩy động phụ thuộc vào thứ tự các phép tính, vì vậy cùng một mô hình được triển khai hai lần có thể khác nhau ở những chữ số cuối cùng, và một sổ tay nghiên cứu không khớp với dịch vụ sản xuất sẽ tốn cả tuần để điều tra. Một công cụ được sử dụng từ cả hai phía loại bỏ toàn bộ loại sai lệch đó, đây là lập luận bền vững cho một lõi biên dịch với các liên kết bất kể ngôn ngữ nào được viết. Bản năng tương tự áp dụng cho công việc chiến lược, như một bài kiểm tra lại (backtest) có thể tái lập cho thấy.

Nơi mục tiêu hiệu chỉnh thực sự tồn tại

Hiệu chỉnh cần một thứ gì đó để khớp, và thứ đó là bề mặt của các độ biến động ngụ ý thị trường. Khía cạnh tìm nghiệm của việc đó được đề cập trong cách tính độ biến động ngụ ý. Hình dạng dưới đây là những gì một mô hình phải khớp.

Truy vấnCấu trúc kỳ hạn IV của AAPL (near-the-money) theo thời gian đáo hạn
Câu lệnh SQL chính xác đằng sau mỗi con số
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)
Run this yourself

Gần mức giá tại tiền, các hợp đồng AAPL trong nhóm 0 to 7 days trung bình có độ biến động ngụ ý 29.6% qua các phiên được xem xét, so với 29.3% tại 241 days or more. Một mô hình mang một tham số độ biến động không thể nằm trên cả hai điểm cùng lúc, đó là lý do tại sao các mô hình có cấu trúc kỳ hạn độ biến động tồn tại. Khớp một mô hình với bề mặt như thế này là bước hiệu chỉnh, và các độ nhạy rút ra từ mô hình đã khớp chính là các chỉ số Hy Lạp (greeks), được đề cập trong giải thích về các chỉ số Hy Lạp của quyền chọn.

Cách các bảng này được xây dựng

Bảng đường cong đọc ngày niêm yết gần nhất trong chuỗi Kho bạc và trải mười một cột kỳ hạn của nó thành các hàng, loại bỏ bất kỳ kỳ hạn nào không có báo giá vào ngày đó. Bảng phiên đếm các ngày riêng biệt trên băng ghi SPY mỗi tháng, đây là đại diện sạch cho số lượng phiên giao dịch đầy đủ. Bảng chuỗi đếm các mã hợp đồng riêng biệt có khối lượng khác không trong phiên gần nhất, được nhóm theo tài sản cơ sở. Bảng độ biến động chỉ giữ lại các kết quả giải hội tụ với khối lượng khác không và giá thực hiện (strike) trong phạm vi 5% so với giá đóng cửa của tài sản cơ sở, đây là dải gần tại tiền tiêu chuẩn; nhóm đầu tiên bao gồm các quyền chọn hết hạn trong ngày.

Câu hỏi thường gặp

libitofin có phải là bản thay thế trực tiếp cho QuantLib không?

Không. Tính đến tháng 8 năm 2026, đây là bản chuyển đổi tiền 1.0 bao phủ một phần bề mặt của QuantLib và xác thực kết quả của nó dựa trên bộ kiểm thử của chính QuantLib. Bản thân QuantLib, được tiếp cận thông qua các liên kết Python, vẫn là lựa chọn rộng rãi và ổn định hơn cho công việc sản xuất.

Tiền 1.0 có ý nghĩa gì đối với một thư viện định giá?

Theo quy ước phiên bản của Rust, bản phát hành 0.x không đưa ra cam kết tương thích: phiên bản phụ tiếp theo có quyền đổi tên hoặc xóa bất cứ thứ gì. Trong thực tế, điều đó có nghĩa là ghim một bản phát hành có gắn thẻ chính xác và chạy lại bộ kiểm thử của riêng bạn sau mỗi lần nâng cấp.

Tôi có cần viết Rust để sử dụng libitofin không?

Không. Dự án xuất bản một gói Python có tên itofin, vì vậy công cụ này có thể được gọi từ một tiến trình Python thông thường. Viết Rust trở nên phù hợp khi chính vòng lặp định giá là thứ bạn đang phân phối.

Thư viện định giá mang lại cho tôi những gì mà công thức bảng tính không có?

Các đường cong thay vì lãi suất đơn lẻ, các quy ước đếm ngày với lịch giao dịch thực tế phía sau, một vòng lặp hiệu chỉnh khớp các tham số mô hình với giá niêm yết, và một lớp số học đã được kiểm thử bên dưới cả ba. Công thức dạng đóng chỉ là phần nhỏ của công việc.

Ngôn ngữ lập trình có làm thay đổi giá quyền chọn không?

Không phải về mặt toán học. Nó thay đổi khả năng tái lập: kết quả dấu phẩy động phụ thuộc vào thứ tự các phép tính, vì vậy hai bản triển khai của một mô hình có thể khác nhau ở những chữ số cuối cùng. Chạy nghiên cứu và sản xuất từ cùng một công cụ sẽ loại bỏ khoảng cách đó.


Mỗi bảng ở đây đều chứa mã SQL chính xác bên dưới, vì vậy hãy mở rộng một bảng để xem cách đếm được thực hiện. Các câu hỏi tương tự về đường cong, lịch và chuỗi có thể được hỏi bằng tiếng Anh đơn giản trên thiết bị đầu cuối Strasmore.