我遇到了一个问题,就是从一个楼层的债券中产生现金流。
我最初有一个问题,因为我忽略了设定一个价格。我已经设置了如下的价格。
ql_bond = QuantLib.FloatingRateBond(settlement_days, #settlementDays
face_amount, # faceAmount
ql_schedule,
ql_index,
QuantLib.Thirty360(),
gearings = [],
spreads = [libor_spread],
caps = [],
floors = [libor_floor]
)
volatility = 0
vol = QuantLib.ConstantOptionletVolatility(settlement_days,
QuantLib.UnitedKingdom(),
QuantLib.Unadjusted,
volatility,
QuantLib.Thirty360())
pricer = QuantLib.BlackIborCouponPricer(QuantLib.OptionletVolatilityStructureHandle(vol))
QuantLib.setCouponPricer(ql_bond.cashflows(), pricer)
在某些现金流量上,我能够为现金流量产生合理的金额。其他时候我遇到了错误。为警示(-.0225)指定的值等于libor_floor - libor_spread。我很确定我在这里犯了一个明显的错误,但不知道从哪里开始。如果更熟悉QuantLib的人有任何建议,我们将不胜感激。
Traceback (most recent call last):
File "C:\Users\Ryan\git\optimizer\src\calcs\cashflow_calcs.py", line 161, in generate_cashflow
cashflows.append(utils.cashflow.InterestCashflow(cf_date, cf.amount(), cf_fixing_date, c.indexFixing(), c.accrualDays()))
File "C:\Users\Ryan\Anaconda3\lib\site-packages\QuantLib\QuantLib.py", line 8844, in amount
return _QuantLib.CashFlow_amount(self)
RuntimeError: strike + displacement (-0.0225 + 0) must be non-negative
这与我之前的帖子有关 Using QuantLib to compute cash flows for FloatingRateBond with Floor
答案 0 :(得分:1)
问题不在于QuantLib 本身。 Black模型是对数正态模型,不适用于负值(因为您不能使用它们的对数)。正如你猜测的那样,当利率开始变为负值时,结果证明这是一个问题。它可以通过两种不同的方式解决:第一种是改变模型并使用正常模型,第二种是引入固定位移D
和模型log(R+D)
而不是log(R)
所以对数的参数是正的。
在这两种情况下,波动性都必须改变(实际上,报价波动率也会告诉您使用的是什么模型和位移)。在QuantLib中,这意味着您在构建波动率期限结构时必须传递相关信息 - 这是您目前遇到麻烦的地方。 C ++库已经提供了一段时间的功能,但是Python模块还没有导出相应的ConstantOptionletVolatility
,所以你得到了默认值,即对数正态模型和零位移。
如果您对SWIG感到满意,可以修改相应的接口文件QuantLib-SWIG/SWIG/volatilities.i
(您必须向ConstantOptionletVolatility
构造函数添加几个参数,就像完成它一样对于同一文件中的ConstantSwaptionVolatility
类,重新生成包装器并编译它们。否则,请在https://github.com/lballabio/QuantLib-SWIG/issues处打开一个问题,我们会尝试在下一个版本中添加该功能。
更新:在最新版本中,ConstantOptionletVolatility
可以选择替换。
答案 1 :(得分:0)
您可以建立一个成交量表面,而不使用ConstantOptionLetVolatility
,然后使用OptionletStripper1
将期权的波幅增加到价格中。这是对http://gouthamanbalaraman.com/blog/interest-rate-cap-floor-valuation-quantlib-python.html
pricer = ql.BlackIborCouponPricer()
strikes = [-0.01, 0.0, 0.01]
expiries = [ql.Period(i, ql.Years) for i in range(1,6)] #or tenors of your choice
vols = ql.Matrix(len(expiries), len(strikes))
data = [[65, 65, 65, 65, 65],
[65, 65, 65, 65, 65], #vols of your choice
[65, 65, 65, 65, 65]
]
for i in range(vols.rows()):
for j in range(vols.columns()):
vols[i][j] = data[j][i]/100.0
bdc = ql.Unadjusted
settle_days =0
daycount = ql.Actual360()
capfloor_vol = ql.CapFloorTermVolSurface(settle_days, calendar, bdc, expiries,
strikes, vols, daycount)
optionlet_surf = ql.OptionletStripper1(parVolSurface = capfloor_vol,
index = float_index,
displacement = 0.01) #this make 'k + d' non-neg
pricer.setCapletVolatility(ql.OptionletVolatilityStructureHandle
(ql.StrippedOptionletAdapter(optionlet_surf)))
ql.setCouponPricer(bond.cashflows(), pricer)