Quantlib

重新定價 SOFR 報價和非零 NPV

  • April 26, 2022

我使用 Quantlib Python 生成/校準了 SOFR 曲線,並想知道為什麼在重新定價掉期時 NPV 不為零。感謝任何幫助。謝謝你。

參數

mktDate = ql.Date(8,3,2021)
ql.Settings.instance().evaluationDate = mktDate
Settlement = 2
Calendar = ql.UnitedStates()
DayCount = ql.Actual360()

OIS 曲線助手

oisHelper = []
for quote in marketQuotes:
   oisHelper.append(ql.OISRateHelper(Settlement, ql.Period(quote[0]), 
ql.QuoteHandle(ql.SimpleQuote(quote[1]/100)), ql.Sofr()))

曲線規格

sofrCurve = ql.PiecewiseLinearZero(Settlement, Calendar, oisHelper, DayCount)
valCurve = ql.YieldTermStructureHandle(sofrCurve)
sofrIndex = ql.Sofr(valCurve)
swapEngine = ql.DiscountingSwapEngine(valCurve)

重新定價報價

for quote in marketQuotes:
   start = Calendar.advance(mktDate, Settlement, ql.Days)
   schedule = ql.MakeSchedule(start, Calendar.advance(start, ql.Period(quote[0])), ql.Period('1Y'), calendar = Calendar)
   fixedRate = quote[1]/100
   oisSwap = ql.OvernightIndexedSwap(
       ql.OvernightIndexedSwap.Receiver, 
       1E6, 
       schedule, 
       fixedRate, 
       DayCount,
       sofrIndex)
   oisSwap.setPricingEngine(swapEngine)
   print(quote, round(oisSwap.NPV(),3)) 

輸出

('1W', 0.01982) 0.0
('2W', 0.02394) -0.0
('3W', 0.02503) -0.0
('1M', 0.02897) -0.0
('3M', 0.037) 0.0
('4M', 0.041) -0.0
('5M', 0.043) 0.0
('6M', 0.04597) 0.0
('7M', 0.04797) 0.0
('8M', 0.04997) -0.0
('9M', 0.05197) 0.0
('10M', 0.0535) 0.0
('11M', 0.055) 0.0
('1Y', 0.0565) -0.0
('15M', 0.06) -0.0
('18M', 0.069) 0.003
('21M', 0.083) 0.004
('2Y', 0.10403) 0.0
('3Y', 0.27409) 0.049
('4Y', 0.50109) -0.0
('5Y', 0.718) -0.0
('6Y', 0.90703) 0.0
('7Y', 1.066) -0.0
('8Y', 1.19203) 0.83
('9Y', 1.29306) 0.521
('10Y', 1.37903) -0.0
('12Y', 1.51294) -0.0
('15Y', 1.63591) -0.0
('20Y', 1.72494) 0.766
('25Y', 1.75318) 1.322
('30Y', 1.76979) -0.0
('40Y', 1.71094) 0.0
('50Y', 1.63649) -0.0

差異可能來自沒有完全相同的約定。當您使用ql.MakeOIS所有約定時,將來自ql.Sofr索引,但是當您手動建構 Instrument 時,您將手動ql.OvernightIndexedSwap輸入所有約定,即時間表。

該類ql.MakeSchedule有更多參數,這些參數大多預設為無:

  • 約定=無
  • 終端日期約定=無,
  • 規則=無
  • 轉發=假
  • 向後=假,
  • endOfMonth=無
  • 第一個日期=無
  • nextToLastDate=無

使用 ql.MakeOIS 時似乎可以工作。仍然需要了解為什麼存在差異。有什麼想法嗎?

重新定價報價

for quote in marketQuotes:
   swapTenor = ql.Period(quote[0])
   fixedRate = quote[1]/100
   oisSwap = ql.MakeOIS(swapTenor, sofrIndex, fixedRate, nominal=1E6)
   print(quote, round(oisSwap.NPV(),3)) 

輸出

('1W', 0.01982) 0.0
('2W', 0.02394) 0.0
('3W', 0.02503) 0.0
('1M', 0.02897) 0.0
('3M', 0.037) -0.0
('4M', 0.041) 0.0
('5M', 0.043) 0.0
('6M', 0.04597) 0.0
('7M', 0.04797) 0.0
('8M', 0.04997) 0.0
('9M', 0.05197) -0.0
('10M', 0.0535) -0.0
('11M', 0.055) -0.0
('1Y', 0.0565) 0.0
('15M', 0.06) 0.0
('18M', 0.069) 0.0
('21M', 0.083) -0.0
('2Y', 0.10403) -0.0
('3Y', 0.27409) -0.0
('4Y', 0.50109) 0.0
('5Y', 0.718) 0.0
('6Y', 0.90703) -0.0
('7Y', 1.066) 0.0
('8Y', 1.19203) -0.0
('9Y', 1.29306) -0.0
('10Y', 1.37903) 0.0
('12Y', 1.51294) 0.0
('15Y', 1.63591) 0.0
('20Y', 1.72494) 0.0
('25Y', 1.75318) 0.0
('30Y', 1.76979) 0.0
('40Y', 1.71094) 0.0
('50Y', 1.63649) 0.0

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