quantlib 金融计算——自己动手封装 python 接口(3)
概述
如何封装源代码?
与前一篇文章中的情况不同,要封装的程序不是已经编译好的库文件,而是 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 ]
所得结果和中的完全一致。
如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!