【手把手教你】固定收益和衍生品分析利器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 Cloud:构建分布式系统的利器

引言 在当今的云计算和微服务架构时代,构建高效、可靠的分布式系统成为软件开发的重要任务。Spring Cloud 提供了一套完整的解决方案,帮助开发者快速构建分布式系统中的一些常见模式(例如配置管理、服务发现、断路器等)。本文将探讨 Spring Cloud 的定义、核心组件、应用场景以及未来的发展趋势。 什么是 Spring Cloud Spring Cloud 是一个基于 Spring

一份LLM资源清单围观技术大佬的日常;手把手教你在美国搭建「百万卡」AI数据中心;为啥大模型做不好简单的数学计算? | ShowMeAI日报

👀日报&周刊合集 | 🎡ShowMeAI官网 | 🧡 点赞关注评论拜托啦! 1. 为啥大模型做不好简单的数学计算?从大模型高考数学成绩不及格说起 司南评测体系 OpenCompass 选取 7 个大模型 (6 个开源模型+ GPT-4o),组织参与了 2024 年高考「新课标I卷」的语文、数学、英语考试,然后由经验丰富的判卷老师评判得分。 结果如上图所

C++必修:模版的入门到实践

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:C++学习 贝蒂的主页:Betty’s blog 1. 泛型编程 首先让我们来思考一个问题,如何实现一个交换函数? void swap(int& x, int& y){int tmp = x;x = y;y = tmp;} 相信大家很快就能写出上面这段代码,但是如果要求这个交换函数支持字符型

零基础STM32单片机编程入门(一)初识STM32单片机

文章目录 一.概要二.单片机型号命名规则三.STM32F103系统架构四.STM32F103C8T6单片机启动流程五.STM32F103C8T6单片机主要外设资源六.编程过程中芯片数据手册的作用1.单片机外设资源情况2.STM32单片机内部框图3.STM32单片机管脚图4.STM32单片机每个管脚可配功能5.单片机功耗数据6.FALSH编程时间,擦写次数7.I/O高低电平电压表格8.外设接口

[职场] 公务员的利弊分析 #知识分享#经验分享#其他

公务员的利弊分析     公务员作为一种稳定的职业选择,一直备受人们的关注。然而,就像任何其他职业一样,公务员职位也有其利与弊。本文将对公务员的利弊进行分析,帮助读者更好地了解这一职业的特点。 利: 1. 稳定的职业:公务员职位通常具有较高的稳定性,一旦进入公务员队伍,往往可以享受到稳定的工作环境和薪资待遇。这对于那些追求稳定的人来说,是一个很大的优势。 2. 薪资福利优厚:公务员的薪资和

ps基础入门

1.基础      1.1新建文件      1.2创建指定形状      1.4移动工具          1.41移动画布中的任意元素          1.42移动画布          1.43修改画布大小          1.44修改图像大小      1.5框选工具      1.6矩形工具      1.7图层          1.71图层颜色修改          1

C++入门01

1、.h和.cpp 源文件 (.cpp)源文件是C++程序的实际实现代码文件,其中包含了具体的函数和类的定义、实现以及其他相关的代码。主要特点如下:实现代码: 源文件中包含了函数、类的具体实现代码,用于实现程序的功能。编译单元: 源文件通常是一个编译单元,即单独编译的基本单位。每个源文件都会经过编译器的处理,生成对应的目标文件。包含头文件: 源文件可以通过#include指令引入头文件,以使

高度内卷下,企业如何通过VOC(客户之声)做好竞争分析?

VOC,即客户之声,是一种通过收集和分析客户反馈、需求和期望,来洞察市场趋势和竞争对手动态的方法。在高度内卷的市场环境下,VOC不仅能够帮助企业了解客户的真实需求,还能为企业提供宝贵的竞争情报,助力企业在竞争中占据有利地位。 那么,企业该如何通过VOC(客户之声)做好竞争分析呢?深圳天行健企业管理咨询公司解析如下: 首先,要建立完善的VOC收集机制。这包括通过线上渠道(如社交媒体、官网留言

LVGL快速入门笔记

目录 一、基础知识 1. 基础对象(lv_obj) 2. 基础对象的大小(size) 3. 基础对象的位置(position) 3.1 直接设置方式 3.2 参照父对象对齐 3.3 获取位置 4. 基础对象的盒子模型(border-box) 5. 基础对象的样式(styles) 5.1 样式的状态和部分 5.1.1 对象可以处于以下状态States的组合: 5.1.2 对象

C语言入门系列:探秘二级指针与多级指针的奇妙世界

文章目录 一,指针的回忆杀1,指针的概念2,指针的声明和赋值3,指针的使用3.1 直接给指针变量赋值3.2 通过*运算符读写指针指向的内存3.2.1 读3.2.2 写 二,二级指针详解1,定义2,示例说明3,二级指针与一级指针、普通变量的关系3.1,与一级指针的关系3.2,与普通变量的关系,示例说明 4,二级指针的常见用途5,二级指针扩展到多级指针 小结 C语言的学习之旅中,二级