QuantLib 金融计算——自己动手封装 Python 接口(3)
程序员文章站
2022-09-04 20:28:03
[TOC] QuantLib 金融计算——自己动手封装 Python 接口(3) 概述 承接 "《自己动手封装 Python 接口(2)》" 中留下的问题,即封装 "QuantLibEx" 中的几个期限结构模型。 如何封装源代码? 与前一篇文章中的情况不同,要封装的程序不是已经编译好的库文件,而是 ......
quantlib 金融计算——自己动手封装 python 接口(3)
概述
承接《自己动手封装 python 接口(2)》中留下的问题,即封装 quantlibex 中的几个期限结构模型。
如何封装源代码?
与前一篇文章中的情况不同,要封装的程序不是已经编译好的库文件,而是 c++ 源代码。
swig 可以从源代码的层面封装 c++ 接口,一方面要提供头文件,告知 swig 类、函数等的声明;另一方面要提供源文件,让 swig 知道方法的实现,swig 会自动对源文件进行编译,并最终链接到生成的 python 接口中。
实践
幸运的是 quantlibex 中几个 ns 型期限结构模型的构造函数没有引入新的类型,所以“最小功能集合”没有变。
要封装这几个模型,只需对 fittedbondcurve.i
和 setup.py
稍加修改。在 fittedbondcurve.i
中编写接口代码,在 setup.py
添加头文件路径和几个源文件就可以了。
六个 ns 型期限结构模型的参数估计
把中的 c++ 代码翻译成 python,验证封装后的接口是否可用。
import quantlibex as qlx print(qlx.__version__) bondnum = 16 cleanprice = [100.4941, 103.5572, 104.4135, 105.0056, 99.8335, 101.25, 102.3832, 97.0053, 99.5164, 101.2435, 104.0539, 101.15, 96.1395, 91.1123, 122.0027, 92.4369] pricehandle = [qlx.quotehandle(qlx.simplequote(p)) for p in cleanprice] issueyear = [1999, 1999, 2001, 2002, 2003, 1999, 2004, 2005, 2006, 2007, 2003, 2008, 2005, 2006, 1997, 2007] issuemonth = [qlx.february, qlx.october, qlx.january, qlx.january, qlx.may, qlx.january, qlx.january, qlx.april, qlx.april, qlx.september, qlx.january, qlx.january, qlx.january, qlx.january, qlx.july, qlx.january] issueday = [22, 22, 4, 9, 20, 15, 15, 26, 21, 17, 15, 8, 14, 11, 10, 12] maturityyear = [2009, 2010, 2011, 2012, 2013, 2014, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2027, 2037] maturitymonth = [qlx.july, qlx.january, qlx.january, qlx.july, qlx.october, qlx.january, qlx.july, qlx.july, qlx.september, qlx.september, qlx.january, qlx.march, qlx.july, qlx.september, qlx.july, qlx.march] maturityday = [15, 15, 4, 15, 20, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15] issuedate = [] maturitydate = [] for i in range(bondnum): issuedate.append( qlx.date(issueday[i], issuemonth[i], issueyear[i])) maturitydate.append( qlx.date(maturityday[i], maturitymonth[i], maturityyear[i])) couponrate = [ 0.04, 0.055, 0.0525, 0.05, 0.038, 0.04125, 0.043, 0.035, 0.04, 0.043, 0.0465, 0.0435, 0.039, 0.035, 0.0625, 0.0415] # 配置 helper frequency = qlx.annual daycounter = qlx.actual365fixed(qlx.actual365fixed.standard) paymentconv = qlx.unadjusted terminationdateconv = qlx.unadjusted convention = qlx.unadjusted redemption = 100.0 faceamount = 100.0 calendar = qlx.australia() today = calendar.adjust(qlx.date(30, qlx.january, 2008)) qlx.settings.instance().evaluationdate = today bondsettlementdays = 0 bondsettlementdate = calendar.advance( today, qlx.period(bondsettlementdays, qlx.days)) instruments = [] maturity = [] for i in range(bondnum): bondcoupon = [couponrate[i]] schedule = qlx.schedule( issuedate[i], maturitydate[i], qlx.period(frequency), calendar, convention, terminationdateconv, qlx.dategeneration.backward, false) helper = qlx.fixedratebondhelper( pricehandle[i], bondsettlementdays, faceamount, schedule, bondcoupon, daycounter, paymentconv, redemption) maturity.append(daycounter.yearfraction( bondsettlementdate, helper.maturitydate())) instruments.append(helper) accuracy = 1.0e-6 maxevaluations = 5000 weights = qlx.array() # 正则化条件 l2ns = qlx.array(4, 0.5) guessns = qlx.array(4) guessns[0] = 4 / 100.0 guessns[1] = 0.0 guessns[2] = 0.0 guessns[3] = 0.5 l2sv = qlx.array(6, 0.5) guesssv = qlx.array(6) guesssv[0] = 4 / 100.0 guesssv[1] = 0.0 guesssv[2] = 0.0 guesssv[3] = 0.0 guesssv[4] = 0.2 guesssv[5] = 0.15 l2asv = qlx.array(6, 0.5) guessasv = qlx.array(6) guessasv[0] = 4 / 100.0 guessasv[1] = 0.0 guessasv[2] = 0.0 guessasv[3] = 0.0 guessasv[4] = 0.2 guessasv[5] = 0.3 l2bc = qlx.array(5, 0.5) guessbc = qlx.array(5) guessbc[0] = 4 / 100.0 guessbc[1] = 0.0 guessbc[2] = 0.0 guessbc[3] = 0.0 guessbc[4] = 0.2 l2bl = qlx.array(5, 0.5) guessbl = qlx.array(5) guessbl[0] = 4 / 100.0 guessbl[1] = 0.0 guessbl[2] = 0.0 guessbl[3] = 0.5 guessbl[4] = 0.5 optmethod = qlx.levenbergmarquardt() # 拟合方法 nsf = qlx.nelsonsiegelfitting( weights, optmethod, l2ns) svf = qlx.svenssonfitting( weights, optmethod, l2sv) asvf = qlx.adjustedsvenssonfitting( weights, optmethod, l2asv) dlf = qlx.dieboldlifitting( 0.5, weights, optmethod) bcf = qlx.bjorkchristensenfitting( weights, optmethod, l2bc) blf = qlx.blissfitting( weights, optmethod, l2bl) tsnelsonsiegel = qlx.fittedbonddiscountcurve( bondsettlementdate, instruments, daycounter, nsf, accuracy, maxevaluations, guessns, 1.0) tssvensson = qlx.fittedbonddiscountcurve( bondsettlementdate, instruments, daycounter, svf, accuracy, maxevaluations, guesssv) tsadjustedsvensson = qlx.fittedbonddiscountcurve( bondsettlementdate, instruments, daycounter, asvf, accuracy, maxevaluations, guessasv) tsdieboldli = qlx.fittedbonddiscountcurve( bondsettlementdate, instruments, daycounter, dlf, accuracy, maxevaluations) tsbjorkchristensen = qlx.fittedbonddiscountcurve( bondsettlementdate, instruments, daycounter, bcf, accuracy, maxevaluations, guessbc) tsbliss = qlx.fittedbonddiscountcurve( bondsettlementdate, instruments, daycounter, blf, accuracy, maxevaluations, guessbl) print("nelsonsiegel results: \t\t", tsnelsonsiegel.fitresults().solution()) print("svensson results: \t\t\t", tssvensson.fitresults().solution()) print("adjustedsvensson results: \t", tsadjustedsvensson.fitresults().solution()) print("dieboldli results: \t\t\t", tsdieboldli.fitresults().solution()) print("bjorkchristensen results: \t", tsbjorkchristensen.fitresults().solution()) print("bliss results: \t\t\t\t", tsbliss.fitresults().solution())
nelsonsiegel results: [ 0.0500803; -0.0105414; -0.0303842; 0.456529 ] svensson results: [ 0.0431095; -0.00716036; -0.0340932; 0.0391339; 0.228995; 0.117208 ] adjustedsvensson results: [ 0.0506269; -0.0116339; 0.0029305; -0.0135686; 0.179066; 0.267767 ] dieboldli results: [ 0.0496643; -0.00879931; -0.0329267 ] bjorkchristensen results: [ 0.0508039; -0.0555185; 0.0115282; 0.0415581; 0.227838 ] bliss results: [ 0.0500892; -0.0106013; -0.0315605; 0.513831; 0.456329 ]
所得结果和中的完全一致。