Strasmore Research
सीखें Matt Connorलेखक: Matt Connor · data as of August 12, 2026 · refreshed weekly

Rust में QuantLib: libitofin और इसके उपयोग की जानकारी

libitofin Rust में QuantLib का एक पोर्ट है जिसे itofin के माध्यम से Python में इस्तेमाल किया जा सकता है। यह लेख बताता है कि एक प्राइसिंग लाइब्रेरी स्प्रेडशीट से बेहतर क्यों है।

Rust में QuantLib, libitofin का एक पंक्ति में विवरण है: यह QuantLib का एक पोर्ट है। QuantLib वह C++ लाइब्रेरी है जो 2000 के दशक की शुरुआत से डेरिवेटिव्स प्राइसिंग के लिए ओपन-सोर्स संदर्भ रही है। इसे Rust में पोर्ट किया गया है, और इसके ऊपर itofin नाम का एक Python पैकेज है। अगस्त 2026 तक, यह प्रोजेक्ट खुद को pre-1.0 के रूप में वर्णित करता है, और यही लेबल इसके उपयोग से जुड़ी हर व्यावहारिक बात को नियंत्रित करता है। एक प्राइसिंग लाइब्रेरी फॉर्मूले के इर्द-गिर्द बनी मशीनरी के माध्यम से अपनी जगह बनाती है, और वह मशीनरी किसी भी भाषा में एक ही काम करती है।

एक प्राइसिंग लाइब्रेरी आपको वह क्या देती है जो स्प्रेडशीट फॉर्मूला नहीं देता

स्प्रेडशीट में एक Black-Scholes सेल पांच इनपुट लेता है और एक कीमत देता है। फॉर्मूला तो आसान हिस्सा है। इसके चारों ओर चार परतें होती हैं, और वे परतें ही लाइब्रेरी हैं।

Term structures. डिस्काउंट रेट परिपक्वता (maturities) के आधार पर एक कर्व होता है, जिसमें उन बिंदुओं के बीच के अंतर के लिए इंटरपोलेशन नियम होते हैं जिन्हें वास्तव में कोट (quote) किया जाता है। नीचे दिया गया पैनल कच्चा माल है: एक ही तारीख पर कोट किए गए Treasury tenors।

क्वेरीनवीनतम उद्धृत तिथि पर ट्रेजरी कर्व
हर आंकड़े के पीछे का पूरा SQL
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

Aug 10, 2026 तक, कोट किए गए कर्व में 7 tenors थे, जो 3.79% से 1 month तक और 5.25% से 30 years तक थे। एक स्प्रेडशीट इसे एक लुकअप और हार्डकोडेड 4% के साथ पूरा करती है। एक लाइब्रेरी इसे एक कर्व ऑब्जेक्ट के साथ पूरा करती है जिससे हर इंस्ट्रूमेंट की प्राइसिंग होती है, जो एक निर्धारित इंटरपोलेशन (zero rates पर linear, discount factors पर log-linear, monotone splines) और अंतिम बिंदु के बाद एक निर्धारित एक्सट्रपलेशन नीति के तहत काम करती है। उस एक ऑब्जेक्ट को एक basis point से शिफ्ट करें और बुक में हर संवेदनशीलता (sensitivity) उसके साथ लगातार बदल जाती है।

Day-count conventions. ब्याज एक वर्ष के एक अंश पर अर्जित होता है, और उस अंश की परिभाषा इंस्ट्रूमेंट से जुड़ी एक परंपरा है। Actual/360 बीते हुए दिनों को 360 से विभाजित करता है। Actual/365 इसे 365 से विभाजित करता है। 30/360 परिवार यह मान लेता है कि हर महीने में 30 दिन होते हैं। Business/252 एक 252-दिवसीय वर्ष के मुकाबले ट्रेडिंग सत्रों की गिनती करता है, जिसके लिए छुट्टियों के साथ पहले से लोड किए गए एक वास्तविक एक्सचेंज कैलेंडर की आवश्यकता होती है। मान लीजिए कि 90 दिनों के लिए 5% पर एक मिलियन डॉलर उधार लिए गए हैं: actual/360 पर $12,500 और actual/365 पर उसी ट्रेड पर $12,329 अर्जित होते हैं। नीचे दिया गया पैनल दिखाता है कि business-day आधार को विभाजक के बजाय कैलेंडर की आवश्यकता क्यों होती है।

क्वेरीमाह के अनुसार, कैलेंडर दिनों के मुकाबले ट्रेडिंग सत्र
हर आंकड़े के पीछे का पूरा SQL
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

12 महीनों के दौरान, 2026-07 में 31 कैलेंडर दिनों के मुकाबले 22 सत्र थे। कोई भी अंकगणितीय नियम वह पहली संख्या उत्पन्न नहीं करता है। यह एक हॉलिडे कैलेंडर से आता है, और हर महीने का अपना उत्तर होता है। एक लाइब्रेरी उन कैलेंडरों को प्रति स्थान और प्रति देश भेजती है; एक स्प्रेडशीट आपसे उन्हें बनाए रखने के लिए कहती है।

Calibration machinery. मॉडल पैरामीटर कहीं भी कोट नहीं किए जाते हैं। आप उन्हें कोट के पूरे सरफेस पर देखे गए बाजार मूल्यों के साथ मॉडल मूल्यों को फिट करके चुनते हैं, फिर जैसे-जैसे सरफेस बदलती है, उन्हें फिर से फिट करते हैं। यह एक सीमित least-squares समस्या है, और लाइब्रेरी इसके चारों ओर लूप प्रदान करती है: एक Levenberg-Marquardt ऑप्टिमाइज़र, पैरामीटर ट्रांसफ़ॉर्म जो बिना कठोर बाधाओं के variance को सकारात्मक रखते हैं, कोट सेट पर एक लागत फ़ंक्शन, और कन्वर्जेंस मानदंड जो चुपचाप शुरुआती अनुमान लौटाने के बजाय स्पष्ट रूप से विफल हो जाते हैं।

A numerics layer. हर चीज़ के नीचे लीनियर अलजेब्रा और इंटीग्रेशन होता है। QR और SVD डिकंपोज़िशन उन सिस्टम को हल करते हैं जो एक फिट उत्पन्न करते हैं, क्वाड्रैचर और फूरियर इंटीग्रेशन उन मॉडलों की प्राइसिंग करते हैं जिनके फॉर्मूले इंटीग्रल हैं, और रूट फाइंडर्स implied volatility को वापस निकालते हैं। यह परत उबाऊ है, और यह बिल्कुल वही परत है जिसे खराब तरीके से फिर से लागू किया जाता है। क्लासिक संस्करण एक हाथ से बनाया गया Newton सॉल्वर है जो लिक्विड at-the-money कोट पर कन्वर्ज होता है और deep out-of-the-money कोट पर भटक जाता है। दूसरा स्थान एक मैट्रिक्स इनवर्स का है जो near-singular फिट पर सटीकता खो देता है और ऐसे पैरामीटर देता है जो पूरी तरह से प्रशंसनीय लगते हैं। यदि आप स्क्रैच से मेंटल मॉडल बना रहे हैं, तो an open source quant trading book किसी भी लाइब्रेरी के API संदर्भ से बेहतर शुरुआती बिंदु है।

libitofin क्या है, और क्या यह Rust में QuantLib है?

हाँ, उस अर्थ में जो मायने रखता है। यह QuantLib के डिज़ाइन का Rust में एक पोर्ट है, और प्रोजेक्ट का कहना है कि इसका परीक्षण QuantLib के अपने टेस्ट सूट के खिलाफ किया गया है। एक न्यूमेरिक्स लाइब्रेरी को पोर्ट करने का यही ईमानदार तरीका है: परिणामों की जांच संदर्भ कार्यान्वयन के खिलाफ की जाती है, न कि इस बात की हाथ से लिखी गई अपेक्षा के खिलाफ कि उत्तर क्या होना चाहिए। Python पाथ itofin नाम का एक पैकेज है, इसलिए एक Python प्रक्रिया लूप में C++ टूलचेन के बिना Rust इंजन तक पहुंच सकती है।

जो लेबल अधिक मायने रखता है वह pre-1.0 है। Rust के वर्ज़निंग कन्वेंशन के तहत, 0.x रिलीज़ माइनर वर्ज़न के बीच कोई संगतता वादा नहीं करती है: 0.4 से 0.5 में किसी भी चीज़ का नाम बदलना, उसे स्थानांतरित करना या हटाना अनुमत है। API को एक चलते-फिरते लक्ष्य के रूप में मानें, और कुछ आदतें अपनाएं।

  • अपनी lockfile में एक सटीक टैग की गई रिलीज़ को पिन करें और जानबूझकर अपग्रेड करें, जिसमें आपका अपना टेस्ट सूट गेट के रूप में हो।
  • लाइब्रेरी के प्रकारों के चारों ओर अपना एक पतला रैपर रखें, ताकि नाम बदलने पर बदलाव चालीस के बजाय एक फ़ाइल में हो।
  • लाइब्रेरी वर्ज़न को उन नंबरों के बगल में रिकॉर्ड करें जो इसने उत्पन्न किए हैं, ताकि यदि दोबारा चलाने पर परिणाम अलग आए, तो वह अपग्रेड की ओर इशारा करे न कि बाजार की ओर।
  • प्रोडक्शन मार्जिन, कोलेटरल और विनियामक जोखिम संख्याओं को किसी ऐसी चीज़ पर रखें जो 1.0 आने तक संगतता का वादा करती हो।

इसमें से कुछ भी प्रोजेक्ट की आलोचना नहीं है। Pre-1.0 एक सटीक स्व-विवरण है और एक बहुत बड़ी लाइब्रेरी के युवा पोर्ट के लिए सही जगह है। विफलता का मोड यह है कि कोई पाठक इसे एक ड्रॉप-इन QuantLib स्वैप के रूप में माने और एक माइनर रिलीज़ में बदले हुए सिग्नेचर का सामना करे। इंस्टॉलेशन निर्देश भी वर्ज़न के साथ बदलते हैं, और cargo और pip दोनों को कुछ भी हल करने के लिए नेटवर्क एक्सेस की आवश्यकता होती है, इसलिए ब्लॉग पोस्ट से कॉपी किए गए स्निपेट के बजाय उस टैग पर प्रोजेक्ट का अपना README पढ़ें जिसे आप पिन करना चाहते हैं।

Python, एक कंपाइल इंजन, या Rust?

दो प्रश्न इसे तय करते हैं, और कोई भी स्वाद के बारे में नहीं है। आप प्रति सेकंड कितनी बार रीप्राइस करते हैं, और क्या आपके नंबर अलग-अलग प्रक्रियाओं में मेल खाने चाहिए? चेन का आकार पहले प्रश्न का पैमाना तय करता है।

क्वेरीएक सत्र में ट्रेड किए गए विशिष्ट विकल्प अनुबंध
हर आंकड़े के पीछे का पूरा SQL
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

Aug 11, 2026 पर, SPY में एक ही सत्र में 5336 अलग-अलग अनुबंध ट्रेड हुए, जबकि 360 के लिए KO थे। पूरी चेन की एक बार प्राइसिंग करना कुछ भी नहीं है। हर कोट अपडेट पर, अंडरलाइंग की एक बुक के पार, प्रति अनुबंध पांच संवेदनशीलता के साथ इसकी प्राइसिंग करना, अलग-अलग बाधाओं वाला एक अलग प्रोग्राम है।

जब लूप को प्रति मिनट हजारों मूल्यांकन में मापा जाता है और आसपास का काम शोध, विश्लेषण या दिन के अंत के निशान होते हैं, तो एक स्थापित लाइब्रेरी के साथ Python में रहें। QuantLib के अपने Python बाइंडिंग परिपक्व विकल्प हैं: वही C++ इंजन, सबसे व्यापक इंस्ट्रूमेंट कवरेज, और वर्षों का प्रोडक्शन माइलेज। शोध कोड में गति शायद ही कभी बाध्यकारी बाधा होती है; कवरेज और शुद्धता होती है।

जब लूप हॉट हो और उसके आसपास का कोड न हो, तो Python से एक कंपाइल इंजन को कॉल करें। ध्यान देने वाली लागत स्वयं सीमा है। Python से प्रति-अनुबंध कॉल हर क्रॉसिंग पर ओवरहेड का भुगतान करती है, और इसका समाधान इंजन को एक ऐरे देना और वापस एक ऐरे लेना है। यह वह सीट है जिस पर itofin, QuantLib-Python के साथ लक्ष्य बना रहा है।

Rust तब लिखें जब प्राइसिंग लूप ही उत्पाद हो: एक कोटिंग सर्विस के अंदर एक प्राइसर, एक शेड्यूल पर जोखिम जो आप मिस नहीं कर सकते, या बिना Python वाले बॉक्स पर भेजा गया बाइनरी। दूसरा प्रश्न भी यहीं आता है। फ्लोटिंग पॉइंट परिणाम संचालन के क्रम पर निर्भर करते हैं, इसलिए एक ही मॉडल को दो बार लागू करने पर अंतिम अंकों में असहमति हो सकती है, और एक शोध नोटबुक जो प्रोडक्शन सर्विस से असहमत है, वह एक सप्ताह की फॉरेंसिक है। दोनों तरफ से उपयोग किया जाने वाला एक इंजन विसंगति की उस पूरी श्रेणी को हटा देता है, जो किसी भी भाषा में लिखे गए बाइंडिंग के साथ कंपाइल कोर के लिए टिकाऊ तर्क है। यही प्रवृत्ति रणनीति के काम पर भी लागू होती है, जैसा कि a reproducible backtest दिखाता है।

कैलिब्रेशन लक्ष्य वास्तव में कहाँ रहता है

कैलिब्रेशन को फिट करने के लिए किसी चीज़ की आवश्यकता होती है, और वह चीज़ बाजार-निहित अस्थिरता (market-implied volatilities) का एक सरफेस है। इसका रूट-फाइंडिंग पक्ष how implied volatility is calculated में कवर किया गया है। नीचे दिया गया आकार वह है जिसे एक मॉडल को मैच करना है।

क्वेरीसमाप्ति अवधि के अनुसार AAPL नियर-द-मनी इंप्लाइड वोलैटिलिटी
हर आंकड़े के पीछे का पूरा SQL
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

मनी के करीब, 0 to 7 days बकेट में AAPL अनुबंधों ने देखे गए सत्रों में औसतन 29.6% निहित अस्थिरता (implied volatility) दर्ज की, जबकि 29.3% पर 241 days or more थी। एक अस्थिरता पैरामीटर वाला मॉडल एक ही समय में दोनों बिंदुओं पर नहीं बैठ सकता है, यही कारण है कि अस्थिरता टर्म स्ट्रक्चर वाले मॉडल मौजूद हैं। इस तरह के सरफेस पर एक को फिट करना कैलिब्रेशन चरण है, और फिट किए गए मॉडल से जो संवेदनशीलता निकलती है, वे ग्रीक हैं, जो the option greeks explained में कवर किए गए हैं।

ये पैनल कैसे बनाए गए

कर्व पैनल ट्रेजरी श्रृंखला में सबसे हालिया कोट की गई तारीख को पढ़ता है और इसके ग्यारह टेनर कॉलम को पंक्तियों में खोलता है, उस दिन बिना कोट वाले किसी भी टेनर को छोड़ देता है। सत्र पैनल प्रति माह SPY टेप पर अलग-अलग तारीखों की गिनती करता है, जो पूर्ण एक्सचेंज सत्र गणना के लिए एक स्वच्छ प्रॉक्सी है। चेन पैनल नवीनतम उपलब्ध सत्र पर गैर-शून्य वॉल्यूम वाले अलग-अलग अनुबंध कोड की गिनती करता है, जिसे अंडरलाइंग द्वारा समूहीकृत किया गया है। अस्थिरता पैनल केवल गैर-शून्य वॉल्यूम और अंडरलाइंग क्लोज के 5% के भीतर स्ट्राइक के साथ कन्वर्ज्ड सॉल्व्स को रखता है, जो मानक near-the-money बैंड है; फ्रंट बकेट में उसी दिन की एक्सपायरी शामिल है।

FAQ

क्या libitofin QuantLib का ड्रॉप-इन प्रतिस्थापन है?

नहीं। अगस्त 2026 तक यह एक pre-1.0 पोर्ट है जो QuantLib के सरफेस के कुछ हिस्से को कवर करता है और QuantLib के अपने टेस्ट सूट के खिलाफ अपने परिणामों को मान्य करता है। QuantLib स्वयं, अपनी Python बाइंडिंग के माध्यम से, प्रोडक्शन कार्य के लिए व्यापक और अधिक स्थिर विकल्प बना हुआ है।

एक प्राइसिंग लाइब्रेरी के लिए pre-1.0 का क्या अर्थ है?

Rust के वर्ज़निंग कन्वेंशन के तहत, 0.x रिलीज़ कोई संगतता वादा नहीं करती है: अगला माइनर वर्ज़न किसी भी चीज़ का नाम बदलने या हटाने के लिए स्वतंत्र है। व्यवहार में इसका मतलब है कि एक सटीक टैग की गई रिलीज़ को पिन करना और हर अपग्रेड पर अपने स्वयं के टेस्ट सूट को फिर से चलाना।

क्या libitofin का उपयोग करने के लिए मुझे Rust लिखने की आवश्यकता है?

नहीं। प्रोजेक्ट itofin नाम का एक Python पैकेज प्रकाशित करता है, इसलिए इंजन को एक सामान्य Python प्रक्रिया से कॉल किया जा सकता है। Rust लिखना तब प्रासंगिक हो जाता है जब प्राइसिंग लूप ही वह चीज़ हो जिसे आप शिप कर रहे हैं।

एक प्राइसिंग लाइब्रेरी मुझे वह क्या देती है जो स्प्रेडशीट फॉर्मूला नहीं देता?

एकल दरों के बजाय कर्व, उनके पीछे वास्तविक एक्सचेंज कैलेंडर के साथ डे-काउंट कन्वेंशन, एक कैलिब्रेशन लूप जो मॉडल पैरामीटर को कोट की गई कीमतों में फिट करता है, और इन तीनों के नीचे एक परीक्षण की गई न्यूमेरिक्स परत। क्लोज्ड-फॉर्म फॉर्मूला काम का छोटा हिस्सा है।

क्या प्रोग्रामिंग भाषा ऑप्शन की कीमत बदलती है?

गणितीय रूप से नहीं। यह पुनरुत्पादन (reproducibility) को बदलती है: फ्लोटिंग पॉइंट परिणाम संचालन के क्रम पर निर्भर करते हैं, इसलिए एक मॉडल के दो कार्यान्वयन अंतिम अंकों में असहमत हो सकते हैं। एक ही इंजन से शोध और प्रोडक्शन चलाने से वह अंतर खत्म हो जाता है।


यहाँ हर पैनल के नीचे उसका सटीक SQL है, इसलिए यह देखने के लिए कि गणना कैसे की गई, किसी एक को विस्तार दें। वही कर्व, कैलेंडर और चेन प्रश्न Strasmore टर्मिनल पर सादे अंग्रेजी में पूछे जा सकते हैं।