diff --git a/docs/termstructures/volatility.rst b/docs/termstructures/volatility.rst index 75fd082..9f478e0 100644 --- a/docs/termstructures/volatility.rst +++ b/docs/termstructures/volatility.rst @@ -74,6 +74,69 @@ BlackVarianceSurface ) volatilitySurface.enableExtrapolation() + +HestonBlackVolSurface +********************* + +.. function:: ql.HestonBlackVolSurface(hestonModelHandle) + +.. code-block:: python + + flatTs = ql.YieldTermStructureHandle( + ql.FlatForward(ql.Date().todaysDate(), 0.05, ql.Actual365Fixed()) + ) + dividendTs = ql.YieldTermStructureHandle( + ql.FlatForward(ql.Date().todaysDate(), 0.02, ql.Actual365Fixed()) + ) + + v0 = 0.01; kappa = 0.01; theta = 0.01; rho = 0.0; sigma = 0.01 + spot = 100 + process = ql.HestonProcess(flatTs, dividendTs, + ql.QuoteHandle(ql.SimpleQuote(spot)), + v0, kappa, theta, sigma, rho + ) + + hestonModel = ql.HestonModel(process) + hestonHandle = ql.HestonModelHandle(hestonModel) + hestonVolSurface = ql.HestonBlackVolSurface(hestonHandle) + + +AndreasenHugeVolatilityAdapter +****************************** + +An implementation of the arb-free Andreasen-Huge vol interpolation described in "Andreasen J., Huge B., 2010. Volatility Interpolation" (https://ssrn.com/abstract=1694972). An advantage of this method is that it can take a non-rectangular grid of option quotes. + +.. function:: ql.AndreasenHugeVolatilityAdapter(AndreasenHugeVolatilityInterpl) + +.. code-block:: python + + today = ql.Date().todaysDate() + calendar = ql.NullCalendar() + dayCounter = ql.Actual365Fixed() + spot = 100 + r, q = 0.02, 0.05 + + spotQuote = ql.QuoteHandle(ql.SimpleQuote(spot)) + ratesTs = ql.YieldTermStructureHandle(ql.FlatForward(today, r, dayCounter)) + dividendTs = ql.YieldTermStructureHandle(ql.FlatForward(today, q, dayCounter)) + + # Market options price quotes + optionStrikes = [95, 97.5, 100, 102.5, 105, 90, 95, 100, 105, 110, 80, 90, 100, 110, 120] + optionMaturities = ["3M", "3M", "3M", "3M", "3M", "6M", "6M", "6M", "6M", "6M", "1Y", "1Y", "1Y", "1Y", "1Y"] + optionQuotedVols = [0.11, 0.105, 0.1, 0.095, 0.095, 0.12, 0.11, 0.105, 0.1, 0.105, 0.12, 0.115, 0.11, 0.11, 0.115] + + calibrationSet = ql.CalibrationSet() + + for strike, expiry, impliedVol in zip(optionStrikes, optionMaturities, optionQuotedVols): + payoff = ql.PlainVanillaPayoff(ql.Option.Call, strike) + exercise = ql.EuropeanExercise(calendar.advance(today, ql.Period(expiry))) + + calibrationSet.push_back((ql.VanillaOption(payoff, exercise), ql.SimpleQuote(impliedVol))) + + ahInterpolation = ql.AndreasenHugeVolatilityInterpl(calibrationSet, spotQuote, ratesTs, dividendTs) + ahSurface = ql.AndreasenHugeVolatilityAdapter(ahInterpolation) + + BlackVolTermStructureHandle *************************** @@ -100,31 +163,6 @@ RelinkableBlackVolTermStructureHandle blackTSHandle.linkTo(volatilitySurface) - -HestonBlackVolSurface -********************* - -.. function:: ql.HestonBlackVolSurface(hestonModelHandle) - -.. code-block:: python - - flat_ts = ql.YieldTermStructureHandle( - ql.FlatForward(ql.Date().todaysDate(), 0.05, ql.Actual365Fixed()) - ) - dividend_ts = ql.YieldTermStructureHandle( - ql.FlatForward(ql.Date().todaysDate(), 0.02, ql.Actual365Fixed()) - ) - v0 = 0.01; kappa = 0.01; theta = 0.01; rho = 0.0; sigma = 0.01 - spot = 100 - process = ql.HestonProcess(flat_ts, dividend_ts, - ql.QuoteHandle(ql.SimpleQuote(spot)), - v0, kappa, theta, sigma, rho - ) - heston_model = ql.HestonModel(process) - heston_handle = ql.HestonModelHandle(heston_model) - heston_vol_surface = ql.HestonBlackVolSurface(heston_handle) - - LocalConstantVol **************** @@ -184,6 +222,40 @@ This powerful but dangerous surface will swallow any exceptions and return the s ql.NoExceptLocalVolSurface(blackVolTs, ratesTs, dividendTs, spot, illegalVolOverride) +AndreasenHugeLocalVolAdapter +**************************** + +.. function:: ql.AndreasenHugeLocalVolAdapter(AndreasenHugeVolatilityInterpl) + +.. code-block:: python + + today = ql.Date().todaysDate() + calendar = ql.NullCalendar() + dayCounter = ql.Actual365Fixed() + spot = 100 + r, q = 0.02, 0.05 + + spotQuote = ql.QuoteHandle(ql.SimpleQuote(spot)) + ratesTs = ql.YieldTermStructureHandle(ql.FlatForward(today, r, dayCounter)) + dividendTs = ql.YieldTermStructureHandle(ql.FlatForward(today, q, dayCounter)) + + # Market options price quotes + optionStrikes = [95, 97.5, 100, 102.5, 105, 90, 95, 100, 105, 110, 80, 90, 100, 110, 120] + optionMaturities = ["3M", "3M", "3M", "3M", "3M", "6M", "6M", "6M", "6M", "6M", "1Y", "1Y", "1Y", "1Y", "1Y"] + optionQuotedVols = [0.11, 0.105, 0.1, 0.095, 0.095, 0.12, 0.11, 0.105, 0.1, 0.105, 0.12, 0.115, 0.11, 0.11, 0.115] + + calibrationSet = ql.CalibrationSet() + + for strike, expiry, impliedVol in zip(optionStrikes, optionMaturities, optionQuotedVols): + payoff = ql.PlainVanillaPayoff(ql.Option.Call, strike) + exercise = ql.EuropeanExercise(calendar.advance(today, ql.Period(expiry))) + + calibrationSet.push_back((ql.VanillaOption(payoff, exercise), ql.SimpleQuote(impliedVol))) + + ahInterpolation = ql.AndreasenHugeVolatilityInterpl(calibrationSet, spotQuote, ratesTs, dividendTs) + ahLocalSurface = ql.AndreasenHugeLocalVolAdapter(ahInterpolation) + + LocalVolTermStructureHandle ***************************