Python

使用 QuantLib Python 計算 Swap DV01

  • January 12, 2022

我想使用 QuantLib Python 來計算利率掉期的 DV01。

最初我想分別計算固定腿 DV01 和浮動腿 DV01,然後將兩條腿 DV01 相加得到交換 DV01。但是,我不知道如何使用 QuantLib Python 計算浮動腿 DV01。

最後,我使用以下程式碼採用了不同的方法來計算利率掉期 DV01:

from QuantLib import *

# global data
calendar = TARGET()
todaysDate = Date(6,November,2001);
Settings.instance().evaluationDate = todaysDate
settlementDate = Date(8,November,2001);

# market quotes
deposits = { (1,Weeks): 0.0382,
            (1,Months): 0.0372,
            (3,Months): 0.0363,
            (6,Months): 0.0353,
            (9,Months): 0.0348,
            (1,Years): 0.0345 }

swaps = { (2,Years): 0.037125,
         (3,Years): 0.0398,
         (5,Years): 0.0443,
         (10,Years): 0.05165,
         (15,Years): 0.055175 }

# convert them to Quote objects
for n,unit in deposits.keys():
   deposits[(n,unit)] = SimpleQuote(deposits[(n,unit)])
for n,unit in swaps.keys():
   swaps[(n,unit)] = SimpleQuote(swaps[(n,unit)])

# build rate helpers

dayCounter = Actual360()
settlementDays = 2
depositHelpers = [ DepositRateHelper(QuoteHandle(deposits[(n,unit)]),
                                    Period(n,unit), settlementDays,
                                    calendar, ModifiedFollowing,
                                    False, dayCounter)
                  for n, unit in [(1,Weeks),(1,Months),(3,Months),
                                  (6,Months),(9,Months),(1,Years)] ]

fixedLegFrequency = Annual
fixedLegTenor = Period(1,Years)
fixedLegAdjustment = Unadjusted
fixedLegDayCounter = Thirty360()
floatingLegFrequency = Semiannual
floatingLegTenor = Period(6,Months)
floatingLegAdjustment = ModifiedFollowing
swapHelpers = [ SwapRateHelper(QuoteHandle(swaps[(n,unit)]),
                              Period(n,unit), calendar,
                              fixedLegFrequency, fixedLegAdjustment,
                              fixedLegDayCounter, Euribor6M())
               for n, unit in swaps.keys() ]

# term structure handles

discountTermStructure = RelinkableYieldTermStructureHandle()
forecastTermStructure = RelinkableYieldTermStructureHandle()

# term-structure construction

helpers = depositHelpers + swapHelpers
depoSwapCurve = PiecewiseFlatForward(settlementDate, helpers, Actual360())

swapEngine = DiscountingSwapEngine(discountTermStructure)

# 5Y Swap 

nominal = 1000000
maturity = calendar.advance(settlementDate,5,Years)

fixedLegFrequency = Annual
fixedLegAdjustment = Unadjusted
fixedLegDayCounter = Thirty360()
fixedRate = 0.04

floatingLegFrequency = Semiannual
spread = 0.0
fixingDays = 2
index = Euribor6M(forecastTermStructure)
floatingLegAdjustment = ModifiedFollowing
floatingLegDayCounter = index.dayCounter()

fixedSchedule = Schedule(settlementDate, maturity,
                        fixedLegTenor, calendar,
                        fixedLegAdjustment, fixedLegAdjustment,
                        DateGeneration.Forward, False)
floatingSchedule = Schedule(settlementDate, maturity,
                           floatingLegTenor, calendar,
                           floatingLegAdjustment, floatingLegAdjustment,
                           DateGeneration.Forward, False)

swap = VanillaSwap(VanillaSwap.Receiver, nominal,
                  fixedSchedule, fixedRate, fixedLegDayCounter,
                  floatingSchedule, index, spread,
                  floatingLegDayCounter)
swap.setPricingEngine(swapEngine)


discountTermStructure.linkTo(depoSwapCurve)
forecastTermStructure.linkTo(depoSwapCurve)
print('Fixed Leg DV01')
print(swap.fixedLegBPS())

shift = 0.0001

temp_fyc_handle = YieldTermStructureHandle(depoSwapCurve)
temp_dyc_handle = YieldTermStructureHandle(depoSwapCurve)
shiftedForwardCurve = ZeroSpreadedTermStructure(temp_fyc_handle, QuoteHandle(SimpleQuote(shift)))
shiftedDiscountCurve = ZeroSpreadedTermStructure(temp_dyc_handle, QuoteHandle(SimpleQuote(shift)))
discountTermStructure.linkTo(shiftedDiscountCurve)
forecastTermStructure.linkTo(shiftedForwardCurve)
P_p = swap.NPV()

temp_fyc_handle = YieldTermStructureHandle(depoSwapCurve)
temp_dyc_handle = YieldTermStructureHandle(depoSwapCurve)
shiftedForwardCurve = ZeroSpreadedTermStructure(temp_fyc_handle, QuoteHandle(SimpleQuote(-shift)))
shiftedDiscountCurve = ZeroSpreadedTermStructure(temp_dyc_handle, QuoteHandle(SimpleQuote(-shift)))
discountTermStructure.linkTo(shiftedDiscountCurve)
forecastTermStructure.linkTo(shiftedForwardCurve)
P_m = swap.NPV()

dv01 = (P_m - P_p) / 2.0
print('Swap DV01')
print(dv01)

我在如何使用 QuantLib Python 計算利率掉期 DV01 方面是否正確?上面程式碼的輸出顯示固定支路 DV01 小於整個交換的 DV01。那正確嗎?

不,恐怕你是在比較蘋果和橙子。您對掉期 DV01 的計算是正確的(需要注意的是,見下文),但返回的數字swap.fixedLegBPS不可比較。

DV01 告訴您如果利率曲線發生變化,NPV 會發生什麼變化;在固定腿的情況下,這會影響用於貼現票面金額的貼現因子,但不會影響固定金額本身。

BPS 告訴您如果固定息票的利率增加 1 個基點而利率(以及貼現因子)保持不變,NPV 會發生什麼變化。計算公平利率很有用,或者在您定義交易時,但一旦建立交換並且其利率固定,可能就不那麼有用了。所以:不同的東西。

如果你想單獨計算固定腿的 DV01,你可以這樣做:

shift = 0.0001

temp_dyc_handle = YieldTermStructureHandle(depoSwapCurve)
shiftedDiscountCurve = ZeroSpreadedTermStructure(temp_dyc_handle, QuoteHandle(SimpleQuote(shift)))
discountTermStructure.linkTo(shiftedDiscountCurve)
P_p = CashFlows.npv(swap.fixedLeg(), discountTermStructure, False, settlementDate)

temp_dyc_handle = YieldTermStructureHandle(depoSwapCurve)
shiftedDiscountCurve = ZeroSpreadedTermStructure(temp_dyc_handle, QuoteHandle(SimpleQuote(-shift)))
discountTermStructure.linkTo(shiftedDiscountCurve)
P_m = CashFlows.npv(swap.fixedLeg(), discountTermStructure, False, settlementDate)

dv01 = (P_m - P_p) / 2.0
print('Fixed Leg DV01')
print(dv01)

關於我上面提到的警告:你正在做

discountTermStructure.linkTo(depoSwapCurve)
forecastTermStructure.linkTo(depoSwapCurve)

也就是說,您使用相同的曲線來預測浮動利率固定和現金流貼現,這就是我們在 QuantLib 版本中包含的範例中所做的。我們真的應該更新它;如今,實踐是使用兩條不同的曲線進行預測和貼現。在這種情況下,當您像現在一樣移動兩條曲線時,將 DV01 定義為 NPV 的變化可能仍然有意義;但請確保這是您想要的。

引用自:https://quant.stackexchange.com/questions/37091