|
From: Giuseppe T. <tr...@gm...> - 2023-08-17 22:16:50
|
Good evening everyone, Peter,
Thank you for the quick reply! I checked as you suggested, the outcome is
the same. Again, using EuriborSwapIsdaFixA works fine regardless of the
tenor used for the smile calibration. Please find below a small code
example.
I'm on Windows 11, MSVC 143, boost 1.83 (prebuilt binaries, msvc143),
QuantLib 1.31 (Release).
As always, thanks in advance for your time.
#include <ql/models/shortrate/onefactormodels/markovfunctional.hpp>
> #include <ql/indexes/ibor/libor.hpp>
> #include <ql/indexes/swap/euriborswap.hpp>
> #include <ql/termstructures/yield/flatforward.hpp>
> #include <ql/termstructures/volatility/swaption/swaptionconstantvol.hpp>
> #include <ql/quotes/simplequote.hpp>
> #include <ql/time/calendars/unitedstates.hpp>
> #include <ql/time/daycounters/actual360.hpp>
> #include <ql/currencies/america.hpp>
>
> #include <iostream>
> #include <iomanip>
>
> using namespace QuantLib;
>
> int main(int argc, char *argv[]) {
>
> try {
>
> Date refDate(31, May, 2023);
> Settings::instance().evaluationDate() = refDate;
>
> Real forwardRate = 0.02;
>
> Handle<Quote> forwardRateQuote(
> ext::make_shared<SimpleQuote>(forwardRate));
>
> Calendar calendar = UnitedStates(UnitedStates::SOFR);
>
> Handle<YieldTermStructure>
> forwardCurve(ext::make_shared<FlatForward>(
> 2, calendar, forwardRateQuote, Actual360()));
>
>
> Real volLevel = 0.20;
> Handle<Quote> volQuote(ext::make_shared<SimpleQuote>(volLevel));
> Handle<SwaptionVolatilityStructure> swaptionVol(
> ext::make_shared<ConstantSwaptionVolatility>(
> 2, calendar, ModifiedFollowing, volQuote,
> Actual365Fixed()));
>
> //ext::shared_ptr<SwapIndex> swapBase =
> // ext::make_shared<EuriborSwapIsdaFixA>(
> // 10 * Years, forwardCurve
> // );
>
>
> ext::shared_ptr<IborIndex> iborIndex =
> ext::make_shared<Libor>(
> "DummyIborIndex", 1 * Years, 2, USDCurrency(), calendar,
> Actual360(), forwardCurve
> );
>
>
> ext::shared_ptr<SwapIndex> swapBase =
> ext::make_shared<SwapIndex>(
> "DummySwapIndex", 10 * Years, 2, USDCurrency(), calendar,
> 1 * Years, ModifiedFollowing, Actual360(), iborIndex
> );
>
>
> std::vector<Real> sigmas(2, 0.01);
> Real reversion = 0.05;
>
> Date exerciseDate = Date(30, May, 2025);
>
> std::vector<Date> exerciseDates;
> exerciseDates.push_back(exerciseDate);
>
> const std::vector<Date> swaptionDates(1, exerciseDate);
>
> // smileTenors > fixed leg tenor => ERROR
> std::vector<Period> smileTenors(1, 5 * Years);
>
> // smileTenors <= fixed leg tenor => NO ERROR
> //std::vector<Period> smileTenors(1, 1 * Years);
>
>
> ext::shared_ptr<MarkovFunctional> markov =
> ext::make_shared<MarkovFunctional>(
> forwardCurve, reversion, exerciseDates, sigmas,
> swaptionVol,
> swaptionDates, smileTenors, swapBase,
> MarkovFunctional::ModelSettings().withYGridPoints(16)
> );
>
>
> } catch (const QuantLib::Error& e) {
> std::cout << "terminated with a ql exception: " << e.what()
> << std::endl;
> return 1;
> } catch (const std::exception& e) {
> std::cout << "terminated with a general exception: " << e.what()
> << std::endl;
> return 1;
> }
> }
>
Il giorno gio 17 ago 2023 alle ore 20:05 Peter Caspers <
pca...@gm...> ha scritto:
> Hi Giuseppe
>
> can you possibly check whether the problem occurs in pure C++ code as well?
>
> Thank you
> Peter
>
>
>
> Giuseppe Trapani <tr...@gm...> schrieb am Do. 17. Aug. 2023 um 18:17:
>
>> Good evening everyone,
>>
>> I am working with QuantLib python (version 1.31 from pypi). I'm trying to
>> instantiate *MarkovFunctional to be calibrated on a single expiry /
>> smile* and I noticed the following RuntimeError:
>>
>> RuntimeError: year 2200 out of bounds. It must be in [1901,2199]
>>
>>
>> The error is raised in the following case:
>>
>>
>> - The SwapIndex passed to MarkovFunctional has a certain fixed leg
>> tenor (e.g., 1y)
>> - The swaptionTenors (that is, the smile to be calibrated to) is
>> greater than that of the fixed leg tenor of the SwapIndex (from the example
>> above, > 1y).
>>
>>
>> Notice that *this happens only for SwapIndex with a fixed leg tenor
>> greater or equal than 1y*: if I create a SwapIndex with fixed leg tenor
>> smaller than 1y, the MarkovFunctional object gets instantiated correctly
>> with whatever smile I choose.
>>
>> *Another weird thing*: if I use a standard EuriborSwapIsdaFixA (that has
>> a fixed leg tenor of 1y), I can also correctly instantiate the
>> MarkovFunctional object with whatever smile I choose.
>>
>> Is this behaviour expected? Please, find below a minimum replication code.
>>
>>
>> Thanks in advance for your time and availability.
>>
>>
>>
>> ivol = 0.25
>>>
>>> ivol_quote = ql.SimpleQuote(ivol)
>>>
>>> ln_shift = 0.02
>>>
>>>
>>>> forward_rate = 0.02
>>>
>>> forward_rate_quote = ql.SimpleQuote(forward_rate)
>>>
>>>
>>>> calendar = ql.UnitedStates(ql.UnitedStates.SOFR)
>>>
>>>
>>>> oswp_blackvols = ql.ConstantSwaptionVolatility(2, calendar,
>>>> ql.Following, ql.QuoteHandle(ivol_quote), ql.Actual365Fixed(),
>>>> ql.ShiftedLognormal, ln_shift)
>>>
>>> forward_curve = ql.FlatForward(2, calendar,
>>>> ql.QuoteHandle(forward_rate_quote), ql.Actual360())
>>>
>>>
>>>> #swap_index = ql.EuriborSwapIsdaFixA(
>>>
>>> # ql.Period("10y"),
>>>
>>> # ql.YieldTermStructureHandle(forward_curve),
>>>
>>> # ql.YieldTermStructureHandle(forward_curve)
>>>
>>> #)
>>>
>>>
>>>>
>>>> floating_leg_tenor = ql.Period("6m")
>>>
>>> fixed_leg_tenor = ql.Period("1y")
>>>
>>> ibor_index = ql.Libor("DummyIborIndex", floating_leg_tenor, 2,
>>>> ql.USDCurrency(), calendar, ql.Actual360(),
>>>> ql.YieldTermStructureHandle(forward_curve))
>>>
>>> swap_index = ql.SwapIndex("DummySwapIndex", ql.Period("10y"), 2,
>>>> ql.USDCurrency(), calendar, fixed_leg_tenor, ql.ModifiedFollowing,
>>>> ql.Actual360(), ibor_index)
>>>
>>>
>>>> mean_reversion = 0.05
>>>
>>>
>>>> exercise_dates = [ql.Date(30, 5, 2025)]
>>>
>>> swaption_dates = [ql.Date(30, 5, 2025)]
>>>
>>>
>>>>
>>>> ## smile_tenors > then fixed_leg_tenor => ERROR
>>>
>>> smile_tenors = [ql.Period("5y")]
>>>
>>>
>>>> ## smile_tenors <= fixed_leg_tenor => NO ERROR
>>>
>>> # smile_tenors = [ql.Period("1y")]
>>>
>>>
>>>> mm = ql.MarkovFunctional(
>>>
>>> ql.YieldTermStructureHandle(forward_curve),
>>>
>>> mean_reversion,
>>>
>>> exercise_dates,
>>>
>>> [0.01, 0.01],
>>>
>>> ql.SwaptionVolatilityStructureHandle(oswp_blackvols),
>>>
>>> swaption_dates,
>>>
>>> smile_tenors,
>>>
>>> swap_index
>>>
>>> )
>>>
>>>
>>
>>
>>
>> --
>> *Giuseppe Trapani*
>> _______________________________________________
>> QuantLib-users mailing list
>> Qua...@li...
>> https://lists.sourceforge.net/lists/listinfo/quantlib-users
>>
>
--
*Giuseppe Trapani*
|