Quantlib
重新定價 SOFR 報價和非零 NPV
我使用 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