|
From: Peter C. <pca...@gm...> - 2022-08-12 08:20:05
|
Hi Aditya
1. correct
2. the pricer takes any SwaptionVolatilityStructure, i.e. a
ConstantSwaptionVolatilityStructure should work. Is that what you
mean?
3. this might be related to smile extrapolation, which strike range do
you cover in your swaption cube and how do you set up the
extrapolation? The pricer uses an integration over [-200%, +200%] by
default.
4. I agree 500% is much to high, let's discuss further once 3 is
resolved, i.e. QL / BBG matches
In addition, the linear TSR model might not work well when the time to
expiry is large. Do you have more info on which model BBG uses?
Thank you
Peter
On Fri, 12 Aug 2022 at 09:36, Aditya Gupta <adi...@co...> wrote:
>
> Hi,
>
>
>
> I am trying to price a CMS Spread Cap using Quantlib. I am using data from Bloomberg, and I am using the following classes:
>
>
>
> yts is a bootstrapped Sofr curve
>
> Instrument = ql.CappedFlooredCmsSpreadCoupon()
>
> volCube = ql.SwaptionVolCube2() with the correct data and volType = ql.Normal
>
> cmsPricer = ql.LinearTSRPricer(volHandle, meanReversion, yts)
>
> pricer = ql.LognormalCmsSpreadPricer(cmsPricer, correlation, yts, 16)
>
>
>
> I have a few questions.
>
>
>
> It seems to me that to price a ql. CappedFlooredCmsSpreadCoupon, the only option is to use a ql.LognormalCmsSpreadPricer, and hence if we use Normal volatility, the input cmsPricer must be the LinearTSRPricer (Hagan cannot be used). Is my assessment correct?
> In order to check the pricing, I used a ‘constant’ volatility cube (set the atm matrix to a constant, rest to 0) and tested the pricing. The instrument was priced correctly (within the error from the discount curve). Can the pricer accept a constant volatility otherwise?
> The volCube seems to be returning the correct volatilities (within reason) when compared to Bloomberg, and is being passed to the pricer without error. But for some reason, the price is completely different (about half of what it should be). What could be the cause for the error, or how could I go about debugging this?
> If I use scipy.optimize to ‘artificially’ optimize the price as a function of the mean reversion, for a value of around 5 (which is way too high for the mean correlation), I was able to bring the error down to less than 1 dollar. Clearly this approach is not sensible. So I used the HullWhite model on the swaption matrix, and calibrated the mean reversion. But the error for this value of the mean reversion is much too high. How can I determine a good value for the mean reversion?
>
>
>
> Right now I am content with there being some error compared to Bloomberg, but I am unable to understand the blackbox behind the pricing engine and the mean reversion calibration, and if there is any way to solve these issues. Any and all help would be greatly appreciated. Thank you.
>
>
>
> Some of the code and data is as follows:
>
>
>
> today = ql.Date(25, 7, 2022)
>
> ql.Settings.instance().evaluationDate = today
>
>
>
> #Global variables
>
> calendar = ql.UnitedStates(ql.UnitedStates.FederalReserve)
>
> convention = ql.ModifiedFollowing
>
> endOfMonth = False
>
> dayCounter = ql.Actual360()
>
> fixingDays = 0
>
> compounding = ql.Compounded
>
> compoundingFrequency = ql.Annual
>
>
>
> yts = ql.RelinkableYieldTermStructureHandle()
>
> index = ql.Sofr(yts)
>
>
>
> helper = []
>
>
>
> # sofrData are just the rates from a dataframe
>
>
>
> helper += [
>
> ql.DepositRateHelper(
>
> ql.QuoteHandle(ql.SimpleQuote(sofrData['Shifted Rate'][0] / 100.0)),
>
> index)
>
> ]
>
>
>
> helper += [
>
> ql.OISRateHelper(0,
>
> ql.Period(expiration),
>
> ql.QuoteHandle(ql.SimpleQuote(rate / 100.0)),
>
> index,
>
> paymentLag=0,
>
> paymentConvention=convention,
>
> paymentFrequency=ql.Annual,
>
> paymentCalendar=calendar,
>
> averagingMethod=ql.RateAveraging.Compound) for rate,
>
> expiration in zip(sofrData['Shifted Rate'][1:], sofrData["Term"][1:])
>
> ]
>
>
>
> curve = ql.PiecewiseSplineCubicDiscount(today, helper, ql.Actual360())
>
> curve.enableExtrapolation()
>
> yts.linkTo(curve)
>
>
>
> meanReversion = ql.QuoteHandle(ql.SimpleQuote(5.037702498779181)) #this is the ‘optimised’ value but I need further help
>
> correlation = ql.QuoteHandle(ql.SimpleQuote(36.6 * 1e-4))
>
>
>
> nominal = 1e9
>
> gearing = 1.0
>
> spread = 0.0
>
> cap = -8 * 1e-4
>
> floor = ql.nullDouble() #infinite floor
>
>
>
> startDate = ql.Date(26, 9, 2022)
>
> endDate = ql.Date(26, 9, 2023)
>
> paymentDate = ql.Date(26, 9, 2023)
>
>
>
> isInArrears = False
>
> exCouponDate = ql.Date()
>
>
>
> fixingDays = 0
>
>
>
> swapIndex1 = ql.UsdLiborSwapIsdaFixAm(ql.Period('30y'), yts, yts)
>
> ql.IndexManager.instance().clearHistory(swapIndex1.name())
>
>
>
> swapIndex2 = ql.UsdLiborSwapIsdaFixAm(ql.Period('10y'), yts, yts)
>
> ql.IndexManager.instance().clearHistory(swapIndex2.name())
>
>
>
> spreadIndex = ql.SwapSpreadIndex("Joint Index", swapIndex1, swapIndex2)
>
>
>
> instrument = ql.CappedFlooredCmsSpreadCoupon(paymentDate, nominal, startDate,
>
> endDate, fixingDays, spreadIndex,
>
> gearing, spread, cap, floor,
>
> ql.Date(), ql.Date(), dayCounter,
>
> isInArrears, exCouponDate)
>
>
>
> cmsPricer = ql.LinearTsrPricer(volHandle, meanReversion, yts)
>
>
>
> # cmsPricer = ql.NumericHaganPricer(volHandle, ql.GFunctionFactory.ParallelShifts , meanReversion)#, Rate lowerLimit=0.0, Rate upperLimit=1.0, Real precision=1.0e-6, Real hardUpperLimit=QL_MAX_REAL)
>
>
>
> integrationPoints = 16
>
>
>
> pricer = ql.LognormalCmsSpreadPricer(cmsPricer, correlation, yts,
>
> integrationPoints)
>
>
>
> instrument.setPricer(pricer)
>
>
>
> Regards,
>
> Aditya Gupta.
>
>
>
> ________________________________
> Complus Asset Management Limited ("CAML") is licensed by the Securities and Futures Commission of Hong Kong (“SFC”) for the Regulated Activities of Advising on Securities and Asset Management with CE number AWX256. CAML is subject to certain SFC codes and regulations, details of which can be found on the SFC's website at http://www.sfc.hk. CAML is a company incorporated in Hong Kong with its registered office and principal place of business as indicated above.
>
> Unless specifically indicated, this message should not be construed as an offer to sell or solicitation to purchase any securities, financial products or services or the giving of investment advice within or outside Hong Kong. This message is intended solely for the person(s) to whom it is addressed. If you receive this message in error, please immediately delete it and all copies of it from your computer network or hard copies, and notify the sender.
> _______________________________________________
> QuantLib-users mailing list
> Qua...@li...
> https://lists.sourceforge.net/lists/listinfo/quantlib-users
|