簡體   English   中英

債券現金流量僅從評估日期開始

[英]Bond cashflows only from evaluation date onwards

假設評估日期為今天,並且有一個浮動利率債券,且其發行日期為過去。 我想使用Bond類(或FloatingRateBond )的cashflows()方法僅從評估日期開始計算現金流量。 問題在於,我既沒有過去的市場數據(用於固定利率),也沒有對過去發生的利率現金流感興趣。
我了解hasOccurred的方法, CashFlow ,但是這並不能幫助我,因為QuantLib拋出它錯過市場的數據,在過去,當我喚起了錯誤cashflows()
我可以告訴cashflows()僅計算在特定日期之后發生的現金流量嗎?

以下代碼重現該錯誤
RuntimeError: Missing EoniaON Actual/360 fixing for December 29th, 2017

import QuantLib as ql

referenceDate = ql.Date(1,1,2019)
ql.Settings.instance().evaluationDate = referenceDate

##################
# curve definition
##################
# curve data
periods = [ql.Period("1D"), ql.Period("2D"), ql.Period("3D"), ql.Period("1W"), ql.Period("2W"), ql.Period("4W3D"), ql.Period("8W5D"), ql.Period("12W6D"), ql.Period("17W2D"), ql.Period("21W4D"), ql.Period("26W"), ql.Period("30W2D"), ql.Period("34W5D"), ql.Period("39W1D"), ql.Period("43W3D"), ql.Period("47W6D"), ql.Period("52W1D"), ql.Period("65W"), ql.Period("78W1D"), ql.Period("91W2D"), ql.Period("104W2D"), ql.Period("117W2D"), ql.Period("130W3D"), ql.Period("143W4D"), ql.Period("156W4D"), ql.Period("169W3D"), ql.Period("182W4D"), ql.Period("195W5D"), ql.Period("208W5D"), ql.Period("221W4D"), ql.Period("234W5D"), ql.Period("247W6D"), ql.Period("260W6D"), ql.Period("273W5D"), ql.Period("286W6D"), ql.Period("300W"), ql.Period("313W"), ql.Period("326W"), ql.Period("339W1D"), ql.Period("352W2D"), ql.Period("365W2D"), ql.Period("378W1D"), ql.Period("391W2D"), ql.Period("404W3D"), ql.Period("417W3D"), ql.Period("430W2D"), ql.Period("443W3D"), ql.Period("456W4D"), ql.Period("469W4D"), ql.Period("482W3D"), ql.Period("495W4D"), ql.Period("508W5D"), ql.Period("521W5D"), ql.Period("534W5D"), ql.Period("547W6D"), ql.Period("561W"), ql.Period("574W"), ql.Period("586W6D"), ql.Period("600W"), ql.Period("613W1D"), ql.Period("626W1D"), ql.Period("639W"), ql.Period("652W1D"), ql.Period("665W2D"), ql.Period("678W2D"), ql.Period("691W1D"), ql.Period("704W2D"), ql.Period("717W3D"), ql.Period("730W3D"), ql.Period("743W3D"), ql.Period("756W4D"), ql.Period("769W5D"), ql.Period("782W5D"), ql.Period("834W6D"), ql.Period("887W"), ql.Period("939W1D"), ql.Period("991W3D"), ql.Period("1043W4D"), ql.Period("1095W5D"), ql.Period("1147W6D"), ql.Period("1200W1D"), ql.Period("1252W2D"), ql.Period("1304W3D"), ql.Period("1356W4D"), ql.Period("1408W6D"), ql.Period("1461W"), ql.Period("1513W1D"), ql.Period("1565W2D"), ql.Period("1617W4D"), ql.Period("1669W5D"), ql.Period("1721W6D"), ql.Period("1774W"), ql.Period("1826W2D"), ql.Period("1878W3D"), ql.Period("1930W4D"), ql.Period("1982W5D"), ql.Period("2035W"), ql.Period("2087W1D"), ql.Period("2139W2D"), ql.Period("2191W3D"), ql.Period("2243W5D"), ql.Period("2295W6D"), ql.Period("2348W"), ql.Period("2400W1D"), ql.Period("2452W3D"), ql.Period("2504W4D"), ql.Period("2556W5D"), ql.Period("2608W6D")]
zeroRates = [-0.003509, -0.0035994, -0.0035994, -0.003583013, -0.003552871, -0.0035322829999999998, -0.003516268, -0.0034983690000000003, -0.0035032929999999998, -0.003504438, -0.003495866, -0.0034945840000000002, -0.003478077, -0.00345774, -0.0034395790000000003, -0.003427, -0.0034006059999999996, -0.0033090059999999998, -0.003129996, -0.002900087, -0.002612546, -0.0022843539999999997, -0.0019280470000000002, -0.001559065, -0.001193597, -0.000840967, -0.000490511, -0.00014884299999999998, 0.00018241900000000002, 0.0005049, 0.000830168, 0.001151439, 0.0014659279999999998, 0.0017742779999999998, 0.002086053, 0.002393539, 0.0026927709999999996, 0.002986763, 0.003279388, 0.003568822, 0.003853275, 0.004133911, 0.0044197740000000004, 0.004703852, 0.004982476, 0.005255206, 0.005530559, 0.005802013000000001, 0.0060663869999999995, 0.006323573000000001, 0.006582067, 0.006836485, 0.0070842959999999995, 0.0073285880000000005, 0.007571736999999999, 0.007810716999999999, 0.008042855, 0.008267911, 0.00849312, 0.008713048000000001, 0.008925159, 0.009129278000000001, 0.009332287, 0.009529535, 0.009719003, 0.009901006, 0.010081563, 0.010256504, 0.010424104, 0.010586399, 0.010745208000000001, 0.010898543, 0.011044967, 0.011580671, 0.012041008, 0.012432549, 0.012763392, 0.013038589, 0.013267155, 0.013454629, 0.0136077, 0.013731867, 0.013833949, 0.013920055, 0.013993108, 0.014054918999999999, 0.014108182, 0.014155454, 0.014198216999999999, 0.014236871000000002, 0.01427123, 0.014301092, 0.014326257, 0.014346227, 0.014360703, 0.014369678, 0.014372562, 0.014369345, 0.01435993, 0.014344611, 0.014324081, 0.014299043999999999, 0.014270096999999999, 0.014237841999999999, 0.014202977, 0.014166105, 0.014128021999999999, 0.01408933]

# create quotes from rates so that they are observable (well, but the quotes aren't modified in this example code)
quotes = []
for rate in zeroRates:
    q = ql.SimpleQuote(rate)
    quotes.append(q)

nodes = zip(periods, quotes)

zcHelpers = [ql.DepositRateHelper(ql.QuoteHandle(quote), tenor,
                                    0, ql.UnitedStates(), ql.Unadjusted,
                                    True, ql.Actual365Fixed())
            for (tenor, quote) in nodes ]

curve = ql.PiecewiseLinearZero(referenceDate, zcHelpers, ql.Actual365Fixed())

curveHandle = ql.RelinkableYieldTermStructureHandle()
curveHandle.linkTo(curve)

index = ql.Eonia(curveHandle)
##################
######## end curve
##################

#################
# bond definition
#################

schedule =  ql.Schedule(referenceDate - ql.Period("1Y"), # effective date
                        referenceDate + ql.Period("5Y"), # termination date
                        ql.Period("3M"), # tenor
                        ql.UnitedStates(), # calendar 
                        ql.Unadjusted, # convention
                        ql.Unadjusted, # terminationDateConvention
                        ql.DateGeneration.Backward, # date generation rule 
                        True # end of month
                        )

bond_leg = ql.FloatingRateBond(0, # settlementDays,,
                                500000, # current notional
                                schedule, # schedule
                                index, 
                                ql.Actual365Fixed(), # accrual day count convention
                                ql.Unadjusted, # payment convention
                                spreads=[0.0], # spreads                  
                                inArrears=False, # in arrears
                                redemption=100, # redemption
                                issueDate=referenceDate - ql.Period("1Y") # issuance date
                                )

# set pricing engine
bondEngine = ql.DiscountingBondEngine(curveHandle)
bond_leg.setPricingEngine(bondEngine)

# coupon pricers
pricer = ql.BlackIborCouponPricer()

# optionlet volatilities
vol = ql.ConstantOptionletVolatility(0, # settlementDays
                                    ql.UnitedStates(), # calendar
                                    ql.Unadjusted, # payment convention
                                    0.0, # volatility
                                    ql.Actual365Fixed()) # accrual day count

pricer.setCapletVolatility(ql.OptionletVolatilityStructureHandle(vol))
ql.setCouponPricer(bond_leg.cashflows(), pricer)

print([(c.date(), c.amount()) for c in bond_leg.cashflows()])

不是cashflows()會引起錯誤。 您可以通過將最后一行重寫為

cfs = bond_leg.cashflows()
print([(c.date(), c.amount()) for c in cfs])

錯誤發生在第二行,而不是第一行。

cashflows()方法不會按日期過濾其結果,但是您可以在調用amount()之前執行此操作。 就像是

cfs = bond_leg.cashflows()
min_date = referenceDate + ql.Period("6M")
print([(c.date(), c.amount()) for c in cfs if c.date() >= min_date])

將基於CashFlow接口工作。 如果您想了解更多信息,可以使用一種向下轉換現金流量的功能; 但是在這種情況下,如果現金流量不是浮動利率,您還必須檢查是否有可能導致轉換失敗(例如,發生在贖回時):

for cf in bond_leg.cashflows():
    c = ql.as_floating_rate_coupon(cf)
    if c and c.fixingDate() >= referenceDate:
        print(c.date(), c.amount())

if c檢查有效的轉換)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM