You can subscribe to this list here.
| 2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(17) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2001 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(23) |
| 2002 |
Jan
(18) |
Feb
(20) |
Mar
(22) |
Apr
(41) |
May
(28) |
Jun
(25) |
Jul
(10) |
Aug
(7) |
Sep
(5) |
Oct
(20) |
Nov
(13) |
Dec
(11) |
| 2003 |
Jan
(28) |
Feb
(5) |
Mar
(6) |
Apr
(5) |
May
(17) |
Jun
(6) |
Jul
(45) |
Aug
(35) |
Sep
(24) |
Oct
(50) |
Nov
(53) |
Dec
(6) |
| 2004 |
Jan
(4) |
Feb
(10) |
Mar
(52) |
Apr
(46) |
May
(8) |
Jun
(25) |
Jul
(12) |
Aug
(6) |
Sep
(8) |
Oct
(8) |
Nov
(9) |
Dec
(7) |
| 2005 |
Jan
(18) |
Feb
(60) |
Mar
(19) |
Apr
(26) |
May
(14) |
Jun
(27) |
Jul
(8) |
Aug
(15) |
Sep
(19) |
Oct
(53) |
Nov
(20) |
Dec
(23) |
| 2006 |
Jan
(16) |
Feb
(27) |
Mar
(33) |
Apr
(51) |
May
(36) |
Jun
(25) |
Jul
(54) |
Aug
(30) |
Sep
(25) |
Oct
(67) |
Nov
(43) |
Dec
(13) |
| 2007 |
Jan
(23) |
Feb
(27) |
Mar
(55) |
Apr
(79) |
May
(60) |
Jun
(66) |
Jul
(46) |
Aug
(30) |
Sep
(90) |
Oct
(49) |
Nov
(85) |
Dec
(74) |
| 2008 |
Jan
(68) |
Feb
(59) |
Mar
(64) |
Apr
(28) |
May
(66) |
Jun
(35) |
Jul
(73) |
Aug
(76) |
Sep
(65) |
Oct
(46) |
Nov
(41) |
Dec
(19) |
| 2009 |
Jan
(46) |
Feb
(90) |
Mar
(51) |
Apr
(104) |
May
(13) |
Jun
(24) |
Jul
(20) |
Aug
(39) |
Sep
(109) |
Oct
(101) |
Nov
(117) |
Dec
(57) |
| 2010 |
Jan
(55) |
Feb
(42) |
Mar
(39) |
Apr
(22) |
May
(33) |
Jun
(41) |
Jul
(25) |
Aug
(52) |
Sep
(75) |
Oct
(60) |
Nov
(62) |
Dec
(52) |
| 2011 |
Jan
(70) |
Feb
(31) |
Mar
(26) |
Apr
(28) |
May
(17) |
Jun
(38) |
Jul
(51) |
Aug
(35) |
Sep
(27) |
Oct
(35) |
Nov
(10) |
Dec
(20) |
| 2012 |
Jan
(21) |
Feb
(29) |
Mar
(13) |
Apr
(37) |
May
(33) |
Jun
(12) |
Jul
(34) |
Aug
(27) |
Sep
(29) |
Oct
(35) |
Nov
(58) |
Dec
(27) |
| 2013 |
Jan
(27) |
Feb
(16) |
Mar
(40) |
Apr
(16) |
May
(34) |
Jun
(37) |
Jul
(6) |
Aug
(3) |
Sep
(4) |
Oct
(49) |
Nov
(13) |
Dec
(12) |
| 2014 |
Jan
(15) |
Feb
(21) |
Mar
(11) |
Apr
(13) |
May
(27) |
Jun
(60) |
Jul
(19) |
Aug
(29) |
Sep
(20) |
Oct
(28) |
Nov
(41) |
Dec
(15) |
| 2015 |
Jan
(33) |
Feb
(29) |
Mar
(26) |
Apr
(17) |
May
(2) |
Jun
(13) |
Jul
(21) |
Aug
(30) |
Sep
(22) |
Oct
(15) |
Nov
(46) |
Dec
(20) |
| 2016 |
Jan
(6) |
Feb
(5) |
Mar
(9) |
Apr
(15) |
May
(9) |
Jun
(4) |
Jul
(3) |
Aug
(4) |
Sep
(39) |
Oct
(8) |
Nov
(5) |
Dec
(8) |
| 2017 |
Jan
(4) |
Feb
(14) |
Mar
(4) |
Apr
(16) |
May
(5) |
Jun
(10) |
Jul
(25) |
Aug
(2) |
Sep
(5) |
Oct
(11) |
Nov
(8) |
Dec
(11) |
| 2018 |
Jan
(7) |
Feb
(4) |
Mar
|
Apr
(1) |
May
(4) |
Jun
(21) |
Jul
(8) |
Aug
(3) |
Sep
(2) |
Oct
(2) |
Nov
(1) |
Dec
|
| 2019 |
Jan
(1) |
Feb
(5) |
Mar
(18) |
Apr
(9) |
May
(5) |
Jun
(21) |
Jul
(25) |
Aug
(25) |
Sep
(4) |
Oct
(2) |
Nov
(2) |
Dec
(5) |
| 2020 |
Jan
|
Feb
|
Mar
(3) |
Apr
|
May
(2) |
Jun
(2) |
Jul
(1) |
Aug
|
Sep
(1) |
Oct
(2) |
Nov
(6) |
Dec
|
| 2021 |
Jan
(1) |
Feb
|
Mar
(2) |
Apr
(1) |
May
(4) |
Jun
|
Jul
(1) |
Aug
|
Sep
(2) |
Oct
(9) |
Nov
(1) |
Dec
(5) |
| 2022 |
Jan
(7) |
Feb
(3) |
Mar
|
Apr
(2) |
May
(5) |
Jun
(3) |
Jul
(3) |
Aug
(3) |
Sep
(3) |
Oct
(14) |
Nov
|
Dec
(1) |
| 2023 |
Jan
(10) |
Feb
|
Mar
|
Apr
(2) |
May
|
Jun
(2) |
Jul
(2) |
Aug
(1) |
Sep
|
Oct
(5) |
Nov
|
Dec
|
| 2024 |
Jan
(8) |
Feb
|
Mar
(2) |
Apr
(1) |
May
|
Jun
|
Jul
(4) |
Aug
(5) |
Sep
|
Oct
(4) |
Nov
(1) |
Dec
(1) |
| 2025 |
Jan
(3) |
Feb
(2) |
Mar
(2) |
Apr
(1) |
May
(2) |
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
|
| 2026 |
Jan
(1) |
Feb
(12) |
Mar
|
Apr
(2) |
May
(8) |
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: Oleg B. <ole...@nl...> - 2008-03-19 15:28:27
|
Chris Kenyon <chris.kenyon <at> yahoo.com> writes: > > Hi Oleg, & list,both of the first two layers are really interfaces:- the first says what you get- the second (interpolated) says that if you already know the answer here is what you get, as you say a data representation.- the third layer says how to build something on the secondI.e. the third layer is a specific way to construct an interpolated whatever. I would argue (am arguing ) against combining levels two and three because combining them would force the second layer (interpolated) to be made in a certain way from a certain set of input data. As a design point I think that it's b > etter to leave the construction of the data separate from the data itself. Best regards,Chris Hi Chris, I agree with you and the idea to separate level 2 and level 3. Although , ways to do this may differ. It would be nice to discuss which is the best. [However, what I propose may require too large volume of changes.] For sake of clarity let's postulate following: Level 2 comprises of static data and collateral methods, all but bootstrapping. It also _implements_ what level 1 defines, therefore instances of level2 are creatable. Level 3 subclasses level2, aggregates the bootstrap and makes curve observable. Should one level 2 be different from another , if _implementation_ is somewhere outside ? Not likely. Data containers and all manipulations with them seem to be copied from class to class. Should level 3 be a subclass of level 2? What if bootstrap is just another object, the observer linked to instrument helpers? Then , the curve is essentially level2, with _implementation_ and data arrays has been filled up by extern bootstrap. We pay for having another instance, bootstrap, in the program. But does not this decouple bare curve and its bootstrap? What prevents us from separating bootstrap and curve? Bootstrap uses very limited set of operations to modify curve points. Basically, these are: reset (size), add(time, value), set(index, value). All these interpolator->update() look redundant, because we should assume that the bare curve knows about how to update its interpolator _better_ than bootstrap does. So we can decouple them to having just a common interface, e.g. CurveBuildStrategy. What keeps bootsrapper inside the level 3 _now_ is observability, namely, the issue with calling calculate() inside every member. Since bootstrap is separate, curve has to be able to wake it. It can be done surprisingly simple. OK, let's see what we get here: the TCurve<xxxStructure, yyyInterpolator> class, with constructors: template<class T1,class T2> TCurve(T1 begin, T1 end, T2 vbegin,...) // static data TCurve(refDate,...); // dynamic data and here is TCurveBuilder<Curve,Traits> with constructor TCurveBuilder(Curve &, instruments ) TCurve template lays down layer 2 for _all_ curves. One layer 3 class per curve type subclasses layer 2 as it did before, but now layer 3 is merely the _implementation_ (formerly presented in layer 2), and , at least , a pair of delegating constructors, one for static and one for dynamic. I can show inflation and credit risk curves implemented this way, and both classes look exactly as I said, interface + 2 constructors. Does this sound any better? Best regards, Oleg Burundukov, ABN AMRO > > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2008. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > > _______________________________________________ > QuantLib-dev mailing list > QuantLib-dev <at> lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/quantlib-dev > |
|
From: SourceForge.net <no...@so...> - 2008-03-19 09:40:26
|
Feature Requests item #1918100, was opened at 2008-03-18 18:00 Message generated for change (Settings changed) made by abhiabhi001 You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=362740&aid=1918100&group_id=12740 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None >Status: Deleted Priority: 8 Private: No Submitted By: abhishek Srivastava (abhiabhi001) Assigned to: Nobody/Anonymous (nobody) Summary: Few more instruments need to be added Initial Comment: Hi After going throgh all the instrumnets supported by Quantlib i come up with few more instruments for those class files need to be created. The list of those class files are as follows: Average Strike Option Best of Option Bond Future Bond Future Option Bond Option Brady Bond Calender Spread Option Cash Flow Dated CashFlow Currency Swap Option Commodity Swap Differential Swap Index Swap Option Index Swap Credit Default Swap Over Night Index Swap European Future Option Options Discretely monitored Barrier option Digital Option Average Price Equity Option Equity Option Forward Option Strip Option Strip Spread Option Dual Asset Option Spread Option Crack Option Commodities Futures Eurocurrency Futures Equity Futures Equity Cash Futures or Forward Commodities Physical Money Market Instrument Range Accrual Repo Swing Contracts Exchange Rates Yeild Curve Floting Rate Notes ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=362740&aid=1918100&group_id=12740 |
|
From: SourceForge.net <no...@so...> - 2008-03-19 09:13:50
|
Feature Requests item #1918100, was opened at 2008-03-18 18:00 Message generated for change (Settings changed) made by abhiabhi001 You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=362740&aid=1918100&group_id=12740 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Open >Priority: 8 Private: No Submitted By: abhishek Srivastava (abhiabhi001) Assigned to: Nobody/Anonymous (nobody) Summary: Few more instruments need to be added Initial Comment: Hi After going throgh all the instrumnets supported by Quantlib i come up with few more instruments for those class files need to be created. The list of those class files are as follows: Average Strike Option Best of Option Bond Future Bond Future Option Bond Option Brady Bond Calender Spread Option Cash Flow Dated CashFlow Currency Swap Option Commodity Swap Differential Swap Index Swap Option Index Swap Credit Default Swap Over Night Index Swap European Future Option Options Discretely monitored Barrier option Digital Option Average Price Equity Option Equity Option Forward Option Strip Option Strip Spread Option Dual Asset Option Spread Option Crack Option Commodities Futures Eurocurrency Futures Equity Futures Equity Cash Futures or Forward Commodities Physical Money Market Instrument Range Accrual Repo Swing Contracts Exchange Rates Yeild Curve Floting Rate Notes ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=362740&aid=1918100&group_id=12740 |
|
From: SourceForge.net <no...@so...> - 2008-03-18 12:30:05
|
Feature Requests item #1918100, was opened at 2008-03-18 18:00 Message generated for change (Tracker Item Submitted) made by Item Submitter You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=362740&aid=1918100&group_id=12740 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Open Priority: 5 Private: No Submitted By: abhishek Srivastava (abhiabhi001) Assigned to: Nobody/Anonymous (nobody) Summary: Few more instruments need to be added Initial Comment: Hi After going throgh all the instrumnets supported by Quantlib i come up with few more instruments for those class files need to be created. The list of those class files are as follows: Average Strike Option Best of Option Bond Future Bond Future Option Bond Option Brady Bond Calender Spread Option Cash Flow Dated CashFlow Currency Swap Option Commodity Swap Differential Swap Index Swap Option Index Swap Credit Default Swap Over Night Index Swap European Future Option Options Discretely monitored Barrier option Digital Option Average Price Equity Option Equity Option Forward Option Strip Option Strip Spread Option Dual Asset Option Spread Option Crack Option Commodities Futures Eurocurrency Futures Equity Futures Equity Cash Futures or Forward Commodities Physical Money Market Instrument Range Accrual Repo Swing Contracts Exchange Rates Yeild Curve Floting Rate Notes ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=362740&aid=1918100&group_id=12740 |
|
From: Chris K. <chr...@ya...> - 2008-03-14 17:51:21
|
Hi Oleg, & list, both of the first two layers are really interfaces: - the first says what you get - the second (interpolated) says that if you already know the answer here is what you get, as you say a data representation. - the third layer says how to build something on the second I.e. the third layer is a specific way to construct an interpolated whatever. I would argue (am arguing ;-)) against combining levels two and three because combining them would force the second layer (interpolated) to be made in a certain way from a certain set of input data. As a design point I think that it's better to leave the construction of the data separate from the data itself. Best regards, Chris |
|
From: SourceForge.net <no...@so...> - 2008-03-14 16:18:21
|
Feature Requests item #1914167, was opened at 2008-03-14 10:34 Message generated for change (Comment added) made by lballabio You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=362740&aid=1914167&group_id=12740 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None >Status: Deleted Priority: 5 Private: No Submitted By: Nobody/Anonymous (nobody) Assigned to: Nobody/Anonymous (nobody) Summary: Memory Issue Initial Comment: Hi I am totally new to Quantlib. I have gone through many codes. The use of pointers is very good but there is no arrangement for freeing those pointer variables.There is no module to free the memory reserved by these pointers. Thanks Abhishek ---------------------------------------------------------------------- >Comment By: Luigi Ballabio (lballabio) Date: 2008-03-14 17:18 Message: Logged In: YES user_id=75450 Originator: NO Duplicate item ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=362740&aid=1914167&group_id=12740 |
|
From: SourceForge.net <no...@so...> - 2008-03-14 16:17:42
|
Feature Requests item #1914168, was opened at 2008-03-14 10:38 Message generated for change (Comment added) made by lballabio You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=362740&aid=1914168&group_id=12740 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None >Status: Closed Priority: 5 Private: No Submitted By: abhishek Srivastava (abhiabhi001) Assigned to: Nobody/Anonymous (nobody) Summary: Memory Issue Initial Comment: Hi I am totally new to Quantlib. I have gone through many codes. The use of pointers is very good but there is no arrangement for freeing those pointer variables.There is no module to free the memory reserved by these pointers. Thanks Abhishek ---------------------------------------------------------------------- >Comment By: Luigi Ballabio (lballabio) Date: 2008-03-14 17:17 Message: Logged In: YES user_id=75450 Originator: NO This tracker is for requesting features to be added to the library. For requesting explanations, please use the quantlib-users mailing list. (Anyway, shared_ptr takes care of the deletion. See the docs at the Boost web site.) Luigi ---------------------------------------------------------------------- Comment By: Luigi Ballabio (lballabio) Date: 2008-03-14 17:16 Message: Logged In: YES user_id=75450 Originator: NO This tracker is for requesting features to be added to the library. For requesting explanations, please use the quantlib-users mailing list. (Anyway, shared_ptr takes care of the deletion. See the docs at the Boost web site.) Luigi ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=362740&aid=1914168&group_id=12740 |
|
From: SourceForge.net <no...@so...> - 2008-03-14 16:16:55
|
Feature Requests item #1914168, was opened at 2008-03-14 10:38 Message generated for change (Comment added) made by lballabio You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=362740&aid=1914168&group_id=12740 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None >Status: Deleted Priority: 5 Private: No Submitted By: abhishek Srivastava (abhiabhi001) Assigned to: Nobody/Anonymous (nobody) Summary: Memory Issue Initial Comment: Hi I am totally new to Quantlib. I have gone through many codes. The use of pointers is very good but there is no arrangement for freeing those pointer variables.There is no module to free the memory reserved by these pointers. Thanks Abhishek ---------------------------------------------------------------------- >Comment By: Luigi Ballabio (lballabio) Date: 2008-03-14 17:16 Message: Logged In: YES user_id=75450 Originator: NO This tracker is for requesting features to be added to the library. For requesting explanations, please use the quantlib-users mailing list. (Anyway, shared_ptr takes care of the deletion. See the docs at the Boost web site.) Luigi ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=362740&aid=1914168&group_id=12740 |
|
From: Luigi B. <lui...@gm...> - 2008-03-14 15:11:45
|
On Thu, 2008-03-06 at 18:10 +0000, a akpitidis wrote: > I tried to add to 8.0 the CAD vanilla swaps for the curve building and > i came across with some design issues, mainlly because i don't want to > change existing modules of the library. However, i want to reuse most > of the core code. > > In my mind someone who wants to extend a library shouldn't have to > change existing files, but the library needs to provide the > appropriate hooks (i.e. interfaces, template classes/functions and so > on). We all agree here. However... > At the same time, as we all know, that takes time and effort, and in > the main time the DIY solution fits most clients :). It's not just that. Generalization can be applied if one knows in what direction to generalize. For instance, until you wrote about your problem, I wasn't aware of the CAD convention, not could I have imagined it. Since early generalization risks going in the wrong direction and burdening the code with unused abstractions, I prefer waiting for use cases such as yours and generalize based on actual need. > Here are some sugestions for the future: > > 1. Create a template class VanillaSwapG ( G for generic), the > coupontype should be the template parameters and they should be > propagated down to the construction of the floating leg. > > 3. Those template arguments should be propagated upwards to > MakeVanillaSwap and SwapRateHelper. Does your coupon's constructor take the same number of arguments as the existing IborCoupon? Otherwise, one would also have to generalize coupon creation so that it has a common interface (we'd probably need some kind of factory.) > 4. Finally, i need to be able to hook my own code into the > SwapRateHelper::initializeDates as i need to set the custom floating > leg tenor, which is different from the index tenor. Then again that > extra information needs to come from somewhere, but then i need to > have my new SwapRateHelper class, but i don't want to copy existing > code. This kind of hook is already provided by the language. You can inherit from SwapRatehelper and override SwapRateHelper::initializeDates (you don't need to copy any code; you can call the parent-class method after executing the CAD-specific code.) The extra data can go in the derived class. Luigi -- It is always the best policy to tell the truth, unless, of course, you are an exceptionally good liar. -- Jerome K. Jerome |
|
From: SourceForge.net <no...@so...> - 2008-03-14 09:38:22
|
Feature Requests item #1914168, was opened at 2008-03-14 15:08 Message generated for change (Tracker Item Submitted) made by Item Submitter You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=362740&aid=1914168&group_id=12740 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Open Priority: 5 Private: No Submitted By: abhishek Srivastava (abhiabhi001) Assigned to: Nobody/Anonymous (nobody) Summary: Memory Issue Initial Comment: Hi I am totally new to Quantlib. I have gone through many codes. The use of pointers is very good but there is no arrangement for freeing those pointer variables.There is no module to free the memory reserved by these pointers. Thanks Abhishek ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=362740&aid=1914168&group_id=12740 |
|
From: SourceForge.net <no...@so...> - 2008-03-14 09:34:13
|
Feature Requests item #1914167, was opened at 2008-03-14 02:34 Message generated for change (Tracker Item Submitted) made by Item Submitter You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=362740&aid=1914167&group_id=12740 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Open Priority: 5 Private: No Submitted By: Nobody/Anonymous (nobody) Assigned to: Nobody/Anonymous (nobody) Summary: Memory Issue Initial Comment: Hi I am totally new to Quantlib. I have gone through many codes. The use of pointers is very good but there is no arrangement for freeing those pointer variables.There is no module to free the memory reserved by these pointers. Thanks Abhishek ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=362740&aid=1914167&group_id=12740 |
|
From: Luigi B. <lui...@gm...> - 2008-03-14 08:48:40
|
On Thu, 2008-03-13 at 10:08 -0700, Yee Man Chan wrote: > > It would be nice to have a test case exercising your > > process. May you write one? > > > > Of course I am going to write a test case. Ok, thanks. Luigi P.S. I never went to Stanford... -- Hofstadter's Law: It always takes longer than you expect, even when you take Hofstadter's Law into account. |
|
From: Yee M. C. <ym...@ya...> - 2008-03-13 17:08:45
|
Hi Luigi
>
> > I am not quite sure what kind of code is within
> \f[ ].
> > Can someone tell me?
>
> It's LaTeX formulas. If you're not familiar with
> LaTeX, send me the
> formulas in some format and I'll write the LaTeX
> code.
Oh I see. I think I will learn a bit of it and write
something out. The formula for the stochastic
volatility process is fairly convoluted when market
price of risk (lambda) is non-zero. I think you can
compare what I write in the cpp file to fix my latex
code in the hpp.
>
> > Also, any comments and questions are welcome.
>
> It would be nice to have a test case exercising your
> process. May you
> write one? Or at least, do you have an example of
> input data and their
> expected output?
>
Of course I am going to write a test case.
Attached is the Duan et al (2006) paper published in
Journal of Computational Finance. It has 1M run Monte
Carlo numbers we can check for the program's validity.
I am going to use QuantLib's QMC/Brownian Bridge code
to do the test case. I hope they don't disappoint. ;)
Yee Man
> Luigi
>
>
> --
>
> Discontent is the first necessity of progress.
> -- Thomas A. Edison
>
>
>
____________________________________________________________________________________
Looking for last minute shopping deals?
Find them fast with Yahoo! Search. http://tools.search.yahoo.com/newsearch/category.php?category=shopping |
|
From: Luigi B. <lui...@gm...> - 2008-03-13 10:52:56
|
On Tue, 2008-03-11 at 16:39 -0700, Yee Man Chan wrote: > Attached is my gjrgarchprocess.hpp. Basically I just > modified hestonprocess.hpp to suit my needs. Yee Man, thanks for the contribution. I'll try and have a look at it as soon as I get some time. > I am not quite sure what kind of code is within \f[ ]. > Can someone tell me? It's LaTeX formulas. If you're not familiar with LaTeX, send me the formulas in some format and I'll write the LaTeX code. > Also, any comments and questions are welcome. It would be nice to have a test case exercising your process. May you write one? Or at least, do you have an example of input data and their expected output? Luigi -- Discontent is the first necessity of progress. -- Thomas A. Edison |
|
From: Luigi B. <lui...@gm...> - 2008-03-13 10:47:39
|
On Sun, 2008-03-02 at 20:48 +0000, Andrea wrote: > The PathPricer receives the MultiPath, extract the values of the > assets on the times requested by the product (the time grind having > potentially more dates than the product needs) into some sort of > matrix and passes it to the product. > The product return (for the time being) one single number, and the > PathPricer takes care of discounting it. > > I want to write only one instance of the PathPricer and many > Products/Payoffs. > > Is it correct? Andrea, just to remove ambiguity, I wouldn't speak of product---that suggests an instance of the Instrument class (and in fact, it got me confused earlier.) Let's use "Payoff" instead. This said: some path pricers happen to use a Payoff instance, but this is not necessarily always the case. True, you could expand the Payoff hierarchy until it becomes some kind of interpreted language (at which point the PathPricer becomes little more than a discounter.) But if you want to express a number of exotic path-dependent payoffs, and if you don't need to specify the formula for your payoff at run-time (in which case you'll have to go for the interpreter, but it's a lot of work) you might be better off if: a) you write a general engine which does the setup, defines an abstract pathPricer() method to instantiate the payoff, and runs the simulation; b) you inherit specific engines which implement pathPricer() by returning a derived PathPricer with the specific formula you need. The path pricer doesn't need to use a Payoff object, mind you: it can just implement the formula itself. Luigi -- Ogden's Law: The sooner you fall behind, the more time you have to catch up. |
|
From: Ferdinando A. <na...@am...> - 2008-03-12 14:48:28
|
Hi Chris On Mon, Mar 10, 2008 at 12:49 PM, Chris Kenyon <chr...@ya...> wrote: > suggested changes below & attached. I've committed your changes in revision 14564 (actually a slightly modified version in order to make it work with the current SVN code base) Thank you very much ciao -- Nando PS Since you are quite active on our mailing lists and in private communications I suggest you to get familiar with the current SVN code base if possible ;-) |
|
From: Oleg B. <ole...@nl...> - 2008-03-12 13:35:20
|
Hello, everybody, The QL architecture of term structures/curves requires to introduce 3 classes for every new type of curve: YYYstructure for the interface (which is fine), static "interpolatedYYYcurve" and bootstrappable "piecewiseYYYcurve". Difference between second and 3rd is in the way they may be constructed. Although they are both merely containers of discrete points. Their members, such as dates_, times_ , data_ , interpolator_ and primitive manipulating functions appear same in every YYYcurve. If interpolated and bootstrappable curve versions joined, and if their primitives were implemented via pimpl or via curveBase template , it would reduce the amount of code for every new curve. Having common code for data primitives makes adding nice shortcuts easy too, such as operator[], operator(), sample(F), transform(F) and others. Every curve becomes robust, STL-ready object. This issue didn't catch an eye in 0.8.1, but 0.9.5 extends number of curves and shows up the problem quite clearly. Would you consider this improvement as item for 1.0 ? I can volunteer to contribute. Best regards, Oleg Burundukov, ABN AMRO, Amsterdam |
|
From: Ferdinando A. <na...@am...> - 2008-03-12 10:56:10
|
On Tue, Mar 11, 2008 at 6:15 PM, Simon Ibbotson <Sim...@st...> wrote: > I think I've found a bug – the test suite is generating errors on my PC > under the debug build (but not under release). > [...] > I've tracked them down to a code point in the test file > assetswap.cpp, where the code is determining the floor on a CMS bond rate > and the SmileSection class is not initializing the exerciseTime_ member > variable. thank you very much for the bug report, it was very clear and straight to the point. I've fixed the bug in Revision 14563. I would appreciate if you could double check that i've solved the issue. I prefer not to think about what was going on in Release mode when exreciseTime_ was not initialized to zero... probably my production code was accessing the SmileSection using the volatility inspector, not the variance one... ciao -- Nando |
|
From: Yee M. C. <ym...@ya...> - 2008-03-11 23:40:22
|
Attached is my gjrgarchprocess.hpp. Basically I just modified hestonprocess.hpp to suit my needs. The naming convention of the model parameters follows the Hull 2005 book. I am not quite sure what kind of code is within \f[ ]. Can someone tell me? Also, any comments and questions are welcome. Thanks Yee Man --- Yee Man Chan <ym...@ya...> wrote: > Hi Luigi > > Thanks for your reply. Are you still at Stanford? > Maybe we can hang out one day. > > I will start coding then. It shouldn't be too > hard. > I can just copy the Heston code and change the > stochastic process for volatility. I also have an > implementation for analytical approximation of > GJR-GARCH option pricing model as described in Duan > 2004 paper. > > Do you guys give out remote CVS access for > developers? That's what I got for my previous open > source contribution. If this is not how it works > here, > I am ok sending files directly to Luigi. > > Have a great day! > Yee Man > > > > --- Luigi Ballabio <lui...@gm...> wrote: > > > Hi Yee Man, > > > > On Thu, 2008-03-06 at 17:20 -0800, Yee Man Chan > > wrote: > > > I recently finished my implementation of > > > GJR-GARCH(1,1) option pricing model for European > > > options using QMC with Brownian Bridge. > > > > > > I find that you guys don't have this pricing > > model. > > > Do you mind if I implement this for Quantlib? > > > > I'll be happy if you do. > > > > > If so, how should I proceed? > > > > You can send me the files and I'll add them to the > > repository. > > You should code your model as a pricing engine; if > > you're not yet > > familiar with our pricing framework, you can read > > chapter 2 at > > <http://luigi.ballabio.googlepages.com/qlbook> for > > an introduction. > > Also, it should use the existing facilities for > > random-number > > generation. As an example, you can look at the > > current MC engine for > > European options in > > <ql/pricingengines/vanilla/mceuropeanengine.hpp>. > > > > Later, > > Luigi > > > > > > -- > > > > Every solution breeds new problems. > > -- unknown > > > > > > > > > > > ____________________________________________________________________________________ > Be a better friend, newshound, and > know-it-all with Yahoo! Mobile. Try it now. > http://mobile.yahoo.com/;_ylt=Ahu06i62sR8HDtDypao8Wcj9tAcJ > > > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio > 2008. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > _______________________________________________ > QuantLib-dev mailing list > Qua...@li... > https://lists.sourceforge.net/lists/listinfo/quantlib-dev > ____________________________________________________________________________________ Looking for last minute shopping deals? Find them fast with Yahoo! Search. http://tools.search.yahoo.com/newsearch/category.php?category=shopping |
|
From: Yee M. C. <ym...@ya...> - 2008-03-11 18:22:13
|
Hi Luigi Thanks for your reply. Are you still at Stanford? Maybe we can hang out one day. I will start coding then. It shouldn't be too hard. I can just copy the Heston code and change the stochastic process for volatility. I also have an implementation for analytical approximation of GJR-GARCH option pricing model as described in Duan 2004 paper. Do you guys give out remote CVS access for developers? That's what I got for my previous open source contribution. If this is not how it works here, I am ok sending files directly to Luigi. Have a great day! Yee Man --- Luigi Ballabio <lui...@gm...> wrote: > Hi Yee Man, > > On Thu, 2008-03-06 at 17:20 -0800, Yee Man Chan > wrote: > > I recently finished my implementation of > > GJR-GARCH(1,1) option pricing model for European > > options using QMC with Brownian Bridge. > > > > I find that you guys don't have this pricing > model. > > Do you mind if I implement this for Quantlib? > > I'll be happy if you do. > > > If so, how should I proceed? > > You can send me the files and I'll add them to the > repository. > You should code your model as a pricing engine; if > you're not yet > familiar with our pricing framework, you can read > chapter 2 at > <http://luigi.ballabio.googlepages.com/qlbook> for > an introduction. > Also, it should use the existing facilities for > random-number > generation. As an example, you can look at the > current MC engine for > European options in > <ql/pricingengines/vanilla/mceuropeanengine.hpp>. > > Later, > Luigi > > > -- > > Every solution breeds new problems. > -- unknown > > > ____________________________________________________________________________________ Be a better friend, newshound, and know-it-all with Yahoo! Mobile. Try it now. http://mobile.yahoo.com/;_ylt=Ahu06i62sR8HDtDypao8Wcj9tAcJ |
|
From: Simon I. <Sim...@st...> - 2008-03-11 17:15:57
|
Hi, I think I've found a bug - the test suite is generating errors on my PC under the debug build (but not under release). I checked-out (in a new directory) the QuantLib trunk. I compiled it then ran the test suite. I'm getting the following errors from the test suite:- Testing bond implied value against asset-swap fair price with null spread... 10>unknown location(0): fatal error in "AssetSwapTest::testImpliedValue": std::exception: stdDev (-1.#IND) must be non-negative 10>Testing relationship between market asset swap and par asset swap... 10>unknown location(0): fatal error in "AssetSwapTest::testMarketASWSpread": std::exception: stdDev (-1.#IND) must be non-negative 10>Testing clean and dirty price with null Z-spread against theoretical prices... 10>unknown location(0): fatal error in "AssetSwapTest::testZSpread": std::exception: stdDev (-1.#IND) must be non-negative 10>Testing generic bond implied value against asset-swap fair price with null spread... 10>unknown location(0): fatal error in "AssetSwapTest::testGenericBondImplied": std::exception: stdDev (-1.#IND) must be non-negative 10>Testing market asset swap against par asset swap with generic bond... 10>unknown location(0): fatal error in "AssetSwapTest::testMASWWithGenericBond": std::exception: stdDev (-1.#IND) must be non-negative 10>Testing clean and dirty price with null Z-spread against theoretical prices... 10>unknown location(0): fatal error in "AssetSwapTest::testZSpreadWithGenericBond": std::exception: stdDev (-1.#IND) must be non-negative 10>Testing clean and dirty prices for specialized bond against equivalent generic bond... 10>unknown location(0): fatal error in "AssetSwapTest::testSpecializedBondVsGenericBond": std::exception: stdDev (-1.#IND) must be non-negative 10>Testing asset-swap prices and spreads for specialized bond against equivalent generic bond... 10>unknown location(0): fatal error in "AssetSwapTest::testSpecializedBondVsGenericBondUsingAsw": std::exception: stdDev (-1.#IND) must be non-negative Are these expected? I've tracked them down to a code point in the test file assetswap.cpp, where the code is determining the floor on a CMS bond rate and the SmileSection class is not initializing the exerciseTime_ member variable. Line 53 of conundrumpricer.cpp gets a smile section for use from... Line 78 of swaptionconstantvol.cpp creates a FlatSmileSection using a valid referenceDate. Line 50 of smilesection.cpp defines isFloating_ (false in this case). Line 59 of conundrumpricer.cpp calls the variance of the smile section which has an invalid exerciseTime_ member variable. I don't see why this would be desired behaviour but I can't find any mention (on QuantLib) of the test suite producing deliberate unhandled errors either. Also, this doesn't happen (or it isn't picked up) under the release build. Can anyone enlighten me? Simon Simon Ibbotson Head of Quantitative Analytics Capital Markets Straumur |
|
From: Eric E. <eri...@na...> - 2008-03-10 23:46:55
|
Hi All, On Tue, March 4, 2008 4:10 pm, Ferdinando Ametrano wrote: > On Tue, Mar 4, 2008 at 1:57 PM, Eric Ehlers <eri...@na...> > wrote: >> >> At present, non-ASCII characters (>128, aka extended ASCII) >> >> appear in various comments and literal strings in the source code >> >> >> >> Some possible courses of action: >> >> 1) Restrict ourselves to the ASCII character set >> >> 2) Convert all source code files to Unicode format >> >> 3) Disable C4819 >> >> 4) Do nothing and as today leave affected parties to work around the >> >> problem by implementing one of the above as a local hack >> > >> > Hmm. (3) seems strangely appealing... >> > >> > Luigi >> >> It turns out, (3) doesn't work, at least not with "pragma warning >> disable". When you load a cpp file containing a non-ASCII character, the >> compiler hits the problem character before it sees the pragma directive, >> so C4819 still appears everywhere. >> >> The only way to disable the warning is to add /wd4819 to the compiler >> settings - any objection if I make that change? > > what is so hard about 2 ? > > ciao -- Nando I don't know that (2) is hard and it's probably the correct full long term solution, provided that it doesn't cause problems elsewhere in our development environment - e.g. platforms other than Visual Studio on Windows, subversion - which I suspect it doesn't. For now, (3) is an immediate fix which I would argue is preferable to the current state of affairs, so I went ahead and implemented that, if this causes anyone any problems please let me know. Regards, Eric |
|
From: Luigi B. <lui...@gm...> - 2008-03-10 17:06:42
|
On Fri, 2008-03-07 at 11:56 -0800, tibbar wrote: > Could anyone give me some ideas of how to price callable bonds in quantlib? > > Bond features are: > > - initial deferred period where the bond is not callable > - seperate strike price for exercise in each remaining year of the bond's > life. > > I've seen some discussions that the convertible bond class should be used, > but as a newbee I'm a little intimidated by the quantlib terminology. As already pointed out, the ConvertibleBond class is not the right one to use. Instead, I would start from the Swaption class (together with its TreeSwaptionEngine) and see how it works. You can copy the engine and modify it so that it takes into account a single sequence of cash flows, instead of two legs. Feel free to write to the list if you need any help in understanding the Swaption or TreeSwaptionEngine class. Later, Luigi -- There is no opinion so absurd that some philosopher will not express it. -- Marcus Tullius Cicero, "Ad familiares" |
|
From: Luigi B. <lui...@gm...> - 2008-03-10 17:02:26
|
Hi Yee Man, On Thu, 2008-03-06 at 17:20 -0800, Yee Man Chan wrote: > I recently finished my implementation of > GJR-GARCH(1,1) option pricing model for European > options using QMC with Brownian Bridge. > > I find that you guys don't have this pricing model. > Do you mind if I implement this for Quantlib? I'll be happy if you do. > If so, how should I proceed? You can send me the files and I'll add them to the repository. You should code your model as a pricing engine; if you're not yet familiar with our pricing framework, you can read chapter 2 at <http://luigi.ballabio.googlepages.com/qlbook> for an introduction. Also, it should use the existing facilities for random-number generation. As an example, you can look at the current MC engine for European options in <ql/pricingengines/vanilla/mceuropeanengine.hpp>. Later, Luigi -- Every solution breeds new problems. -- unknown |
|
From: Chris K. <chr...@ya...> - 2008-03-10 11:50:03
|
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (C) 2003 RiskMap srl Copyright (C) 2004, 2005, 2006, 2007 StatPro Italia srl This file is part of QuantLib, a free-software/open-source library for financial quantitative analysts and developers - http://quantlib.org/ QuantLib is free software: you can redistribute it and/or modify it under the terms of the QuantLib license. You should have received a copy of the license along with this program; if not, please email <qua...@li...>. The license is also available online at <http://quantlib.org/license.shtml>. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #include "capfloor.hpp" #include "utilities.hpp" #include <ql/instruments/capfloor.hpp> #include <ql/instruments/vanillaswap.hpp> #include <ql/cashflows/cashflowvectors.hpp> #include <ql/termstructures/yield/flatforward.hpp> #include <ql/indexes/ibor/euribor.hpp> #include <ql/pricingengines/capfloor/blackcapfloorengine.hpp> #include <ql/pricingengines/swap/discountingswapengine.hpp> #include <ql/models/marketmodels/models/flatvol.hpp> #include <ql/models/marketmodels/correlations/expcorrelations.hpp> #include <ql/math/matrix.hpp> #include <ql/time/daycounters/actualactual.hpp> #include <ql/time/daycounters/actual360.hpp> #include <ql/time/schedule.hpp> #include <ql/utilities/dataformatters.hpp> #include <ql/cashflows/cashflows.hpp> #include <ql/cashflows/couponpricer.hpp> #include <iostream> using namespace QuantLib; using namespace boost::unit_test_framework; QL_BEGIN_TEST_LOCALS(CapFloorTest) struct CommonVars { // common data Date settlement; std::vector<Real> nominals; BusinessDayConvention convention; Frequency frequency; boost::shared_ptr<IborIndex> index; Calendar calendar; Natural fixingDays; RelinkableHandle<YieldTermStructure> termStructure; // cleanup SavedSettings backup; // setup CommonVars() { nominals = std::vector<Real>(1,100); frequency = Semiannual; index = boost::shared_ptr<IborIndex>(new Euribor6M(termStructure)); calendar = index->fixingCalendar(); convention = ModifiedFollowing; Date today = calendar.adjust(Date::todaysDate()); Settings::instance().evaluationDate() = today; Natural settlementDays = 2; fixingDays = 2; settlement = calendar.advance(today,settlementDays,Days); termStructure.linkTo(flatRate(settlement,0.05, ActualActual(ActualActual::ISDA))); } // utilities Leg makeLeg(const Date& startDate, Integer length) { Date endDate = calendar.advance(startDate,length*Years,convention); Schedule schedule(startDate, endDate, Period(frequency), calendar, convention, convention, DateGeneration::Forward, false); return IborLeg(schedule, index) .withNotionals(nominals) .withPaymentDayCounter(index->dayCounter()) .withPaymentAdjustment(convention) .withFixingDays(fixingDays); } boost::shared_ptr<PricingEngine> makeEngine(Volatility volatility) { Handle<Quote> vol(boost::shared_ptr<Quote>( new SimpleQuote(volatility))); return boost::shared_ptr<PricingEngine>( new BlackCapFloorEngine(termStructure, vol)); } boost::shared_ptr<CapFloor> makeCapFloor(CapFloor::Type type, const Leg& leg, Rate strike, Volatility volatility) { boost::shared_ptr<CapFloor> result; switch (type) { case CapFloor::Cap: result = boost::shared_ptr<CapFloor>( new Cap(leg, std::vector<Rate>(1, strike))); break; case CapFloor::Floor: result = boost::shared_ptr<CapFloor>( new Floor(leg, std::vector<Rate>(1, strike))); break; default: QL_FAIL("unknown cap/floor type"); } result->setPricingEngine(makeEngine(volatility)); return result; } }; bool checkAbsError(Real x1, Real x2, Real tolerance){ return std::fabs(x1 - x2) < tolerance; } std::string typeToString(CapFloor::Type type) { switch (type) { case CapFloor::Cap: return "cap"; case CapFloor::Floor: return "floor"; case CapFloor::Collar: return "collar"; default: QL_FAIL("unknown cap/floor type"); } } QL_END_TEST_LOCALS(CapFloorTest) void CapFloorTest::testVega() { BOOST_MESSAGE("Testing cap/floor vega..."); CommonVars vars; Integer lengths[] = { 1, 2, 3, 4, 5, 6, 7, 10, 15, 20, 30 }; Volatility vols[] = { 0.01, 0.05, 0.10, 0.15, 0.20 }; Rate strikes[] = { 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09 }; CapFloor::Type types[] = { CapFloor::Cap, CapFloor::Floor}; Date startDate = vars.termStructure->referenceDate(); static const Real shift = 1e-8; static const Real tolerance = 0.005; for (Size i=0; i<LENGTH(lengths); i++) { for (Size j=0; j<LENGTH(vols); j++) { for (Size k=0; k<LENGTH(strikes); k++) { for (Size h=0; h<LENGTH(types); h++) { Leg leg = vars.makeLeg(startDate, lengths[i]); boost::shared_ptr<CapFloor> capFloor = vars.makeCapFloor(types[h],leg, strikes[k],vols[j]); boost::shared_ptr<CapFloor> shiftedCapFloor2 = vars.makeCapFloor(types[h],leg, strikes[k],vols[j]+shift); boost::shared_ptr<CapFloor> shiftedCapFloor1 = vars.makeCapFloor(types[h],leg, strikes[k],vols[j]-shift); Real value1 = shiftedCapFloor1->NPV(); Real value2 = shiftedCapFloor2->NPV(); Real numericalVega = (value2 - value1) / (2*shift); if (numericalVega>1.0e-4) { Real analyticalVega = capFloor->result<Real>("vega"); Real discrepancy = std::fabs(numericalVega - analyticalVega); discrepancy /= numericalVega; if (discrepancy > tolerance) BOOST_FAIL( "failed to compute cap/floor vega:" << "\n lengths: " << lengths[j]*Years << "\n strike: " << io::rate(strikes[k]) << //"\n types: " << types[h] << QL_FIXED << std::setprecision(12) << "\n calculated: " << analyticalVega << "\n expected: " << numericalVega << "\n discrepancy: " << io::rate(discrepancy) << "\n tolerance: " << io::rate(tolerance)); } } } } } } void CapFloorTest::testStrikeDependency() { BOOST_MESSAGE("Testing cap/floor dependency on strike..."); CommonVars vars; Integer lengths[] = { 1, 2, 3, 5, 7, 10, 15, 20 }; Volatility vols[] = { 0.01, 0.05, 0.10, 0.15, 0.20 }; Rate strikes[] = { 0.03, 0.04, 0.05, 0.06, 0.07 }; Date startDate = vars.termStructure->referenceDate(); for (Size i=0; i<LENGTH(lengths); i++) { for (Size j=0; j<LENGTH(vols); j++) { // store the results for different strikes... std::vector<Real> cap_values, floor_values; for (Size k=0; k<LENGTH(strikes); k++) { Leg leg = vars.makeLeg(startDate,lengths[i]); boost::shared_ptr<Instrument> cap = vars.makeCapFloor(CapFloor::Cap,leg, strikes[k],vols[j]); cap_values.push_back(cap->NPV()); boost::shared_ptr<Instrument> floor = vars.makeCapFloor(CapFloor::Floor,leg, strikes[k],vols[j]); floor_values.push_back(floor->NPV()); } // and check that they go the right way std::vector<Real>::iterator it = std::adjacent_find(cap_values.begin(),cap_values.end(), std::less<Real>()); if (it != cap_values.end()) { Size n = it - cap_values.begin(); BOOST_FAIL( "NPV is increasing with the strike in a cap: \n" << std::setprecision(2) << " length: " << lengths[i] << " years\n" << " volatility: " << io::volatility(vols[j]) << "\n" << " value: " << cap_values[n] << " at strike: " << io::rate(strikes[n]) << "\n" << " value: " << cap_values[n+1] << " at strike: " << io::rate(strikes[n+1])); } // same for floors it = std::adjacent_find(floor_values.begin(),floor_values.end(), std::greater<Real>()); if (it != floor_values.end()) { Size n = it - floor_values.begin(); BOOST_FAIL( "NPV is decreasing with the strike in a floor: \n" << std::setprecision(2) << " length: " << lengths[i] << " years\n" << " volatility: " << io::volatility(vols[j]) << "\n" << " value: " << floor_values[n] << " at strike: " << io::rate(strikes[n]) << "\n" << " value: " << floor_values[n+1] << " at strike: " << io::rate(strikes[n+1])); } } } } void CapFloorTest::testConsistency() { BOOST_MESSAGE("Testing consistency between cap, floor and collar..."); CommonVars vars; Size lengths[] = { 1, 2, 3, 5, 7, 10, 15, 20 }; Rate cap_rates[] = { 0.03, 0.04, 0.05, 0.06, 0.07 }; Rate floor_rates[] = { 0.03, 0.04, 0.05, 0.06, 0.07 }; Volatility vols[] = { 0.01, 0.05, 0.10, 0.15, 0.20 }; Date startDate = vars.termStructure->referenceDate(); for (Size i=0; i<LENGTH(lengths); i++) { for (Size j=0; j<LENGTH(cap_rates); j++) { for (Size k=0; k<LENGTH(floor_rates); k++) { for (Size l=0; l<LENGTH(vols); l++) { Leg leg = vars.makeLeg(startDate,lengths[i]); boost::shared_ptr<CapFloor> cap = vars.makeCapFloor(CapFloor::Cap,leg, cap_rates[j],vols[l]); boost::shared_ptr<CapFloor> floor = vars.makeCapFloor(CapFloor::Floor,leg, floor_rates[k],vols[l]); Collar collar(leg,std::vector<Rate>(1,cap_rates[j]), std::vector<Rate>(1,floor_rates[k])); collar.setPricingEngine(vars.makeEngine(vols[l])); if (std::fabs((cap->NPV()-floor->NPV())-collar.NPV()) > 1e-10) { BOOST_FAIL( "inconsistency between cap, floor and collar:\n" << " length: " << lengths[i] << " years\n" << " volatility: " << io::volatility(vols[l]) << "\n" << " cap value: " << cap->NPV() << " at strike: " << io::rate(cap_rates[j]) << "\n" << " floor value: " << floor->NPV() << " at strike: " << io::rate(floor_rates[k]) << "\n" << " collar value: " << collar.NPV()); } // test re-composition by optionlets, N.B. two per year Real capletsNPV = 0.0; std::vector<boost::shared_ptr<CapFloor> > caplets; for (Size m=0; m<lengths[i]*2; m++) { caplets.push_back(cap->optionlet(m)); caplets[m]->setPricingEngine(vars.makeEngine(vols[l])); capletsNPV += caplets[m]->NPV(); } if (std::fabs(cap->NPV() - capletsNPV) > 1e-10) { BOOST_FAIL( "sum of caplet NPVs does not equal cap NPV:\n" << " length: " << lengths[i] << " years\n" << " volatility: " << io::volatility(vols[l]) << "\n" << " cap value: " << cap->NPV() << " at strike: " << io::rate(cap_rates[j]) << "\n" << " sum of caplets value: " << capletsNPV << " at strike (first): " << io::rate(caplets[0]->capRates()[0]) << "\n" ); } Real floorletsNPV = 0.0; std::vector<boost::shared_ptr<CapFloor> > floorlets; for (Size m=0; m<lengths[i]*2; m++) { floorlets.push_back(floor->optionlet(m)); floorlets[m]->setPricingEngine(vars.makeEngine(vols[l])); floorletsNPV += floorlets[m]->NPV(); } if (std::fabs(floor->NPV() - floorletsNPV) > 1e-10) { BOOST_FAIL( "sum of floorlet NPVs does not equal floor NPV:\n" << " length: " << lengths[i] << " years\n" << " volatility: " << io::volatility(vols[l]) << "\n" << " cap value: " << floor->NPV() << " at strike: " << io::rate(floor_rates[j]) << "\n" << " sum of floorlets value: " << floorletsNPV << " at strike (first): " << io::rate(floorlets[0]->floorRates()[0]) << "\n" ); } Real collarletsNPV = 0.0; std::vector<boost::shared_ptr<CapFloor> > collarlets; for (Size m=0; m<lengths[i]*2; m++) { collarlets.push_back(collar.optionlet(m)); collarlets[m]->setPricingEngine(vars.makeEngine(vols[l])); collarletsNPV += collarlets[m]->NPV(); } if (std::fabs(collar.NPV() - collarletsNPV) > 1e-10) { BOOST_FAIL( "sum of collarlet NPVs does not equal floor NPV:\n" << " length: " << lengths[i] << " years\n" << " volatility: " << io::volatility(vols[l]) << "\n" << " cap value: " << collar.NPV() << " at strike floor: " << io::rate(floor_rates[j]) << " at strike cap: " << io::rate(cap_rates[j]) << "\n" << " sum of collarlets value: " << collarletsNPV << " at strike floor (first): " << io::rate(collarlets[0]->floorRates()[0]) << " at strike cap (first): " << io::rate(collarlets[0]->capRates()[0]) << "\n" ); } } } } } } void CapFloorTest::testParity() { BOOST_MESSAGE("Testing cap/floor parity..."); CommonVars vars; Integer lengths[] = { 1, 2, 3, 5, 7, 10, 15, 20 }; Rate strikes[] = { 0., 0.03, 0.04, 0.05, 0.06, 0.07 }; Volatility vols[] = { 0.01, 0.05, 0.10, 0.15, 0.20 }; Date startDate = vars.termStructure->referenceDate(); for (Size i=0; i<LENGTH(lengths); i++) { for (Size j=0; j<LENGTH(strikes); j++) { for (Size k=0; k<LENGTH(vols); k++) { Leg leg = vars.makeLeg(startDate,lengths[i]); boost::shared_ptr<Instrument> cap = vars.makeCapFloor(CapFloor::Cap,leg, strikes[j],vols[k]); boost::shared_ptr<Instrument> floor = vars.makeCapFloor(CapFloor::Floor,leg, strikes[j],vols[k]); Date maturity = vars.calendar.advance(startDate,lengths[i],Years, vars.convention); Schedule schedule(startDate,maturity, Period(vars.frequency),vars.calendar, vars.convention,vars.convention, DateGeneration::Forward,false); VanillaSwap swap(VanillaSwap::Payer, vars.nominals[0], schedule, strikes[j], vars.index->dayCounter(), schedule, vars.index, 0.0, vars.index->dayCounter()); swap.setPricingEngine(boost::shared_ptr<PricingEngine>( new DiscountingSwapEngine(vars.termStructure))); // FLOATING_POINT_EXCEPTION if (std::fabs((cap->NPV()-floor->NPV()) - swap.NPV()) > 1.0e-10) { BOOST_FAIL( "put/call parity violated:\n" << " length: " << lengths[i] << " years\n" << " volatility: " << io::volatility(vols[k]) << "\n" << " strike: " << io::rate(strikes[j]) << "\n" << " cap value: " << cap->NPV() << "\n" << " floor value: " << floor->NPV() << "\n" << " swap value: " << swap.NPV()); } } } } } void CapFloorTest::testATMRate() { BOOST_MESSAGE("Testing cap/floor ATM rate..."); CommonVars vars; Integer lengths[] = { 1, 2, 3, 5, 7, 10, 15, 20 }; Rate strikes[] = { 0., 0.03, 0.04, 0.05, 0.06, 0.07 }; Volatility vols[] = { 0.01, 0.05, 0.10, 0.15, 0.20 }; Date startDate = vars.termStructure->referenceDate(); for (Size i=0; i<LENGTH(lengths); i++) { Leg leg = vars.makeLeg(startDate,lengths[i]); Date maturity = vars.calendar.advance(startDate,lengths[i],Years, vars.convention); Schedule schedule(startDate,maturity, Period(vars.frequency),vars.calendar, vars.convention,vars.convention, DateGeneration::Forward,false); for (Size j=0; j<LENGTH(strikes); j++) { for (Size k=0; k<LENGTH(vols); k++) { boost::shared_ptr<CapFloor> cap = vars.makeCapFloor(CapFloor::Cap, leg, strikes[j],vols[k]); boost::shared_ptr<CapFloor> floor = vars.makeCapFloor(CapFloor::Floor, leg, strikes[j],vols[k]); Rate capATMRate = cap->atmRate(**vars.termStructure); Rate floorATMRate = floor->atmRate(**vars.termStructure); if (!checkAbsError(floorATMRate, capATMRate, 1.0e-10)) BOOST_FAIL( "Cap ATM Rate and floor ATM Rate should be equal :\n" << " length: " << lengths[i] << " years\n" << " volatility: " << io::volatility(vols[k]) << "\n" << " strike: " << io::rate(strikes[j]) << "\n" << " cap ATM rate: " << capATMRate << "\n" << " floor ATM rate:" << floorATMRate << "\n" << " relative Error:" << relativeError(capATMRate, floorATMRate, capATMRate)*100 << "%" ); VanillaSwap swap(VanillaSwap::Payer, vars.nominals[0], schedule, floorATMRate, vars.index->dayCounter(), schedule, vars.index, 0.0, vars.index->dayCounter()); swap.setPricingEngine(boost::shared_ptr<PricingEngine>( new DiscountingSwapEngine(vars.termStructure))); Real swapNPV = swap.NPV(); if (!checkAbsError(swapNPV, 0, 1.0e-10)) BOOST_FAIL( "the NPV of a Swap struck at ATM rate " "should be equal to 0:\n" << " length: " << lengths[i] << " years\n" << " volatility: " << io::volatility(vols[k]) << "\n" << " ATM rate: " << io::rate(floorATMRate) << "\n" << " swap NPV: " << swapNPV); } } } } void CapFloorTest::testImpliedVolatility() { BOOST_MESSAGE("Testing implied term volatility for cap and floor..."); CommonVars vars; Size maxEvaluations = 100; Real tolerance = 1.0e-6; CapFloor::Type types[] = { CapFloor::Cap, CapFloor::Floor }; Rate strikes[] = { 0.02, 0.03, 0.04 }; Integer lengths[] = { 1, 5, 10 }; // test data Rate rRates[] = { 0.02, 0.03, 0.04 }; Volatility vols[] = { 0.01, 0.20, 0.30, 0.70, 0.90 }; for (Size k=0; k<LENGTH(lengths); k++) { Leg leg = vars.makeLeg(vars.settlement, lengths[k]); for (Size i=0; i<LENGTH(types); i++) { for (Size j=0; j<LENGTH(strikes); j++) { boost::shared_ptr<CapFloor> capfloor = vars.makeCapFloor(types[i], leg, strikes[j], 0.0); for (Size n=0; n<LENGTH(rRates); n++) { for (Size m=0; m<LENGTH(vols); m++) { Rate r = rRates[n]; Volatility v = vols[m]; vars.termStructure.linkTo(flatRate(vars.settlement,r, Actual360())); capfloor->setPricingEngine(vars.makeEngine(v)); Real value = capfloor->NPV(); Volatility implVol = 0.0; try { implVol = capfloor->impliedVolatility(value, vars.termStructure, tolerance, maxEvaluations); } catch (std::exception& e) { BOOST_FAIL(typeToString(types[i]) << "\n strike: " << io::rate(strikes[j]) << "\n risk-free: " << io::rate(r) << "\n length: " << lengths[k] << "Y" << "\n volatility: " << io::volatility(v) << "\n" << e.what()); } if (std::fabs(implVol-v) > tolerance) { // the difference might not matter capfloor->setPricingEngine( vars.makeEngine(implVol)); Real value2 = capfloor->NPV(); if (std::fabs(value-value2) > tolerance) { BOOST_FAIL( typeToString(types[i]) << ":\n" << " strike: " << strikes[j] << "\n" << " risk-free rate: " << io::rate(r) << "\n" << " length: " << lengths[k] << " years\n\n" << " original volatility: " << io::volatility(v) << "\n" << " price: " << value << "\n" << " implied volatility: " << io::volatility(implVol) << "\n" << " corresponding price: " << value2); } } } } } } } } void CapFloorTest::testCachedValue() { BOOST_MESSAGE("Testing Black cap/floor price against cached values..."); CommonVars vars; Date cachedToday(14,March,2002), cachedSettlement(18,March,2002); Settings::instance().evaluationDate() = cachedToday; vars.termStructure.linkTo(flatRate(cachedSettlement, 0.05, Actual360())); Date startDate = vars.termStructure->referenceDate(); Leg leg = vars.makeLeg(startDate,20); boost::shared_ptr<Instrument> cap = vars.makeCapFloor(CapFloor::Cap,leg, 0.07,0.20); boost::shared_ptr<Instrument> floor = vars.makeCapFloor(CapFloor::Floor,leg, 0.03,0.20); #ifndef QL_USE_INDEXED_COUPON // par coupon price Real cachedCapNPV = 6.87570026732, cachedFloorNPV = 2.65812927959; #else // index fixing price Real cachedCapNPV = 6.87630307745, cachedFloorNPV = 2.65796764715; #endif // test Black cap price against cached value if (std::fabs(cap->NPV()-cachedCapNPV) > 1.0e-11) BOOST_ERROR( "failed to reproduce cached cap value:\n" << std::setprecision(12) << " calculated: " << cap->NPV() << "\n" << " expected: " << cachedCapNPV); // test Black floor price against cached value if (std::fabs(floor->NPV()-cachedFloorNPV) > 1.0e-11) BOOST_ERROR( "failed to reproduce cached floor value:\n" << std::setprecision(12) << " calculated: " << floor->NPV() << "\n" << " expected: " << cachedFloorNPV); } test_suite* CapFloorTest::suite() { test_suite* suite = BOOST_TEST_SUITE("Cap/floor tests"); suite->add(BOOST_TEST_CASE(&CapFloorTest::testStrikeDependency)); suite->add(BOOST_TEST_CASE(&CapFloorTest::testConsistency)); // FLOATING_POINT_EXCEPTION suite->add(BOOST_TEST_CASE(&CapFloorTest::testParity)); suite->add(BOOST_TEST_CASE(&CapFloorTest::testVega)); suite->add(BOOST_TEST_CASE(&CapFloorTest::testATMRate)); suite->add(BOOST_TEST_CASE(&CapFloorTest::testImpliedVolatility)); suite->add(BOOST_TEST_CASE(&CapFloorTest::testCachedValue)); return suite; } |