In a nutshell, this post will present, how to go from having several XML configuration files for specific QuantLib transaction in a directory (shown on the left side), to have all these transactions constructed and processed through QuantLib (shown on the right side).
Implement the following Python program. First, it will create QuantLib flat yield term structure and discounting bond pricing engine, request a batch of constructed QuantLib transactions from TransactionManager method (located in a separate QuantLibTransactionBuilder), then assign pricing engine for each transaction and finally, print calculated NPV along with some other transaction-related information.
%config IPCompleter.greedy = True from QuantLib import * from QuantLibTransactionBuilder import * # create valuation curve and pricing engine tradeDate = Date(28, November, 2018) settlementDate = TARGET().advance(tradeDate, Period(2, Days)) curveHandle = YieldTermStructureHandle(FlatForward(settlementDate, 0.01, Actual360())) engine = DiscountingBondEngine(curveHandle) # create QuantLib transactions from repository XML files transactionsFolder = '/home/TransactionRepository/' transactions = TransactionManager(transactionsFolder) # set pricing engine for all transactions, request PV for t in range(len(transactions)): transactions[t].setPricingEngine(engine) print('Maturity: ' + str(transactions[t].maturityDate())) print('Notional: ' + str(transactions[t].notional())) print('NPV: ' + str(transactions[t].NPV())) print()
Next, implement the following new module (QuantLibTransactionBuilder.py), which contains specific transaction builder for QuantLib ZeroCouponBond instrument, static class methods for QuantLib-related type conversions and one method for handling a set of given XML files and their conversions into QuantLib objects. Given comments in this module should give crystal clear picture what is happening here.
import os import importlib import re as Regex from bs4 import BeautifulSoup # sudo apt-get install python3-bs4 from QuantLib import * # static class for conversions from string to QuantLib objects/enumerators class QL(): @staticmethod def to_date(s): monthDictionary = { '01': January, '02': February, '03': March, '04': April, '05': May, '06': June, '07': July, '08': August, '09': September, '1': January, '2': February, '3': March, '4': April, '5': May, '6': June, '7': July, '8': August, '9': September, '10': October, '11': November, '12': December } arr = Regex.findall(r"[\w']+", s) day = int(arr[2]) month = monthDictionary[arr[1]] year = int(arr[0]) return Date(day, month, year) @staticmethod def to_businessDayConvention(s): if (s.upper() == 'MODIFIEDFOLLOWING'): return ModifiedFollowing # add new businessdayconvention here @staticmethod def to_calendar(s): if (s.upper() == 'TARGET'): return TARGET() # add new calendar here # loop through XML files in a given folder # for each transaction, read 'transactionBuilder' attribute from XML data # call configured transaction builder, build transaction and add it to list # finally, return list of all built QuantLib transactions to client def TransactionManager(folder): transactions = [] files = os.listdir(folder) for f in range(len(files)): soup = BeautifulSoup(open(folder + files[f]).read(), 'xml') transactionBuilder = soup.find('transactionBuilder').get_text() builder = getattr(importlib.import_module('QuantLibTransactionBuilder'), transactionBuilder)(folder + files[f]) transaction = builder transactions.append(transaction) return transactions # method for constructing QuantLib 'ZeroCouponBond' object from a given XML data def ZeroCouponBondBuilder(filePathName): # assign transaction data from XML to variables using soup # use conversion class methods for all QuantLib-related conversion soup = BeautifulSoup(open(filePathName).read(), 'xml') tradeDate = QL.to_date(soup.find('tradeDate').get_text()) settlementDate = QL.to_date(soup.find('settlementDate').get_text()) calendar = QL.to_calendar(soup.find('calendar').get_text()) faceAmount = float(soup.find('faceAmount').get_text()) maturityDate = QL.to_date(soup.find('maturityDate').get_text()) paymentConvention = QL.to_businessDayConvention(soup.find('paymentConvention').get_text()) settlementDays = settlementDate - tradeDate # create QuantLib object by calling appropriate constructor return ZeroCouponBond(settlementDays, calendar, faceAmount, maturityDate, paymentConvention)
All desired new transaction builders should be implemented into previous module by adding another builder method. Also, corresponding builder method name should be also set into transaction XML file as one input parameter.
<ZeroCouponBond> <transactionBuilder>ZeroCouponBondBuilder</transactionBuilder> <transactionID>CITI.0207</transactionID> <tradeDate>2008-07-02</tradeDate> <settlementDate>2008-07-05</settlementDate> <calendar>target</calendar> <faceAmount>1000000</faceAmount> <maturityDate>2032-07-05</maturityDate> <paymentConvention>modifiedfollowing</paymentConvention> </ZeroCouponBond>
Needless to say, one should also add all required new conversion methods from their string presentation to QuantLib objects into previous module. The original C# implementation can be found in here. Thanks for reading my blog.
-Mike