我想在python中使用QuantLib,主要是在投资组合环境中对利率工具(衍生工具)进行定价。主要要求是将日收益率曲线传递给系统,以便在连续几天进行定价(我们暂时忽略系统性能问题)。我的问题是,我是否正确地构建了下面的示例来实现这一点?我的理解是,我需要至少一个曲线对象,每天与必要的链接等。我已经利用熊猫来尝试这一点。如能提供指导,将不胜感激。在
import QuantLib as ql
import math
import pandas as pd
import datetime as dt
# MARKET PARAMETRES
calendar = ql.SouthAfrica()
bussiness_convention = ql.Unadjusted
day_count = ql.Actual365Fixed()
interpolation = ql.Linear()
compounding = ql.Compounded
compoundingFrequency = ql.Quarterly
def perdelta(start, end, delta):
date_list=[]
curr = start
while curr < end:
date_list.append(curr)
curr += delta
return date_list
def to_datetime(d):
return dt.datetime(d.year(),d.month(), d.dayOfMonth())
def format_rate(r):
return '{0:.4f}'.format(r.rate()*100.00)
#QuantLib must have dates in its date objects
dicPeriod={'DAY':ql.Days,'WEEK':ql.Weeks,'MONTH':ql.Months,'YEAR':ql.Years}
issueDate = ql.Date(19,8,2014)
maturityDate = ql.Date(19,8,2016)
#Bond Schedule
schedule = ql.Schedule (issueDate, maturityDate,
ql.Period(ql.Quarterly),ql.TARGET(),ql.Following, ql.Following,
ql.DateGeneration.Forward,False)
fixing_days = 0
face_amount = 100.0
def price_floater(myqlvalDate,jindex,jibarTermStructure,discount_curve):
bond = ql.FloatingRateBond(settlementDays = 0,
faceAmount = 100,
schedule = schedule,
index = jindex,
paymentDayCounter = ql.Actual365Fixed(),
spreads=[0.02])
bondengine = ql.DiscountingBondEngine(ql.YieldTermStructureHandle(discount_curve))
bond.setPricingEngine(bondengine)
ql.Settings.instance().evaluationDate = myqlvalDate
return [bond.NPV() ,bond.cleanPrice()]
start_date=dt.datetime(2014,8,19)
end_date=dt.datetime(2015,8,19)
all_dates=perdelta(start_date,end_date,dt.timedelta(days=1))
dtes=[];fixings=[]
for d in all_dates:
if calendar.isBusinessDay(ql.QuantLib.Date(d.day,d.month,d.year)):
dtes.append(ql.QuantLib.Date(d.day,d.month,d.year))
fixings.append(0.1)
df_ad=pd.DataFrame(all_dates,columns=['valDate'])
df_ad['qlvalDate']=df_ad.valDate.map(lambda x:ql.DateParser.parseISO(x.strftime('%Y-%m-%d')))
df_ad['jibarTermStructure'] = df_ad.qlvalDate.map(lambda x:ql.RelinkableYieldTermStructureHandle())
df_ad['discountStructure'] = df_ad.qlvalDate.map(lambda x:ql.RelinkableYieldTermStructureHandle())
df_ad['jindex'] = df_ad.jibarTermStructure.map(lambda x: ql.Jibar(ql.Period(3,ql.Months),x))
df_ad.jindex.map(lambda x:x.addFixings(dtes, fixings))
df_ad['flatCurve'] = df_ad.apply(lambda r: ql.FlatForward(r['qlvalDate'],0.1,ql.Actual365Fixed(),compounding,compoundingFrequency),axis=1)
df_ad.apply(lambda x:x['jibarTermStructure'].linkTo(x['flatCurve']),axis=1)
df_ad.apply(lambda x:x['discountStructure'].linkTo(x['flatCurve']),axis=1)
df_ad['discount_curve']= df_ad.apply(lambda x:ql.ZeroSpreadedTermStructure(x['discountStructure'],ql.QuoteHandle(ql.SimpleQuote(math.log(1+0.02)))),axis=1)
df_ad['all_in_price']=df_ad.apply(lambda r:price_floater(r['qlvalDate'],r['jindex'],r['jibarTermStructure'],r['discount_curve'])[0],axis=1)
df_ad['clean_price']=df_ad.apply(lambda r:price_floater(r['qlvalDate'],r['jindex'],r['jibarTermStructure'],r['discount_curve'])[1],axis=1)
df_plt=df_ad[['valDate','all_in_price','clean_price']]
df_plt=df_plt.set_index('valDate')
from matplotlib import ticker
def func(x, pos):
s = str(x)
ind = s.index('.')
return s[:ind] + '.' + s[ind+1:]
ax=df_plt.plot()
ax.yaxis.set_major_formatter(ticker.FuncFormatter(func))
多亏了Luigi Ballabio,我修改了上面的示例,将设计原则纳入QuantLib中,以避免不必要的调用。 现在静态数据是真正静态的,只有市场数据会变化(我希望如此)。 我现在更好地理解了活动对象如何监听链接变量中的更改。在
静态数据如下:
市场数据将是唯一变化的组成部分
修改后的示例如下:
^{pr2}$
你的解决方案是可行的,但是每天建立一个联系有点违背了图书馆的原则。您可以只创建一次bond和JIBAR索引,只需更改评估日期和相应的曲线;bond将检测更改并重新计算。在
在一般情况下,这将类似于:
现在,即使在最一般的情况下,上面的内容也可以优化:您在每个日期调用}。在
price_floater
两次,所以您要做两倍的工作。我不熟悉pandas,但我想你可以打一个电话,用一个单独的赋值设置df_ad['all_in_price']
和{此外,根据您的用例,可能还有进一步简化代码的方法。贴现曲线可能会实例化一次,而价差在定价过程中会发生变化:
^{pr2}$在不同的部分,你会有一系列的信用利差和一系列的贴现曲线。在
如果曲线都是平的,那么可以利用另一个功能来实现同样的操作:如果用天数和日历(而不是日期)初始化曲线,则其参考日期将随评估日期移动(如果天数为0,则为评估日期;如果为1,则为下一个工作日,依此类推)。在
在变化部分,您将用一个简单的速率数组替换jibar曲线数组。在
上面的结果应该与代码相同,但是实例化的对象要少得多,因此可能会节省内存并提高性能。在
最后一个警告:如果pandas的
map
并行计算结果,我的代码和你的代码都不起作用;你将尝试同时将全局评估日期设置为多个值,这不会很好。在相关问题 更多 >
编程相关推荐