Quantlib Python Cookbook 学习

Quantlib入门

目录

以下学习内容以 Quantlib Python Cookbook 为基础,结合我自己对相关知识点的理解和应用, 整理合并而来, 原书作者是 Goutham Balaraman 和 Luigi Ballabio
为了便于理解本文的内容,建议阅读:复习一些必要的基础知识。
弄清量化金融十大话题 (上):https://freewechat.com/a/MzIzMjY0MjE1MA==/2247483968/1
弄清量化金融十大话题 (下):https://posts.careerengine.us/p/5d045bbfac24101e15a1b509

简介

QuantLib是一个专门用于利率、债券与衍生品等金融工具定价分析的库,可以说是固定收益和金融衍生品分析的一个利器。
QuantLib本身是使用C++写的,通过SWING技术封装后可以在Python调用。直接使用pip安装可能会报错,建议下载安装包的whl文件,然后再用pip进行安装。
下载安装
下载:https://www.lfd.uci.edu/~gohlke/pythonlibs/#quantlib
在线文档:https://quantlib-python-docs.readthedocs.io/en/latest/
QuantLib Python Tutorials With Examples
(英文)http://gouthamanbalaraman.com/blog/quantlib-python-tutorials-with-examples.html
(中文)https://www.cnblogs.com/xuruilong100/p/8711520.html
相比TA-Lib在技术分析领域的地位,QuantLib在金融工程领域的地位可以说有过之而无不及。

参考其官方网站,QuantLib中包含的的模块如下(其中个人感觉国内比较有用的添加了中文注释):

  • Currencies and FX rates(货币相关)
  • Date and time calculations(日期和时间计算)
  • Calendars
  • Day counters
  • Design patterns
  • Financial instruments
  • Finite-differences framework
  • Lattice methods
  • Math tools
  • 1-D Interpolations and corresponding traits
  • One-dimensional solvers
  • Optimizers(优化器)
  • Monte Carlo framework (蒙特卡洛模拟框架)
  • Numeric types
  • Output manipulators
  • Pricing engines(定价引擎)
  • Asian option engines(亚式期权)
  • Barrier option engines(障碍期权)
  • Basket option engines(篮子期权)
  • Cap/floor engines
  • Cliquet option engines
  • Forward option engines(远期期权)
  • Quanto option engines
  • Swaption engines
  • Vanilla option engines(普通期权)
  • QuantLib macros
  • Debugging macros
  • Numeric limits
  • Short-rate modelling framework(短期利率建模框架)
  • Stochastic processes(随机过程)
  • Term structures(期限结构)
  • Utilities

Quant-lib 中文作者的BLOG: https://www.cnblogs.com/xuruilong100
他的书:https://leanpub.com/implementingquantlib-cn

其它学习资料
在Python中使用QuantLib
https://zhuanlan.zhihu.com/p/20647300

Dimitri Reiswich contributed the slides he used during a course he taught, along with the corresponding code:
Boost introduction PDF
QuantLib introduction, part I PDF
QuantLib introduction, part II PDF
code samples ZIP
https://www.quantlib.org/docs.shtml

1.Quantlib 基础 (Basics)

Date Class:日期模块

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

from QuantLib import *      #注意,这里的区分大小写,正确写法是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日”

import QuantLib as ql
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

注意:可以使用JointCalendar Class来合并不同的calendar,例如:

date = Date(31,3,2015)
us_calendar = UnitedStates()
italy_calendar = Italy()
period = Period(60,Days)

joint_calendar = JointCalendar(us_calendar,italy_calendar)
joint_date = joint_calendar.advance(date,period)
joint_busdays = joint_calendar.businessDaysBetween(date, joint_date)

print("Add 60 business days in US-Italy:", joint_date)
print("Business days US-Italy:", joint_busdays)

#Add 60 business days in US-Italy: June 29th, 2015
#Business days US-Italy: 60

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')  #或 tenor = ql.Period(ql.Monthly)
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 = False
 
rules = {
    '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])

输出结果:

Backward [Date(6,1,2020), Date(20,1,2020), Date(20,2,2020), Date(20,3,2020), Date(20,4,2020)]
Forward [Date(6,1,2020), Date(5,2,2020), Date(5,3,2020), Date(6,4,2020), Date(20,4,2020)]
Zero [Date(6,1,2020), Date(20,4,2020)]
ThirdWednesDay [Date(6,1,2020), Date(19,2,2020), Date(18,3,2020), Date(15,4,2020), Date(20,4,2020)]
Twentieth [Date(6,1,2020), Date(20,1,2020), Date(20,2,2020), Date(20,3,2020), Date(20,4,2020)]
TwentiethIMM [Date(6,1,2020), Date(20,3,2020), Date(20,4,2020)]
CDS [Date(20,12,2019), Date(20,3,2020), Date(20,4,2020)]

Business Day Convention

利率产品会定期有现金流量在买卖双方支付, 例如约定每个月或每三个月付一次, 但有可会发生预定付款的日期是周末或假日. 假日银行不上班是没办法付款的, 所以在预定付款日不是工作日的话, 就需要做一些调整.
举例来说, 约定好在未来一年内的每月一日付款, 而其中有几个月的一日是周六或周日, 也有放假日, 这时候必须把这些月份的付款日往前或往后调整. 调整的方式就是 Business Day Convention.
这些调整适用于所有利率产品的付款日期, 不只是 IRS, 对所有利率类产品都很重要.
在这里,有更详细的解说的应用:https://www.codeleading.com/article/7501930800/

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)
print (interest_rate)

输出结果:
8.000000 % Actual/Actual (ISDA) Annual compounding
要显示数字本身,可以print (interest_rate.rate()),则显示:0.08

另外,如果ipython下直接输入interest_rate+回车
显示:<QuantLib.QuantLib.InterestRate; proxy of <Swig Object of type 'InterestRate *' at 0x000002329E485AE0> >

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

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

输出结果:1.1664 1.1664

interestRate.discountFactor(2.0)
输出结果:0.9070294784580498
discountFactor方法返回复合因子方法的倒数。在计算未来现金流的现值时,折现系数是非常实用的。

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

输出结果:0.8573 0.8573

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

compound_type= ql.Compounded
t=2.0
new_frequency = ql.Monthly      #或者 = Semiannual
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在固定收益分析中的应用案例,敬请期待。

2.Quantlib 进阶

定价引擎与工具 (Instruments and pricing engines)

本节用来展示定价工具与引擎是如何监控输入数据引起的变化
一个完整的例子:

from QuantLib import *
#set up the global evaluation date.
today = Date(7, March, 2014)
Settings.instance().evaluationDate = today

#The instrument: take European Option as example
option = EuropeanOption(PlainVanillaPayoff(Option.Call, 100.0),EuropeanExercise(Date(7, June, 2014)))

u = SimpleQuote(100.0)
r = SimpleQuote(0.01)
sigma = SimpleQuote(0.20)

riskFreeCurve = FlatForward(0, TARGET(), QuoteHandle(r), Actual360())
volatility = BlackConstantVol(0, TARGET(), QuoteHandle(sigma), Actual360())

process = BlackScholesProcess(QuoteHandle(u),YieldTermStructureHandle(riskFreeCurve),
                               BlackVolTermStructureHandle(volatility))
 
engine = AnalyticEuropeanEngine(process)
option.setPricingEngine(engine)

print('option.NPV():',option.NPV())
print('option.delta():',option.delta())
print('option.gamma():',option.gamma())
print('option.vega():',option.vega())

#option.NPV(): 4.155543462156206
#option.delta(): 0.5302223303784392
#option.gamma(): 0.03934493301271913
#option.vega(): 20.109632428723106

数字指标计算 (Numberical Greeks calculation)

市场报价 (Markets Quotes)

收益率曲线 (Interest-Rate Curves)

期限结构与引用日期 (Term structures and their reference rate)

EONIA曲线引导 (EONIA curve bootstrapping)

Euribor曲线引导 ( Euribor curve bootstrapping)

构建收益率曲线 ( Constructing Yield Curve)

隐含期限结构 ( Implied term structure)

1利率敏感度与零利差( Interest-Rate sensitivities via zero spread)

远期利率曲线及异常( A glitch in forward-rate curves)

收益率模型 (Interest-Rate models)

使用Hull White模型模拟收益率水平 (Simulating Interest Rates Using Hull White Model)

聚合Hull White模型与Monte-Carol模拟方法 (Thoughts on the Convergence of Hull White Model Monte-Carol Simulations)

短期利率模型校准 (Short Interest Rate Model Calibration)

相关代码案例

Date, Calendar, Schedule, InterestRate, CompoundFactor

# -*- coding: utf-8 -*-
"""
Created on Mon Dec 14 09:40:33 2020
Author: John C
功能简介:
本节内容来自:http://gouthamanbalaraman.com/blog/quantlib-basics.html
包括:
    1.如何使用ql.Date,提取年月日,进行日期加减(加天数,或加 Period),
    2.两种方法创建 schedule,并打印
    3.介绍了interestRate,compoundFactor
各种交易日期的区别:
Day count convention:https://en.wikipedia.org/wiki/Day_count_convention
"""

import QuantLib as ql
'''
Time SubModule
The ql/time sub-folder implements various time related classes. Lets take a look at the Date object
 which can be constructed as Date(date, month, year).
'''
date = ql.Date(31, 3, 2015) # 31 March, 2015
print(date)
date.dayOfMonth()   #31
date.month()    #3
date.year() #2015
date.weekday()==ql.Tuesday
#True

# arithmetic with dates
date + 1  # add a day: Date(1,4,2015)
date - 1  # subtract a day:Date(30,3,2015)
date + ql.Period(1, ql.Months)#Date(30,4,2015)
date + ql.Period(1, ql.Weeks)#Date(7,4,2015)
date + ql.Period(1, ql.Years)#Date(31,3,2016)

# logical operations
ql.Date(31, 3, 2015) > ql.Date(1, 3, 2015)#True
'''
The Schedule object can be used to construct a list of dates such as coupon payments. 
Lets look at some examples.
'''
print('
','======生成schedule,方法一======')
date1 = ql.Date(1, 1, 2015)
date2 = ql.Date(1, 1, 2016)
tenor = ql.Period(ql.Monthly)
calendar = ql.UnitedStates()
schedule = ql.Schedule(date1, date2, tenor, calendar, ql.Following,
                           ql.Following, ql.DateGeneration.Forward, False)

print('list(schedule):','
',list(schedule))
#for i,d in enumerate(schedule):
#    print(i+1,d)

print('
','======生成schedule,方法二======')
date1 = ql.Date(1, 1, 2015)
date2 = ql.Date(1, 1, 2016)
tenor = ql.Period(ql.Monthly)
calendar = ql.UnitedStates()
business_convention = ql.Following
termination_business_convertion = ql.Following
date_generation = ql.DateGeneration.Forward
end_of_month = False
myschedule = ql.Schedule(date1, date2, tenor, calendar, business_convention,
                           termination_business_convertion, date_generation,end_of_month)

for i,d in enumerate(myschedule):
    print(i+1,d)

'''
effective_date = ql.Date(1,1,2015)
termination_date = ql.Date(1,1,2016)
tenor = ql.Period(ql.Monthly)
calendar = ql.UnitedStates
business_convention = ql.Following
termination_business_convertion = ql.Following
date_generation = ql.DateGeneration.Forward
end_of_month = False
myschedule = ql.Schedule(effective_date,termination_date,tenor,calendar,business_convention,
                       termination_business_convertion,date_generation,end_of_month)

for i,d in enumerate(myschedule):
    print(i+1,d)


[Date(2,1,2015),
 Date(2,2,2015),
 Date(2,3,2015),
 Date(1,4,2015),
 Date(1,5,2015),
 Date(1,6,2015),
 Date(1,7,2015),
 Date(3,8,2015),
 Date(1,9,2015),
 Date(1,10,2015),
 Date(2,11,2015),
 Date(1,12,2015),
 Date(4,1,2016)]

Here we have generated a Schedule object that will contain dates between date1 and date2 with the tenor
 specifying the Period to be every Month. The calendar object is used for determining holidays. 
 The two arguments following the calendar in the Schedule constructor are the BussinessDayConvention.
 Here we chose the convention to be the day following holidays. That is why we see that holidays are 
 excluded in the list of dates.

Interest Rate
The InterestRate class can be used to store the interest rate with the compounding type, day count
 and the frequency of compounding. Below we show how to create an interest rate of 5.0% compounded
 annually, using Actual/Actual day count convention.
'''
annualRate = 0.05
dayCount = ql.ActualActual()
compoundType = ql.Compounded
frequency = ql.Annual
interestRate = ql.InterestRate(annualRate, dayCount, compoundType, frequency)
'''
Lets say if you invest a dollar at the interest rate described by interestRate, the compoundFactor
 method gives you how much your investment will be worth after t years. Below we show that the value
 returned by compoundFactor for 2 years agrees with the expected compounding formula.
'''
print('interestRate.compoundFactor(2.0):',interestRate.compoundFactor(2.0))  #1.1025
print('(1.0 + annualRate)*(1.0 + annualRate):',(1.0 + annualRate)*(1.0 + annualRate)) # Check the above calculation :1.1025
'''
The discountFactor method returns the reciprocal of the compoundFactor method. The discount factor
 is useful while calculating the present value of future cashflows.
'''
print('interestRate.discountFactor(2.0):',interestRate.discountFactor(2.0))#0.9070294784580498
print('1.0 / interestRate.compoundFactor(2.0):',1.0 / interestRate.compoundFactor(2.0))#0.9070294784580498
'''
A given interest rate can be converted into other types using the equivalentRate method as :
'''
newFrequency = ql.Semiannual
effectiveRate = interestRate.equivalentRate(compoundType, newFrequency, 1)
effectiveRate.rate()#0.04939015319191986
'''
The InterestRate class also has an impliedRate method. The impliedRate method takes compound factor 
to return the implied rate. The impliedRate method is a static method in the InterestRate class and
 can be used without an instance of InterestRate. Internally the equivalentRate method invokes the
 impliedRate method in its calculations.

Here we have converted into a semi-annual compounding type. A 4.939% of semi-annual compounding is
 equivalent to 5.0% annual compounding. This should mean, that both should give identical discount 
 factors. Lets check that:
'''
print('interestRate.discountFactor(1.0):',interestRate.discountFactor(1.0))    #0.9523809523809523
print('effectiveRate.discountFactor(1.0)',effectiveRate.discountFactor(1.0))   #0.9523809523809521

其它学习资料:

在Python中使用QuantLib
https://zhuanlan.zhihu.com/p/20647300

Dimitri Reiswich contributed the slides he used during a course he taught, along with the corresponding code:
Boost introduction PDF
QuantLib introduction, part I PDF
QuantLib introduction, part II PDF
code samples ZIP
https://www.quantlib.org/docs.shtml

参考资料:

  1. Luigi Ballabio and Goutham Balaraman,2017,《QuantLib Python Cookbook》.
  2. QuantLib官方网上英文教程:https://quantlib-python-docs.readthedocs.io/en/latest/dates.html
原文地址:https://www.cnblogs.com/treasury-manager/p/14131846.html