【手把手教你】固定收益和衍生品分析利器QuantLib入门

2023-10-30 21:50

本文主要是介绍【手把手教你】固定收益和衍生品分析利器QuantLib入门,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

引言

QuantLib是一个专门用于利率、债券与衍生品等金融工具定价分析的库,可以说是固定收益和金融衍生品分析的一个利器。QuantLib本身是使用C++写的,通过SWING技术封装后可以在Python调用。直接使用pip安装可能会报错,建议下载安装包的whl文件,然后再用pip进行安装。

https://www.lfd.uci.edu/~gohlke/pythonlibs/#quantlib (建议收藏,涵盖了Python大部分第三方包),找到与自己电脑和Python相对应的版本下载,如我的电脑是64位,Python3.7,选择第一个下载,将下载的文件放在当前工作目录,然后进入cmd模式(cmd模式下的地址即为当前工作目录),输入:

“pip install QuantLib_Python‑1.11‑cp37‑cp37m‑win_amd64.whl”即可,如果import QuantLib没有报错说明安装成功。

在公众号后台回复“quantlib”可以获取quantilib的使用手册(英文版)

如何查看系统环境、包的版本号和当前工作路径呢?

#先pip安装watermark
#查看系统环境和module的版本号
%load_ext watermark
%watermark
%watermark -p pandas,numpy,QuantLib,matplotlib

输出结果:

#查看当前工作目录
import os
os.getcwd()
#输出结果:
'C:\\Users\\zjy'引入QuantLib包
#引入QuantLib
import QuantLib as ql
QuantLib基础模块:Dates

日期模块Dates包含了Date,Period,Calendar,DayCounter,Schedule,DateGeneration等,是QuantLib的基础模块,包含了时间、日期、日历等的定义、生成和逻辑运算等,是数学建模和量化分析的重要基础。

Date:日期

Date是日期格式,日期范围是1901-01-01至2199-12-31。有三种写法:(1)Date(n),与Excel类似,其中n的范围是367-109574之间的数字(含),其他超出该范围的数字都会报错;(2)Date(day,month,year),即日,月,年的输入格式,其中日和年必须是数字,而月可以是其他格式,如ql.June(相当于输入6)。(3)Date(日期,格式),如:Date('20-09-2020', '%d-%m-%Y')

应用实例:定义日期“2020年11月11日”

d1=ql.Date(11,11,2020)
d2=ql.Date('2020-11-11','%Y-%m-%d')
d3=ql.Date('20201111','%Y%m%d')
d4=ql.Date(44146)
#四种写法等价
print(d1==d2==d3==d4)
#输出结果:True


日期定义与运算

today=ql.Date(11,11,2020)
print('初始日期:', today)
print('ISO格式:', today.ISO())
#返回一周七天对应的数字:注意周日(Sunday)是1,周六(Saturday)是7
print('一周中第几天:', today.weekday())
print('该月的第几天:', today.dayOfMonth())
print('本年的第几天:', today.dayOfYear())
print('月份:', today.month())
print('年份:', today.year())
#相当于第一种写法的逆运算
print('日期数字:', today.serialNumber())

输出结果:
初始日期: November 11th, 2020
ISO格式: 2020-11-11
一周中第几天: 4
该月的第几天: 11
本年的第几天: 316
月份: 11
年份: 2020
日期数字: 44146

#逻辑判断
print(today == ql.Date(12, 11, 2020))
print(today > ql.Date(11, 10, 2020))
print(today < ql.Date(1, 12, 2020))
print(today != ql.Date(11, 9, 2020))

输出结果:False、True、True、True

获取Date内置日期和运算函数

print('当前日期:', ql.Date.todaysDate())
print('系统支持最小日期 :', ql.Date.minDate())
print('系统支持最大日期 :', ql.Date.maxDate())
#判断是否闰年
print('是闰年吗? :', ql.Date.isLeap(2020))
print('该月的最后一天:', ql.Date.endOfMonth(ql.Date(11, ql.November, 2020)))
print('是该月的最后一天吗? :', ql.Date.isEndOfMonth(ql.Date(30, 11, 2020)))
print('该日期的下个星期一 :', ql.Date.nextWeekday(ql.Date(11, 11, 2020), ql.Monday))
print('该月的第2个星期五 :', ql.Date.nthWeekday(2, ql.Friday, 11, 2020))

输出结果:
当前日期: November 11th, 2020
系统支持最小日期 : January 1st, 1901
系统支持最大日期 : December 31st, 2199
是闰年吗?: True
该月的最后一天: November 30th, 2020
是该月的最后一天吗?: True
该日期的下个星期一 : November 16th, 2020
该月的第2个星期五 : November 13th, 2020

Period:周期

Period可以生成日期频数,如多少日(周、月、年)等。主要有三种写法:(1)ql.Period(n, units),其中units可以是日:ql.Days,周:ql.Weeks,月:ql.Months,年:ql.Years。(2)ql.Period(periodString),其中periodString可以是日:'1D',周:'1W',月:'1M'和年:'1Y'。(3)ql.Period(frequency),如每年,ql.Annual。

#一年的等价写法
ql.Period('1Y')==ql.Period(1,ql.Years)==ql.Period(ql.Annual)
#输出结果:True

Period主要是用于Date的运算。

today=ql.Date(11,11,2020)
print(f'{today}三天后是{today+3}')
print(f'{today}前一天是{today-1}')
print(f'{today}下一周是{today+ql.Period(1,ql.Weeks)}')
print(f'{today}下一个月是{today+ql.Period(1,ql.Months)}')
print(f'{today}下一年是{today+ql.Period(1,ql.Years)}')

输出结果:
November 11th, 2020三天后是November 14th, 2020
November 11th, 2020前一天是November 10th, 2020
November 11th, 2020下一周是November 18th, 2020
November 11th, 2020下一个月是December 11th, 2020
November 11th, 2020下一年是November 11th, 2021

Calendar:日历

Date对象没有考虑假期因素,而实际应用中,证券交易需要考虑指定交易所或者国家的假期,Calendar对主要的交易所给出了交易日历,包括:Argentina : [‘Merval’];Brazil : [‘Exchange’,‘Settlement’],Canada : [‘Settlement’, ‘TSX’]、China : [‘IB’, ‘SSE’];CzechRepublic : [‘PSE’],France : [‘Exchange’, ‘Settlement’];Germany : [‘Eurex’, ‘FrankfurtStockExchange’, ‘Settlement’, ‘Xetra’],HongKong : [‘HKEx’],Iceland : [‘ICEX’],India : [‘NSE’],Indonesia : [‘BEJ’, ‘JSX’],Israel : [‘Settlement’, ‘TASE’],Italy : [‘Exchange’, ‘Settlement’],Mexico : [‘BMV’],Russia : [‘MOEX’, ‘Settlement’],SaudiArabia : [‘Tadawul’],Singapore :[‘SGX’],Slovakia : [‘BSSE’],SouthKorea : [‘KRX’, ‘Settlement’],Taiwan : [‘TSEC’],Ukraine : [‘USE’],UnitedKingdom : [‘Exchange’, ‘Metals’, ‘Settlement’];UnitedStates :[‘FederalReserve’,‘GovernmentBond’,‘LiborImpact’, ‘NERC’, ‘NYSE’, ‘Settlement’]

calendar1 = ql.UnitedKingdom(ql.UnitedKingdom.Exchange)
calendar2 = ql.UnitedStates(ql.UnitedStates.NYSE)
calendar3 = ql.China(ql.China.SSE)
day1=ql.Date(1,1,2020)
day2=ql.Date(31,12,2020)
uk_bday=calendar1.businessDaysBetween(day1,day2)
us_bday=calendar2.businessDaysBetween(day1,day2)
ch_bday=calendar3.businessDaysBetween(day1,day2)
print(day1,'至',day2,'之间有',uk_bday,'个英国交易日')
print(day1,'至',day2,'之间有',us_bday,'个美国交易日')
print(day1,'至',day2,'之间有',ch_bday,'个中国交易日')

输出结果:
January 1st, 2020 至 December 31st, 2020 之间有 253 个英国交易日
January 1st, 2020 至 December 31st, 2020 之间有 252 个美国交易日
January 1st, 2020 至 December 31st, 2020 之间有 260 个中国交易日

判断日期类型

cal1 = ql.China()
cal2 = ql.UnitedStates()
mydate = ql.Date(1, 10, 2020)
#判断交易日
print(mydate,'在中国是交易日吗? :', cal1.isBusinessDay(mydate))
print(mydate,'在美国是交易日吗? :', cal2.isBusinessDay(mydate))

输出结果:
October 1st, 2020 在中国是交易日吗?: True
October 1st, 2020 在美国是交易日吗?: True

cal = ql.China()
day1 = ql.Date(11, 11, 2020)
day2 = ql.Date(14, 11, 2020)
print('Is Business Day : ', cal.isBusinessDay(day1))
print('Is Business Day : ', cal.isBusinessDay(day2))
#添加或者移除节假日设定
cal.addHoliday(day1)
cal.removeHoliday(day2)
print('Is Business Day : ', cal.isBusinessDay(day1))
print('Is Business Day : ', cal.isBusinessDay(day2))

输出结果:
Is Business Day : True
Is Business Day : False
Is Business Day : False
Is Business Day : True

不同国家日历日和交易日的区别

date = ql.Date(11, 11, 2020)
us_calendar = ql.UnitedStates()
ch_calendar = ql.China()
raw_date = date + ql.Period(30, ql.Days)
us_date = us_calendar.advance(date, ql.Period(30, ql.Days))
ch_date = ch_calendar.advance(date, ql.Period(30, ql.Days))
print(date,"后推30个日历日:     ", raw_date)
print(date,"后推美国30个交易日: ", us_date)
print(date,"后推中国30个交易日: ", ch_date)

输出结果:
November 11th, 2020 后推30个日历日:December 11th, 2020
November 11th, 2020 后推美国30个交易日:December 24th, 2020
November 11th, 2020 后推中国30个交易日:December 22nd, 2020

DayCounter:天数计算

DayCounter可以统计某两个日期之间的天数,是固定收益类产品估值和分析的重要基础,常用的计数函数包括:

  • Actual360 : Actual / 360,一年按360天

  • Actual365Fixed : Actual / 365(Fixed),一年按365天

  • Standard:标准;Canadian:加拿大;NoLeap:即所有年份都是365天

  • ActualActual : 按每年实际天数

  • ISMA \ Bond\ ISDA\ Historical\ Actual365\ AFB\ Euro

  • Business252 : Business / 252,证券交易日

  • Thirty360 : 30 / 360,按月30天,年360天

  • SimpleDayCounter:简单的日计数

常用的函数有两个:

dayCount(d1,d2):计算 d1,d2 之间的天数

yearFraction(d1, d2):将 d1,d2 之间的天数年化

d1 = ql.Date(1,10,2020)
d2 = ql.Date(11,11,2020)
dc=ql.Business252()
dd=dc.dayCount(d1,d2)
yf=dc.yearFraction(startDate,endDate)
print(f'日历间隔天数:{d2-d1}')
print(f'Business252计算规则天数:{dd}')
print(f'Business252计算规则天数年化:{yf:.4f}')
日历间隔天数:41
Business252计算规则天数:27
Business252计算规则天数年化:0.1071
dayCounters = {'SimpleDayCounter': ql.SimpleDayCounter(),'Thirty360': ql.Thirty360(),'Actual360': ql.Actual360(),'Actual365Fixed': ql.Actual365Fixed(),'Actual365Fixed(Canadian)': ql.Actual365Fixed(ql.Actual365Fixed.Canadian),'Actual365NoLeap': ql.Actual365NoLeap(),'ActualActual': ql.ActualActual(),'Business252': ql.Business252()}
for name,dc in dayCounters.items():dd=dc.dayCount(startDate,endDate)print(name,'计算规则天数',dd)       

输出结果:
SimpleDayCounter 计算规则天数 40
Thirty360 计算规则天数 40
Actual360 计算规则天数 41
Actual365Fixed 计算规则天数 41
Actual365Fixed(Canadian) 计算规则天数 41
Actual365NoLeap 计算规则天数 41
ActualActual 计算规则天数 41
Business252 计算规则天数 27

Schedule:时间表

Schedule(effectiveDate, terminationDate, tenor, calendar, convention, terminationDateConvention, rule, endOfMonth, firstDate=Date(), nextToLastDate=Date()),各变量分别代表:

  • effectiveDate, terminationDate : 日历列表的起始和终止日期, 比如债券的定价和到期日期

  • tenor : Period对象, 两个日期的间隔, 如债券发行频率(1年或6个月)或利率掉期利率(3个月)。

  • calendar : 一个日历表,用于生成要遵循的日期的特定日历。

  • convention : 整数型,如何调整非工作天(最后一天除外),值范围是quantlib-python的一些保留变量。

  • terminationDateConvention : 整数型,如果最后的日期是非工作日,如何调整它,值范围是quantlib-python的一些保留变量。

  • Rule : 日期生成的一个成员,用于为日期生成规则。

  • endOfMonth : 如果开始日期在月底,是否需要在月底安排其他日期(最后日期除外)。

  • firstDate : nextToLastDate(可选):Date,为生成的方法规则提供的开始和结束日期(不常用)。

Schedule对象的行为和list类似,是一种存储Date对象的序列容器。使用len(sch):返回 Schedule 对象sch内日期的个数,[i]:返回第 i 个日期,Schedule对象是可迭代的。

effectiveDate = ql.Date(1,1,2018)
terminationDate = ql.Date(15,6,2020)
frequency = ql.Period('6M')
#默认使用当前系统日期
calendar = ql.TARGET()
convention = ql.ModifiedFollowing
terminationDateConvention = ql.ModifiedFollowing
#Forward是以初始日期向后推算,Backward是以结束日期向前推算
rule = ql.DateGeneration.Forward
endOfMonth = False
mysch = ql.Schedule(effectiveDate, terminationDate, frequency, calendar, convention, terminationDateConvention, rule, endOfMonth)
for i,d in enumerate(mysch):print(i+1,d)

输出结果:
1 January 2nd, 2018
2 July 2nd, 2018
3 January 2nd, 2019
4 July 1st, 2019
5 January 2nd, 2020
6 June 15th, 2020

schedule常用的函数:

  • until(d):从日期列表中截取前半部分,并保证最后一个日期是d。

  • isRegular(i):判断第 i 个区间是否完整。如果一个Schedule对象有 n 个日期,该对象就有 n-1个区间,那么第 i 个区间的长度和事先规定的时间间隔一致,则判断该区间是完整的(Regular)。

mys=mysch.until(ql.Date(15, ql.June, 2019))
for i in range(len(mys)-1):print(mys[i],'至',mys[i+1],'该区间完整吗?',mys.isRegular(i+1))

输出结果:
January 2nd, 2018 至 July 2nd, 2018 该区间完整吗?True
July 2nd, 2018 至 January 2nd, 2019 该区间完整吗?True
January 2nd, 2019 至 June 15th, 2019 该区间完整吗?False

DateGeneration

许多产品的估值依赖于对未来现金流的分析,因此准确地列出未来现金流的日期是至关重要的。在给定开始和结束日期后,可以采用“反向方法”或“正向方法”生成日期列表。

effectiveDate = ql.Date(5,1,2020)
terminationDate = ql.Date(20,4,2020)
frequency = ql.Period('1M')
#默认使用当前系统日期
calendar = ql.TARGET()
convention = ql.ModifiedFollowing
terminationDateConvention = ql.ModifiedFollowing
#Forward是以初始日期向后推算,Backward是以结束日期向前推算endOfMonth = Falserules = {'Backward': ql.DateGeneration.Backward,'Forward': ql.DateGeneration.Forward,'Zero': ql.DateGeneration.Zero,'ThirdWednesDay': ql.DateGeneration.ThirdWednesday,'Twentieth': ql.DateGeneration.Twentieth,'TwentiethIMM': ql.DateGeneration.TwentiethIMM,'CDS': ql.DateGeneration.CDS}for name, rule in rules.items():schedule = ql.Schedule(effectiveDate, terminationDate, frequency, calendar, convention, terminationDateConvention, rule, endOfMonth)print(name, [dt for dt in schedule])

输出结果:

InterestRate:利率类

InterestRate类可用于存储具有复利类型、日计数和复利频率的利率。下面我们将展示如何使用实际日计数惯例(Actual/Actual)创建8.0%复利年利率。

annual_rate = 0.08
day_count = ql.ActualActual()
compound_type = ql.Compounded
frequency = ql.Annual
interest_rate = ql.InterestRate(annual_rate,day_count,compound_type,frequency)

假设你以上述描述的利率投资一美元,利息对象中的复合因子法给出你的投资在任何时期后的价值。下面演示由复合因子返回的2年的值与预期的复利公式是一致的。

t = 2.0
print (interest_rate.compoundFactor(t))
print((1.0+annual_rate)**2) 

输出结果:1.1664  1.1664

discountFactor方法返回复合因子方法的倒数。在计算未来现金流的现值时,折现系数是非常实用的。

print (f'{interest_rate.discountFactor(t):.4f}')
print (f'{1.0/interest_rate.compoundFactor(t):.4f}')

输出结果:0.8573  0.8573

一个给定的利率可以转换为其他的复利类型和复利频率使用相等的中心方法。

compound_type= ql.Compounded
t=2.0
new_frequency = ql.Monthly
new_interest_rate =interest_rate.equivalentRate(compound_type, new_frequency,t)
new_annual_rate = new_interest_rate.rate()
print (f'{new_annual_rate:.4f}')

输出结果:0.0772

两个利率对象(interest_rate和new_interest_rate)的折现因子相同,如下所示。

print (f'{interest_rate.discountFactor(t):.4f}')
print (f'{new_interest_rate.discountFactor(t):.4f}')

输出结果:0.8573    0.8573

结语

QuantLib主要用于固定收益和衍生品的量化分析,内容包罗万象,涵盖的领域也比较广。本文主要介绍了QuantLib的基础模块——Dates日期类和InterestRate利率类。这两个类是后续利率、债券、金融衍生品估值和定价分析的重要基础。后续推文将以专题的形式介绍Quantlib在固定收益分析中的应用案例,敬请期待。

看完记得点赞和在看哦~

参考资料:

1. Luigi Ballabio and Goutham Balaraman,2017,《QuantLib Python Cookbook》.

2. QuantLib官方网上英文教程:https://quantlib-python-docs.readthedocs.io/en/latest/dates.html

关于Python金融量化

专注于分享Python在金融量化领域的应用。加入知识星球,可以免费获取量化投资视频资料、量化金融相关PDF资料、公众号文章Python完整源码、量化投资前沿分析框架,与博主直接交流、结识圈内朋友等。

这篇关于【手把手教你】固定收益和衍生品分析利器QuantLib入门的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/310802

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

Java 创建图形用户界面(GUI)入门指南(Swing库 JFrame 类)概述

概述 基本概念 Java Swing 的架构 Java Swing 是一个为 Java 设计的 GUI 工具包,是 JAVA 基础类的一部分,基于 Java AWT 构建,提供了一系列轻量级、可定制的图形用户界面(GUI)组件。 与 AWT 相比,Swing 提供了许多比 AWT 更好的屏幕显示元素,更加灵活和可定制,具有更好的跨平台性能。 组件和容器 Java Swing 提供了许多

【IPV6从入门到起飞】5-1 IPV6+Home Assistant(搭建基本环境)

【IPV6从入门到起飞】5-1 IPV6+Home Assistant #搭建基本环境 1 背景2 docker下载 hass3 创建容器4 浏览器访问 hass5 手机APP远程访问hass6 更多玩法 1 背景 既然电脑可以IPV6入站,手机流量可以访问IPV6网络的服务,为什么不在电脑搭建Home Assistant(hass),来控制你的设备呢?@智能家居 @万物互联

poj 2104 and hdu 2665 划分树模板入门题

题意: 给一个数组n(1e5)个数,给一个范围(fr, to, k),求这个范围中第k大的数。 解析: 划分树入门。 bing神的模板。 坑爹的地方是把-l 看成了-1........ 一直re。 代码: poj 2104: #include <iostream>#include <cstdio>#include <cstdlib>#include <al

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

MOLE 2.5 分析分子通道和孔隙

软件介绍 生物大分子通道和孔隙在生物学中发挥着重要作用,例如在分子识别和酶底物特异性方面。 我们介绍了一种名为 MOLE 2.5 的高级软件工具,该工具旨在分析分子通道和孔隙。 与其他可用软件工具的基准测试表明,MOLE 2.5 相比更快、更强大、功能更丰富。作为一项新功能,MOLE 2.5 可以估算已识别通道的物理化学性质。 软件下载 https://pan.quark.cn/s/57

MySQL-CRUD入门1

文章目录 认识配置文件client节点mysql节点mysqld节点 数据的添加(Create)添加一行数据添加多行数据两种添加数据的效率对比 数据的查询(Retrieve)全列查询指定列查询查询中带有表达式关于字面量关于as重命名 临时表引入distinct去重order by 排序关于NULL 认识配置文件 在我们的MySQL服务安装好了之后, 会有一个配置文件, 也就

衡石分析平台使用手册-单机安装及启动

单机安装及启动​ 本文讲述如何在单机环境下进行 HENGSHI SENSE 安装的操作过程。 在安装前请确认网络环境,如果是隔离环境,无法连接互联网时,请先按照 离线环境安装依赖的指导进行依赖包的安装,然后按照本文的指导继续操作。如果网络环境可以连接互联网,请直接按照本文的指导进行安装。 准备工作​ 请参考安装环境文档准备安装环境。 配置用户与安装目录。 在操作前请检查您是否有 sud