You can subscribe to this list here.
| 2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
(60) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2001 |
Jan
(18) |
Feb
(4) |
Mar
(6) |
Apr
(2) |
May
|
Jun
(12) |
Jul
(48) |
Aug
(6) |
Sep
(3) |
Oct
(24) |
Nov
(15) |
Dec
(18) |
| 2002 |
Jan
(39) |
Feb
(12) |
Mar
(80) |
Apr
(72) |
May
(46) |
Jun
(27) |
Jul
(23) |
Aug
(34) |
Sep
(65) |
Oct
(71) |
Nov
(19) |
Dec
(14) |
| 2003 |
Jan
(44) |
Feb
(59) |
Mar
(18) |
Apr
(62) |
May
(54) |
Jun
(27) |
Jul
(46) |
Aug
(15) |
Sep
(44) |
Oct
(36) |
Nov
(19) |
Dec
(12) |
| 2004 |
Jan
(26) |
Feb
(33) |
Mar
(47) |
Apr
(63) |
May
(36) |
Jun
(65) |
Jul
(80) |
Aug
(163) |
Sep
(65) |
Oct
(39) |
Nov
(36) |
Dec
(39) |
| 2005 |
Jan
(97) |
Feb
(78) |
Mar
(64) |
Apr
(64) |
May
(48) |
Jun
(55) |
Jul
(89) |
Aug
(57) |
Sep
(51) |
Oct
(111) |
Nov
(86) |
Dec
(76) |
| 2006 |
Jan
(84) |
Feb
(103) |
Mar
(143) |
Apr
(92) |
May
(55) |
Jun
(58) |
Jul
(71) |
Aug
(57) |
Sep
(74) |
Oct
(59) |
Nov
(8) |
Dec
(32) |
| 2007 |
Jan
(60) |
Feb
(40) |
Mar
(50) |
Apr
(26) |
May
(61) |
Jun
(120) |
Jul
(119) |
Aug
(48) |
Sep
(121) |
Oct
(66) |
Nov
(103) |
Dec
(43) |
| 2008 |
Jan
(60) |
Feb
(109) |
Mar
(92) |
Apr
(106) |
May
(82) |
Jun
(59) |
Jul
(67) |
Aug
(118) |
Sep
(131) |
Oct
(56) |
Nov
(37) |
Dec
(69) |
| 2009 |
Jan
(75) |
Feb
(76) |
Mar
(103) |
Apr
(78) |
May
(61) |
Jun
(35) |
Jul
(66) |
Aug
(69) |
Sep
(166) |
Oct
(46) |
Nov
(72) |
Dec
(65) |
| 2010 |
Jan
(48) |
Feb
(57) |
Mar
(93) |
Apr
(85) |
May
(123) |
Jun
(82) |
Jul
(98) |
Aug
(121) |
Sep
(146) |
Oct
(86) |
Nov
(72) |
Dec
(34) |
| 2011 |
Jan
(96) |
Feb
(55) |
Mar
(73) |
Apr
(57) |
May
(33) |
Jun
(74) |
Jul
(89) |
Aug
(71) |
Sep
(103) |
Oct
(76) |
Nov
(52) |
Dec
(61) |
| 2012 |
Jan
(48) |
Feb
(54) |
Mar
(78) |
Apr
(60) |
May
(75) |
Jun
(59) |
Jul
(33) |
Aug
(66) |
Sep
(43) |
Oct
(46) |
Nov
(75) |
Dec
(51) |
| 2013 |
Jan
(112) |
Feb
(72) |
Mar
(49) |
Apr
(48) |
May
(42) |
Jun
(44) |
Jul
(80) |
Aug
(19) |
Sep
(33) |
Oct
(37) |
Nov
(38) |
Dec
(98) |
| 2014 |
Jan
(113) |
Feb
(93) |
Mar
(49) |
Apr
(106) |
May
(97) |
Jun
(155) |
Jul
(87) |
Aug
(127) |
Sep
(85) |
Oct
(48) |
Nov
(41) |
Dec
(37) |
| 2015 |
Jan
(34) |
Feb
(50) |
Mar
(104) |
Apr
(80) |
May
(82) |
Jun
(66) |
Jul
(41) |
Aug
(84) |
Sep
(37) |
Oct
(65) |
Nov
(83) |
Dec
(52) |
| 2016 |
Jan
(68) |
Feb
(35) |
Mar
(42) |
Apr
(35) |
May
(54) |
Jun
(75) |
Jul
(45) |
Aug
(52) |
Sep
(60) |
Oct
(52) |
Nov
(36) |
Dec
(64) |
| 2017 |
Jan
(92) |
Feb
(59) |
Mar
(35) |
Apr
(53) |
May
(83) |
Jun
(43) |
Jul
(65) |
Aug
(68) |
Sep
(46) |
Oct
(75) |
Nov
(40) |
Dec
(49) |
| 2018 |
Jan
(68) |
Feb
(54) |
Mar
(48) |
Apr
(58) |
May
(51) |
Jun
(44) |
Jul
(40) |
Aug
(68) |
Sep
(35) |
Oct
(15) |
Nov
(7) |
Dec
(37) |
| 2019 |
Jan
(43) |
Feb
(7) |
Mar
(22) |
Apr
(21) |
May
(31) |
Jun
(39) |
Jul
(73) |
Aug
(45) |
Sep
(47) |
Oct
(89) |
Nov
(19) |
Dec
(69) |
| 2020 |
Jan
(52) |
Feb
(63) |
Mar
(45) |
Apr
(59) |
May
(42) |
Jun
(57) |
Jul
(30) |
Aug
(29) |
Sep
(75) |
Oct
(64) |
Nov
(96) |
Dec
(22) |
| 2021 |
Jan
(14) |
Feb
(24) |
Mar
(35) |
Apr
(58) |
May
(36) |
Jun
(15) |
Jul
(18) |
Aug
(31) |
Sep
(30) |
Oct
(33) |
Nov
(27) |
Dec
(16) |
| 2022 |
Jan
(35) |
Feb
(22) |
Mar
(14) |
Apr
(20) |
May
(44) |
Jun
(53) |
Jul
(25) |
Aug
(56) |
Sep
(11) |
Oct
(47) |
Nov
(22) |
Dec
(36) |
| 2023 |
Jan
(30) |
Feb
(17) |
Mar
(31) |
Apr
(48) |
May
(31) |
Jun
(7) |
Jul
(25) |
Aug
(26) |
Sep
(61) |
Oct
(66) |
Nov
(19) |
Dec
(21) |
| 2024 |
Jan
(37) |
Feb
(29) |
Mar
(26) |
Apr
(26) |
May
(34) |
Jun
(9) |
Jul
(27) |
Aug
(13) |
Sep
(15) |
Oct
(25) |
Nov
(13) |
Dec
(8) |
| 2025 |
Jan
(13) |
Feb
(1) |
Mar
(16) |
Apr
(17) |
May
(8) |
Jun
(6) |
Jul
(9) |
Aug
|
Sep
(6) |
Oct
(15) |
Nov
(6) |
Dec
|
| 2026 |
Jan
(6) |
Feb
(4) |
Mar
(20) |
Apr
(7) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: Philippe H. <phi...@ex...> - 2020-06-26 12:38:29
|
I followed published code to generate paths of short rates using the
Hull-White model via already published code as follows.
hw_process = ql.HullWhiteProcess(crv_handle, mean_rev, sigma)
rng = ql.GaussianRandomSequenceGenerator(ql.UniformRandomSequenceGenerator(time_step,
ql.UniformRandomGenerator()))
seq = ql.GaussianPathGenerator(hw_process, length_years, time_step, rng, False)
for i in range(num_paths):
sample_path = seq.next()
path = sample_path.value()
My question, very simply, is: "
What is the easiest way to rebuild a curve handle from the path of rates
created by the HW process above?"
My goal is to use such curve handle to reprice bond instances via NPV(), so
I need a curve handle. I could certainly bootstrap/compound the short rates
to create discount factors (zero coupon prices) from each path above, from
which to build a ZeroCurve() but I was hoping there is a more direct method?
Regards
Philippe
--
Brokerage services offered through Exos Securities LLC, member of
SIPC <http://www.sipc.org/> / FINRA <http://www.finra.org/>. For important
disclosures, click here <https://www.exosfinancial.com/disclosures>.
|
|
From: Klaus S. <kl...@sp...> - 2020-06-25 21:26:51
|
please ignore my comment on "Observation 1 on Case 2", it is wrong, On Donnerstag, 25. Juni 2020 22:45:18 CEST Klaus Spanderen wrote: > Hi, > > thanks for sharing your results. > > W.r.t. your questions > 1. Douglas and Crank-Nicolson scheme are exactly the same for one-dimensional problems like the Black-Scholes equation. In higher dimensions operator splitting schemes like Douglas or Craig-Sneyd are better suited than Crank-Nicolson, hence there wasn't really a need to implement it (even though for the sake of completeness the Crank-Nicolson scheme has been added with the 1.18 release in C++). > 2. The spot dividend model is described e.q. in "Back to Basics: a new approach to the discrete dividend problem". People might argue that the spot dividend process is more realistic for path dependent options like barrier options or structured equity notes. > 3. As far as I know there is no general and meaningful algorithm for this problem, which is as easy as for Monte-Carlo. > > Observation 1 on Case 2. If I remember correctly then there was subtle difference between interest rate treatment for discrete dividents between the FDDividendAmericanEngine on the one side and AnalyticDividendEuropeanEngine,FdBlackScholesVanillaEngine on the other side. > Observation 2: For these pathologic cases the default number of S grid steps is too small. In general I'd use 500 or more S grid steps. > > best regards > Klaus > > > > > _______________________________________________ > QuantLib-users mailing list > Qua...@li... > https://lists.sourceforge.net/lists/listinfo/quantlib-users > |
|
From: Klaus S. <kl...@sp...> - 2020-06-25 21:09:31
|
Hi, thanks for sharing your results. W.r.t. your questions 1. Douglas and Crank-Nicolson scheme are exactly the same for one-dimensional problems like the Black-Scholes equation. In higher dimensions operator splitting schemes like Douglas or Craig-Sneyd are better suited than Crank-Nicolson, hence there wasn't really a need to implement it (even though for the sake of completeness the Crank-Nicolson scheme has been added with the 1.18 release in C++). 2. The spot dividend model is described e.q. in "Back to Basics: a new approach to the discrete dividend problem". People might argue that the spot dividend process is more realistic for path dependent options like barrier options or structured equity notes. 3. As far as I know there is no general and meaningful algorithm for this problem, which is as easy as for Monte-Carlo. Observation 1 on Case 2. If I remember correctly then there was subtle difference between interest rate treatment for discrete dividents between the FDDividendAmericanEngine on the one side and AnalyticDividendEuropeanEngine,FdBlackScholesVanillaEngine on the other side. Observation 2: For these pathologic cases the default number of S grid steps is too small. In general I'd use 500 or more S grid steps. best regards Klaus |
|
From: Shenze W. <she...@da...> - 2020-06-24 17:19:28
|
Hi Luigi, Thanks for your codes. Yes, they do change. I did not understand that the dividend model is about the discrete dividends. I was pricing options with dividend yields but without discrete dividends. That’s why I didn’t observe the differences of the two different dividend models. Based on your Python code, I priced some American options. The results of 3 test cases are in the attached “results.txt”. The Python code is in the attached “FD_engines.py”. Here are some findings and questions. Findings: 1. In some cases (Case 1), FDDividendAmericanEngine and FdBlackScholesVanillaEngine with Escrowed generate similar results, and the new engine shows better converge performance. However, in some cases (Case 2), the result of old engine does not match any results from the new engine. The option in Case 2 is the same as Case 1 except that there is an interest rate. 2. In some cases (Case 3), the spot dividend model seems to generate wrong results. The option in Case 3 is an option with a big dividend right after the evaluation date. The results of spot dividend model is very different from others. The price also changes a lot when mesh changes. Questions: 1. About FD schemes. Why there is no CrankNicolson scheme in the latest version? Is it replaced by Douglas scheme because Douglas is generally better? 2. About Dividend models. I understand that in Escrowed Model it is assumed that the stock price minus the present value of dividends follows Geometric Brownian Motion. But I am not sure what’s the Spot Dividend Model in QuantLib. What’s assumption of this model? By checking the C++ codes, it seems that the only difference of this two models is the spotAdjustment in this line: https://github.com/lballabio/QuantLib/blob/master/ql/methods/finitedifferences/meshers/fdmblackscholesmesher.cpp#L81 3. It seems that there is no error estimator for FD engines. Will we have one? Thanks a lot. Best, Shenze On Jun 18, 2020, 4:52 AM -0400, Luigi Ballabio <lui...@gm...>, wrote: > Yes, they do change. See the script I'm attaching for a simple example. > > Luigi > > > On Thu, Jun 18, 2020 at 10:32 AM Luigi Ballabio <lui...@gm...> wrote: > > > Hmm. No, I would expect the result to change at least slightly. Let me check that. Can you share the code you're using? > > > > > > Luigi > > > > > > > > > > On Tue, Jun 16, 2020 at 11:02 PM Shenze Wang <she...@da...> wrote: > > > > > Hi Luigi, > > > > > > > > > > Thanks a lot for the reply. > > > > > > > > > > I did not set the parameter `CashDividendModle` of the constructor `FdBlackScolesVanillaEngine` explicitly in my previous calculations. > > > > > > > > > > However, it seems that the parameter `CashDividendModle` does not affect the results at all. > > > > > > > > > > I calculated the prices of a bunch of American options with dividend yields with the engine `FdBlackScolesVanillaEngine` from QuantLib 1.18. The results from 'CashDividendModel cashDividendModel = Spot’ and the results from 'CashDividendModel cashDividendModel = Escrowed’ are identical, literally. I am using the Python wrap. > > > > > > > > > > Is this normal? > > > > > > > > > > > > > > > Best, > > > > > Shenze > > > > > > > > > > On Jun 16, 2020, 4:51 AM -0400, Luigi Ballabio <lui...@gm...>, wrote: > > > > > > Hello, > > > > > > thanks for the analysis. > > > > > > > > > > > > There are people here which are more capable of answering than I am, but just to make sure that we're comparing equals to equals: FdBlackScholesVanillaEngine has two possible ways to handle dividends, and we should document this better. One is the scale/shift model, and the other is the escrowed dividend model; you can choose the model by mans of an optional last parameter for the constructor (see <https://github.com/lballabio/QuantLib-SWIG/blob/master/SWIG/options.i#L1202>). > > > > > > > > > > > > Now, FDDividendAmericanEngine uses the escrowed dividend model, which I'm told is the one described in most texts. Instead, FdBlackScholesVanillaEngine uses by default the scale/shift model. If you didn't set the model explicitly, this might be the reason for the differences. Passing Escrowed as the model would cause the results to be closer. > > > > > > > > > > > > If you did that already, though, we'll have to look closer into the code. > > > > > > > > > > > > Hope this helps, > > > > > > Luigi > > > > > > > > > > > > > > > > > > > > > > > > > On Mon, Jun 15, 2020 at 10:01 PM Shenze Wang <she...@da...> wrote: > > > > > > > > Hi, > > > > > > > > > > > > > > > > We are currently using `FDDividendAmericanEngine` (denoted by DA in following) of QuantLib 1.12. Since this engine is removed in QuantLib 1.16, we’d like to switch to `FdBlackScholesVanillaEngine` (denoted by FD in following) of QuantLib 1.18. Before we do the switch, we’d like to know the difference between these two engines (DA engine in QuantLib 1.12 and FD engine in QuantLib 1.18) and what are the impacts on the pricing results. We are using the Python version of QuantLib. > > > > > > > > > > > > > > > > I priced ~7000 options with different ivols, strikes, interest rates, dividend yields with 3 engines: (a) DA12 - `FDDividendAmericanEngine` in QuantLib 1.12, (b) FD12 - `FdBlackScholesVanillaEngine` in QuantLib 1.12, and (c) FD18 - `FdBlackScholesVanillaEngine` in QuantLib 1.18. > > > > > > > > > > > > > > > > Here are some comparisons of the results. > > > > > > > > > > > > > > > > (1) The difference between FD18 and DA12 including two parts: the difference between FD12 & DA12, and the difference between FD18 & FD12. The difference between FD12 & DA12 is much greater than the difference between FD18 & FD12, as shown in the following form. The form shows CDF of the differences. The numbers in the form are the probability that the difference is in a certain range. > > > > > > > > > > > > > > > > > > > > > > > > (2) FD12 vs DA12. The option prices generated by FD12 is greater than DA12 for in-the-money options, but lower for at-the-money and out-of-the-money options. Compared to the analytical solutions, FD12 is more accurate for at-the-money and out-of-the-money options, while DA12 is more accurate for in-the-money options. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > (3) FD18 vs FD12. Though it is relatively small, there is still a difference between FD18 and FD12, as shown in the following figure. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > So, my questions are: > > > > > > > > > > > > > > > > a. Do the difference between FD12 & DA12 and the difference between FD18 & FD12 described above behave as expected? > > > > > > > > b. What’s the potential reasons for these differences? > > > > > > > > > > > > > > > > I know the answers to these questions could be very subtle, but we’d like to understand the reasons for these differences, at least to some extent. I also tried to dig into the C++ codes, but I am not familiar with the codes and I do not know where to start. If you could provide some explanations or point me the right directions, I would be super grateful. > > > > > > > > > > > > > > > > Thanks a lot. > > > > > > > > > > > > > > > > > > > > > > > > Best Regards, > > > > > > > > Shenze Wang > > > > > > > > > > > > > > > > DataDock Solutions > > > > > > > > _______________________________________________ > > > > > > > > QuantLib-users mailing list > > > > > > > > Qua...@li... > > > > > > > > https://lists.sourceforge.net/lists/listinfo/quantlib-users |
|
From: Brian S. <bri...@ya...> - 2020-06-22 16:51:08
|
Hi, I was looking for some pricing algorithm to value an Average Rate option (European style) with strike price lets assume K. Exercise will be at the time T and the averaging would be done based on prices of S&P500 for last 5 consecutive business days on prior week. Is there any way to calculate the fair value and sensitivities of this option in QuantLib? An example would be highly appreciated. Many thanks, |
|
From: Luigi B. <lui...@gm...> - 2020-06-18 08:52:48
|
Yes, they do change. See the script I'm attaching for a simple example. Luigi On Thu, Jun 18, 2020 at 10:32 AM Luigi Ballabio <lui...@gm...> wrote: > Hmm. No, I would expect the result to change at least slightly. Let me > check that. Can you share the code you're using? > > Luigi > > > On Tue, Jun 16, 2020 at 11:02 PM Shenze Wang < > she...@da...> wrote: > >> Hi Luigi, >> >> Thanks a lot for the reply. >> >> I did not set the parameter `CashDividendModle` of the constructor >> `FdBlackScolesVanillaEngine` explicitly in my previous calculations. >> >> However, it seems that the parameter `CashDividendModle` does not affect >> the results at all. >> >> I calculated the prices of a bunch of American options with dividend >> yields with the engine `FdBlackScolesVanillaEngine` from QuantLib 1.18. >> The results from 'CashDividendModel cashDividendModel = Spot’ and the >> results from 'CashDividendModel cashDividendModel = Escrowed’ are >> *identical*, literally. I am using the Python wrap. >> >> Is this normal? >> >> >> Best, >> Shenze >> >> On Jun 16, 2020, 4:51 AM -0400, Luigi Ballabio <lui...@gm...>, >> wrote: >> >> Hello, >> thanks for the analysis. >> >> There are people here which are more capable of answering than I am, but >> just to make sure that we're comparing equals to >> equals: FdBlackScholesVanillaEngine has two possible ways to handle >> dividends, and we should document this better. One is the scale/shift >> model, and the other is the escrowed dividend model; you can choose the >> model by mans of an optional last parameter for the constructor (see < >> https://github.com/lballabio/QuantLib-SWIG/blob/master/SWIG/options.i#L1202 >> >). >> >> Now, FDDividendAmericanEngine uses the escrowed dividend model, which I'm >> told is the one described in most texts. >> Instead, FdBlackScholesVanillaEngine uses by default the scale/shift >> model. If you didn't set the model explicitly, this might be the reason >> for the differences. Passing Escrowed as the model would cause the results >> to be closer. >> >> If you did that already, though, we'll have to look closer into the code. >> >> Hope this helps, >> Luigi >> >> >> >> On Mon, Jun 15, 2020 at 10:01 PM Shenze Wang < >> she...@da...> wrote: >> >>> Hi, >>> >>> We are currently using `FD*D*ividend*A*mericanEngine` (denoted by *DA* in >>> following) of QuantLib 1.12. Since this engine is removed in QuantLib 1.16, >>> we’d like to switch to `*Fd*BlackScholesVanillaEngine` (denoted by *FD *in >>> following) of QuantLib 1.18. Before we do the switch, we’d like to know the >>> difference between these two engines (DA engine in QuantLib 1.12 and FD >>> engine in QuantLib 1.18) and what are the impacts on the pricing results. >>> We are using the Python version of QuantLib. >>> >>> I priced ~7000 options with different ivols, strikes, interest rates, >>> dividend yields with 3 engines: (a) *DA12* - `FDDividendAmericanEngine` >>> in QuantLib 1.12, (b) *FD12* - `FdBlackScholesVanillaEngine` in >>> QuantLib 1.12, and (c) *FD18* - `FdBlackScholesVanillaEngine` in >>> QuantLib 1.18. >>> >>> Here are some comparisons of the results. >>> >>> *(1)* The difference between FD18 and DA12 including two parts: the >>> difference between FD12 & DA12, and the difference between FD18 & FD12. The >>> difference between FD12 & DA12 is much greater than the difference between >>> FD18 & FD12, as shown in the following form. The form shows CDF of the >>> differences. The numbers in the form are the probability that the >>> difference is in a certain range. >>> >>> >>> *(2)* *FD12 vs DA12*. The option prices generated by FD12 is greater >>> than DA12 for in-the-money options, but lower for at-the-money and >>> out-of-the-money options. Compared to the analytical solutions, FD12 is >>> more accurate for at-the-money and out-of-the-money options, while DA12 is >>> more accurate for in-the-money options. >>> >>> >>> >>> *(3)* *FD18 vs FD12. *Though it is relatively small, there is still a >>> difference between FD18 and FD12, as shown in the following figure. >>> >>> >>> >>> So, my questions are: >>> >>> 1. Do the difference between FD12 & DA12 and the difference between >>> FD18 & FD12 described above behave as expected? >>> 2. What’s the potential reasons for these differences? >>> >>> I know the answers to these questions could be very subtle, but we’d >>> like to understand the reasons for these differences, at least to some >>> extent. I also tried to dig into the C++ codes, but I am not familiar with >>> the codes and I do not know where to start. If you could provide some >>> explanations or point me the right directions, I would be super grateful. >>> >>> Thanks a lot. >>> >>> >>> Best Regards, >>> Shenze Wang >>> >>> DataDock Solutions >>> _______________________________________________ >>> QuantLib-users mailing list >>> Qua...@li... >>> https://lists.sourceforge.net/lists/listinfo/quantlib-users >>> >> |
|
From: Luigi B. <lui...@gm...> - 2020-06-18 08:32:43
|
Hmm. No, I would expect the result to change at least slightly. Let me check that. Can you share the code you're using? Luigi On Tue, Jun 16, 2020 at 11:02 PM Shenze Wang < she...@da...> wrote: > Hi Luigi, > > Thanks a lot for the reply. > > I did not set the parameter `CashDividendModle` of the constructor > `FdBlackScolesVanillaEngine` explicitly in my previous calculations. > > However, it seems that the parameter `CashDividendModle` does not affect > the results at all. > > I calculated the prices of a bunch of American options with dividend > yields with the engine `FdBlackScolesVanillaEngine` from QuantLib 1.18. > The results from 'CashDividendModel cashDividendModel = Spot’ and the > results from 'CashDividendModel cashDividendModel = Escrowed’ are > *identical*, literally. I am using the Python wrap. > > Is this normal? > > > Best, > Shenze > > On Jun 16, 2020, 4:51 AM -0400, Luigi Ballabio <lui...@gm...>, > wrote: > > Hello, > thanks for the analysis. > > There are people here which are more capable of answering than I am, but > just to make sure that we're comparing equals to > equals: FdBlackScholesVanillaEngine has two possible ways to handle > dividends, and we should document this better. One is the scale/shift > model, and the other is the escrowed dividend model; you can choose the > model by mans of an optional last parameter for the constructor (see < > https://github.com/lballabio/QuantLib-SWIG/blob/master/SWIG/options.i#L1202 > >). > > Now, FDDividendAmericanEngine uses the escrowed dividend model, which I'm > told is the one described in most texts. > Instead, FdBlackScholesVanillaEngine uses by default the scale/shift > model. If you didn't set the model explicitly, this might be the reason > for the differences. Passing Escrowed as the model would cause the results > to be closer. > > If you did that already, though, we'll have to look closer into the code. > > Hope this helps, > Luigi > > > > On Mon, Jun 15, 2020 at 10:01 PM Shenze Wang < > she...@da...> wrote: > >> Hi, >> >> We are currently using `FD*D*ividend*A*mericanEngine` (denoted by *DA* in >> following) of QuantLib 1.12. Since this engine is removed in QuantLib 1.16, >> we’d like to switch to `*Fd*BlackScholesVanillaEngine` (denoted by *FD *in >> following) of QuantLib 1.18. Before we do the switch, we’d like to know the >> difference between these two engines (DA engine in QuantLib 1.12 and FD >> engine in QuantLib 1.18) and what are the impacts on the pricing results. >> We are using the Python version of QuantLib. >> >> I priced ~7000 options with different ivols, strikes, interest rates, >> dividend yields with 3 engines: (a) *DA12* - `FDDividendAmericanEngine` >> in QuantLib 1.12, (b) *FD12* - `FdBlackScholesVanillaEngine` in QuantLib >> 1.12, and (c) *FD18* - `FdBlackScholesVanillaEngine` in QuantLib 1.18. >> >> Here are some comparisons of the results. >> >> *(1)* The difference between FD18 and DA12 including two parts: the >> difference between FD12 & DA12, and the difference between FD18 & FD12. The >> difference between FD12 & DA12 is much greater than the difference between >> FD18 & FD12, as shown in the following form. The form shows CDF of the >> differences. The numbers in the form are the probability that the >> difference is in a certain range. >> >> >> *(2)* *FD12 vs DA12*. The option prices generated by FD12 is greater >> than DA12 for in-the-money options, but lower for at-the-money and >> out-of-the-money options. Compared to the analytical solutions, FD12 is >> more accurate for at-the-money and out-of-the-money options, while DA12 is >> more accurate for in-the-money options. >> >> >> >> *(3)* *FD18 vs FD12. *Though it is relatively small, there is still a >> difference between FD18 and FD12, as shown in the following figure. >> >> >> >> So, my questions are: >> >> 1. Do the difference between FD12 & DA12 and the difference between >> FD18 & FD12 described above behave as expected? >> 2. What’s the potential reasons for these differences? >> >> I know the answers to these questions could be very subtle, but we’d like >> to understand the reasons for these differences, at least to some extent. I >> also tried to dig into the C++ codes, but I am not familiar with the codes >> and I do not know where to start. If you could provide some explanations or >> point me the right directions, I would be super grateful. >> >> Thanks a lot. >> >> >> Best Regards, >> Shenze Wang >> >> DataDock Solutions >> _______________________________________________ >> QuantLib-users mailing list >> Qua...@li... >> https://lists.sourceforge.net/lists/listinfo/quantlib-users >> > |
|
From: Luís M. A. <lui...@gm...> - 2020-06-17 21:26:44
|
Sorry miss pasted a part of the code, here is it fully (missed part is in
bold):
*today = ql.Date(9, 6, 2020)*
*ql.Settings.instance().evaluationDate = todayON = today + ql.Period('1D')*
*A = list(ql.Schedule(ql.Date(1, today.month(), 2020), ql.Date(1, 11,
2021), ql.Period(ql.Monthly), ql.UnitedStates(),
ql.Unadjusted, ql.Unadjusted, ql.DateGeneration.Forward,
False))*
*I have the following instruments:- 1 overnight deposit - From 9/6/2020 to
10/6/2020-17 1month FF futures - First is the June contract 2020 contract,
second is July 2020, .. *
*FF_schedule = [today] + A*
*Start = FF_schedule[:-1]*
*End = [ON] + FF_schedule[2:]*
*Tenor = ['OIS', 'FF1', 'FF2', 'FF3', 'FF4', 'FF5', 'FF6', 'FF7', 'FF8',
'FF9', 'FF10', 'FF11', 'FF12', 'FF13', 'FF14', 'FF15', 'FF16',
'FF17']*
*Mids = [0.070, 99.92375, 99.9225, 99.9275, 99.9325, 99.9425, 99.9475,
99.9475, 99.9525, 99.9625, 99.9650, 99.9625, 99.9725, 99.9775, 99.9975,
99.9825, 99.9800, 99.9750]*
*calendar = ql.NullCalendar()dc = ql.ActualActual()bc =
ql.Followingsettlement_date = todaysettlementDays = 1end_of_month =
Truehelpers = []depo_helper =
[ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(Tenor_Rates['OIS']/100)),
ql.Period(ON - today, ql.Days),
settlementDays, calendar, bc, end_of_month, dc)]helpers += depo_helper*
*#Just organising the dates*
*fed_funds = ql.FedFunds()Start_Futures = [Start[0]] + Start[2:]End_Futures
= End[1:]Futures_Mids = Mids[1:]Futures_Rates = [100-i for i in
Futures_Mids]*
*#Using Sofr_Future_Rate_HelperOvernightIndex = ql.Sofr()Sofr_data = []for
i in range(len(End_Futures)): Sofr_data.append([Futures_Mids[i],
End_Futures[i].month(), End_Futures[i].year()])referenceFreq = ql.Monthly
futures_helper =
[ql.SofrFutureRateHelper(ql.QuoteHandle(ql.SimpleQuote(Futures_Mid)),
reference_month, reference_year,
referenceFreq, OvernightIndex) for Futures_Mid,
reference_month, reference_year in Sofr_data]
helpers_with_SOFR_Future_Rate_Helpers += sofr_future_helper*
*OIS_Curve = ql.PiecewiseLogLinearDiscount(today, futures_helper , dc)*
Kind regards,
Luis
On Wed, Jun 17, 2020 at 10:19 PM Luís Miguel Aguiar <
lui...@gm...> wrote:
> Good evening everyone,
>
> I have been trying to use the SofrFutureRateHelper class but am having
> some trouble with it and was hoping I could post my doubt here.
>
> As it is quite recent (only in Version 1.18), I have trouble finding
> examples online, plus I am doing it in Python and not C++, where examples
> are scarcer.
>
> Could anyone be so kind to point out where I am wrong in the code?
>
> When I see the discount factors of the pillars, I see it is giving me
> quite different results than the following:
>
> Tenor Start End Mid FRA DF (in End
> Date)
> OIS 9/6/20 10/6/20 0.070% 0.070% a
> FF1 1/6/20 1/7/20 99.92375 0.07625% b
> FF2 1/7/20 1/8/20 99.9225 0.0775% c
> FF3 1/8/20 1/9/20 99.9275 0.0725% d
> FF4 1/9/20 1/10/20 99.9325 0.0675% e
> .................
> FF17 1/10/21 1/11/21 99.9750 0.0250%
>
> a = 1/(1+0.070%*(10/6/20 - 9/6/20)/366) = 0.9999980874353520
> b = 1/(1+0.07625%*(1/7/20-9/6/20)/366) = 0.9999541687672650
> c = b/(1+0.0775%*(1/8/20-1/7/20)/366 = 0.9998885340076210
> d = c/(1+0.0725%*(1/9/20-1/8/20)/366 = 0.9998271375187800
> e = d/(1+0.0675%*(1/10/20-1/9/20)/366 = 0.9997718222745150
>
> So for all my pillars (1 ON deposit rate and 17 futures) the correct DFs
> should be
>
> Correct_DFs = [0.9999980874353520, 0.9999541687672650,
> 0.9998885340076210,
> 0.9998271375187800, 0.9997718222745150, 0.9997231335727230,
> 0.9996801145514000, 0.9996356635393120,
> 0.9995953373986460,
> 0.9995665827435260, 0.9995368704831300,
> 0.9995060637893830,
> 0.9994827197066830, 0.9994642364639530, 0.9994451374781070,
> 0.9994302829321210, 0.9994138542112300,
> 0.9993926342306400]
>
> I cannot seem to replicate the correct answers with the following code:
>
>
>
>
> *today = ql.Date(9, 6, 2020)ql.Settings.instance().evaluationDate =
> todayON = today + ql.Period('1D')*
>
>
>
>
> *A = list(ql.Schedule(ql.Date(1, today.month(), 2020), ql.Date(1, 11,
> 2021), ql.Period(ql.Monthly), ql.UnitedStates(),
> ql.Unadjusted, ql.Unadjusted,
> ql.DateGeneration.Forward, False))*
>
>
>
> *I have the following instruments:- 1 overnight deposit - From 9/6/2020 to
> 10/6/2020-17 1month FF futures - First is the June contract 2020 contract,
> second is July 2020, .. *
>
>
> *Tenor = ['OIS', 'FF1', 'FF2', 'FF3', 'FF4', 'FF5', 'FF6', 'FF7', 'FF8',
> 'FF9', 'FF10', 'FF11', 'FF12', 'FF13', 'FF14', 'FF15', 'FF16',
> 'FF17']*
>
>
> *Mids = [0.070, 99.92375, 99.9225, 99.9275, 99.9325, 99.9425, 99.9475,
> 99.9475, 99.9525, 99.9625, 99.9650, 99.9625, 99.9725, 99.9775, 99.9975,
> 99.9825, 99.9800, 99.9750]*
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> *calendar = ql.NullCalendar()dc = ql.ActualActual()bc =
> ql.Followingsettlement_date = todaysettlementDays = 1end_of_month =
> Truehelpers = []depo_helper =
> [ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(Tenor_Rates['OIS']/100)),
> ql.Period(ON - today, ql.Days),
> settlementDays, calendar, bc, end_of_month, dc)]helpers += depo_helper*
>
> *#Just organising the dates*
>
>
>
>
>
> *fed_funds = ql.FedFunds()Start_Futures = [Start[0]] +
> Start[2:]End_Futures = End[1:]Futures_Mids = Mids[1:]Futures_Rates = [100-i
> for i in Futures_Mids]*
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> *#Using Sofr_Future_Rate_HelperOvernightIndex = ql.Sofr()Sofr_data = []for
> i in range(len(End_Futures)): Sofr_data.append([Futures_Mids[i],
> End_Futures[i].month(), End_Futures[i].year()])referenceFreq = ql.Monthly
> futures_helper =
> [ql.SofrFutureRateHelper(ql.QuoteHandle(ql.SimpleQuote(Futures_Mid)),
> reference_month, reference_year,
> referenceFreq, OvernightIndex) for Futures_Mid,
> reference_month, reference_year in Sofr_data]
> helpers_with_SOFR_Future_Rate_Helpers += sofr_future_helper*
>
>
> *OIS_Curve = ql.PiecewiseLogLinearDiscount(today, futures_helper , dc)*
>
> Sorry for the lengthy doubt and possibly inefficient code. I have just
> been trying to get it right the past few days and unfortunately made no
> progress.
>
> Kind regards,
> Luis Aguiar
>
|
|
From: Luís M. A. <lui...@gm...> - 2020-06-17 21:20:20
|
Good evening everyone,
I have been trying to use the SofrFutureRateHelper class but am having some
trouble with it and was hoping I could post my doubt here.
As it is quite recent (only in Version 1.18), I have trouble finding
examples online, plus I am doing it in Python and not C++, where examples
are scarcer.
Could anyone be so kind to point out where I am wrong in the code?
When I see the discount factors of the pillars, I see it is giving me quite
different results than the following:
Tenor Start End Mid FRA DF (in End
Date)
OIS 9/6/20 10/6/20 0.070% 0.070% a
FF1 1/6/20 1/7/20 99.92375 0.07625% b
FF2 1/7/20 1/8/20 99.9225 0.0775% c
FF3 1/8/20 1/9/20 99.9275 0.0725% d
FF4 1/9/20 1/10/20 99.9325 0.0675% e
.................
FF17 1/10/21 1/11/21 99.9750 0.0250%
a = 1/(1+0.070%*(10/6/20 - 9/6/20)/366) = 0.9999980874353520
b = 1/(1+0.07625%*(1/7/20-9/6/20)/366) = 0.9999541687672650
c = b/(1+0.0775%*(1/8/20-1/7/20)/366 = 0.9998885340076210
d = c/(1+0.0725%*(1/9/20-1/8/20)/366 = 0.9998271375187800
e = d/(1+0.0675%*(1/10/20-1/9/20)/366 = 0.9997718222745150
So for all my pillars (1 ON deposit rate and 17 futures) the correct DFs
should be
Correct_DFs = [0.9999980874353520, 0.9999541687672650, 0.9998885340076210,
0.9998271375187800,
0.9997718222745150, 0.9997231335727230,
0.9996801145514000, 0.9996356635393120, 0.9995953373986460,
0.9995665827435260, 0.9995368704831300,
0.9995060637893830,
0.9994827197066830, 0.9994642364639530, 0.9994451374781070,
0.9994302829321210, 0.9994138542112300,
0.9993926342306400]
I cannot seem to replicate the correct answers with the following code:
*today = ql.Date(9, 6, 2020)ql.Settings.instance().evaluationDate = todayON
= today + ql.Period('1D')*
*A = list(ql.Schedule(ql.Date(1, today.month(), 2020), ql.Date(1, 11,
2021), ql.Period(ql.Monthly), ql.UnitedStates(),
ql.Unadjusted, ql.Unadjusted,
ql.DateGeneration.Forward, False))*
*I have the following instruments:- 1 overnight deposit - From 9/6/2020 to
10/6/2020-17 1month FF futures - First is the June contract 2020 contract,
second is July 2020, .. *
*Tenor = ['OIS', 'FF1', 'FF2', 'FF3', 'FF4', 'FF5', 'FF6', 'FF7', 'FF8',
'FF9', 'FF10', 'FF11', 'FF12', 'FF13', 'FF14', 'FF15', 'FF16',
'FF17']*
*Mids = [0.070, 99.92375, 99.9225, 99.9275, 99.9325, 99.9425, 99.9475,
99.9475, 99.9525, 99.9625, 99.9650, 99.9625, 99.9725, 99.9775, 99.9975,
99.9825, 99.9800, 99.9750]*
*calendar = ql.NullCalendar()dc = ql.ActualActual()bc =
ql.Followingsettlement_date = todaysettlementDays = 1end_of_month =
Truehelpers = []depo_helper =
[ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(Tenor_Rates['OIS']/100)),
ql.Period(ON - today, ql.Days),
settlementDays, calendar, bc, end_of_month, dc)]helpers += depo_helper*
*#Just organising the dates*
*fed_funds = ql.FedFunds()Start_Futures = [Start[0]] + Start[2:]End_Futures
= End[1:]Futures_Mids = Mids[1:]Futures_Rates = [100-i for i in
Futures_Mids]*
*#Using Sofr_Future_Rate_HelperOvernightIndex = ql.Sofr()Sofr_data = []for
i in range(len(End_Futures)): Sofr_data.append([Futures_Mids[i],
End_Futures[i].month(), End_Futures[i].year()])referenceFreq = ql.Monthly
futures_helper =
[ql.SofrFutureRateHelper(ql.QuoteHandle(ql.SimpleQuote(Futures_Mid)),
reference_month, reference_year,
referenceFreq, OvernightIndex) for Futures_Mid,
reference_month, reference_year in Sofr_data]
helpers_with_SOFR_Future_Rate_Helpers += sofr_future_helper*
*OIS_Curve = ql.PiecewiseLogLinearDiscount(today, futures_helper , dc)*
Sorry for the lengthy doubt and possibly inefficient code. I have just been
trying to get it right the past few days and unfortunately made no progress.
Kind regards,
Luis Aguiar
|
|
From: Shenze W. <she...@da...> - 2020-06-16 21:28:11
|
Hi Luigi, Thanks a lot for the reply. I did not set the parameter `CashDividendModle` of the constructor `FdBlackScolesVanillaEngine` explicitly in my previous calculations. However, it seems that the parameter `CashDividendModle` does not affect the results at all. I calculated the prices of a bunch of American options with dividend yields with the engine `FdBlackScolesVanillaEngine` from QuantLib 1.18. The results from 'CashDividendModel cashDividendModel = Spot’ and the results from 'CashDividendModel cashDividendModel = Escrowed’ are identical, literally. I am using the Python wrap. Is this normal? Best, Shenze On Jun 16, 2020, 4:51 AM -0400, Luigi Ballabio <lui...@gm...>, wrote: > Hello, > thanks for the analysis. > > There are people here which are more capable of answering than I am, but just to make sure that we're comparing equals to equals: FdBlackScholesVanillaEngine has two possible ways to handle dividends, and we should document this better. One is the scale/shift model, and the other is the escrowed dividend model; you can choose the model by mans of an optional last parameter for the constructor (see <https://github.com/lballabio/QuantLib-SWIG/blob/master/SWIG/options.i#L1202>). > > Now, FDDividendAmericanEngine uses the escrowed dividend model, which I'm told is the one described in most texts. Instead, FdBlackScholesVanillaEngine uses by default the scale/shift model. If you didn't set the model explicitly, this might be the reason for the differences. Passing Escrowed as the model would cause the results to be closer. > > If you did that already, though, we'll have to look closer into the code. > > Hope this helps, > Luigi > > > > > On Mon, Jun 15, 2020 at 10:01 PM Shenze Wang <she...@da...> wrote: > > > Hi, > > > > > > We are currently using `FDDividendAmericanEngine` (denoted by DA in following) of QuantLib 1.12. Since this engine is removed in QuantLib 1.16, we’d like to switch to `FdBlackScholesVanillaEngine` (denoted by FD in following) of QuantLib 1.18. Before we do the switch, we’d like to know the difference between these two engines (DA engine in QuantLib 1.12 and FD engine in QuantLib 1.18) and what are the impacts on the pricing results. We are using the Python version of QuantLib. > > > > > > I priced ~7000 options with different ivols, strikes, interest rates, dividend yields with 3 engines: (a) DA12 - `FDDividendAmericanEngine` in QuantLib 1.12, (b) FD12 - `FdBlackScholesVanillaEngine` in QuantLib 1.12, and (c) FD18 - `FdBlackScholesVanillaEngine` in QuantLib 1.18. > > > > > > Here are some comparisons of the results. > > > > > > (1) The difference between FD18 and DA12 including two parts: the difference between FD12 & DA12, and the difference between FD18 & FD12. The difference between FD12 & DA12 is much greater than the difference between FD18 & FD12, as shown in the following form. The form shows CDF of the differences. The numbers in the form are the probability that the difference is in a certain range. > > > > > > > > > (2) FD12 vs DA12. The option prices generated by FD12 is greater than DA12 for in-the-money options, but lower for at-the-money and out-of-the-money options. Compared to the analytical solutions, FD12 is more accurate for at-the-money and out-of-the-money options, while DA12 is more accurate for in-the-money options. > > > > > > > > > > > > (3) FD18 vs FD12. Though it is relatively small, there is still a difference between FD18 and FD12, as shown in the following figure. > > > > > > > > > > > > So, my questions are: > > > > > > a. Do the difference between FD12 & DA12 and the difference between FD18 & FD12 described above behave as expected? > > > b. What’s the potential reasons for these differences? > > > > > > I know the answers to these questions could be very subtle, but we’d like to understand the reasons for these differences, at least to some extent. I also tried to dig into the C++ codes, but I am not familiar with the codes and I do not know where to start. If you could provide some explanations or point me the right directions, I would be super grateful. > > > > > > Thanks a lot. > > > > > > > > > Best Regards, > > > Shenze Wang > > > > > > DataDock Solutions > > > _______________________________________________ > > > QuantLib-users mailing list > > > Qua...@li... > > > https://lists.sourceforge.net/lists/listinfo/quantlib-users |
|
From: Peter C. <pca...@gm...> - 2020-06-16 19:53:16
|
Hi Matthias S, if you have n step dates the GSR model (in its most general form) has n+1 volatility and n+1 reversion parameters, i.e. 2n+2 free parameters in total. Alternatively you can use a time independent mean reversion which leaves you with n+2 free parameters. You can fix any subset of these parameters to values of your choice and calibrate the remaining parameters using the CalibratedModel::calibrate() function to an arbitrary set of CalibrationHelpers. The number of helpers that are required to run the optimisation depends on the optimiser you choose. The GSR model has some predefined convenience functions to fix certain parameters (FixedReversions(), FixedVolatilities(), MoveVolatility(), MoveReversion()), you can look at their implementation to see how to set up a general vector of booleans that fixes the parameter subset you want. There are also customised calibration functions (calibrateVolatilitiesIterative(), calibrateReversionsIterative()) which run several calibrations on subsets of parameters in sequence, which can be more efficient than calibrating all free parameters in one optimisation. The most usual use case (at least from my point of view) is to have a time independent, fixed mean reversion and a stepwise volatility function that is calibrated to a strip of swaptions or caps. If you post a concrete example you are trying to run and which causes problems, we can help you with that. Thanks Peter > On 16. Jun 2020, at 17:41, Matthias Siemering <mat...@gm...> wrote: > > Hello Matthias, > > Thank you for the pointer to Peter Caspers' blog. > Now ceased the attempts to calibrate mean reversion with Gsr. > > Have been looking at the GeneralizedHullWhite implementation, too. "Interesting" results when comparing to the regular one, but need further investigation before it potentially bears another question. > > > Regards, > > Matthias > > > On Sat, Jun 6, 2020 at 2:00 PM lungwitz <lun...@go... <mailto:lun...@go...>> wrote: > Hi Matthias, > > Peter Caspers has written a quite detailed description on his Blog on his GSR implementation that I have found very helpful: > > https://quantlib.wordpress.com/2015/03/29/gaussian-models/ <https://quantlib.wordpress.com/2015/03/29/gaussian-models/> > > For callable Bonds you can use a nonstandard swaption (including a rebate and a Credit Spread) as described there, through this does not capture the Credit Spread volatility related part of the option. > > Indeed the mean reversion has to be provided as an external input. > > Best regards > Matthias > > -------- Ursprüngliche Nachricht -------- > Von: mat...@gm... <mailto:mat...@gm...> > Datum: 06.06.20 12:36 (GMT+01:00) > An: qua...@li... <mailto:qua...@li...> > Betreff: [Quantlib-users] Gaussian short rate model + calibration > > Dear QL users, > > I cannot say I have great familiarity with short-rate or market models, so please bear with me on this one: > > Trying to value a multi-callable swaption and bond using a Hull-White model with (piecewise) time-dependent volatility. > As I understand, <ql/models/shortrate/onefactormodels/hullwhite.hpp> does not satisfy this condition: > > This class implements the standard single-factor Hull-White model defined by > \f[ > dr_t = (\theta(t) - \alpha r_t)dt + \sigma dW_t > \f] > where \f$ \alpha \f$ and \f$ \sigma \f$ are constants. > > I believe it was this ML's archive where I picked up Gsr as a recommended alternative and it looks fine (for some definition of "fine") for swaption pricing. > There are two questions, however: > > 1) It is apparently not possible to calibrate both volatilities and reversion(s). > > While Gsr implements CalibratedModel, performing "joint" calibration like this > > // vector<bool> fixedParms = gsr->FixedReversions(); > vector<Real> modelVols(voldates.size() + 1, 0.01); > fixedParms = vector<bool>(modelVols.size() + 1, false); > gsr->calibrate(calibSet, lm, ec, NoConstraint{}, vector<Real>{}, fixedParms); > > would not work, because only the first modelVols.size() number of calibration instruments are acknowledged, leaving the optimizer with an under-determined function. > > Likely there is a good reason for this. Market practice to have mean reversion as a given model parameter? Or that is just the way the model is supposed to work? > > 2) There is no pricing engine for callable bonds that can consume Gsr, if I am not mistaken. Gsr does not seem to implement ShortRateModel: > > Gsr <- {Gaussian1dModel, CalibratedModel, ...} <- {TermStructureConsistentModel, ...} > > Likely to do with the tree(const TimeGrid&) method in that interface. Alternatively, there is <ql/experimental/shortrate/generalizedhullwhite.hpp>. It sits in the "experimental" folder, but so does everything callable bond related. So I wonder whether the latter is more suitable for instrument/bond pricing while Gsr might be more model of choice for scenario generation purposes? > > > Again, apologies for any incorrect terminology or confusing remarks. Happy to clarify further, if necessary (and possible for me). > > > Thank you, > > Matthias > > > > > > _______________________________________________ > QuantLib-users mailing list > Qua...@li... <mailto:Qua...@li...> > https://lists.sourceforge.net/lists/listinfo/quantlib-users <https://lists.sourceforge.net/lists/listinfo/quantlib-users> > _______________________________________________ > QuantLib-users mailing list > Qua...@li... > https://lists.sourceforge.net/lists/listinfo/quantlib-users |
|
From: Matthias S. <mat...@gm...> - 2020-06-16 15:42:03
|
Hello Matthias, Thank you for the pointer to Peter Caspers' blog. Now ceased the attempts to calibrate mean reversion with Gsr. Have been looking at the GeneralizedHullWhite implementation, too. "Interesting" results when comparing to the regular one, but need further investigation before it potentially bears another question. Regards, Matthias On Sat, Jun 6, 2020 at 2:00 PM lungwitz <lun...@go...> wrote: > Hi Matthias, > > Peter Caspers has written a quite detailed description on his Blog on his > GSR implementation that I have found very helpful: > > https://quantlib.wordpress.com/2015/03/29/gaussian-models/ > > For callable Bonds you can use a nonstandard swaption (including a rebate > and a Credit Spread) as described there, through this does not capture the > Credit Spread volatility related part of the option. > > Indeed the mean reversion has to be provided as an external input. > > Best regards > Matthias > > -------- Ursprüngliche Nachricht -------- > Von: mat...@gm... > Datum: 06.06.20 12:36 (GMT+01:00) > An: qua...@li... > Betreff: [Quantlib-users] Gaussian short rate model + calibration > > Dear QL users, > > I cannot say I have great familiarity with short-rate or market models, so > please bear with me on this one: > > Trying to value a multi-callable swaption and bond using a Hull-White > model with (piecewise) time-dependent volatility. > As I understand, <ql/models/shortrate/onefactormodels/hullwhite.hpp> does > not satisfy this condition: > > This class implements the standard single-factor Hull-White model defined > by > \f[ > dr_t = (\theta(t) - \alpha r_t)dt + \sigma dW_t > \f] > where \f$ \alpha \f$ and \f$ \sigma \f$ are constants. > > I believe it was this ML's archive where I picked up Gsr as a recommended > alternative and it looks fine (for some definition of "fine") for swaption > pricing. > There are two questions, however: > > 1) It is apparently not possible to calibrate both volatilities and > reversion(s). > > While Gsr implements CalibratedModel, performing "joint" calibration like > this > > // vector<bool> fixedParms = gsr->FixedReversions(); > vector<Real> modelVols(voldates.size() + 1, 0.01); > fixedParms = vector<bool>(modelVols.size() + 1, false); > gsr->calibrate(calibSet, lm, ec, NoConstraint{}, vector<Real>{}, > fixedParms); > > would not work, because only the first modelVols.size() number of > calibration instruments are acknowledged, leaving the optimizer with an > under-determined function. > > Likely there is a good reason for this. Market practice to have mean > reversion as a given model parameter? Or that is just the way the model is > supposed to work? > > 2) There is no pricing engine for callable bonds that can consume Gsr, if > I am not mistaken. Gsr does not seem to implement ShortRateModel: > > Gsr <- {Gaussian1dModel, CalibratedModel, ...} <- > {TermStructureConsistentModel, ...} > > Likely to do with the tree(const TimeGrid&) method in that interface. > Alternatively, there is > <ql/experimental/shortrate/generalizedhullwhite.hpp>. It sits in the > "experimental" folder, but so does everything callable bond related. So I > wonder whether the latter is more suitable for instrument/bond pricing > while Gsr might be more model of choice for scenario generation purposes? > > > Again, apologies for any incorrect terminology or confusing remarks. Happy > to clarify further, if necessary (and possible for me). > > > Thank you, > > Matthias > > > > > > _______________________________________________ > QuantLib-users mailing list > Qua...@li... > https://lists.sourceforge.net/lists/listinfo/quantlib-users > |
|
From: Luigi B. <lui...@gm...> - 2020-06-16 08:51:09
|
Hello,
thanks for the analysis.
There are people here which are more capable of answering than I am, but
just to make sure that we're comparing equals to
equals: FdBlackScholesVanillaEngine has two possible ways to handle
dividends, and we should document this better. One is the scale/shift
model, and the other is the escrowed dividend model; you can choose the
model by mans of an optional last parameter for the constructor (see <
https://github.com/lballabio/QuantLib-SWIG/blob/master/SWIG/options.i#L1202
>).
Now, FDDividendAmericanEngine uses the escrowed dividend model, which I'm
told is the one described in most texts.
Instead, FdBlackScholesVanillaEngine uses by default the scale/shift
model. If you didn't set the model explicitly, this might be the reason
for the differences. Passing Escrowed as the model would cause the results
to be closer.
If you did that already, though, we'll have to look closer into the code.
Hope this helps,
Luigi
On Mon, Jun 15, 2020 at 10:01 PM Shenze Wang <
she...@da...> wrote:
> Hi,
>
> We are currently using `FD*D*ividend*A*mericanEngine` (denoted by *DA* in
> following) of QuantLib 1.12. Since this engine is removed in QuantLib 1.16,
> we’d like to switch to `*Fd*BlackScholesVanillaEngine` (denoted by *FD *in
> following) of QuantLib 1.18. Before we do the switch, we’d like to know the
> difference between these two engines (DA engine in QuantLib 1.12 and FD
> engine in QuantLib 1.18) and what are the impacts on the pricing results.
> We are using the Python version of QuantLib.
>
> I priced ~7000 options with different ivols, strikes, interest rates,
> dividend yields with 3 engines: (a) *DA12* - `FDDividendAmericanEngine`
> in QuantLib 1.12, (b) *FD12* - `FdBlackScholesVanillaEngine` in QuantLib
> 1.12, and (c) *FD18* - `FdBlackScholesVanillaEngine` in QuantLib 1.18.
>
> Here are some comparisons of the results.
>
> *(1)* The difference between FD18 and DA12 including two parts: the
> difference between FD12 & DA12, and the difference between FD18 & FD12. The
> difference between FD12 & DA12 is much greater than the difference between
> FD18 & FD12, as shown in the following form. The form shows CDF of the
> differences. The numbers in the form are the probability that the
> difference is in a certain range.
>
>
> *(2)* *FD12 vs DA12*. The option prices generated by FD12 is greater than
> DA12 for in-the-money options, but lower for at-the-money and
> out-of-the-money options. Compared to the analytical solutions, FD12 is
> more accurate for at-the-money and out-of-the-money options, while DA12 is
> more accurate for in-the-money options.
>
>
>
> *(3)* *FD18 vs FD12. *Though it is relatively small, there is still a
> difference between FD18 and FD12, as shown in the following figure.
>
>
>
> So, my questions are:
>
> 1. Do the difference between FD12 & DA12 and the difference between
> FD18 & FD12 described above behave as expected?
> 2. What’s the potential reasons for these differences?
>
> I know the answers to these questions could be very subtle, but we’d like
> to understand the reasons for these differences, at least to some extent. I
> also tried to dig into the C++ codes, but I am not familiar with the codes
> and I do not know where to start. If you could provide some explanations or
> point me the right directions, I would be super grateful.
>
> Thanks a lot.
>
>
> Best Regards,
> Shenze Wang
>
> DataDock Solutions
> _______________________________________________
> QuantLib-users mailing list
> Qua...@li...
> https://lists.sourceforge.net/lists/listinfo/quantlib-users
>
|
|
From: Shenze W. <she...@da...> - 2020-06-15 19:58:40
|
Hi, We are currently using `FD*D*ividend*A*mericanEngine` (denoted by *DA* in following) of QuantLib 1.12. Since this engine is removed in QuantLib 1.16, we’d like to switch to `*Fd*BlackScholesVanillaEngine` (denoted by *FD *in following) of QuantLib 1.18. Before we do the switch, we’d like to know the difference between these two engines (DA engine in QuantLib 1.12 and FD engine in QuantLib 1.18) and what are the impacts on the pricing results. We are using the Python version of QuantLib. I priced ~7000 options with different ivols, strikes, interest rates, dividend yields with 3 engines: (a) *DA12* - `FDDividendAmericanEngine` in QuantLib 1.12, (b) *FD12* - `FdBlackScholesVanillaEngine` in QuantLib 1.12, and (c) *FD18* - `FdBlackScholesVanillaEngine` in QuantLib 1.18. Here are some comparisons of the results. *(1)* The difference between FD18 and DA12 including two parts: the difference between FD12 & DA12, and the difference between FD18 & FD12. The difference between FD12 & DA12 is much greater than the difference between FD18 & FD12, as shown in the following form. The form shows CDF of the differences. The numbers in the form are the probability that the difference is in a certain range. *(2)* *FD12 vs DA12*. The option prices generated by FD12 is greater than DA12 for in-the-money options, but lower for at-the-money and out-of-the-money options. Compared to the analytical solutions, FD12 is more accurate for at-the-money and out-of-the-money options, while DA12 is more accurate for in-the-money options. *(3)* *FD18 vs FD12. *Though it is relatively small, there is still a difference between FD18 and FD12, as shown in the following figure. So, my questions are: 1. Do the difference between FD12 & DA12 and the difference between FD18 & FD12 described above behave as expected? 2. What’s the potential reasons for these differences? I know the answers to these questions could be very subtle, but we’d like to understand the reasons for these differences, at least to some extent. I also tried to dig into the C++ codes, but I am not familiar with the codes and I do not know where to start. If you could provide some explanations or point me the right directions, I would be super grateful. Thanks a lot. Best Regards, Shenze Wang DataDock Solutions |
|
From: Christofer B. <bog...@gm...> - 2020-06-14 08:38:04
|
Hi, I have a related question (operational perspective) how to implement this code, given that I use Quantlib with Python/R I am not strong C++ guru, but want to focus on valuation/pricing using this amazing library, so some step-by-step approach would be highly appreciated. Many thanks, On Sun, Jun 14, 2020 at 1:56 PM Peter Caspers <pca...@gm...> wrote: > > Hi Luis, > > I think the OvernightIndexFutureRateHelper (or the SofrFutureRateHelper) defined here > > https://github.com/lballabio/QuantLib/blob/master/ql/experimental/futures/overnightindexfutureratehelper.hpp > > is what you are looking for. > > Best Regards > Peter > > On 14. Jun 2020, at 09:55, Luís Miguel Aguiar <lui...@gm...> wrote: > > Hello, > > By mistake did a reply to a different topic on an update sent by Luigi. > > I have been looking if it is possible to apply the futures_rate_helper class to 1m fed funds futures. All the examples I see online only use 3m instruments, and also as part of the inputs is the index, such as IMM, it only accepts IIM dates (which are quarterly). > > Is it possible or do I need to use a different class? > > Kind regards, > Luis Aguiar > _______________________________________________ > QuantLib-users mailing list > Qua...@li... > https://lists.sourceforge.net/lists/listinfo/quantlib-users > > > _______________________________________________ > QuantLib-users mailing list > Qua...@li... > https://lists.sourceforge.net/lists/listinfo/quantlib-users |
|
From: Peter C. <pca...@gm...> - 2020-06-14 08:25:09
|
Hi Luis, I think the OvernightIndexFutureRateHelper (or the SofrFutureRateHelper) defined here https://github.com/lballabio/QuantLib/blob/master/ql/experimental/futures/overnightindexfutureratehelper.hpp <https://github.com/lballabio/QuantLib/blob/master/ql/experimental/futures/overnightindexfutureratehelper.hpp> is what you are looking for. Best Regards Peter > On 14. Jun 2020, at 09:55, Luís Miguel Aguiar <lui...@gm...> wrote: > > Hello, > > By mistake did a reply to a different topic on an update sent by Luigi. > > I have been looking if it is possible to apply the futures_rate_helper class to 1m fed funds futures. All the examples I see online only use 3m instruments, and also as part of the inputs is the index, such as IMM, it only accepts IIM dates (which are quarterly). > > Is it possible or do I need to use a different class? > > Kind regards, > Luis Aguiar > _______________________________________________ > QuantLib-users mailing list > Qua...@li... > https://lists.sourceforge.net/lists/listinfo/quantlib-users |
|
From: Luís M. A. <lui...@gm...> - 2020-06-14 07:55:53
|
Hello, By mistake did a reply to a different topic on an update sent by Luigi. I have been looking if it is possible to apply the futures_rate_helper class to 1m fed funds futures. All the examples I see online only use 3m instruments, and also as part of the inputs is the index, such as IMM, it only accepts IIM dates (which are quarterly). Is it possible or do I need to use a different class? Kind regards, Luis Aguiar |
|
From: Luís M. A. <lui...@gm...> - 2020-06-14 07:51:55
|
Hello, I have been looking if it is possible to apply the futures_rate_helper class to 1m fed funds futures. All the examples I see online only use 3m instruments, and also as part of the inputs is the index, such as IMM, it only accepts IIM dates (which are quarterly). Is it possible or do I need to use a different class? Kind regards, Luis Aguiar On Thu, 11 Jun 2020, 09:25 Luigi Ballabio, <lui...@gm...> wrote: > Hi all, > QuantLib-SWIG 1.18.1 was released today. Its source code is > identical to version 1.18, but the wrapper code for this version was > generated with the newly-released SWIG 4.0.2, which (among other things) > avoids a memory leak in the Python wrappers when using vectors of > shared_ptr. The new Python wrappers are available via "pip install". > > Luigi > > _______________________________________________ > QuantLib-users mailing list > Qua...@li... > https://lists.sourceforge.net/lists/listinfo/quantlib-users > |
|
From: Tom A. <tw...@ur...> - 2020-06-11 18:13:34
|
Hello again, I'm back with what is probably a stupid question. I'm building a 6-month Euribor curve using FRAs. The curve comes out looking rather hair-raising. I suspect that this is because the market data isn't great - there are probably some illiquid points that aren't really consistent with the rest. The overlapping nature of FRAs will tend to turn such inconsistencies into substantial deformities. However, i would like to confirm that i have not made a daft mistake using the FRA helpers, or in some other aspect of curve construction, before i make that conclusion. Here's a minimal, self-contained example showing my approach: https://gist.github.com/tomwhoiscontrary/bc5489ce05e9b64631dd5912871f717b Here's a plot of the output: https://imgur.com/a/NhAAmH6 Now, maybe that's what the front of the curve really looks like, and it's more exciting than i thought. But if not, any thoughts on what i have done wrong? Many thanks, tom -- Transform your language. |
|
From: Luigi B. <lui...@gm...> - 2020-06-11 08:24:08
|
Hi all,
QuantLib-SWIG 1.18.1 was released today. Its source code is identical
to version 1.18, but the wrapper code for this version was generated with
the newly-released SWIG 4.0.2, which (among other things) avoids a memory
leak in the Python wrappers when using vectors of shared_ptr. The new
Python wrappers are available via "pip install".
Luigi
|
|
From: Aleksis A. R. <ale...@go...> - 2020-06-10 13:03:00
|
Understood.
Indeed, for the swaption case the jags can be removed when the rate delta calculation is adjusted by a -vega*(dvol/dr) term.
Thanks very much for your help.
> On 9 Jun 2020, at 16:33, Peter Caspers <pca...@gm...> wrote:
>
> I think they use linear interpolation as well. But they have fixed strikes, i.e. imply a sticky strike dynamics, which means the vol does not change when the ATM level changes.
>
>> On 9. Jun 2020, at 13:38, Aleksis Ali Raza <ale...@go... <mailto:ale...@go...>> wrote:
>>
>> Thanks Peter - that makes sense: the linear interpolation in strike direction explains it. Btw, this isn’t the case for capfloor vol surfaces so i assume they’re using a different interpolation in strike.
>>
>>> On 9 Jun 2020, at 12:01, Peter Caspers <pca...@gm... <mailto:pca...@gm...>> wrote:
>>>
>>> Hi Aleksis, I am just guessing, but from SwaptionVolCube2 you get “sticky moneyness” deltas: If you shift the rates input, the ATM levels in the cube will change. Since the volatilities are set up relative to these ATM levels, the volatility for a given fixed strike (the one from the trade you price) changes under the rate shift as well. Since SwaptionVolCube2 uses a linear interpolation in strike direction, this might cause issues in particular at the points where the vol(strike) - function is non-differentiable.
>>> Best Regards, Peter
>>>
>>>> On 08 Jun 2020, at 21:22, Aleksis Ali Raza <ale...@go... <mailto:ale...@go...>> wrote:
>>>>
>>>> Hi Peter. That’s correct - the delta (and vega,gamma, etc) all smoothen out to normal when I zero out the skew in the volcube.
>>>>
>>>> Btw, the jags are still present when using ’Naive’ mode in the GSR calibration.
>>>>
>>>> Moreover, what’s more relevant is that they are also present even when just using a simple BachelierSwaptionEngine for the vanilla swaption case so I don’t think it’s model related.
>>>>
>>>> FYI, I’m using normal vols throughout (with skew definition essentially a simple +5 normal vols for each 25bp otm - both for payers and recs)
>>>>
>>>> In any case, to answer your question reg gsr calibration, I think I'm doing both (a) and (b) - essentially I’ve added a modified NPV attribute to the below-mentioned swaption class. So it’s a simple 'bump up,calc NPV,bump down, calc NPV, take difference’ using this NPV attribute. Maybe i’m missing one of the steps (a) or (b) in this code?
>>>>
>>>> def NPV(self):
>>>> engine = ql.Gaussian1dSwaptionEngine(self.model, 64, 7.0, True, False, self.discount_curve)
>>>> basket = self.nsswaption.calibrationBasket(self.swapbase, self.swvolcube, 'MaturityStrikeByDeltaGamma')
>>>> for basket_i in basket:
>>>> ql.as_black_helper(basket_i).setPricingEngine(engine)
>>>> method = ql.LevenbergMarquardt()
>>>> ec = ql.EndCriteria(1000, 10, 1e-8, 1e-8, 1e-8)
>>>> self.model.calibrateVolatilitiesIterative(basket, method, ec)
>>>> npv = self.nsswaption.NPV()*self.position
>>>> return npv
>>>>
>>>>
>>>>
>>>>> On Jun 8, 2020, at 7:21 PM, Peter Caspers <pca...@gm... <mailto:pca...@gm...>> wrote:
>>>>>
>>>>> Hi Aleksis,
>>>>>
>>>>> do you get the jags only when using a smile, i.e. does the delta get smoother when you use an ATM matrix only?
>>>>>
>>>>> Another question I have is a) whether you recalibrate the GSR model after each bump and b) whether you recalculate the calibration basket after each bump as well?
>>>>>
>>>>> Thanks
>>>>> Peter
>>>>>
>>>>>> On 08 Jun 2020, at 17:31, Aleksis Ali Raza via QuantLib-users <qua...@li... <mailto:qua...@li...>> wrote:
>>>>>>
>>>>>> Sure, essentially it’s run off this class:
>>>>>>
>>>>>> class bermudanswaption():
>>>>>>
>>>>>> def __init__(self, calendar,settlement, used_model, swap, ratecurves, index, swvolcube_clean, swapbase,
>>>>>> mean_reversion,position):
>>>>>>
>>>>>> discount_curve = ratecurves.loc['discountcurve', 'ratecurves']
>>>>>> self.swvolcube = swvolcube_clean
>>>>>> self.swapbase = swapbase
>>>>>> self.used_model = used_model
>>>>>> self.discount_curve = discount_curve
>>>>>> self.position=position
>>>>>>
>>>>>> fixed_schedule=swap.fixedSchedule()
>>>>>> exerciseDates = [calendar.advance(i, -ql.Period('2D')) for i in fixed_schedule][1:-1]
>>>>>> exercise = ql.BermudanExercise(exerciseDates)
>>>>>> stepDates = exerciseDates
>>>>>> self.exerciseDates=exerciseDates
>>>>>> sigmas = [ql.QuoteHandle(ql.SimpleQuote(0.01))]*(1+len(exerciseDates))
>>>>>> self.used_model = used_model
>>>>>>
>>>>>> if settlement == 'physical':
>>>>>> type = 0
>>>>>> method = 1
>>>>>> else:
>>>>>> type = 1
>>>>>> method = 3
>>>>>>
>>>>>> self.nsswaption = ql.NonstandardSwaption(swap, exercise, type, method)
>>>>>> gsr = ql.Gsr(ratecurves.loc[index, 'ratecurves'],
>>>>>> stepDates, sigmas, [ql.QuoteHandle(ql.SimpleQuote(mean_reversion))])
>>>>>> engine = ql.Gaussian1dNonstandardSwaptionEngine(gsr, 64, 7.0, True, False,
>>>>>> ql.QuoteHandle(ql.SimpleQuote(0)),
>>>>>> discount_curve, 2)
>>>>>> self.engine = ql.Gaussian1dSwaptionEngine(gsr, 64, 7.0, True, False, discount_curve)
>>>>>> self.nsswaption.setPricingEngine(engine)
>>>>>> self.model = gsr
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>> On 8 Jun 2020, at 15:50, Christofer Bogaso <bog...@gm... <mailto:bog...@gm...>> wrote:
>>>>>>>
>>>>>>> Hi, could you please share your python code? Thanks,
>>>>>>>
>>>>>>> On Mon, Jun 8, 2020 at 8:00 PM Aleksis Ali Raza via QuantLib-users <qua...@li... <mailto:qua...@li...>> wrote:
>>>>>>> Hi. In case anyone has an explanation: I get a jagged behaviour in a my greeks when I define a (what is to my knowledge sensible) swaption smile using swaptionvolcube2.
>>>>>>>
>>>>>>> The greeks are being calculated by source bumping (using a 1bp shift for the rate delta, shown below along with the NPV). The behaviour isn’t too sensitive to the bump size.
>>>>>>>
>>>>>>> Portfolio 1 consists of a 1y4y otm payer swaption and Portfolio 2 of a same strike 5y otm bermudan swaption with annual calls (both valued using the Hull-White GSR model calibrated to the swaption vol cube with MaturityStrikeByDeltaGamma mode).
>>>>>>>
>>>>>>> The code is in Python.
>>>>>>>
>>>>>>> Thanks, Aleksis
>>>>>>>
>>>>>>>
>>>>>>> <optionanalysis_rate.png>
>>>>>>> _______________________________________________
>>>>>>> QuantLib-users mailing list
>>>>>>> Qua...@li... <mailto:Qua...@li...>
>>>>>>> https://lists.sourceforge.net/lists/listinfo/quantlib-users <https://lists.sourceforge.net/lists/listinfo/quantlib-users>
>>>>>>
>>>>>> _______________________________________________
>>>>>> QuantLib-users mailing list
>>>>>> Qua...@li... <mailto:Qua...@li...>
>>>>>> https://lists.sourceforge.net/lists/listinfo/quantlib-users <https://lists.sourceforge.net/lists/listinfo/quantlib-users>
>>>>>
>>>>
>>>
>>
>
|
|
From: Luigi B. <lui...@gm...> - 2020-06-09 16:11:35
|
Hello Frederick,
unfortunately the optimizer can impose constraints on the parameters,
not the fitted quotes. I would do as you already did, that is, modify
FittingCost::values() to add a penalty when the quotes are outside the
range. I'm not sure why that would give you a worse curve, but optimizers
are hard to reason about. If I had to guess, it might be that the
unconstrained optimization goes through the forbidden range before going to
the minimum, and by adding a penalty you're blocking that path. But you
would need to print out the values during optimization to be sure of what's
happening.
Sorry this wasn't a lot of help,
Luigi
On Fri, May 15, 2020 at 2:25 PM Frederick Delaroche <
fre...@ri...> wrote:
> Hi all,
>
>
>
> I am using FittingBondDiscountCurve, Svensson fitting method. Fitting is
> working nicely; however, I wanted to add a specific control over change in
> quotes (i.e. no constraint on Svensson parameters) to keep the fitted quote
> within a given range (e.g. a bid / ask).
>
>
>
> - *Is there any way to do this with QuantLib?*
>
>
>
> I have tried a basic solution (modifying the FittingCost::values function
> by changing the error when error itself was above (or below) a given
> value), but it doesn’t work as expected: depending on the limit, I don’t
> find the optimal values for the fitted quotes.
>
>
>
> “Not find the optimal values” means:
>
> - If I don’t have any limit for quotes move, I have a set of fitted
> quotes. If I check the max error compared to orginal quotes and if I set
> this move as the limit, I will find a different set of fitted quotes which
> give a “worse” discount curve.
>
>
>
> Thanks for your help.
>
>
>
> Rgds,
>
> -
>
> _______________________________________________
> QuantLib-users mailing list
> Qua...@li...
> https://lists.sourceforge.net/lists/listinfo/quantlib-users
>
|
|
From: Luigi B. <lui...@gm...> - 2020-06-09 16:01:48
|
Switching off notifyObservers() would prevent the instruments from recalculating, so I guess that would affect the simulation. How are you setting up the simulation? Do you create the instruments and then relink the handle for each scenario? Or do you create new instruments for different scenarios? Luigi On Fri, Jun 5, 2020 at 6:12 PM Amine Ifri <ami...@gm...> wrote: > Hi Luigi, all, > > I have been working on leveraging QL to create a small multi-step Monte > Carlo framework which simulates market data at each future time step and > calls discounting swap engine on vanilla swaps. A full Monte Carlo run > with 1000 scenarios and 350 time points takes about 4min to run. I run my > application through the time profiler and noticed that quite a bit of time > is spent in the scenario loop where I continuously relink the yield curve > handle to the appropriately simulated curve. > > Are there any ways/tips one could provide on where I could look for extra > time savings? I found out that by using the discount(Time ) instead of the > discount(Date&) variant of the method for example, one can save on the year > fraction calculation, which improves the time a bit. I also de-activated a > check on MaxTime() in TermStructure::checkRange() which is continuously > called at each scenario. > > In particular, I would like to know if I could switch off the notify > observers() in the Handle::linkTo() method without affecting the inner > workings, as I am not interested at this stage in using the > observable/observer pattern. > > Thanks and Regards, > Amine |
|
From: Peter C. <pca...@gm...> - 2020-06-09 15:33:52
|
I think they use linear interpolation as well. But they have fixed strikes, i.e. imply a sticky strike dynamics, which means the vol does not change when the ATM level changes.
> On 9. Jun 2020, at 13:38, Aleksis Ali Raza <ale...@go...> wrote:
>
> Thanks Peter - that makes sense: the linear interpolation in strike direction explains it. Btw, this isn’t the case for capfloor vol surfaces so i assume they’re using a different interpolation in strike.
>
>> On 9 Jun 2020, at 12:01, Peter Caspers <pca...@gm... <mailto:pca...@gm...>> wrote:
>>
>> Hi Aleksis, I am just guessing, but from SwaptionVolCube2 you get “sticky moneyness” deltas: If you shift the rates input, the ATM levels in the cube will change. Since the volatilities are set up relative to these ATM levels, the volatility for a given fixed strike (the one from the trade you price) changes under the rate shift as well. Since SwaptionVolCube2 uses a linear interpolation in strike direction, this might cause issues in particular at the points where the vol(strike) - function is non-differentiable.
>> Best Regards, Peter
>>
>>> On 08 Jun 2020, at 21:22, Aleksis Ali Raza <ale...@go... <mailto:ale...@go...>> wrote:
>>>
>>> Hi Peter. That’s correct - the delta (and vega,gamma, etc) all smoothen out to normal when I zero out the skew in the volcube.
>>>
>>> Btw, the jags are still present when using ’Naive’ mode in the GSR calibration.
>>>
>>> Moreover, what’s more relevant is that they are also present even when just using a simple BachelierSwaptionEngine for the vanilla swaption case so I don’t think it’s model related.
>>>
>>> FYI, I’m using normal vols throughout (with skew definition essentially a simple +5 normal vols for each 25bp otm - both for payers and recs)
>>>
>>> In any case, to answer your question reg gsr calibration, I think I'm doing both (a) and (b) - essentially I’ve added a modified NPV attribute to the below-mentioned swaption class. So it’s a simple 'bump up,calc NPV,bump down, calc NPV, take difference’ using this NPV attribute. Maybe i’m missing one of the steps (a) or (b) in this code?
>>>
>>> def NPV(self):
>>> engine = ql.Gaussian1dSwaptionEngine(self.model, 64, 7.0, True, False, self.discount_curve)
>>> basket = self.nsswaption.calibrationBasket(self.swapbase, self.swvolcube, 'MaturityStrikeByDeltaGamma')
>>> for basket_i in basket:
>>> ql.as_black_helper(basket_i).setPricingEngine(engine)
>>> method = ql.LevenbergMarquardt()
>>> ec = ql.EndCriteria(1000, 10, 1e-8, 1e-8, 1e-8)
>>> self.model.calibrateVolatilitiesIterative(basket, method, ec)
>>> npv = self.nsswaption.NPV()*self.position
>>> return npv
>>>
>>>
>>>
>>>> On Jun 8, 2020, at 7:21 PM, Peter Caspers <pca...@gm... <mailto:pca...@gm...>> wrote:
>>>>
>>>> Hi Aleksis,
>>>>
>>>> do you get the jags only when using a smile, i.e. does the delta get smoother when you use an ATM matrix only?
>>>>
>>>> Another question I have is a) whether you recalibrate the GSR model after each bump and b) whether you recalculate the calibration basket after each bump as well?
>>>>
>>>> Thanks
>>>> Peter
>>>>
>>>>> On 08 Jun 2020, at 17:31, Aleksis Ali Raza via QuantLib-users <qua...@li... <mailto:qua...@li...>> wrote:
>>>>>
>>>>> Sure, essentially it’s run off this class:
>>>>>
>>>>> class bermudanswaption():
>>>>>
>>>>> def __init__(self, calendar,settlement, used_model, swap, ratecurves, index, swvolcube_clean, swapbase,
>>>>> mean_reversion,position):
>>>>>
>>>>> discount_curve = ratecurves.loc['discountcurve', 'ratecurves']
>>>>> self.swvolcube = swvolcube_clean
>>>>> self.swapbase = swapbase
>>>>> self.used_model = used_model
>>>>> self.discount_curve = discount_curve
>>>>> self.position=position
>>>>>
>>>>> fixed_schedule=swap.fixedSchedule()
>>>>> exerciseDates = [calendar.advance(i, -ql.Period('2D')) for i in fixed_schedule][1:-1]
>>>>> exercise = ql.BermudanExercise(exerciseDates)
>>>>> stepDates = exerciseDates
>>>>> self.exerciseDates=exerciseDates
>>>>> sigmas = [ql.QuoteHandle(ql.SimpleQuote(0.01))]*(1+len(exerciseDates))
>>>>> self.used_model = used_model
>>>>>
>>>>> if settlement == 'physical':
>>>>> type = 0
>>>>> method = 1
>>>>> else:
>>>>> type = 1
>>>>> method = 3
>>>>>
>>>>> self.nsswaption = ql.NonstandardSwaption(swap, exercise, type, method)
>>>>> gsr = ql.Gsr(ratecurves.loc[index, 'ratecurves'],
>>>>> stepDates, sigmas, [ql.QuoteHandle(ql.SimpleQuote(mean_reversion))])
>>>>> engine = ql.Gaussian1dNonstandardSwaptionEngine(gsr, 64, 7.0, True, False,
>>>>> ql.QuoteHandle(ql.SimpleQuote(0)),
>>>>> discount_curve, 2)
>>>>> self.engine = ql.Gaussian1dSwaptionEngine(gsr, 64, 7.0, True, False, discount_curve)
>>>>> self.nsswaption.setPricingEngine(engine)
>>>>> self.model = gsr
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> On 8 Jun 2020, at 15:50, Christofer Bogaso <bog...@gm... <mailto:bog...@gm...>> wrote:
>>>>>>
>>>>>> Hi, could you please share your python code? Thanks,
>>>>>>
>>>>>> On Mon, Jun 8, 2020 at 8:00 PM Aleksis Ali Raza via QuantLib-users <qua...@li... <mailto:qua...@li...>> wrote:
>>>>>> Hi. In case anyone has an explanation: I get a jagged behaviour in a my greeks when I define a (what is to my knowledge sensible) swaption smile using swaptionvolcube2.
>>>>>>
>>>>>> The greeks are being calculated by source bumping (using a 1bp shift for the rate delta, shown below along with the NPV). The behaviour isn’t too sensitive to the bump size.
>>>>>>
>>>>>> Portfolio 1 consists of a 1y4y otm payer swaption and Portfolio 2 of a same strike 5y otm bermudan swaption with annual calls (both valued using the Hull-White GSR model calibrated to the swaption vol cube with MaturityStrikeByDeltaGamma mode).
>>>>>>
>>>>>> The code is in Python.
>>>>>>
>>>>>> Thanks, Aleksis
>>>>>>
>>>>>>
>>>>>> <optionanalysis_rate.png>
>>>>>> _______________________________________________
>>>>>> QuantLib-users mailing list
>>>>>> Qua...@li... <mailto:Qua...@li...>
>>>>>> https://lists.sourceforge.net/lists/listinfo/quantlib-users <https://lists.sourceforge.net/lists/listinfo/quantlib-users>
>>>>>
>>>>> _______________________________________________
>>>>> QuantLib-users mailing list
>>>>> Qua...@li... <mailto:Qua...@li...>
>>>>> https://lists.sourceforge.net/lists/listinfo/quantlib-users <https://lists.sourceforge.net/lists/listinfo/quantlib-users>
>>>>
>>>
>>
>
|
|
From: Aleksis A. R. <ale...@go...> - 2020-06-09 11:38:30
|
Thanks Peter - that makes sense: the linear interpolation in strike direction explains it. Btw, this isn’t the case for capfloor vol surfaces so i assume they’re using a different interpolation in strike.
> On 9 Jun 2020, at 12:01, Peter Caspers <pca...@gm...> wrote:
>
> Hi Aleksis, I am just guessing, but from SwaptionVolCube2 you get “sticky moneyness” deltas: If you shift the rates input, the ATM levels in the cube will change. Since the volatilities are set up relative to these ATM levels, the volatility for a given fixed strike (the one from the trade you price) changes under the rate shift as well. Since SwaptionVolCube2 uses a linear interpolation in strike direction, this might cause issues in particular at the points where the vol(strike) - function is non-differentiable.
> Best Regards, Peter
>
>> On 08 Jun 2020, at 21:22, Aleksis Ali Raza <ale...@go... <mailto:ale...@go...>> wrote:
>>
>> Hi Peter. That’s correct - the delta (and vega,gamma, etc) all smoothen out to normal when I zero out the skew in the volcube.
>>
>> Btw, the jags are still present when using ’Naive’ mode in the GSR calibration.
>>
>> Moreover, what’s more relevant is that they are also present even when just using a simple BachelierSwaptionEngine for the vanilla swaption case so I don’t think it’s model related.
>>
>> FYI, I’m using normal vols throughout (with skew definition essentially a simple +5 normal vols for each 25bp otm - both for payers and recs)
>>
>> In any case, to answer your question reg gsr calibration, I think I'm doing both (a) and (b) - essentially I’ve added a modified NPV attribute to the below-mentioned swaption class. So it’s a simple 'bump up,calc NPV,bump down, calc NPV, take difference’ using this NPV attribute. Maybe i’m missing one of the steps (a) or (b) in this code?
>>
>> def NPV(self):
>> engine = ql.Gaussian1dSwaptionEngine(self.model, 64, 7.0, True, False, self.discount_curve)
>> basket = self.nsswaption.calibrationBasket(self.swapbase, self.swvolcube, 'MaturityStrikeByDeltaGamma')
>> for basket_i in basket:
>> ql.as_black_helper(basket_i).setPricingEngine(engine)
>> method = ql.LevenbergMarquardt()
>> ec = ql.EndCriteria(1000, 10, 1e-8, 1e-8, 1e-8)
>> self.model.calibrateVolatilitiesIterative(basket, method, ec)
>> npv = self.nsswaption.NPV()*self.position
>> return npv
>>
>>
>>
>>> On Jun 8, 2020, at 7:21 PM, Peter Caspers <pca...@gm... <mailto:pca...@gm...>> wrote:
>>>
>>> Hi Aleksis,
>>>
>>> do you get the jags only when using a smile, i.e. does the delta get smoother when you use an ATM matrix only?
>>>
>>> Another question I have is a) whether you recalibrate the GSR model after each bump and b) whether you recalculate the calibration basket after each bump as well?
>>>
>>> Thanks
>>> Peter
>>>
>>>> On 08 Jun 2020, at 17:31, Aleksis Ali Raza via QuantLib-users <qua...@li... <mailto:qua...@li...>> wrote:
>>>>
>>>> Sure, essentially it’s run off this class:
>>>>
>>>> class bermudanswaption():
>>>>
>>>> def __init__(self, calendar,settlement, used_model, swap, ratecurves, index, swvolcube_clean, swapbase,
>>>> mean_reversion,position):
>>>>
>>>> discount_curve = ratecurves.loc['discountcurve', 'ratecurves']
>>>> self.swvolcube = swvolcube_clean
>>>> self.swapbase = swapbase
>>>> self.used_model = used_model
>>>> self.discount_curve = discount_curve
>>>> self.position=position
>>>>
>>>> fixed_schedule=swap.fixedSchedule()
>>>> exerciseDates = [calendar.advance(i, -ql.Period('2D')) for i in fixed_schedule][1:-1]
>>>> exercise = ql.BermudanExercise(exerciseDates)
>>>> stepDates = exerciseDates
>>>> self.exerciseDates=exerciseDates
>>>> sigmas = [ql.QuoteHandle(ql.SimpleQuote(0.01))]*(1+len(exerciseDates))
>>>> self.used_model = used_model
>>>>
>>>> if settlement == 'physical':
>>>> type = 0
>>>> method = 1
>>>> else:
>>>> type = 1
>>>> method = 3
>>>>
>>>> self.nsswaption = ql.NonstandardSwaption(swap, exercise, type, method)
>>>> gsr = ql.Gsr(ratecurves.loc[index, 'ratecurves'],
>>>> stepDates, sigmas, [ql.QuoteHandle(ql.SimpleQuote(mean_reversion))])
>>>> engine = ql.Gaussian1dNonstandardSwaptionEngine(gsr, 64, 7.0, True, False,
>>>> ql.QuoteHandle(ql.SimpleQuote(0)),
>>>> discount_curve, 2)
>>>> self.engine = ql.Gaussian1dSwaptionEngine(gsr, 64, 7.0, True, False, discount_curve)
>>>> self.nsswaption.setPricingEngine(engine)
>>>> self.model = gsr
>>>>
>>>>
>>>>
>>>>
>>>>> On 8 Jun 2020, at 15:50, Christofer Bogaso <bog...@gm... <mailto:bog...@gm...>> wrote:
>>>>>
>>>>> Hi, could you please share your python code? Thanks,
>>>>>
>>>>> On Mon, Jun 8, 2020 at 8:00 PM Aleksis Ali Raza via QuantLib-users <qua...@li... <mailto:qua...@li...>> wrote:
>>>>> Hi. In case anyone has an explanation: I get a jagged behaviour in a my greeks when I define a (what is to my knowledge sensible) swaption smile using swaptionvolcube2.
>>>>>
>>>>> The greeks are being calculated by source bumping (using a 1bp shift for the rate delta, shown below along with the NPV). The behaviour isn’t too sensitive to the bump size.
>>>>>
>>>>> Portfolio 1 consists of a 1y4y otm payer swaption and Portfolio 2 of a same strike 5y otm bermudan swaption with annual calls (both valued using the Hull-White GSR model calibrated to the swaption vol cube with MaturityStrikeByDeltaGamma mode).
>>>>>
>>>>> The code is in Python.
>>>>>
>>>>> Thanks, Aleksis
>>>>>
>>>>>
>>>>> <optionanalysis_rate.png>
>>>>> _______________________________________________
>>>>> QuantLib-users mailing list
>>>>> Qua...@li... <mailto:Qua...@li...>
>>>>> https://lists.sourceforge.net/lists/listinfo/quantlib-users <https://lists.sourceforge.net/lists/listinfo/quantlib-users>
>>>>
>>>> _______________________________________________
>>>> QuantLib-users mailing list
>>>> Qua...@li... <mailto:Qua...@li...>
>>>> https://lists.sourceforge.net/lists/listinfo/quantlib-users <https://lists.sourceforge.net/lists/listinfo/quantlib-users>
>>>
>>
>
|