QuantLib 金融计算——自己动手封装 Python 接口(2)
QuantLib 金融计算——自己动手封装 Python 接口(2)
概述
对于一项简单功能,通常只需要包装少数几个类就可以,正如《自己动手封装 Python 接口(1)》演示的那样。
下面,将演示如何包装 QuantLib 中的复杂功能,最终实现从固息债交易数据中估计期限结构模型的参数。
如何封装一项复杂功能?
经过一翻摸索后发现,要封装一项复杂功能,首先要找到最小功能集合,即这项功能直接或间接涉及的类和函数有哪些。然后,找到最小功能集合后再对涉及到的类或函数分别编写接口文件。最后,按照常规流程生成包装好的 Python 接口。
对于简单功能来说最小功能集合可能就是一两个类或函数。而对于复杂功能来说,寻找最小功能集合是一个递归的过程(A 用到 B,B 用到 C,...),最终可能找到很多类或函数需要包装。
寻找最小功能集合的策略
寻找最小功能集合有一些经验性的方法,以“从固息债交易数据中估计期限结构模型的参数”这项功能为例:
- 找到核心功能类,即
FittedBondDiscountCurve,最小功能集合要包含这个类、它的基类以及基类的基类,等等; - 找到构造
FittedBondDiscountCurve对象时涉及到一系列的类,例如Calendar和FittingMethod等,这些类、它们的基类以及基类的基类也要包含在最小功能集合中; - 找到
FittedBondDiscountCurve成员函数涉及到一系列的类,这些类、它们的基类以及基类的基类也要包含在最小功能集合中; - 把第 2 和第 3 步递归地进行下去,直到最小功能集合中的类和函数不再增加。
需要注意的是,到现在为止最小功能集合中出现的类有的可以发挥实际作用,例如 Date;而有的只是充当接口的基类,例如 FittingMethod,对于这些情况,要把它们能够发挥实际作用的派生类包含进最小功能集合。
实践
QuantLib-SWIG 从 1.16 开始修改了智能指针的包装方式,为了和最新版本保持一致,这里以 QuantLib 1.17 的 SWIG 接口文件为基础做适当修改,删去一些冗余代码,用以包装 QuantLib 1.15 的接口。
官方发布的接口文件中 FittingMethod 的构造函数不能接受 OptimizationMethod 对象,也不能进行 \(L^2\) 正则化约束。在本次自定义的接口文件中扩展了构造函数的接口,克服上述局限。
接口文件请见 QuantLibEx-SWIG。
估计期限结构参数
把《收益率曲线之构建曲线(5)》中的 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
optMethod = qlx.LevenbergMarquardt()
# 拟合方法
nsf = qlx.NelsonSiegelFitting(
weights, optMethod, l2Ns)
svf = qlx.SvenssonFitting(
weights, optMethod, l2Sv)
tsNelsonSiegel = qlx.FittedBondDiscountCurve(
bondSettlementDate,
instruments,
dayCounter,
nsf,
accuracy,
maxEvaluations,
guessNs,
1.0)
tsSvensson = qlx.FittedBondDiscountCurve(
bondSettlementDate,
instruments,
dayCounter,
svf,
accuracy,
maxEvaluations,
guessSv)
print("NelsonSiegel Results: \t", tsNelsonSiegel.fitResults().solution())
print("Svensson Results: \t\t", tsSvensson.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 ]
所得结果和《收益率曲线之构建曲线(5)》中的完全一致。

修改官方接口文件
如果已经安装了 1.16 以后的 QuantLib,只要对官方接口文件稍加修改再重新包装 Python 接口,就可以扩展 FittingMethod 的构造函数,使其能接受 OptimizationMethod 对象,并能进行正则化。
以 NelsonSiegelFitting 为例,需要在 fittedbondcurve.i 文件中用
class NelsonSiegelFitting : public FittingMethod {
public:
NelsonSiegelFitting(
const Array& weights = Array(),
boost::shared_ptr< OptimizationMethod > optimizationMethod = boost::shared_ptr< OptimizationMethod >(),
const Array &l2 = Array());
};
替换
class NelsonSiegelFitting : public FittingMethod {
public:
NelsonSiegelFitting(const Array& weights = Array());
};
下一步的计划
- 包装 QuantLibEx 中的几个期限结构模型;
- scipy 的优化算法引擎要相较于 QuantLib 自身提供的要更丰富,尝试使
FittingMethod能接受 scipy 的算法。
QuantLib 金融计算——自己动手封装 Python 接口(2)的更多相关文章
- QuantLib 金融计算——自己动手封装 Python 接口(1)
目录 QuantLib 金融计算--自己动手封装 Python 接口(1) 概述 QuantLib 如何封装 Python 接口? 自己封装 Python 接口 封装 Array 和 Matrix 类 ...
- QuantLib 金融计算——收益率曲线之构建曲线(3)
目录 QuantLib 金融计算--收益率曲线之构建曲线(3) 概述 估算期限结构的步骤 读取样本券数据 一些基本配置 配置 *Helper 对象 配置期限结构 估算期限结构 汇总结果 当前实现存在的 ...
- QuantLib 金融计算——基本组件之 Currency 类
目录 QuantLib 金融计算--基本组件之 Currency 类 概述 构造函数 成员函数 如果未做特别说明,文中的程序都是 python3 代码. QuantLib 金融计算--基本组件之 Cu ...
- QuantLib 金融计算——高级话题之模拟跳扩散过程
目录 QuantLib 金融计算--高级话题之模拟跳扩散过程 跳扩散过程 模拟算法 面临的问题 "脏"的方法 "干净"的方法 实现 示例 参考文献 如果未做特别 ...
- QuantLib 金融计算——基本组件之 Date 类
目录 QuantLib 金融计算--基本组件之 Date 类 Date 对象的构造 一些常用的成员函数 一些常用的静态函数 为估值计算配置日期 如果未做特别说明,文中的程序都是 Python3 代码. ...
- QuantLib 金融计算——基本组件之 Schedule 类
目录 QuantLib 金融计算--基本组件之 Schedule 类 Schedule 对象的构造 作为"容器"的 Schedule 对象 一些常用的成员函数 如果未做特别说明,文 ...
- QuantLib 金融计算——基本组件之 Index 类
目录 QuantLib 金融计算--基本组件之 Index 类 QuantLib 金融计算--基本组件之 Index 类 Index 类用于表示已知的指数或者收益率,例如 Libor 或 Shibor ...
- QuantLib 金融计算——基本组件之 InterestRate 类
目录 QuantLib 金融计算--基本组件之 InterestRate 类 InterestRate 对象的构造 一些常用的成员函数 如果未做特别说明,文中的程序都是 Python3 代码. Qua ...
- QuantLib 金融计算——数学工具之数值积分
目录 QuantLib 金融计算--数学工具之数值积分 概述 常见积分方法 高斯积分 如果未做特别说明,文中的程序都是 Python3 代码. QuantLib 金融计算--数学工具之数值积分 载入模 ...
随机推荐
- 源码分析系列 | 从零开始写MVC框架
1. 前言 2. 为什么要自己手写框架 3. 简单MVC框架设计思路 4. 课程目标 5. 编码实战 5.1 配置阶段 web.xml配置 config.properties 自定义注解 5.2 初始 ...
- SpringBoot+vue+Iview前后端分离权限内容管理CMS系统
hrcms基于springBoot框架的内容管理系统,采用最新最主流的技术,后端采用spring boot,mybatis-plus,freemaker,shiro,redis,mysql,等,主要功 ...
- Spring Boot入门简介-Maven配置
一.简介 -- 简化Spring应用开发的一个框架: -- 整个Spring技术栈的一个大整合: -- J2EE开发的一站式解决方案. 二.背景: ① J2EE笨重的开发.繁多的配置.低下的开发效率. ...
- 一个支持高网络吞吐量、基于机器性能评分的TCP负载均衡器gobalan
一个支持高网络吞吐量.基于机器性能评分的TCP负载均衡器gobalan 作者最近用golang实现了一个TCP负载均衡器,灵感来自grpc.几个主要的特性就是: 支持高网络吞吐量 实现了基于机器性能评 ...
- 优雅地关闭worker进程
关闭nginx两种方式 nginx -s stop 立即停止nginx进程 nginx -s quit 优雅地关闭worker进程 开始优雅的关闭worker进程后 01设置定时器 worker_ ...
- C# 把带有父子关系的数据转化为------树形结构的数据 ,以及 找出父子级关系的数据中里面的根数据Id
紧接上一篇,将List<Menu>的扁平结构数据, 转换成树形结构的数据 返回给前端 , 废话不多说,开撸! --------------------- 步骤: 1. 建 Menu ...
- 移植freertos到stm32 f103 的基本流程和总结
为什么要在stm32 f103上面移植freertos stm32 f103 以他的全面的文档,亲民的价格,强大的功能.成为无数微设备的方案首选.在市场上有极大的使用量.市场占有率也是非常的高.f ...
- 数据清洗:按照进行数据清洗,并将清洗后的数据导入hive数据库中。
虚拟机: hadoop:3.2.0 hive:3.1.2 win10: eclipse 两阶段数据清洗: (1)第一阶段:把需要的信息从原始日志中提取出来 ip: 199.30.25.88 ti ...
- 动态主机配置协议-DHCP
一.DHCP 概述 当局域网中有大量的PC时.如果我们逐个为每台PC去手动配置IP.那这就是一个吃力也未必讨好的办法 累死你 而DHCP 刚好可以解决这个问题.DHCP全称(动态主机配置协议).使用的 ...
- Django表单Form类对空值None的替换
最近在写项目的时候用到Form,发现这个类什么都好,就是有些空值的默认赋值真是很不合我胃口. 查阅资料.官方文档后发现并没有设置该值的方式.于是,便开始了我的踩坑之路...... 不过现在完美解决了, ...