Hello, I'm using PiecewiseYieldCurve to build a YieldTermStructure which is ultimately used by BlackScholesMertonProcess in my option pricing. I believe I'm running into an issue on days that are holidays in the UK (but not the US). Here's the error I'm seeing when trying to run the code below for May 5, 2014 (Early May Bank Holiday):
terminate called after throwing an instance of 'QuantLib::Error' what(): 1st iteration: failed at 1st alive instrument, maturity May 14th, 2014, reference date May 7th, 2014: Missing no-fix1W Actual/360 fixing for May 2nd, 2014
Aborted Everything seems to work fine on other days... Am I doing something wrong with setting up the PiecewiseYieldCurve? Thanks, George
#include <ql/quantlib.hpp> using namespace std ; using namespace QuantLib ; int main(int argc, char** argv) { vector<Rate> liborRates ;
liborRates.push_back(0.12075 / 100.0) ; //1W liborRates.push_back(0.1515 / 100.0) ; //1M liborRates.push_back(0.1935 / 100.0) ; //2M liborRates.push_back(0.22535 / 100.0) ; //3M
liborRates.push_back(0.323 / 100.0) ; //6M liborRates.push_back(0.549 / 100.0) ; //12M vector<Period> periods ; periods.push_back(Period(1,Weeks)) ;
periods.push_back(Period(1,Months)) ; periods.push_back(Period(2,Months)) ; periods.push_back(Period(3,Months)) ; periods.push_back(Period(6,Months)) ; periods.push_back(Period(12,Months)) ;
vector<boost::shared_ptr<RateHelper> > instruments ; for (vector<int>::size_type i = 0 ; i < liborRates.size() ; i++) { boost::shared_ptr<Quote> liborQuote(new SimpleQuote(liborRates[i])) ;
Handle<Quote> liborHandle(liborQuote) ; boost::shared_ptr<IborIndex> liborIndex(new USDLibor(periods[i])) ; boost::shared_ptr<RateHelper> rateHelper(new DepositRateHelper(liborHandle,liborIndex)) ;
instruments.push_back(rateHelper) ; } Calendar calendar = UnitedStates(); Date today (5 , May ,2014); Settings::instance().evaluationDate() = today ;
Natural settlementDays = 2; Date settlement = calendar.advance ( today , settlementDays , Days ); DayCounter dc = Actual360 (); Date maturity(20, Jun, 2014) ;
double strikePrice = 100.0 ; Option::Type optionType = Option::Call ; double dividendYield = 0.0 ; double impliedVolatility = 0.15 ; double underlyingPrice = 100.0 ;
Handle<Quote> underlyingHandle(boost::shared_ptr<Quote>(new SimpleQuote(underlyingPrice))); Handle<YieldTermStructure> rateTermStructure(boost::shared_ptr<YieldTermStructure>(new PiecewiseYieldCurve<ZeroYield,Linear>(settlement, instruments, dc))) ;
Handle<YieldTermStructure> dividendTermStructure(boost::shared_ptr<YieldTermStructure>(new FlatForward(today, dividendYield,
dc))); Handle<BlackVolTermStructure> volTermStructure(boost::shared_ptr<BlackVolTermStructure>(new BlackConstantVol(today,
calendar, impliedVolatility, dc)));
boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(new BlackScholesMertonProcess(underlyingHandle, dividendTermStructure,
rateTermStructure, volTermStructure)); boost::shared_ptr<Exercise> americanExercise(new AmericanExercise(today, maturity)) ;
boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff(optionType, strikePrice)); VanillaOption americanOption(payoff, americanExercise); americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
new FDAmericanEngine<CrankNicolson>(bsmProcess, 101,100))); cout << americanOption.NPV() << endl ; return 0 ; } ------------------------------------------------------------------------------ Want fast and easy access to all the code in your enterprise? Index and search up to 200,000 lines of code with a free copy of Black Duck Code Sight - the same software that powers the world's largest code search on Ohloh, the Black Duck Open Hub! Try it now. http://p.sf.net/sfu/bds _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
Hi George, the problem occurs because you are trying to bootstrap on a UnitedKingdom holiday, which is implicitly included in the definition of USDLibor. The Libor class makes a joint calendar between the given financial center calendar and the UK calendar. Since Libor is a London poll, there are only fixings for it on UK business days. If one wants to bootstrap the curve on a holiday, the indice's historical fixings (actually just the closest fixing to the given date) need to be provided. Mit freundlichen Grüßen / Kind regards Dr. Andres Hernandez Senior Financial Engineer Business Analytics Risk Analytics Phone: +49-69-6645-1351 IBM Deutschland (Embedded image moved to file: pic65048.gif) Mobile: +49-163-609-3280 Wilhelm-Fay-Str. 30-34 E-Mail: [hidden email] 65936 Frankfurt am Main Germany IBM Deutschland GmbH / Vorsitzender des Aufsichtsrats: Martin Jetter Geschäftsführung: Martina Koederitz (Vorsitzende), Reinhard Reschke, Dieter Scholz, Gregor Pillen, Christian Noll, Ivo Koerner Sitz der Gesellschaft: Ehningen / Registergericht: Amtsgericht Stuttgart, HRB 14562 / WEEE-Reg.-Nr. DE 99369940 From: George Cowie <[hidden email]> To: QuantLib users <[hidden email]> Date: 22/07/2014 14:10 Subject: [Quantlib-users] UK Holiday for USDLibor/PiecewiseYieldCurve Hello, I'm using PiecewiseYieldCurve to build a YieldTermStructure which is ultimately used by BlackScholesMertonProcess in my option pricing. I believe I'm running into an issue on days that are holidays in the UK (but not the US). Here's the error I'm seeing when trying to run the code below for May 5, 2014 (Early May Bank Holiday): terminate called after throwing an instance of 'QuantLib::Error' what(): 1st iteration: failed at 1st alive instrument, maturity May 14th, 2014, reference date May 7th, 2014: Missing no-fix1W Actual/360 fixing for May 2nd, 2014 Aborted Everything seems to work fine on other days... Am I doing something wrong with setting up the PiecewiseYieldCurve? Thanks, George #include <ql/quantlib.hpp> using namespace std ; using namespace QuantLib ; int main(int argc, char** argv) { vector<Rate> liborRates ; liborRates.push_back(0.12075 / 100.0) ; //1W liborRates.push_back(0.1515 / 100.0) ; //1M liborRates.push_back(0.1935 / 100.0) ; //2M liborRates.push_back(0.22535 / 100.0) ; //3M liborRates.push_back(0.323 / 100.0) ; //6M liborRates.push_back(0.549 / 100.0) ; //12M vector<Period> periods ; periods.push_back(Period(1,Weeks)) ; periods.push_back(Period(1,Months)) ; periods.push_back(Period(2,Months)) ; periods.push_back(Period(3,Months)) ; periods.push_back(Period(6,Months)) ; periods.push_back(Period(12,Months)) ; vector<boost::shared_ptr<RateHelper> > instruments ; for (vector<int>::size_type i = 0 ; i < liborRates.size() ; i++) { boost::shared_ptr<Quote> liborQuote(new SimpleQuote(liborRates[i])) ; Handle<Quote> liborHandle(liborQuote) ; boost::shared_ptr<IborIndex> liborIndex(new USDLibor(periods[i])) ; boost::shared_ptr<RateHelper> rateHelper(new DepositRateHelper (liborHandle,liborIndex)) ; instruments.push_back(rateHelper) ; } Calendar calendar = UnitedStates(); Date today (5 , May ,2014); Settings::instance().evaluationDate() = today ; Natural settlementDays = 2; Date settlement = calendar.advance ( today , settlementDays , Days ); DayCounter dc = Actual360 (); Date maturity(20, Jun, 2014) ; double strikePrice = 100.0 ; Option::Type optionType = Option::Call ; double dividendYield = 0.0 ; double impliedVolatility = 0.15 ; double underlyingPrice = 100.0 ; Handle<Quote> underlyingHandle(boost::shared_ptr<Quote>(new SimpleQuote (underlyingPrice))); Handle<YieldTermStructure> rateTermStructure (boost::shared_ptr<YieldTermStructure>(new PiecewiseYieldCurve<ZeroYield,Linear>(settlement, instruments, dc))) ; Handle<YieldTermStructure> dividendTermStructure(boost::shared_ptr<YieldTermStructure>(new FlatForward(today, dividendYield, dc))); Handle<BlackVolTermStructure> volTermStructure(boost::shared_ptr<BlackVolTermStructure>(new BlackConstantVol(today, calendar, impliedVolatility, dc))); boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(new BlackScholesMertonProcess(underlyingHandle, dividendTermStructure, rateTermStructure, volTermStructure)); boost::shared_ptr<Exercise> americanExercise(new AmericanExercise(today, maturity)) ; boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff (optionType, strikePrice)); VanillaOption americanOption(payoff, americanExercise); americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>( new FDAmericanEngine<CrankNicolson>(bsmProcess, 101,100))); cout << americanOption.NPV() << endl ; return 0 ; } ------------------------------------------------------------------------------ Want fast and easy access to all the code in your enterprise? Index and search up to 200,000 lines of code with a free copy of Black Duck Code Sight - the same software that powers the world's largest code search on Ohloh, the Black Duck Open Hub! Try it now. http://p.sf.net/sfu/bds_______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users ------------------------------------------------------------------------------ Want fast and easy access to all the code in your enterprise? Index and search up to 200,000 lines of code with a free copy of Black Duck Code Sight - the same software that powers the world's largest code search on Ohloh, the Black Duck Open Hub! Try it now. http://p.sf.net/sfu/bds _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users pic65048.gif (2K) Download Attachment |
Thank you Andres. What you're describing makes sense, but I can't seem to avoid an error when trying to value the option on May 5, 2014. I've copied the updated code snippet with changed section highlighted/bolded below. I seem to always get an exception of the form: terminate called after throwing an instance of 'QuantLib::Error' what(): 1st iteration: failed at 1st alive instrument, maturity May 14th, 2014, reference date May 6th, 2014: Missing no-fix1W Actual/360 fixing for May 2nd, 2014
Is there something wrong with my approach here? Thanks, George #include <ql/quantlib.hpp> using namespace std ;
using namespace QuantLib ; int main(int argc, char** argv) { vector<Rate> liborRates ; liborRates.push_back(0.12075 / 100.0) ; //1W liborRates.push_back(0.1515 / 100.0) ; //1M
liborRates.push_back(0.1935 / 100.0) ; //2M liborRates.push_back(0.22535 / 100.0) ; //3M liborRates.push_back(0.323 / 100.0) ; //6M liborRates.push_back(0.549 / 100.0) ; //12M
vector<Period> periods ; periods.push_back(Period(1,Weeks)) ; periods.push_back(Period(1,Months)) ; periods.push_back(Period(2,Months)) ; periods.push_back(Period(3,Months)) ;
periods.push_back(Period(6,Months)) ; periods.push_back(Period(12,Months)) ; vector<boost::shared_ptr<RateHelper> > instruments ; for (vector<int>::size_type i = 0 ; i < liborRates.size() ; i++)
{ boost::shared_ptr<Quote> liborQuote(new SimpleQuote(liborRates[i])) ; Handle<Quote> liborHandle(liborQuote) ; boost::shared_ptr<IborIndex> liborIndex(new USDLibor(periods[i])) ;
boost::shared_ptr<RateHelper> rateHelper(new DepositRateHelper(liborHandle,liborIndex)) ; instruments.push_back(rateHelper) ; } Calendar calendar = UnitedStates();
Date today (5 , May ,2014); Date liborDate (2, May, 2014) ; Settings::instance().evaluationDate() = today ; Natural settlementDays = 2;
Date settlement = calendar.advance ( liborDate , settlementDays , Days ); DayCounter dc = Actual360 (); Date maturity(20, Jun, 2014) ;
double strikePrice = 100.0 ; Option::Type optionType = Option::Call ; double dividendYield = 0.0 ; double impliedVolatility = 0.15 ; double underlyingPrice = 100.0 ;
Handle<Quote> underlyingHandle(boost::shared_ptr<Quote>(new SimpleQuote(underlyingPrice))); Handle<YieldTermStructure> rateTermStructure(boost::shared_ptr<YieldTermStructure>(new PiecewiseYieldCurve<ZeroYield,Linear>(settlement, instruments, dc))) ;
Handle<YieldTermStructure> dividendTermStructure(boost::shared_ptr<YieldTermStructure>(new FlatForward(today, dividendYield,
dc))); Handle<BlackVolTermStructure> volTermStructure(boost::shared_ptr<BlackVolTermStructure>(new BlackConstantVol(today,
calendar, impliedVolatility, dc)));
boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(new BlackScholesMertonProcess(underlyingHandle, dividendTermStructure,
rateTermStructure, volTermStructure)); boost::shared_ptr<Exercise> americanExercise(new AmericanExercise(today,
maturity)) ; boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff(optionType, strikePrice)); VanillaOption americanOption(payoff, americanExercise);
americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>( new FDAmericanEngine<CrankNicolson>(bsmProcess,
101,100))); cout << americanOption.NPV() << endl ; return 0 ; } On Tue, Jul 22, 2014 at 7:39 AM, Andres Hernandez <[hidden email]> wrote:
------------------------------------------------------------------------------ Want fast and easy access to all the code in your enterprise? Index and search up to 200,000 lines of code with a free copy of Black Duck Code Sight - the same software that powers the world's largest code search on Ohloh, the Black Duck Open Hub! Try it now. http://p.sf.net/sfu/bds _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
Hi George, you are still setting the evaluation date to a holiday: Date today (5 , May ,2014); Date liborDate (2, May, 2014) ; Settings::instance().evaluationDate() = today ; Let's follow the logic: During bootstrapping, the method impliedQuote() of the rate helper is called to compare against the market quote. The DepositRateHelper simply returns the fixing corresponding to the fixingDate_ as a return value. The fixingDate_ is set during initialization as the return value of the function InterestRate::fixingDate(earliestDate_). The function InterestRate::fixingDate sets back the date given as input parameter by the number of fixing days according to the index' calendar. The parameter earliestDate_ being passed to fixingDate is set during initialization to the evaluation date (which you set to the 5th of May) moved forward by the number of fixing days according to the index' calendar. Note that if the evaluation date is a holiday you do not end up with the same date, but rather with the last business day prior to evaluation date. The first act moves the date from the 5th of May to the 7th and checks whether it is a business day, which it is. The second move sets it back two days to the 5th, and checks whether it is a business day, which it isn't, so it sets it back until it finds a business day, i.e. the 2nd of May. Since the value is in the past, it requests a historical fixing, which you did not provide and so the QL_REQUIRE throws. Mit freundlichen Grüßen / Kind regards Dr. Andres Hernandez Senior Financial Engineer Business Analytics Risk Analytics Phone: +49-69-6645-1351 IBM Deutschland (Embedded image moved to file: pic64586.gif) Mobile: +49-163-609-3280 Wilhelm-Fay-Str. 30-34 E-Mail: [hidden email] 65936 Frankfurt am Main Germany IBM Deutschland GmbH / Vorsitzender des Aufsichtsrats: Martin Jetter Geschäftsführung: Martina Koederitz (Vorsitzende), Reinhard Reschke, Dieter Scholz, Gregor Pillen, Christian Noll, Ivo Koerner Sitz der Gesellschaft: Ehningen / Registergericht: Amtsgericht Stuttgart, HRB 14562 / WEEE-Reg.-Nr. DE 99369940 From: George Cowie <[hidden email]> To: Andres Hernandez/Germany/IBM@IBMDE Cc: QuantLib users <[hidden email]> Date: 23/07/2014 11:51 Subject: Re: [Quantlib-users] UK Holiday for USDLibor/PiecewiseYieldCurve Thank you Andres. What you're describing makes sense, but I can't seem to avoid an error when trying to value the option on May 5, 2014. I've copied the updated code snippet with changed section highlighted/bolded below. I seem to always get an exception of the form: terminate called after throwing an instance of 'QuantLib::Error' what(): 1st iteration: failed at 1st alive instrument, maturity May 14th, 2014, reference date May 6th, 2014: Missing no-fix1W Actual/360 fixing for May 2nd, 2014 Is there something wrong with my approach here? Thanks, George #include <ql/quantlib.hpp> using namespace std ; using namespace QuantLib ; int main(int argc, char** argv) { vector<Rate> liborRates ; liborRates.push_back(0.12075 / 100.0) ; //1W liborRates.push_back(0.1515 / 100.0) ; //1M liborRates.push_back(0.1935 / 100.0) ; //2M liborRates.push_back(0.22535 / 100.0) ; //3M liborRates.push_back(0.323 / 100.0) ; //6M liborRates.push_back(0.549 / 100.0) ; //12M vector<Period> periods ; periods.push_back(Period(1,Weeks)) ; periods.push_back(Period(1,Months)) ; periods.push_back(Period(2,Months)) ; periods.push_back(Period(3,Months)) ; periods.push_back(Period(6,Months)) ; periods.push_back(Period(12,Months)) ; vector<boost::shared_ptr<RateHelper> > instruments ; for (vector<int>::size_type i = 0 ; i < liborRates.size() ; i++) { boost::shared_ptr<Quote> liborQuote(new SimpleQuote(liborRates[i])) ; Handle<Quote> liborHandle(liborQuote) ; boost::shared_ptr<IborIndex> liborIndex(new USDLibor(periods[i])) ; boost::shared_ptr<RateHelper> rateHelper(new DepositRateHelper (liborHandle,liborIndex)) ; instruments.push_back(rateHelper) ; } Calendar calendar = UnitedStates(); Date today (5 , May ,2014); Date liborDate (2, May, 2014) ; Settings::instance().evaluationDate() = today ; Natural settlementDays = 2; Date settlement = calendar.advance ( liborDate , settlementDays , Days ); DayCounter dc = Actual360 (); Date maturity(20, Jun, 2014) ; double strikePrice = 100.0 ; Option::Type optionType = Option::Call ; double dividendYield = 0.0 ; double impliedVolatility = 0.15 ; double underlyingPrice = 100.0 ; Handle<Quote> underlyingHandle(boost::shared_ptr<Quote>(new SimpleQuote (underlyingPrice))); Handle<YieldTermStructure> rateTermStructure (boost::shared_ptr<YieldTermStructure>(new PiecewiseYieldCurve<ZeroYield,Linear>(settlement, instruments, dc))) ; Handle<YieldTermStructure> dividendTermStructure(boost::shared_ptr<YieldTermStructure>(new FlatForward(today, dividendYield, dc))); Handle<BlackVolTermStructure> volTermStructure(boost::shared_ptr<BlackVolTermStructure>(new BlackConstantVol(today, calendar, impliedVolatility, dc))); boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(new BlackScholesMertonProcess(underlyingHandle, dividendTermStructure, rateTermStructure, volTermStructure)); boost::shared_ptr<Exercise> americanExercise(new AmericanExercise(today, maturity)) ; boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff (optionType, strikePrice)); VanillaOption americanOption(payoff, americanExercise); americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>( new FDAmericanEngine<CrankNicolson>(bsmProcess, 101,100))); cout << americanOption.NPV() << endl ; return 0 ; } On Tue, Jul 22, 2014 at 7:39 AM, Andres Hernandez < [hidden email]> wrote: Hi George, the problem occurs because you are trying to bootstrap on a UnitedKingdom holiday, which is implicitly included in the definition of USDLibor. The Libor class makes a joint calendar between the given financial center calendar and the UK calendar. Since Libor is a London poll, there are only fixings for it on UK business days. If one wants to bootstrap the curve on a holiday, the indice's historical fixings (actually just the closest fixing to the given date) need to be provided. Mit freundlichen Grüßen / Kind regards Dr. Andres Hernandez Senior Financial Engineer Business Analytics Risk Analytics Phone: +49-69-6645-1351 IBM Deutschland (Embedded image moved to file: pic20635.gif) Mobile: +49-163-609-3280 Wilhelm-Fay-Str. 30-34 E-Mail: [hidden email] 65936 Frankfurt am Main Germany IBM Deutschland GmbH / Vorsitzender des Aufsichtsrats: Martin Jetter Geschäftsführung: Martina Koederitz (Vorsitzende), Reinhard Reschke, Dieter Scholz, Gregor Pillen, Christian Noll, Ivo Koerner Sitz der Gesellschaft: Ehningen / Registergericht: Amtsgericht Stuttgart, HRB 14562 / WEEE-Reg.-Nr. DE 99369940 From: George Cowie <[hidden email]> To: QuantLib users <[hidden email]> Date: 22/07/2014 14:10 Subject: [Quantlib-users] UK Holiday for USDLibor/PiecewiseYieldCurve Hello, I'm using PiecewiseYieldCurve to build a YieldTermStructure which is ultimately used by BlackScholesMertonProcess in my option pricing. I believe I'm running into an issue on days that are holidays in the UK (but not the US). Here's the error I'm seeing when trying to run the code below for May 5, 2014 (Early May Bank Holiday): terminate called after throwing an instance of 'QuantLib::Error' what(): 1st iteration: failed at 1st alive instrument, maturity May 14th, 2014, reference date May 7th, 2014: Missing no-fix1W Actual/360 fixing for May 2nd, 2014 Aborted Everything seems to work fine on other days... Am I doing something wrong with setting up the PiecewiseYieldCurve? Thanks, George #include <ql/quantlib.hpp> using namespace std ; using namespace QuantLib ; int main(int argc, char** argv) { vector<Rate> liborRates ; liborRates.push_back(0.12075 / 100.0) ; //1W liborRates.push_back(0.1515 / 100.0) ; //1M liborRates.push_back(0.1935 / 100.0) ; //2M liborRates.push_back(0.22535 / 100.0) ; //3M liborRates.push_back(0.323 / 100.0) ; //6M liborRates.push_back(0.549 / 100.0) ; //12M vector<Period> periods ; periods.push_back(Period(1,Weeks)) ; periods.push_back(Period(1,Months)) ; periods.push_back(Period(2,Months)) ; periods.push_back(Period(3,Months)) ; periods.push_back(Period(6,Months)) ; periods.push_back(Period(12,Months)) ; vector<boost::shared_ptr<RateHelper> > instruments ; for (vector<int>::size_type i = 0 ; i < liborRates.size() ; i++) { boost::shared_ptr<Quote> liborQuote(new SimpleQuote(liborRates [i])) ; Handle<Quote> liborHandle(liborQuote) ; boost::shared_ptr<IborIndex> liborIndex(new USDLibor(periods [i])) ; boost::shared_ptr<RateHelper> rateHelper(new DepositRateHelper (liborHandle,liborIndex)) ; instruments.push_back(rateHelper) ; } Calendar calendar = UnitedStates(); Date today (5 , May ,2014); Settings::instance().evaluationDate() = today ; Natural settlementDays = 2; Date settlement = calendar.advance ( today , settlementDays , Days ); DayCounter dc = Actual360 (); Date maturity(20, Jun, 2014) ; double strikePrice = 100.0 ; Option::Type optionType = Option::Call ; double dividendYield = 0.0 ; double impliedVolatility = 0.15 ; double underlyingPrice = 100.0 ; Handle<Quote> underlyingHandle(boost::shared_ptr<Quote>(new SimpleQuote (underlyingPrice))); Handle<YieldTermStructure> rateTermStructure (boost::shared_ptr<YieldTermStructure>(new PiecewiseYieldCurve<ZeroYield,Linear>(settlement, instruments, dc))) ; Handle<YieldTermStructure> dividendTermStructure(boost::shared_ptr<YieldTermStructure>(new FlatForward(today, dividendYield, dc))); Handle<BlackVolTermStructure> volTermStructure(boost::shared_ptr<BlackVolTermStructure>(new BlackConstantVol(today, calendar, impliedVolatility, dc))); boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(new BlackScholesMertonProcess(underlyingHandle, dividendTermStructure, rateTermStructure, volTermStructure)); boost::shared_ptr<Exercise> americanExercise(new AmericanExercise (today, maturity)) ; boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff (optionType, strikePrice)); VanillaOption americanOption(payoff, americanExercise); americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>( new FDAmericanEngine<CrankNicolson>(bsmProcess, 101,100))); cout << americanOption.NPV() << endl ; return 0 ; } ------------------------------------------------------------------------------ Want fast and easy access to all the code in your enterprise? Index and search up to 200,000 lines of code with a free copy of Black Duck Code Sight - the same software that powers the world's largest code search on Ohloh, the Black Duck Open Hub! Try it now. http://p.sf.net/sfu/bds_______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users ------------------------------------------------------------------------------ Want fast and easy access to all the code in your enterprise? Index and search up to 200,000 lines of code with a free copy of Black Duck Code Sight - the same software that powers the world's largest code search on Ohloh, the Black Duck Open Hub! Try it now. http://p.sf.net/sfu/bds _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users pic64586.gif (2K) Download Attachment |
Hi,
I think this question is an older one but I don't remember that it was finally decided how to handle this situation (?) - which is, should we allow to bootstrap a curve on a day which is a holiday for the cash instruments in the curve or not. If negative, we could maybe throw a different message ( the current one indeed sounds a bit paradoxical ). If yes ( which would be my personal preference, because you simply want to run your daily processes spitting out numbers even if not a hundred percent sensible all of them ), one has to define how a deposit which is not traded on that day should be calculated. One obvious way would be to just treat the evaluation date as a business day when calculating the helper's fixing date. I did not try, but it may be enough to join the business days of the helper's calendar with a new one just having one business day (the evaluation date) before passing it to the no-fix index to make this kind of solution work. What do you think ? Peter On 23 July 2014 15:05, Andres Hernandez <[hidden email]> wrote: > > Hi George, > > you are still setting the evaluation date to a holiday: > > Date today (5 , May ,2014); > Date liborDate (2, May, 2014) ; > Settings::instance().evaluationDate() = today ; > > > Let's follow the logic: > During bootstrapping, the method impliedQuote() of the rate helper is > called to compare against the market quote. The DepositRateHelper simply > returns the fixing corresponding to the fixingDate_ as a return value. > The fixingDate_ is set during initialization as the return value of the > function InterestRate::fixingDate(earliestDate_). The function > InterestRate::fixingDate sets back the date given as input parameter by the > number of fixing days according to the index' calendar. > The parameter earliestDate_ being passed to fixingDate is set during > initialization to the evaluation date (which you set to the 5th of May) > moved forward by the number of fixing days according to the index' > calendar. > Note that if the evaluation date is a holiday you do not end up with the > same date, but rather with the last business day prior to evaluation date. > The first act moves the date from the 5th of May to the 7th and checks > whether it is a business day, which it is. The second move sets it back two > days to the 5th, and checks whether it is a business day, which it isn't, > so it sets it back until it finds a business day, i.e. the 2nd of May. > Since the value is in the past, it requests a historical fixing, which you > did not provide and so the QL_REQUIRE throws. > > Mit freundlichen Grüßen / Kind regards > > Dr. Andres Hernandez > > Senior Financial Engineer > Business Analytics > Risk Analytics > > > > > > Phone: +49-69-6645-1351 IBM Deutschland (Embedded > image moved > to file: > pic64586.gif) > > Mobile: +49-163-609-3280 Wilhelm-Fay-Str. 30-34 > > E-Mail: [hidden email] 65936 Frankfurt am Main > > Germany > > > > > > IBM Deutschland > GmbH / > Vorsitzender des > Aufsichtsrats: > Martin Jetter > Geschäftsführung: > Martina Koederitz > (Vorsitzende), > Reinhard Reschke, > Dieter Scholz, > Gregor Pillen, > Christian Noll, > Ivo Koerner > Sitz der > Gesellschaft: > Ehningen / > Registergericht: > Amtsgericht > Stuttgart, HRB > 14562 / > WEEE-Reg.-Nr. DE > 99369940 > > > > > > > From: George Cowie <[hidden email]> > To: Andres Hernandez/Germany/IBM@IBMDE > Cc: QuantLib users <[hidden email]> > Date: 23/07/2014 11:51 > Subject: Re: [Quantlib-users] UK Holiday for > USDLibor/PiecewiseYieldCurve > > > > > Thank you Andres. What you're describing makes sense, but I can't seem to > avoid an error when trying to value the option on May 5, 2014. I've copied > the updated code snippet with changed section highlighted/bolded below. I > seem to always get an exception of the form: > > terminate called after throwing an instance of 'QuantLib::Error' > what(): 1st iteration: failed at 1st alive instrument, maturity May > 14th, 2014, reference date May 6th, 2014: Missing no-fix1W Actual/360 > fixing for May 2nd, 2014 > > Is there something wrong with my approach here? > > Thanks, > George > > > #include <ql/quantlib.hpp> > > using namespace std ; > using namespace QuantLib ; > > int main(int argc, char** argv) > { > vector<Rate> liborRates ; > liborRates.push_back(0.12075 / 100.0) ; //1W > liborRates.push_back(0.1515 / 100.0) ; //1M > liborRates.push_back(0.1935 / 100.0) ; //2M > liborRates.push_back(0.22535 / 100.0) ; //3M > liborRates.push_back(0.323 / 100.0) ; //6M > liborRates.push_back(0.549 / 100.0) ; //12M > > vector<Period> periods ; > periods.push_back(Period(1,Weeks)) ; > periods.push_back(Period(1,Months)) ; > periods.push_back(Period(2,Months)) ; > periods.push_back(Period(3,Months)) ; > periods.push_back(Period(6,Months)) ; > periods.push_back(Period(12,Months)) ; > > vector<boost::shared_ptr<RateHelper> > instruments ; > > for (vector<int>::size_type i = 0 ; i < liborRates.size() ; i++) > { > boost::shared_ptr<Quote> liborQuote(new SimpleQuote(liborRates[i])) ; > Handle<Quote> liborHandle(liborQuote) ; > boost::shared_ptr<IborIndex> liborIndex(new USDLibor(periods[i])) ; > boost::shared_ptr<RateHelper> rateHelper(new DepositRateHelper > (liborHandle,liborIndex)) ; > instruments.push_back(rateHelper) ; > } > > Calendar calendar = UnitedStates(); > Date today (5 , May ,2014); > Date liborDate (2, May, 2014) ; > Settings::instance().evaluationDate() = today ; > Natural settlementDays = 2; > Date settlement = calendar.advance ( liborDate , settlementDays , Days ); > DayCounter dc = Actual360 (); > > Date maturity(20, Jun, 2014) ; > double strikePrice = 100.0 ; > Option::Type optionType = Option::Call ; > double dividendYield = 0.0 ; > double impliedVolatility = 0.15 ; > double underlyingPrice = 100.0 ; > > Handle<Quote> underlyingHandle(boost::shared_ptr<Quote>(new SimpleQuote > (underlyingPrice))); > > Handle<YieldTermStructure> rateTermStructure > (boost::shared_ptr<YieldTermStructure>(new > PiecewiseYieldCurve<ZeroYield,Linear>(settlement, instruments, dc))) ; > > Handle<YieldTermStructure> > dividendTermStructure(boost::shared_ptr<YieldTermStructure>(new > FlatForward(today, > dividendYield, > dc))); > Handle<BlackVolTermStructure> > volTermStructure(boost::shared_ptr<BlackVolTermStructure>(new > BlackConstantVol(today, > calendar, > impliedVolatility, > dc))); > > boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(new > BlackScholesMertonProcess(underlyingHandle, > dividendTermStructure, > rateTermStructure, > volTermStructure)); > > boost::shared_ptr<Exercise> americanExercise(new AmericanExercise(today, > maturity)) ; > boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff > (optionType, strikePrice)); > > VanillaOption americanOption(payoff, americanExercise); > > americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>( > new FDAmericanEngine<CrankNicolson>(bsmProcess, > 101,100))); > > cout << americanOption.NPV() << endl ; > > return 0 ; > } > > > > On Tue, Jul 22, 2014 at 7:39 AM, Andres Hernandez < > [hidden email]> wrote: > > Hi George, > > the problem occurs because you are trying to bootstrap on a > UnitedKingdom > holiday, which is implicitly included in the definition of USDLibor. > The > Libor class makes a joint calendar between the given financial center > calendar and the UK calendar. Since Libor is a London poll, there are > only > fixings for it on UK business days. If one wants to bootstrap the > curve on > a holiday, the indice's historical fixings (actually just the closest > fixing to the given date) need to be provided. > > > Mit freundlichen Grüßen / Kind regards > > Dr. Andres Hernandez > > Senior Financial Engineer > Business Analytics > Risk Analytics > > > > > > Phone: +49-69-6645-1351 IBM Deutschland > (Embedded > image moved > to file: > pic20635.gif) > > Mobile: +49-163-609-3280 Wilhelm-Fay-Str. > 30-34 > > E-Mail: [hidden email] 65936 Frankfurt am > Main > > Germany > > > > > > IBM Deutschland > GmbH / > Vorsitzender des > Aufsichtsrats: > Martin Jetter > Geschäftsführung: > Martina Koederitz > (Vorsitzende), > Reinhard Reschke, > Dieter Scholz, > Gregor Pillen, > Christian Noll, > Ivo Koerner > Sitz der > Gesellschaft: > Ehningen / > Registergericht: > Amtsgericht > Stuttgart, HRB > 14562 / > WEEE-Reg.-Nr. DE > 99369940 > > > > > > > From: George Cowie <[hidden email]> > To: QuantLib users <[hidden email]> > Date: 22/07/2014 14:10 > Subject: [Quantlib-users] UK Holiday for > USDLibor/PiecewiseYieldCurve > > > > Hello, > > I'm using PiecewiseYieldCurve to build a YieldTermStructure which > is > ultimately used by BlackScholesMertonProcess in my option pricing. I > believe I'm running into an issue on days that are holidays in the UK > (but > not the US). Here's the error I'm seeing when trying to run the code > below > for May 5, 2014 (Early May Bank Holiday): > > terminate called after throwing an instance of 'QuantLib::Error' > what(): 1st iteration: failed at 1st alive instrument, maturity > May > 14th, 2014, reference date May 7th, 2014: Missing no-fix1W Actual/360 > fixing for May 2nd, 2014 > Aborted > > Everything seems to work fine on other days... Am I doing > something > wrong with setting up the PiecewiseYieldCurve? > > Thanks, > George > > #include <ql/quantlib.hpp> > > using namespace std ; > using namespace QuantLib ; > > int main(int argc, char** argv) > { > vector<Rate> liborRates ; > liborRates.push_back(0.12075 / 100.0) ; //1W > liborRates.push_back(0.1515 / 100.0) ; //1M > liborRates.push_back(0.1935 / 100.0) ; //2M > liborRates.push_back(0.22535 / 100.0) ; //3M > liborRates.push_back(0.323 / 100.0) ; //6M > liborRates.push_back(0.549 / 100.0) ; //12M > > vector<Period> periods ; > periods.push_back(Period(1,Weeks)) ; > periods.push_back(Period(1,Months)) ; > periods.push_back(Period(2,Months)) ; > periods.push_back(Period(3,Months)) ; > periods.push_back(Period(6,Months)) ; > periods.push_back(Period(12,Months)) ; > > vector<boost::shared_ptr<RateHelper> > instruments ; > > for (vector<int>::size_type i = 0 ; i < liborRates.size() ; i++) > { > boost::shared_ptr<Quote> liborQuote(new SimpleQuote(liborRates > [i])) ; > Handle<Quote> liborHandle(liborQuote) ; > boost::shared_ptr<IborIndex> liborIndex(new USDLibor(periods > [i])) ; > boost::shared_ptr<RateHelper> rateHelper(new DepositRateHelper > (liborHandle,liborIndex)) ; > instruments.push_back(rateHelper) ; > } > > Calendar calendar = UnitedStates(); > Date today (5 , May ,2014); > Settings::instance().evaluationDate() = today ; > Natural settlementDays = 2; > Date settlement = calendar.advance ( today , settlementDays , > Days ); > DayCounter dc = Actual360 (); > > Date maturity(20, Jun, 2014) ; > double strikePrice = 100.0 ; > Option::Type optionType = Option::Call ; > double dividendYield = 0.0 ; > double impliedVolatility = 0.15 ; > double underlyingPrice = 100.0 ; > > Handle<Quote> underlyingHandle(boost::shared_ptr<Quote>(new > SimpleQuote > (underlyingPrice))); > > Handle<YieldTermStructure> rateTermStructure > (boost::shared_ptr<YieldTermStructure>(new > PiecewiseYieldCurve<ZeroYield,Linear>(settlement, instruments, > dc))) ; > > Handle<YieldTermStructure> > dividendTermStructure(boost::shared_ptr<YieldTermStructure>(new > FlatForward(today, > dividendYield, > dc))); > Handle<BlackVolTermStructure> > volTermStructure(boost::shared_ptr<BlackVolTermStructure>(new > BlackConstantVol(today, > calendar, > impliedVolatility, > dc))); > > boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(new > BlackScholesMertonProcess(underlyingHandle, > dividendTermStructure, > rateTermStructure, > volTermStructure)); > > boost::shared_ptr<Exercise> americanExercise(new AmericanExercise > (today, > maturity)) ; > boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff > (optionType, strikePrice)); > > VanillaOption americanOption(payoff, americanExercise); > > americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>( > new FDAmericanEngine<CrankNicolson>(bsmProcess, > 101,100))); > > cout << americanOption.NPV() << endl ; > > return 0 ; > } > ------------------------------------------------------------------------------ > > > Want fast and easy access to all the code in your enterprise? Index > and > search up to 200,000 lines of code with a free copy of Black Duck > Code Sight - the same software that powers the world's largest code > search on Ohloh, the Black Duck Open Hub! Try it now. > http://p.sf.net/sfu/bds_______________________________________________ > > QuantLib-users mailing list > [hidden email] > https://lists.sourceforge.net/lists/listinfo/quantlib-users > > ------------------------------------------------------------------------------ > Want fast and easy access to all the code in your enterprise? Index and > search up to 200,000 lines of code with a free copy of Black Duck > Code Sight - the same software that powers the world's largest code > search on Ohloh, the Black Duck Open Hub! Try it now. > http://p.sf.net/sfu/bds > _______________________________________________ > QuantLib-users mailing list > [hidden email] > https://lists.sourceforge.net/lists/listinfo/quantlib-users > ------------------------------------------------------------------------------ Want fast and easy access to all the code in your enterprise? Index and search up to 200,000 lines of code with a free copy of Black Duck Code Sight - the same software that powers the world's largest code search on Ohloh, the Black Duck Open Hub! Try it now. http://p.sf.net/sfu/bds _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
Hi Peter, I agree that it would be nice to at least have it as an option. We currently do a small workaround, whereby we set in our system a parameter for the curve specifying the holiday calendar for that curve. The only use of that calendar is to determine if it is a holiday for the curve or not and if yes to make a fallback to yesterday's values. In the case of the EUR curves, this is arguably a good behaviour as the index and the geographical region have the same calendar, but for the USD case, we are basically forcing a fallback for a holiday on a different country. The issue is compounded by the fact that in this case the deposit is traded on that day, it is just the index that gets no fixing. I took a look and I am almost sure that removing the evaluation date from the fixing calendar in InterestRate constructor would be enough to make deposits go through. This could simply be accomplished with an extra public member function that one would call if one wanted it to go through on holidays. A more involved and important problem would be to get the SwapRateHelper to go though on holidays (if desired), as I am positive that that was the reason for our instituting the fallback. I will see if I have the time to change it, and would then probably subscribe to the developers list to get some feedback in how to go about changing it. Mit freundlichen Grüßen / Kind regards Dr. Andres Hernandez Senior Financial Engineer Business Analytics Risk Analytics Phone: +49-69-6645-1351 IBM Deutschland (Embedded image moved to file: pic08098.gif) Mobile: +49-163-609-3280 Wilhelm-Fay-Str. 30-34 E-Mail: [hidden email] 65936 Frankfurt am Main Germany IBM Deutschland GmbH / Vorsitzender des Aufsichtsrats: Martin Jetter Geschäftsführung: Martina Koederitz (Vorsitzende), Reinhard Reschke, Dieter Scholz, Gregor Pillen, Christian Noll, Ivo Koerner Sitz der Gesellschaft: Ehningen / Registergericht: Amtsgericht Stuttgart, HRB 14562 / WEEE-Reg.-Nr. DE 99369940 From: Peter Caspers <[hidden email]> To: Andres Hernandez/Germany/IBM@IBMDE Cc: George Cowie <[hidden email]>, QuantLib users <[hidden email]> Date: 23/07/2014 21:56 Subject: Re: [Quantlib-users] UK Holiday for USDLibor/PiecewiseYieldCurve Hi, I think this question is an older one but I don't remember that it was finally decided how to handle this situation (?) - which is, should we allow to bootstrap a curve on a day which is a holiday for the cash instruments in the curve or not. If negative, we could maybe throw a different message ( the current one indeed sounds a bit paradoxical ). If yes ( which would be my personal preference, because you simply want to run your daily processes spitting out numbers even if not a hundred percent sensible all of them ), one has to define how a deposit which is not traded on that day should be calculated. One obvious way would be to just treat the evaluation date as a business day when calculating the helper's fixing date. I did not try, but it may be enough to join the business days of the helper's calendar with a new one just having one business day (the evaluation date) before passing it to the no-fix index to make this kind of solution work. What do you think ? Peter On 23 July 2014 15:05, Andres Hernandez <[hidden email]> wrote: > > Hi George, > > you are still setting the evaluation date to a holiday: > > Date today (5 , May ,2014); > Date liborDate (2, May, 2014) ; > Settings::instance().evaluationDate() = today ; > > > Let's follow the logic: > During bootstrapping, the method impliedQuote() of the rate helper is > called to compare against the market quote. The DepositRateHelper simply > returns the fixing corresponding to the fixingDate_ as a return value. > The fixingDate_ is set during initialization as the return value of the > function InterestRate::fixingDate(earliestDate_). The function > InterestRate::fixingDate sets back the date given as input parameter by > number of fixing days according to the index' calendar. > The parameter earliestDate_ being passed to fixingDate is set during > initialization to the evaluation date (which you set to the 5th of May) > moved forward by the number of fixing days according to the index' > calendar. > Note that if the evaluation date is a holiday you do not end up with the > same date, but rather with the last business day prior to evaluation > The first act moves the date from the 5th of May to the 7th and checks > whether it is a business day, which it is. The second move sets it back two > days to the 5th, and checks whether it is a business day, which it isn't, > so it sets it back until it finds a business day, i.e. the 2nd of May. > Since the value is in the past, it requests a historical fixing, which you > did not provide and so the QL_REQUIRE throws. > > Mit freundlichen Grüßen / Kind regards > > Dr. Andres Hernandez > > Senior Financial Engineer > Business Analytics > Risk Analytics > > > > > > Phone: +49-69-6645-1351 IBM Deutschland > > to file: > pic64586.gif) > > Mobile: +49-163-609-3280 Wilhelm-Fay-Str. 30-34 > > E-Mail: [hidden email] 65936 Frankfurt am Main > > Germany > > > > > > IBM Deutschland > GmbH / > Vorsitzender des > Aufsichtsrats: > Martin Jetter > Geschäftsführung: > Martina Koederitz > (Vorsitzende), > Reinhard Reschke, > Dieter Scholz, > Gregor Pillen, > Christian Noll, > Ivo Koerner > Sitz der > Gesellschaft: > Ehningen / > Registergericht: > Amtsgericht > Stuttgart, HRB > 14562 / > WEEE-Reg.-Nr. DE > 99369940 > > > > > > > From: George Cowie <[hidden email]> > To: Andres Hernandez/Germany/IBM@IBMDE > Cc: QuantLib users <[hidden email]> > Date: 23/07/2014 11:51 > Subject: Re: [Quantlib-users] UK Holiday for > USDLibor/PiecewiseYieldCurve > > > > > Thank you Andres. What you're describing makes sense, but I can't seem > avoid an error when trying to value the option on May 5, 2014. I've > the updated code snippet with changed section highlighted/bolded below. I > seem to always get an exception of the form: > > terminate called after throwing an instance of 'QuantLib::Error' > what(): 1st iteration: failed at 1st alive instrument, maturity May > 14th, 2014, reference date May 6th, 2014: Missing no-fix1W Actual/360 > fixing for May 2nd, 2014 > > Is there something wrong with my approach here? > > Thanks, > George > > > #include <ql/quantlib.hpp> > > using namespace std ; > using namespace QuantLib ; > > int main(int argc, char** argv) > { > vector<Rate> liborRates ; > liborRates.push_back(0.12075 / 100.0) ; //1W > liborRates.push_back(0.1515 / 100.0) ; //1M > liborRates.push_back(0.1935 / 100.0) ; //2M > liborRates.push_back(0.22535 / 100.0) ; //3M > liborRates.push_back(0.323 / 100.0) ; //6M > liborRates.push_back(0.549 / 100.0) ; //12M > > vector<Period> periods ; > periods.push_back(Period(1,Weeks)) ; > periods.push_back(Period(1,Months)) ; > periods.push_back(Period(2,Months)) ; > periods.push_back(Period(3,Months)) ; > periods.push_back(Period(6,Months)) ; > periods.push_back(Period(12,Months)) ; > > vector<boost::shared_ptr<RateHelper> > instruments ; > > for (vector<int>::size_type i = 0 ; i < liborRates.size() ; i++) > { > boost::shared_ptr<Quote> liborQuote(new SimpleQuote(liborRates > Handle<Quote> liborHandle(liborQuote) ; > boost::shared_ptr<IborIndex> liborIndex(new USDLibor(periods[i])) ; > boost::shared_ptr<RateHelper> rateHelper(new DepositRateHelper > (liborHandle,liborIndex)) ; > instruments.push_back(rateHelper) ; > } > > Calendar calendar = UnitedStates(); > Date today (5 , May ,2014); > Date liborDate (2, May, 2014) ; > Settings::instance().evaluationDate() = today ; > Natural settlementDays = 2; > Date settlement = calendar.advance ( liborDate , settlementDays , > DayCounter dc = Actual360 (); > > Date maturity(20, Jun, 2014) ; > double strikePrice = 100.0 ; > Option::Type optionType = Option::Call ; > double dividendYield = 0.0 ; > double impliedVolatility = 0.15 ; > double underlyingPrice = 100.0 ; > > Handle<Quote> underlyingHandle(boost::shared_ptr<Quote>(new SimpleQuote > (underlyingPrice))); > > Handle<YieldTermStructure> rateTermStructure > (boost::shared_ptr<YieldTermStructure>(new > PiecewiseYieldCurve<ZeroYield,Linear>(settlement, instruments, dc))) ; > > Handle<YieldTermStructure> > dividendTermStructure(boost::shared_ptr<YieldTermStructure>(new > FlatForward(today, > dividendYield, > dc))); > Handle<BlackVolTermStructure> > volTermStructure(boost::shared_ptr<BlackVolTermStructure>(new > BlackConstantVol(today, > calendar, > impliedVolatility, > dc))); > > boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(new > BlackScholesMertonProcess(underlyingHandle, > dividendTermStructure, > rateTermStructure, > volTermStructure)); > > boost::shared_ptr<Exercise> americanExercise(new AmericanExercise > maturity)) ; > boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff > (optionType, strikePrice)); > > VanillaOption americanOption(payoff, americanExercise); > > americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>( > new FDAmericanEngine<CrankNicolson>(bsmProcess, > 101,100))); > > cout << americanOption.NPV() << endl ; > > return 0 ; > } > > > > On Tue, Jul 22, 2014 at 7:39 AM, Andres Hernandez < > [hidden email]> wrote: > > Hi George, > > the problem occurs because you are trying to bootstrap on a > UnitedKingdom > holiday, which is implicitly included in the definition of > The > Libor class makes a joint calendar between the given financial > calendar and the UK calendar. Since Libor is a London poll, there are > only > fixings for it on UK business days. If one wants to bootstrap the > curve on > a holiday, the indice's historical fixings (actually just the closest > fixing to the given date) need to be provided. > > > Mit freundlichen Grüßen / Kind regards > > Dr. Andres Hernandez > > Senior Financial Engineer > Business Analytics > Risk Analytics > > > > > > Phone: +49-69-6645-1351 IBM Deutschland > (Embedded > image moved > to file: > pic20635.gif) > > Mobile: +49-163-609-3280 Wilhelm-Fay-Str. > 30-34 > > E-Mail: [hidden email] 65936 Frankfurt > Main > > Germany > > > > > > IBM Deutschland > GmbH / > Vorsitzender des > Aufsichtsrats: > Martin Jetter > Geschäftsführung: > Martina Koederitz > (Vorsitzende), > Reinhard Reschke, > Dieter Scholz, > Gregor Pillen, > Christian Noll, > Ivo Koerner > Sitz der > Gesellschaft: > Ehningen / > Registergericht: > Amtsgericht > Stuttgart, HRB > 14562 / > WEEE-Reg.-Nr. DE > 99369940 > > > > > > > From: George Cowie <[hidden email]> > To: QuantLib users <[hidden email]> > Date: 22/07/2014 14:10 > Subject: [Quantlib-users] UK Holiday for > USDLibor/PiecewiseYieldCurve > > > > Hello, > > I'm using PiecewiseYieldCurve to build a YieldTermStructure which > is > ultimately used by BlackScholesMertonProcess in my option pricing. > believe I'm running into an issue on days that are holidays in the > (but > not the US). Here's the error I'm seeing when trying to run the code > below > for May 5, 2014 (Early May Bank Holiday): > > terminate called after throwing an instance of 'QuantLib::Error' > what(): 1st iteration: failed at 1st alive instrument, maturity > May > 14th, 2014, reference date May 7th, 2014: Missing no-fix1W Actual/360 > fixing for May 2nd, 2014 > Aborted > > Everything seems to work fine on other days... Am I doing > something > wrong with setting up the PiecewiseYieldCurve? > > Thanks, > George > > #include <ql/quantlib.hpp> > > using namespace std ; > using namespace QuantLib ; > > int main(int argc, char** argv) > { > vector<Rate> liborRates ; > liborRates.push_back(0.12075 / 100.0) ; //1W > liborRates.push_back(0.1515 / 100.0) ; //1M > liborRates.push_back(0.1935 / 100.0) ; //2M > liborRates.push_back(0.22535 / 100.0) ; //3M > liborRates.push_back(0.323 / 100.0) ; //6M > liborRates.push_back(0.549 / 100.0) ; //12M > > vector<Period> periods ; > periods.push_back(Period(1,Weeks)) ; > periods.push_back(Period(1,Months)) ; > periods.push_back(Period(2,Months)) ; > periods.push_back(Period(3,Months)) ; > periods.push_back(Period(6,Months)) ; > periods.push_back(Period(12,Months)) ; > > vector<boost::shared_ptr<RateHelper> > instruments ; > > for (vector<int>::size_type i = 0 ; i < liborRates.size() ; i++) > { > boost::shared_ptr<Quote> liborQuote(new SimpleQuote > [i])) ; > Handle<Quote> liborHandle(liborQuote) ; > boost::shared_ptr<IborIndex> liborIndex(new USDLibor(periods > [i])) ; > boost::shared_ptr<RateHelper> rateHelper(new > (liborHandle,liborIndex)) ; > instruments.push_back(rateHelper) ; > } > > Calendar calendar = UnitedStates(); > Date today (5 , May ,2014); > Settings::instance().evaluationDate() = today ; > Natural settlementDays = 2; > Date settlement = calendar.advance ( today , settlementDays , > Days ); > DayCounter dc = Actual360 (); > > Date maturity(20, Jun, 2014) ; > double strikePrice = 100.0 ; > Option::Type optionType = Option::Call ; > double dividendYield = 0.0 ; > double impliedVolatility = 0.15 ; > double underlyingPrice = 100.0 ; > > Handle<Quote> underlyingHandle(boost::shared_ptr<Quote>(new > SimpleQuote > (underlyingPrice))); > > Handle<YieldTermStructure> rateTermStructure > (boost::shared_ptr<YieldTermStructure>(new > PiecewiseYieldCurve<ZeroYield,Linear>(settlement, instruments, > dc))) ; > > Handle<YieldTermStructure> > dividendTermStructure(boost::shared_ptr<YieldTermStructure>(new > FlatForward(today, > dividendYield, > dc))); > Handle<BlackVolTermStructure> > volTermStructure(boost::shared_ptr<BlackVolTermStructure>(new > BlackConstantVol(today, > calendar, > impliedVolatility, > dc))); > > boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(new > BlackScholesMertonProcess(underlyingHandle, > dividendTermStructure, > rateTermStructure, > volTermStructure)); > > boost::shared_ptr<Exercise> americanExercise(new AmericanExercise > (today, > maturity)) ; > boost::shared_ptr<StrikedTypePayoff> payoff(new > (optionType, strikePrice)); > > VanillaOption americanOption(payoff, americanExercise); > > americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>( > new FDAmericanEngine<CrankNicolson>(bsmProcess, > 101,100))); > > cout << americanOption.NPV() << endl ; > > return 0 ; > } > > > > Want fast and easy access to all the code in your enterprise? Index > and > search up to 200,000 lines of code with a free copy of Black Duck > Code Sight - the same software that powers the world's largest code > search on Ohloh, the Black Duck Open Hub! Try it now. > http://p.sf.net/sfu/bds_______________________________________________ > > QuantLib-users mailing list > [hidden email] > https://lists.sourceforge.net/lists/listinfo/quantlib-users > > ------------------------------------------------------------------------------ > Want fast and easy access to all the code in your enterprise? Index and > search up to 200,000 lines of code with a free copy of Black Duck > Code Sight - the same software that powers the world's largest code > search on Ohloh, the Black Duck Open Hub! Try it now. > http://p.sf.net/sfu/bds > _______________________________________________ > QuantLib-users mailing list > [hidden email] > https://lists.sourceforge.net/lists/listinfo/quantlib-users > ------------------------------------------------------------------------------ Want fast and easy access to all the code in your enterprise? Index and search up to 200,000 lines of code with a free copy of Black Duck Code Sight - the same software that powers the world's largest code search on Ohloh, the Black Duck Open Hub! Try it now. http://p.sf.net/sfu/bds _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users pic08098.gif (2K) Download Attachment |
Hi Andres,
yes, the index in the deposit rate helper seems to be merely a convenient way for coding - with the one exception that deposits do not (directly) have anything to do with actual index fixings, and this is also where the code breaks. And yes, it gets even worse in your example when you use the USD Libor index for USD cash deposits on a UK but non-NY holiday (you could use the index-free constructor though and pass the NY calendar directly instead, right, solving half of the problem ?). So just treating the deposit helper's index and its fixing as a computational tool to get the implied Quote seems a reasonable solution, in your USD / Libor example yielding the correct conventions even, if I am not mistaken ? I wouldn't introduce any flag or method to activate this behaviour, it should be the only one present (because checking for holidays can easily be done in the user's code if necessary at all). For swaps on the other hand I think the current behaviour is fine - what fixing would you take for the first period in a Euribor swap on a TARGET holiday ? Probably the same as you take after the fixing around 11am on a trading day, i.e. the last known fixing. That is exactly the logic applied in the library. I wouldn't change anything here. It might be that you get an exception because you just don't provide the historic fixing, but in this case it is a legitimate demand of the library and working around this should only be done in the user code imo. best Peter On 24 July 2014 09:23, Andres Hernandez <[hidden email]> wrote: > > Hi Peter, > > I agree that it would be nice to at least have it as an option. We > currently do a small workaround, whereby we set in our system a parameter > for the curve specifying the holiday calendar for that curve. The only use > of that calendar is to determine if it is a holiday for the curve or not > and if yes to make a fallback to yesterday's values. In the case of the EUR > curves, this is arguably a good behaviour as the index and the geographical > region have the same calendar, but for the USD case, we are basically > forcing a fallback for a holiday on a different country. The issue is > compounded by the fact that in this case the deposit is traded on that day, > it is just the index that gets no fixing. > > I took a look and I am almost sure that removing the evaluation date from > the fixing calendar in InterestRate constructor would be enough to make > deposits go through. This could simply be accomplished with an extra public > member function that one would call if one wanted it to go through on > holidays. A more involved and important problem would be to get the > SwapRateHelper to go though on holidays (if desired), as I am positive that > that was the reason for our instituting the fallback. I will see if I have > the time to change it, and would then probably subscribe to the developers > list to get some feedback in how to go about changing it. > > > Mit freundlichen Grüßen / Kind regards > > Dr. Andres Hernandez > > Senior Financial Engineer > Business Analytics > Risk Analytics > > > > > > Phone: +49-69-6645-1351 IBM Deutschland (Embedded > image moved > to file: > pic02235.gif) > > Mobile: +49-163-609-3280 Wilhelm-Fay-Str. 30-34 > > E-Mail: [hidden email] 65936 Frankfurt am Main > > Germany > > > > > > IBM Deutschland > GmbH / > Vorsitzender des > Aufsichtsrats: > Martin Jetter > Geschäftsführung: > Martina Koederitz > (Vorsitzende), > Reinhard Reschke, > Dieter Scholz, > Gregor Pillen, > Christian Noll, > Ivo Koerner > Sitz der > Gesellschaft: > Ehningen / > Registergericht: > Amtsgericht > Stuttgart, HRB > 14562 / > WEEE-Reg.-Nr. DE > 99369940 > > > > > > > From: Peter Caspers <[hidden email]> > To: Andres Hernandez/Germany/IBM@IBMDE > Cc: George Cowie <[hidden email]>, QuantLib users > <[hidden email]> > Date: 23/07/2014 21:56 > Subject: Re: [Quantlib-users] UK Holiday for > USDLibor/PiecewiseYieldCurve > > > > Hi, > > I think this question is an older one but I don't remember that it was > finally decided how to handle this situation (?) - which is, should we > allow to bootstrap a curve on a day which is a holiday for the cash > instruments in the curve or not. If negative, we could maybe throw a > different message ( the current one indeed sounds a bit paradoxical ). > If yes ( which would be my personal preference, because you simply > want to run your daily processes spitting out numbers even if not a > hundred percent sensible all of them ), one has to define how a > deposit which is not traded on that day should be calculated. One > obvious way would be to just treat the evaluation date as a business > day when calculating the helper's fixing date. I did not try, but it > may be enough to join the business days of the helper's calendar with > a new one just having one business day (the evaluation date) before > passing it to the no-fix index to make this kind of solution work. > What do you think ? > > Peter > > > On 23 July 2014 15:05, Andres Hernandez <[hidden email]> > wrote: >> >> Hi George, >> >> you are still setting the evaluation date to a holiday: >> >> Date today (5 , May ,2014); >> Date liborDate (2, May, 2014) ; >> Settings::instance().evaluationDate() = today ; >> >> >> Let's follow the logic: >> During bootstrapping, the method impliedQuote() of the rate helper is >> called to compare against the market quote. The DepositRateHelper simply >> returns the fixing corresponding to the fixingDate_ as a return value. >> The fixingDate_ is set during initialization as the return value of the >> function InterestRate::fixingDate(earliestDate_). The function >> InterestRate::fixingDate sets back the date given as input parameter by > the >> number of fixing days according to the index' calendar. >> The parameter earliestDate_ being passed to fixingDate is set during >> initialization to the evaluation date (which you set to the 5th of May) >> moved forward by the number of fixing days according to the index' >> calendar. >> Note that if the evaluation date is a holiday you do not end up with the >> same date, but rather with the last business day prior to evaluation > date. >> The first act moves the date from the 5th of May to the 7th and checks >> whether it is a business day, which it is. The second move sets it back > two >> days to the 5th, and checks whether it is a business day, which it isn't, >> so it sets it back until it finds a business day, i.e. the 2nd of May. >> Since the value is in the past, it requests a historical fixing, which > you >> did not provide and so the QL_REQUIRE throws. >> >> Mit freundlichen Grüßen / Kind regards >> >> Dr. Andres Hernandez >> >> Senior Financial Engineer >> Business Analytics >> Risk Analytics >> >> >> >> >> >> Phone: +49-69-6645-1351 IBM Deutschland > (Embedded >> > image moved >> > to file: >> > pic64586.gif) >> >> Mobile: +49-163-609-3280 Wilhelm-Fay-Str. 30-34 >> >> E-Mail: [hidden email] 65936 Frankfurt am Main >> >> Germany >> >> >> >> >> >> IBM Deutschland >> GmbH / >> Vorsitzender des >> Aufsichtsrats: >> Martin Jetter >> Geschäftsführung: >> Martina Koederitz >> (Vorsitzende), >> Reinhard Reschke, >> Dieter Scholz, >> Gregor Pillen, >> Christian Noll, >> Ivo Koerner >> Sitz der >> Gesellschaft: >> Ehningen / >> Registergericht: >> Amtsgericht >> Stuttgart, HRB >> 14562 / >> WEEE-Reg.-Nr. DE >> 99369940 >> >> >> >> >> >> >> From: George Cowie <[hidden email]> >> To: Andres Hernandez/Germany/IBM@IBMDE >> Cc: QuantLib users <[hidden email]> >> Date: 23/07/2014 11:51 >> Subject: Re: [Quantlib-users] UK Holiday for >> USDLibor/PiecewiseYieldCurve >> >> >> >> >> Thank you Andres. What you're describing makes sense, but I can't seem > to >> avoid an error when trying to value the option on May 5, 2014. I've > copied >> the updated code snippet with changed section highlighted/bolded below. > I >> seem to always get an exception of the form: >> >> terminate called after throwing an instance of 'QuantLib::Error' >> what(): 1st iteration: failed at 1st alive instrument, maturity May >> 14th, 2014, reference date May 6th, 2014: Missing no-fix1W Actual/360 >> fixing for May 2nd, 2014 >> >> Is there something wrong with my approach here? >> >> Thanks, >> George >> >> >> #include <ql/quantlib.hpp> >> >> using namespace std ; >> using namespace QuantLib ; >> >> int main(int argc, char** argv) >> { >> vector<Rate> liborRates ; >> liborRates.push_back(0.12075 / 100.0) ; //1W >> liborRates.push_back(0.1515 / 100.0) ; //1M >> liborRates.push_back(0.1935 / 100.0) ; //2M >> liborRates.push_back(0.22535 / 100.0) ; //3M >> liborRates.push_back(0.323 / 100.0) ; //6M >> liborRates.push_back(0.549 / 100.0) ; //12M >> >> vector<Period> periods ; >> periods.push_back(Period(1,Weeks)) ; >> periods.push_back(Period(1,Months)) ; >> periods.push_back(Period(2,Months)) ; >> periods.push_back(Period(3,Months)) ; >> periods.push_back(Period(6,Months)) ; >> periods.push_back(Period(12,Months)) ; >> >> vector<boost::shared_ptr<RateHelper> > instruments ; >> >> for (vector<int>::size_type i = 0 ; i < liborRates.size() ; i++) >> { >> boost::shared_ptr<Quote> liborQuote(new SimpleQuote(liborRates > [i])) ; >> Handle<Quote> liborHandle(liborQuote) ; >> boost::shared_ptr<IborIndex> liborIndex(new USDLibor(periods[i])) ; >> boost::shared_ptr<RateHelper> rateHelper(new DepositRateHelper >> (liborHandle,liborIndex)) ; >> instruments.push_back(rateHelper) ; >> } >> >> Calendar calendar = UnitedStates(); >> Date today (5 , May ,2014); >> Date liborDate (2, May, 2014) ; >> Settings::instance().evaluationDate() = today ; >> Natural settlementDays = 2; >> Date settlement = calendar.advance ( liborDate , settlementDays , > Days ); >> DayCounter dc = Actual360 (); >> >> Date maturity(20, Jun, 2014) ; >> double strikePrice = 100.0 ; >> Option::Type optionType = Option::Call ; >> double dividendYield = 0.0 ; >> double impliedVolatility = 0.15 ; >> double underlyingPrice = 100.0 ; >> >> Handle<Quote> underlyingHandle(boost::shared_ptr<Quote>(new SimpleQuote >> (underlyingPrice))); >> >> Handle<YieldTermStructure> rateTermStructure >> (boost::shared_ptr<YieldTermStructure>(new >> PiecewiseYieldCurve<ZeroYield,Linear>(settlement, instruments, dc))) ; >> >> Handle<YieldTermStructure> >> dividendTermStructure(boost::shared_ptr<YieldTermStructure>(new >> FlatForward(today, >> dividendYield, >> dc))); >> Handle<BlackVolTermStructure> >> volTermStructure(boost::shared_ptr<BlackVolTermStructure>(new >> BlackConstantVol(today, >> calendar, >> impliedVolatility, >> dc))); >> >> boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(new >> BlackScholesMertonProcess(underlyingHandle, >> dividendTermStructure, >> rateTermStructure, >> volTermStructure)); >> >> boost::shared_ptr<Exercise> americanExercise(new AmericanExercise > (today, >> maturity)) ; >> boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff >> (optionType, strikePrice)); >> >> VanillaOption americanOption(payoff, americanExercise); >> >> americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>( >> new FDAmericanEngine<CrankNicolson>(bsmProcess, >> 101,100))); >> >> cout << americanOption.NPV() << endl ; >> >> return 0 ; >> } >> >> >> >> On Tue, Jul 22, 2014 at 7:39 AM, Andres Hernandez < >> [hidden email]> wrote: >> >> Hi George, >> >> the problem occurs because you are trying to bootstrap on a >> UnitedKingdom >> holiday, which is implicitly included in the definition of > USDLibor. >> The >> Libor class makes a joint calendar between the given financial > center >> calendar and the UK calendar. Since Libor is a London poll, there > are >> only >> fixings for it on UK business days. If one wants to bootstrap the >> curve on >> a holiday, the indice's historical fixings (actually just the > closest >> fixing to the given date) need to be provided. >> >> >> Mit freundlichen Grüßen / Kind regards >> >> Dr. Andres Hernandez >> >> Senior Financial Engineer >> Business Analytics >> Risk Analytics >> >> >> >> >> >> Phone: +49-69-6645-1351 IBM Deutschland >> (Embedded >> image moved >> to file: >> pic20635.gif) >> >> Mobile: +49-163-609-3280 Wilhelm-Fay-Str. >> 30-34 >> >> E-Mail: [hidden email] 65936 Frankfurt > am >> Main >> >> Germany >> >> >> >> >> >> IBM Deutschland >> GmbH / >> Vorsitzender des >> Aufsichtsrats: >> Martin Jetter >> Geschäftsführung: >> Martina Koederitz >> (Vorsitzende), >> Reinhard Reschke, >> Dieter Scholz, >> Gregor Pillen, >> Christian Noll, >> Ivo Koerner >> Sitz der >> Gesellschaft: >> Ehningen / >> Registergericht: >> Amtsgericht >> Stuttgart, HRB >> 14562 / >> WEEE-Reg.-Nr. DE >> 99369940 >> >> >> >> >> >> >> From: George Cowie <[hidden email]> >> To: QuantLib users <[hidden email]> >> Date: 22/07/2014 14:10 >> Subject: [Quantlib-users] UK Holiday for >> USDLibor/PiecewiseYieldCurve >> >> >> >> Hello, >> >> I'm using PiecewiseYieldCurve to build a YieldTermStructure which >> is >> ultimately used by BlackScholesMertonProcess in my option pricing. > I >> believe I'm running into an issue on days that are holidays in the > UK >> (but >> not the US). Here's the error I'm seeing when trying to run the > code >> below >> for May 5, 2014 (Early May Bank Holiday): >> >> terminate called after throwing an instance of 'QuantLib::Error' >> what(): 1st iteration: failed at 1st alive instrument, maturity >> May >> 14th, 2014, reference date May 7th, 2014: Missing no-fix1W > Actual/360 >> fixing for May 2nd, 2014 >> Aborted >> >> Everything seems to work fine on other days... Am I doing >> something >> wrong with setting up the PiecewiseYieldCurve? >> >> Thanks, >> George >> >> #include <ql/quantlib.hpp> >> >> using namespace std ; >> using namespace QuantLib ; >> >> int main(int argc, char** argv) >> { >> vector<Rate> liborRates ; >> liborRates.push_back(0.12075 / 100.0) ; //1W >> liborRates.push_back(0.1515 / 100.0) ; //1M >> liborRates.push_back(0.1935 / 100.0) ; //2M >> liborRates.push_back(0.22535 / 100.0) ; //3M >> liborRates.push_back(0.323 / 100.0) ; //6M >> liborRates.push_back(0.549 / 100.0) ; //12M >> >> vector<Period> periods ; >> periods.push_back(Period(1,Weeks)) ; >> periods.push_back(Period(1,Months)) ; >> periods.push_back(Period(2,Months)) ; >> periods.push_back(Period(3,Months)) ; >> periods.push_back(Period(6,Months)) ; >> periods.push_back(Period(12,Months)) ; >> >> vector<boost::shared_ptr<RateHelper> > instruments ; >> >> for (vector<int>::size_type i = 0 ; i < liborRates.size() ; i++) >> { >> boost::shared_ptr<Quote> liborQuote(new SimpleQuote > (liborRates >> [i])) ; >> Handle<Quote> liborHandle(liborQuote) ; >> boost::shared_ptr<IborIndex> liborIndex(new USDLibor(periods >> [i])) ; >> boost::shared_ptr<RateHelper> rateHelper(new > DepositRateHelper >> (liborHandle,liborIndex)) ; >> instruments.push_back(rateHelper) ; >> } >> >> Calendar calendar = UnitedStates(); >> Date today (5 , May ,2014); >> Settings::instance().evaluationDate() = today ; >> Natural settlementDays = 2; >> Date settlement = calendar.advance ( today , settlementDays , >> Days ); >> DayCounter dc = Actual360 (); >> >> Date maturity(20, Jun, 2014) ; >> double strikePrice = 100.0 ; >> Option::Type optionType = Option::Call ; >> double dividendYield = 0.0 ; >> double impliedVolatility = 0.15 ; >> double underlyingPrice = 100.0 ; >> >> Handle<Quote> underlyingHandle(boost::shared_ptr<Quote>(new >> SimpleQuote >> (underlyingPrice))); >> >> Handle<YieldTermStructure> rateTermStructure >> (boost::shared_ptr<YieldTermStructure>(new >> PiecewiseYieldCurve<ZeroYield,Linear>(settlement, instruments, >> dc))) ; >> >> Handle<YieldTermStructure> >> dividendTermStructure(boost::shared_ptr<YieldTermStructure>(new >> FlatForward(today, >> dividendYield, >> dc))); >> Handle<BlackVolTermStructure> >> volTermStructure(boost::shared_ptr<BlackVolTermStructure>(new >> BlackConstantVol(today, >> calendar, >> impliedVolatility, >> dc))); >> >> boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(new >> BlackScholesMertonProcess(underlyingHandle, >> dividendTermStructure, >> rateTermStructure, >> volTermStructure)); >> >> boost::shared_ptr<Exercise> americanExercise(new AmericanExercise >> (today, >> maturity)) ; >> boost::shared_ptr<StrikedTypePayoff> payoff(new > PlainVanillaPayoff >> (optionType, strikePrice)); >> >> VanillaOption americanOption(payoff, americanExercise); >> >> americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>( >> new FDAmericanEngine<CrankNicolson>(bsmProcess, >> 101,100))); >> >> cout << americanOption.NPV() << endl ; >> >> return 0 ; >> } >> > ------------------------------------------------------------------------------ > >> >> >> Want fast and easy access to all the code in your enterprise? Index >> and >> search up to 200,000 lines of code with a free copy of Black Duck >> Code Sight - the same software that powers the world's largest code >> search on Ohloh, the Black Duck Open Hub! Try it now. >> > http://p.sf.net/sfu/bds_______________________________________________ >> >> QuantLib-users mailing list >> [hidden email] >> https://lists.sourceforge.net/lists/listinfo/quantlib-users >> >> > ------------------------------------------------------------------------------ > >> Want fast and easy access to all the code in your enterprise? Index and >> search up to 200,000 lines of code with a free copy of Black Duck >> Code Sight - the same software that powers the world's largest code >> search on Ohloh, the Black Duck Open Hub! Try it now. >> http://p.sf.net/sfu/bds >> _______________________________________________ >> QuantLib-users mailing list >> [hidden email] >> https://lists.sourceforge.net/lists/listinfo/quantlib-users >> > ------------------------------------------------------------------------------ Want fast and easy access to all the code in your enterprise? Index and search up to 200,000 lines of code with a free copy of Black Duck Code Sight - the same software that powers the world's largest code search on Ohloh, the Black Duck Open Hub! Try it now. http://p.sf.net/sfu/bds _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
reminding myself of what workaround we actually implemented for swap
helper :o ... and what Murex offers here (always a good reference), the full set of options would probably be default - require historic fixings, take today's fixing if available ignore today's tixing - require historic fixings, always ignore today's fixing ignore all fixings - ignore all fixings (i.e. estimate forward rates always on the curve - this is technically ok even if the fixing date is in the past, since only the index estimation period's start and end date enter the estimation, and these two dates are always greater or equal today) these options to be applied only in the context of yield curve bootstrapping, ideally to be set on the level of the curve itself. On 24 July 2014 10:26, Peter Caspers <[hidden email]> wrote: > Hi Andres, > > yes, the index in the deposit rate helper seems to be merely a > convenient way for coding - with the one exception that deposits do > not (directly) have anything to do with actual index fixings, and this > is also where the code breaks. And yes, it gets even worse in your > example when you use the USD Libor index for USD cash deposits on a UK > but non-NY holiday (you could use the index-free constructor though > and pass the NY calendar directly instead, right, solving half of the > problem ?). So just treating the deposit helper's index and its fixing > as a computational tool to get the implied Quote seems a reasonable > solution, in your USD / Libor example yielding the correct conventions > even, if I am not mistaken ? I wouldn't introduce any flag or method > to activate this behaviour, it should be the only one present (because > checking for holidays can easily be done in the user's code if > necessary at all). > > For swaps on the other hand I think the current behaviour is fine - > what fixing would you take for the first period in a Euribor swap on a > TARGET holiday ? Probably the same as you take after the fixing around > 11am on a trading day, i.e. the last known fixing. That is exactly the > logic applied in the library. I wouldn't change anything here. It > might be that you get an exception because you just don't provide the > historic fixing, but in this case it is a legitimate demand of the > library and working around this should only be done in the user code > imo. > > best > Peter > > > > > > On 24 July 2014 09:23, Andres Hernandez <[hidden email]> wrote: >> >> Hi Peter, >> >> I agree that it would be nice to at least have it as an option. We >> currently do a small workaround, whereby we set in our system a parameter >> for the curve specifying the holiday calendar for that curve. The only use >> of that calendar is to determine if it is a holiday for the curve or not >> and if yes to make a fallback to yesterday's values. In the case of the EUR >> curves, this is arguably a good behaviour as the index and the geographical >> region have the same calendar, but for the USD case, we are basically >> forcing a fallback for a holiday on a different country. The issue is >> compounded by the fact that in this case the deposit is traded on that day, >> it is just the index that gets no fixing. >> >> I took a look and I am almost sure that removing the evaluation date from >> the fixing calendar in InterestRate constructor would be enough to make >> deposits go through. This could simply be accomplished with an extra public >> member function that one would call if one wanted it to go through on >> holidays. A more involved and important problem would be to get the >> SwapRateHelper to go though on holidays (if desired), as I am positive that >> that was the reason for our instituting the fallback. I will see if I have >> the time to change it, and would then probably subscribe to the developers >> list to get some feedback in how to go about changing it. >> >> >> Mit freundlichen Grüßen / Kind regards >> >> Dr. Andres Hernandez >> >> Senior Financial Engineer >> Business Analytics >> Risk Analytics >> >> >> >> >> >> Phone: +49-69-6645-1351 IBM Deutschland (Embedded >> image moved >> to file: >> pic02235.gif) >> >> Mobile: +49-163-609-3280 Wilhelm-Fay-Str. 30-34 >> >> E-Mail: [hidden email] 65936 Frankfurt am Main >> >> Germany >> >> >> >> >> >> IBM Deutschland >> GmbH / >> Vorsitzender des >> Aufsichtsrats: >> Martin Jetter >> Geschäftsführung: >> Martina Koederitz >> (Vorsitzende), >> Reinhard Reschke, >> Dieter Scholz, >> Gregor Pillen, >> Christian Noll, >> Ivo Koerner >> Sitz der >> Gesellschaft: >> Ehningen / >> Registergericht: >> Amtsgericht >> Stuttgart, HRB >> 14562 / >> WEEE-Reg.-Nr. DE >> 99369940 >> >> >> >> >> >> >> From: Peter Caspers <[hidden email]> >> To: Andres Hernandez/Germany/IBM@IBMDE >> Cc: George Cowie <[hidden email]>, QuantLib users >> <[hidden email]> >> Date: 23/07/2014 21:56 >> Subject: Re: [Quantlib-users] UK Holiday for >> USDLibor/PiecewiseYieldCurve >> >> >> >> Hi, >> >> I think this question is an older one but I don't remember that it was >> finally decided how to handle this situation (?) - which is, should we >> allow to bootstrap a curve on a day which is a holiday for the cash >> instruments in the curve or not. If negative, we could maybe throw a >> different message ( the current one indeed sounds a bit paradoxical ). >> If yes ( which would be my personal preference, because you simply >> want to run your daily processes spitting out numbers even if not a >> hundred percent sensible all of them ), one has to define how a >> deposit which is not traded on that day should be calculated. One >> obvious way would be to just treat the evaluation date as a business >> day when calculating the helper's fixing date. I did not try, but it >> may be enough to join the business days of the helper's calendar with >> a new one just having one business day (the evaluation date) before >> passing it to the no-fix index to make this kind of solution work. >> What do you think ? >> >> Peter >> >> >> On 23 July 2014 15:05, Andres Hernandez <[hidden email]> >> wrote: >>> >>> Hi George, >>> >>> you are still setting the evaluation date to a holiday: >>> >>> Date today (5 , May ,2014); >>> Date liborDate (2, May, 2014) ; >>> Settings::instance().evaluationDate() = today ; >>> >>> >>> Let's follow the logic: >>> During bootstrapping, the method impliedQuote() of the rate helper is >>> called to compare against the market quote. The DepositRateHelper simply >>> returns the fixing corresponding to the fixingDate_ as a return value. >>> The fixingDate_ is set during initialization as the return value of the >>> function InterestRate::fixingDate(earliestDate_). The function >>> InterestRate::fixingDate sets back the date given as input parameter by >> the >>> number of fixing days according to the index' calendar. >>> The parameter earliestDate_ being passed to fixingDate is set during >>> initialization to the evaluation date (which you set to the 5th of May) >>> moved forward by the number of fixing days according to the index' >>> calendar. >>> Note that if the evaluation date is a holiday you do not end up with the >>> same date, but rather with the last business day prior to evaluation >> date. >>> The first act moves the date from the 5th of May to the 7th and checks >>> whether it is a business day, which it is. The second move sets it back >> two >>> days to the 5th, and checks whether it is a business day, which it isn't, >>> so it sets it back until it finds a business day, i.e. the 2nd of May. >>> Since the value is in the past, it requests a historical fixing, which >> you >>> did not provide and so the QL_REQUIRE throws. >>> >>> Mit freundlichen Grüßen / Kind regards >>> >>> Dr. Andres Hernandez >>> >>> Senior Financial Engineer >>> Business Analytics >>> Risk Analytics >>> >>> >>> >>> >>> >>> Phone: +49-69-6645-1351 IBM Deutschland >> (Embedded >>> >> image moved >>> >> to file: >>> >> pic64586.gif) >>> >>> Mobile: +49-163-609-3280 Wilhelm-Fay-Str. 30-34 >>> >>> E-Mail: [hidden email] 65936 Frankfurt am Main >>> >>> Germany >>> >>> >>> >>> >>> >>> IBM Deutschland >>> GmbH / >>> Vorsitzender des >>> Aufsichtsrats: >>> Martin Jetter >>> Geschäftsführung: >>> Martina Koederitz >>> (Vorsitzende), >>> Reinhard Reschke, >>> Dieter Scholz, >>> Gregor Pillen, >>> Christian Noll, >>> Ivo Koerner >>> Sitz der >>> Gesellschaft: >>> Ehningen / >>> Registergericht: >>> Amtsgericht >>> Stuttgart, HRB >>> 14562 / >>> WEEE-Reg.-Nr. DE >>> 99369940 >>> >>> >>> >>> >>> >>> >>> From: George Cowie <[hidden email]> >>> To: Andres Hernandez/Germany/IBM@IBMDE >>> Cc: QuantLib users <[hidden email]> >>> Date: 23/07/2014 11:51 >>> Subject: Re: [Quantlib-users] UK Holiday for >>> USDLibor/PiecewiseYieldCurve >>> >>> >>> >>> >>> Thank you Andres. What you're describing makes sense, but I can't seem >> to >>> avoid an error when trying to value the option on May 5, 2014. I've >> copied >>> the updated code snippet with changed section highlighted/bolded below. >> I >>> seem to always get an exception of the form: >>> >>> terminate called after throwing an instance of 'QuantLib::Error' >>> what(): 1st iteration: failed at 1st alive instrument, maturity May >>> 14th, 2014, reference date May 6th, 2014: Missing no-fix1W Actual/360 >>> fixing for May 2nd, 2014 >>> >>> Is there something wrong with my approach here? >>> >>> Thanks, >>> George >>> >>> >>> #include <ql/quantlib.hpp> >>> >>> using namespace std ; >>> using namespace QuantLib ; >>> >>> int main(int argc, char** argv) >>> { >>> vector<Rate> liborRates ; >>> liborRates.push_back(0.12075 / 100.0) ; //1W >>> liborRates.push_back(0.1515 / 100.0) ; //1M >>> liborRates.push_back(0.1935 / 100.0) ; //2M >>> liborRates.push_back(0.22535 / 100.0) ; //3M >>> liborRates.push_back(0.323 / 100.0) ; //6M >>> liborRates.push_back(0.549 / 100.0) ; //12M >>> >>> vector<Period> periods ; >>> periods.push_back(Period(1,Weeks)) ; >>> periods.push_back(Period(1,Months)) ; >>> periods.push_back(Period(2,Months)) ; >>> periods.push_back(Period(3,Months)) ; >>> periods.push_back(Period(6,Months)) ; >>> periods.push_back(Period(12,Months)) ; >>> >>> vector<boost::shared_ptr<RateHelper> > instruments ; >>> >>> for (vector<int>::size_type i = 0 ; i < liborRates.size() ; i++) >>> { >>> boost::shared_ptr<Quote> liborQuote(new SimpleQuote(liborRates >> [i])) ; >>> Handle<Quote> liborHandle(liborQuote) ; >>> boost::shared_ptr<IborIndex> liborIndex(new USDLibor(periods[i])) ; >>> boost::shared_ptr<RateHelper> rateHelper(new DepositRateHelper >>> (liborHandle,liborIndex)) ; >>> instruments.push_back(rateHelper) ; >>> } >>> >>> Calendar calendar = UnitedStates(); >>> Date today (5 , May ,2014); >>> Date liborDate (2, May, 2014) ; >>> Settings::instance().evaluationDate() = today ; >>> Natural settlementDays = 2; >>> Date settlement = calendar.advance ( liborDate , settlementDays , >> Days ); >>> DayCounter dc = Actual360 (); >>> >>> Date maturity(20, Jun, 2014) ; >>> double strikePrice = 100.0 ; >>> Option::Type optionType = Option::Call ; >>> double dividendYield = 0.0 ; >>> double impliedVolatility = 0.15 ; >>> double underlyingPrice = 100.0 ; >>> >>> Handle<Quote> underlyingHandle(boost::shared_ptr<Quote>(new SimpleQuote >>> (underlyingPrice))); >>> >>> Handle<YieldTermStructure> rateTermStructure >>> (boost::shared_ptr<YieldTermStructure>(new >>> PiecewiseYieldCurve<ZeroYield,Linear>(settlement, instruments, dc))) ; >>> >>> Handle<YieldTermStructure> >>> dividendTermStructure(boost::shared_ptr<YieldTermStructure>(new >>> FlatForward(today, >>> dividendYield, >>> dc))); >>> Handle<BlackVolTermStructure> >>> volTermStructure(boost::shared_ptr<BlackVolTermStructure>(new >>> BlackConstantVol(today, >>> calendar, >>> impliedVolatility, >>> dc))); >>> >>> boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(new >>> BlackScholesMertonProcess(underlyingHandle, >>> dividendTermStructure, >>> rateTermStructure, >>> volTermStructure)); >>> >>> boost::shared_ptr<Exercise> americanExercise(new AmericanExercise >> (today, >>> maturity)) ; >>> boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff >>> (optionType, strikePrice)); >>> >>> VanillaOption americanOption(payoff, americanExercise); >>> >>> americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>( >>> new FDAmericanEngine<CrankNicolson>(bsmProcess, >>> 101,100))); >>> >>> cout << americanOption.NPV() << endl ; >>> >>> return 0 ; >>> } >>> >>> >>> >>> On Tue, Jul 22, 2014 at 7:39 AM, Andres Hernandez < >>> [hidden email]> wrote: >>> >>> Hi George, >>> >>> the problem occurs because you are trying to bootstrap on a >>> UnitedKingdom >>> holiday, which is implicitly included in the definition of >> USDLibor. >>> The >>> Libor class makes a joint calendar between the given financial >> center >>> calendar and the UK calendar. Since Libor is a London poll, there >> are >>> only >>> fixings for it on UK business days. If one wants to bootstrap the >>> curve on >>> a holiday, the indice's historical fixings (actually just the >> closest >>> fixing to the given date) need to be provided. >>> >>> >>> Mit freundlichen Grüßen / Kind regards >>> >>> Dr. Andres Hernandez >>> >>> Senior Financial Engineer >>> Business Analytics >>> Risk Analytics >>> >>> >>> >>> >>> >>> Phone: +49-69-6645-1351 IBM Deutschland >>> (Embedded >>> image moved >>> to file: >>> pic20635.gif) >>> >>> Mobile: +49-163-609-3280 Wilhelm-Fay-Str. >>> 30-34 >>> >>> E-Mail: [hidden email] 65936 Frankfurt >> am >>> Main >>> >>> Germany >>> >>> >>> >>> >>> >>> IBM Deutschland >>> GmbH / >>> Vorsitzender des >>> Aufsichtsrats: >>> Martin Jetter >>> Geschäftsführung: >>> Martina Koederitz >>> (Vorsitzende), >>> Reinhard Reschke, >>> Dieter Scholz, >>> Gregor Pillen, >>> Christian Noll, >>> Ivo Koerner >>> Sitz der >>> Gesellschaft: >>> Ehningen / >>> Registergericht: >>> Amtsgericht >>> Stuttgart, HRB >>> 14562 / >>> WEEE-Reg.-Nr. DE >>> 99369940 >>> >>> >>> >>> >>> >>> >>> From: George Cowie <[hidden email]> >>> To: QuantLib users <[hidden email]> >>> Date: 22/07/2014 14:10 >>> Subject: [Quantlib-users] UK Holiday for >>> USDLibor/PiecewiseYieldCurve >>> >>> >>> >>> Hello, >>> >>> I'm using PiecewiseYieldCurve to build a YieldTermStructure which >>> is >>> ultimately used by BlackScholesMertonProcess in my option pricing. >> I >>> believe I'm running into an issue on days that are holidays in the >> UK >>> (but >>> not the US). Here's the error I'm seeing when trying to run the >> code >>> below >>> for May 5, 2014 (Early May Bank Holiday): >>> >>> terminate called after throwing an instance of 'QuantLib::Error' >>> what(): 1st iteration: failed at 1st alive instrument, maturity >>> May >>> 14th, 2014, reference date May 7th, 2014: Missing no-fix1W >> Actual/360 >>> fixing for May 2nd, 2014 >>> Aborted >>> >>> Everything seems to work fine on other days... Am I doing >>> something >>> wrong with setting up the PiecewiseYieldCurve? >>> >>> Thanks, >>> George >>> >>> #include <ql/quantlib.hpp> >>> >>> using namespace std ; >>> using namespace QuantLib ; >>> >>> int main(int argc, char** argv) >>> { >>> vector<Rate> liborRates ; >>> liborRates.push_back(0.12075 / 100.0) ; //1W >>> liborRates.push_back(0.1515 / 100.0) ; //1M >>> liborRates.push_back(0.1935 / 100.0) ; //2M >>> liborRates.push_back(0.22535 / 100.0) ; //3M >>> liborRates.push_back(0.323 / 100.0) ; //6M >>> liborRates.push_back(0.549 / 100.0) ; //12M >>> >>> vector<Period> periods ; >>> periods.push_back(Period(1,Weeks)) ; >>> periods.push_back(Period(1,Months)) ; >>> periods.push_back(Period(2,Months)) ; >>> periods.push_back(Period(3,Months)) ; >>> periods.push_back(Period(6,Months)) ; >>> periods.push_back(Period(12,Months)) ; >>> >>> vector<boost::shared_ptr<RateHelper> > instruments ; >>> >>> for (vector<int>::size_type i = 0 ; i < liborRates.size() ; i++) >>> { >>> boost::shared_ptr<Quote> liborQuote(new SimpleQuote >> (liborRates >>> [i])) ; >>> Handle<Quote> liborHandle(liborQuote) ; >>> boost::shared_ptr<IborIndex> liborIndex(new USDLibor(periods >>> [i])) ; >>> boost::shared_ptr<RateHelper> rateHelper(new >> DepositRateHelper >>> (liborHandle,liborIndex)) ; >>> instruments.push_back(rateHelper) ; >>> } >>> >>> Calendar calendar = UnitedStates(); >>> Date today (5 , May ,2014); >>> Settings::instance().evaluationDate() = today ; >>> Natural settlementDays = 2; >>> Date settlement = calendar.advance ( today , settlementDays , >>> Days ); >>> DayCounter dc = Actual360 (); >>> >>> Date maturity(20, Jun, 2014) ; >>> double strikePrice = 100.0 ; >>> Option::Type optionType = Option::Call ; >>> double dividendYield = 0.0 ; >>> double impliedVolatility = 0.15 ; >>> double underlyingPrice = 100.0 ; >>> >>> Handle<Quote> underlyingHandle(boost::shared_ptr<Quote>(new >>> SimpleQuote >>> (underlyingPrice))); >>> >>> Handle<YieldTermStructure> rateTermStructure >>> (boost::shared_ptr<YieldTermStructure>(new >>> PiecewiseYieldCurve<ZeroYield,Linear>(settlement, instruments, >>> dc))) ; >>> >>> Handle<YieldTermStructure> >>> dividendTermStructure(boost::shared_ptr<YieldTermStructure>(new >>> FlatForward(today, >>> dividendYield, >>> dc))); >>> Handle<BlackVolTermStructure> >>> volTermStructure(boost::shared_ptr<BlackVolTermStructure>(new >>> BlackConstantVol(today, >>> calendar, >>> impliedVolatility, >>> dc))); >>> >>> boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(new >>> BlackScholesMertonProcess(underlyingHandle, >>> dividendTermStructure, >>> rateTermStructure, >>> volTermStructure)); >>> >>> boost::shared_ptr<Exercise> americanExercise(new AmericanExercise >>> (today, >>> maturity)) ; >>> boost::shared_ptr<StrikedTypePayoff> payoff(new >> PlainVanillaPayoff >>> (optionType, strikePrice)); >>> >>> VanillaOption americanOption(payoff, americanExercise); >>> >>> americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>( >>> new FDAmericanEngine<CrankNicolson>(bsmProcess, >>> 101,100))); >>> >>> cout << americanOption.NPV() << endl ; >>> >>> return 0 ; >>> } >>> >> ------------------------------------------------------------------------------ >> >>> >>> >>> Want fast and easy access to all the code in your enterprise? Index >>> and >>> search up to 200,000 lines of code with a free copy of Black Duck >>> Code Sight - the same software that powers the world's largest code >>> search on Ohloh, the Black Duck Open Hub! Try it now. >>> >> http://p.sf.net/sfu/bds_______________________________________________ >>> >>> QuantLib-users mailing list >>> [hidden email] >>> https://lists.sourceforge.net/lists/listinfo/quantlib-users >>> >>> >> ------------------------------------------------------------------------------ >> >>> Want fast and easy access to all the code in your enterprise? Index and >>> search up to 200,000 lines of code with a free copy of Black Duck >>> Code Sight - the same software that powers the world's largest code >>> search on Ohloh, the Black Duck Open Hub! Try it now. >>> http://p.sf.net/sfu/bds >>> _______________________________________________ >>> QuantLib-users mailing list >>> [hidden email] >>> https://lists.sourceforge.net/lists/listinfo/quantlib-users >>> >> ------------------------------------------------------------------------------ Want fast and easy access to all the code in your enterprise? Index and search up to 200,000 lines of code with a free copy of Black Duck Code Sight - the same software that powers the world's largest code search on Ohloh, the Black Duck Open Hub! Try it now. http://p.sf.net/sfu/bds _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
Interesting discussion... sorry to change the subject, but I'm still trying to figure out how to adapt my code to this situation. How do I force my YieldTermStructure to bootstrap with a different date? I have to value the option on May 5th, but as you pointed out, changing the evaluation date to a holiday has the described consequences.
On Thu, Jul 24, 2014 at 6:00 AM, Peter Caspers <[hidden email]> wrote: reminding myself of what workaround we actually implemented for swap ------------------------------------------------------------------------------ Want fast and easy access to all the code in your enterprise? Index and search up to 200,000 lines of code with a free copy of Black Duck Code Sight - the same software that powers the world's largest code search on Ohloh, the Black Duck Open Hub! Try it now. http://p.sf.net/sfu/bds _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
Hi George,
as Peter mentioned, you can use another of the constructors. If you want to use the USDLibor conventions you could use something like the following inside the loop: boost::shared_ptr<IborIndex> liborIndex(new USDLibor(periods[i])) ; Calendar calendar = liborIndex->fixingCalendar(); calendar.removeHoliday(today); boost::shared_ptr<RateHelper> rateHelper(new DepositRateHelper ( liborHandle, liborIndex->tenor(), liborIndex->fixingDays(), calendar, liborIndex-> businessDayConvention(), liborIndex->endOfMonth(), liborIndex->dayCounter ()) ); instruments.push_back(rateHelper); @Peter, you are right,no modification would be needed and the behaviour for the swaps is the correct one. cheers, Andres From: George Cowie <[hidden email]> To: Peter Caspers <[hidden email]> Cc: Andres Hernandez/Germany/IBM@IBMDE, QuantLib users <[hidden email]> Date: 24/07/2014 13:52 Subject: Re: [Quantlib-users] UK Holiday for USDLibor/PiecewiseYieldCurve Interesting discussion... sorry to change the subject, but I'm still trying to figure out how to adapt my code to this situation. How do I force my YieldTermStructure to bootstrap with a different date? I have to value the option on May 5th, but as you pointed out, changing the evaluation date to a holiday has the described consequences. On Thu, Jul 24, 2014 at 6:00 AM, Peter Caspers <[hidden email]> wrote: reminding myself of what workaround we actually implemented for swap helper :o ... and what Murex offers here (always a good reference), the full set of options would probably be default - require historic fixings, take today's fixing if available ignore today's tixing - require historic fixings, always ignore today's fixing ignore all fixings - ignore all fixings (i.e. estimate forward rates always on the curve - this is technically ok even if the fixing date is in the past, since only the index estimation period's start and end date enter the estimation, and these two dates are always greater or equal today) these options to be applied only in the context of yield curve bootstrapping, ideally to be set on the level of the curve itself. On 24 July 2014 10:26, Peter Caspers <[hidden email]> wrote: > Hi Andres, > > yes, the index in the deposit rate helper seems to be merely a > convenient way for coding - with the one exception that deposits do > not (directly) have anything to do with actual index fixings, and this > is also where the code breaks. And yes, it gets even worse in your > example when you use the USD Libor index for USD cash deposits on a UK > but non-NY holiday (you could use the index-free constructor though > and pass the NY calendar directly instead, right, solving half of the > problem ?). So just treating the deposit helper's index and its fixing > as a computational tool to get the implied Quote seems a reasonable > solution, in your USD / Libor example yielding the correct conventions > even, if I am not mistaken ? I wouldn't introduce any flag or method > to activate this behaviour, it should be the only one present (because > checking for holidays can easily be done in the user's code if > necessary at all). > > For swaps on the other hand I think the current behaviour is fine - > what fixing would you take for the first period in a Euribor swap on a > TARGET holiday ? Probably the same as you take after the fixing around > 11am on a trading day, i.e. the last known fixing. That is exactly the > logic applied in the library. I wouldn't change anything here. It > might be that you get an exception because you just don't provide the > historic fixing, but in this case it is a legitimate demand of the > library and working around this should only be done in the user code > imo. > > best > Peter > > > > > > On 24 July 2014 09:23, Andres Hernandez < [hidden email]> wrote: >> >> Hi Peter, >> >> I agree that it would be nice to at least have it as an option. We >> currently do a small workaround, whereby we set in our system a parameter >> for the curve specifying the holiday calendar for that curve. The only use >> of that calendar is to determine if it is a holiday for the curve or not >> and if yes to make a fallback to yesterday's values. In the case of the EUR >> curves, this is arguably a good behaviour as the index and the geographical >> region have the same calendar, but for the USD case, we are basically >> forcing a fallback for a holiday on a different country. The issue is >> compounded by the fact that in this case the deposit is traded on that day, >> it is just the index that gets no fixing. >> >> I took a look and I am almost sure that removing the evaluation date from >> the fixing calendar in InterestRate constructor would be enough to make >> deposits go through. This could simply be accomplished with an extra public >> member function that one would call if one wanted it to go through on >> holidays. A more involved and important problem would be to get the >> SwapRateHelper to go though on holidays (if desired), as I am positive that >> that was the reason for our instituting the fallback. I will see if I have >> the time to change it, and would then probably subscribe to the developers >> list to get some feedback in how to go about changing it. >> >> >> Mit freundlichen Grüßen / Kind regards >> >> Dr. Andres Hernandez >> >> Senior Financial Engineer >> Business Analytics >> Risk Analytics >> >> >> >> >> >> Phone: +49-69-6645-1351 IBM Deutschland (Embedded >> image moved >> to file: >> pic02235.gif) >> >> Mobile: +49-163-609-3280 Wilhelm-Fay-Str. 30-34 >> >> E-Mail: [hidden email] 65936 Frankfurt am Main >> >> Germany >> >> >> >> >> >> IBM Deutschland >> GmbH / >> Vorsitzender des >> Aufsichtsrats: >> Martin Jetter >> Geschäftsführung: >> Martina Koederitz >> (Vorsitzende), >> Reinhard Reschke, >> Dieter Scholz, >> Gregor Pillen, >> Christian Noll, >> Ivo Koerner >> Sitz der >> Gesellschaft: >> Ehningen / >> Registergericht: >> Amtsgericht >> Stuttgart, HRB >> 14562 / >> WEEE-Reg.-Nr. DE >> 99369940 >> >> >> >> >> >> >> From: Peter Caspers <[hidden email]> >> To: Andres Hernandez/Germany/IBM@IBMDE >> Cc: George Cowie <[hidden email]>, QuantLib users >> <[hidden email]> >> Date: 23/07/2014 21:56 >> Subject: Re: [Quantlib-users] UK Holiday for >> USDLibor/PiecewiseYieldCurve >> >> >> >> Hi, >> >> I think this question is an older one but I don't remember that it was >> finally decided how to handle this situation (?) - which is, should we >> allow to bootstrap a curve on a day which is a holiday for the cash >> instruments in the curve or not. If negative, we could maybe throw a >> different message ( the current one indeed sounds a bit paradoxical ). >> If yes ( which would be my personal preference, because you simply >> want to run your daily processes spitting out numbers even if not a >> hundred percent sensible all of them ), one has to define how a >> deposit which is not traded on that day should be calculated. One >> obvious way would be to just treat the evaluation date as a business >> day when calculating the helper's fixing date. I did not try, but it >> may be enough to join the business days of the helper's calendar with >> a new one just having one business day (the evaluation date) before >> passing it to the no-fix index to make this kind of solution work. >> What do you think ? >> >> Peter >> >> >> On 23 July 2014 15:05, Andres Hernandez < [hidden email]> >> wrote: >>> >>> Hi George, >>> >>> you are still setting the evaluation date to a holiday: >>> >>> Date today (5 , May ,2014); >>> Date liborDate (2, May, 2014) ; >>> Settings::instance().evaluationDate() = today ; >>> >>> >>> Let's follow the logic: >>> During bootstrapping, the method impliedQuote() of the rate helper is >>> called to compare against the market quote. The DepositRateHelper simply >>> returns the fixing corresponding to the fixingDate_ as a return value. >>> The fixingDate_ is set during initialization as the return value of the >>> function InterestRate::fixingDate(earliestDate_). The function >>> InterestRate::fixingDate sets back the date given as input parameter by >> the >>> number of fixing days according to the index' calendar. >>> The parameter earliestDate_ being passed to fixingDate is set during >>> initialization to the evaluation date (which you set to the 5th of May) >>> moved forward by the number of fixing days according to the index' >>> calendar. >>> Note that if the evaluation date is a holiday you do not end up with the >>> same date, but rather with the last business day prior to evaluation >> date. >>> The first act moves the date from the 5th of May to the 7th and checks >>> whether it is a business day, which it is. The second move sets it back >> two >>> days to the 5th, and checks whether it is a business day, which it isn't, >>> so it sets it back until it finds a business day, i.e. the 2nd of May. >>> Since the value is in the past, it requests a historical fixing, which >> you >>> did not provide and so the QL_REQUIRE throws. >>> >>> Mit freundlichen Grüßen / Kind regards >>> >>> Dr. Andres Hernandez >>> >>> Senior Financial Engineer >>> Business Analytics >>> Risk Analytics >>> >>> >>> >>> >>> >>> Phone: +49-69-6645-1351 IBM Deutschland >> (Embedded >>> >> image moved >>> >> to file: >>> >> pic64586.gif) >>> >>> Mobile: +49-163-609-3280 Wilhelm-Fay-Str. 30-34 >>> >>> E-Mail: [hidden email] 65936 Frankfurt am Main >>> >>> Germany >>> >>> >>> >>> >>> >>> IBM Deutschland >>> GmbH / >>> Vorsitzender des >>> Aufsichtsrats: >>> Martin Jetter >>> Geschäftsführung: >>> Martina Koederitz >>> (Vorsitzende), >>> Reinhard Reschke, >>> Dieter Scholz, >>> Gregor Pillen, >>> Christian Noll, >>> Ivo Koerner >>> Sitz der >>> Gesellschaft: >>> Ehningen / >>> Registergericht: >>> Amtsgericht >>> Stuttgart, HRB >>> 14562 / >>> WEEE-Reg.-Nr. DE >>> 99369940 >>> >>> >>> >>> >>> >>> >>> From: George Cowie <[hidden email]> >>> To: Andres Hernandez/Germany/IBM@IBMDE >>> Cc: QuantLib users <[hidden email]> >>> Date: 23/07/2014 11:51 >>> Subject: Re: [Quantlib-users] UK Holiday for >>> USDLibor/PiecewiseYieldCurve >>> >>> >>> >>> >>> Thank you Andres. What you're describing makes sense, but I can't seem >> to >>> avoid an error when trying to value the option on May 5, 2014. I've >> copied >>> the updated code snippet with changed section highlighted/bolded below. >> I >>> seem to always get an exception of the form: >>> >>> terminate called after throwing an instance of 'QuantLib::Error' >>> what(): 1st iteration: failed at 1st alive instrument, maturity May >>> 14th, 2014, reference date May 6th, 2014: Missing no-fix1W Actual/360 >>> fixing for May 2nd, 2014 >>> >>> Is there something wrong with my approach here? >>> >>> Thanks, >>> George >>> >>> >>> #include <ql/quantlib.hpp> >>> >>> using namespace std ; >>> using namespace QuantLib ; >>> >>> int main(int argc, char** argv) >>> { >>> vector<Rate> liborRates ; >>> liborRates.push_back(0.12075 / 100.0) ; //1W >>> liborRates.push_back(0.1515 / 100.0) ; //1M >>> liborRates.push_back(0.1935 / 100.0) ; //2M >>> liborRates.push_back(0.22535 / 100.0) ; //3M >>> liborRates.push_back(0.323 / 100.0) ; //6M >>> liborRates.push_back(0.549 / 100.0) ; //12M >>> >>> vector<Period> periods ; >>> periods.push_back(Period(1,Weeks)) ; >>> periods.push_back(Period(1,Months)) ; >>> periods.push_back(Period(2,Months)) ; >>> periods.push_back(Period(3,Months)) ; >>> periods.push_back(Period(6,Months)) ; >>> periods.push_back(Period(12,Months)) ; >>> >>> vector<boost::shared_ptr<RateHelper> > instruments ; >>> >>> for (vector<int>::size_type i = 0 ; i < liborRates.size() ; i+ +) >>> { >>> boost::shared_ptr<Quote> liborQuote(new SimpleQuote (liborRates >> [i])) ; >>> Handle<Quote> liborHandle(liborQuote) ; >>> boost::shared_ptr<IborIndex> liborIndex(new USDLibor (periods[i])) ; >>> boost::shared_ptr<RateHelper> rateHelper(new DepositRateHelper >>> (liborHandle,liborIndex)) ; >>> instruments.push_back(rateHelper) ; >>> } >>> >>> Calendar calendar = UnitedStates(); >>> Date today (5 , May ,2014); >>> Date liborDate (2, May, 2014) ; >>> Settings::instance().evaluationDate() = today ; >>> Natural settlementDays = 2; >>> Date settlement = calendar.advance ( liborDate , settlementDays , >> Days ); >>> DayCounter dc = Actual360 (); >>> >>> Date maturity(20, Jun, 2014) ; >>> double strikePrice = 100.0 ; >>> Option::Type optionType = Option::Call ; >>> double dividendYield = 0.0 ; >>> double impliedVolatility = 0.15 ; >>> double underlyingPrice = 100.0 ; >>> >>> Handle<Quote> underlyingHandle(boost::shared_ptr<Quote>(new SimpleQuote >>> (underlyingPrice))); >>> >>> Handle<YieldTermStructure> rateTermStructure >>> (boost::shared_ptr<YieldTermStructure>(new >>> PiecewiseYieldCurve<ZeroYield,Linear>(settlement, instruments, dc))) ; >>> >>> Handle<YieldTermStructure> >>> dividendTermStructure(boost::shared_ptr<YieldTermStructure> (new >>> FlatForward(today, >>> dividendYield, >>> dc))); >>> Handle<BlackVolTermStructure> >>> volTermStructure(boost::shared_ptr<BlackVolTermStructure>(new >>> BlackConstantVol(today, >>> calendar, >>> impliedVolatility, >>> dc))); >>> >>> boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(new >>> BlackScholesMertonProcess(underlyingHandle, >>> dividendTermStructure, >>> rateTermStructure, >>> volTermStructure)); >>> >>> boost::shared_ptr<Exercise> americanExercise(new AmericanExercise >> (today, >>> maturity)) ; >>> boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff >>> (optionType, strikePrice)); >>> >>> VanillaOption americanOption(payoff, americanExercise); >>> >>> americanOption.setPricingEngine (boost::shared_ptr<PricingEngine>( >>> new FDAmericanEngine<CrankNicolson>(bsmProcess, >>> 101,100))); >>> >>> cout << americanOption.NPV() << endl ; >>> >>> return 0 ; >>> } >>> >>> >>> >>> On Tue, Jul 22, 2014 at 7:39 AM, Andres Hernandez < >>> [hidden email]> wrote: >>> >>> Hi George, >>> >>> the problem occurs because you are trying to bootstrap on a >>> UnitedKingdom >>> holiday, which is implicitly included in the definition of >> USDLibor. >>> The >>> Libor class makes a joint calendar between the given financial >> center >>> calendar and the UK calendar. Since Libor is a London poll, there >> are >>> only >>> fixings for it on UK business days. If one wants to bootstrap the >>> curve on >>> a holiday, the indice's historical fixings (actually just the >> closest >>> fixing to the given date) need to be provided. >>> >>> >>> Mit freundlichen Grüßen / Kind regards >>> >>> Dr. Andres Hernandez >>> >>> Senior Financial Engineer >>> Business Analytics >>> Risk Analytics >>> >>> >>> >>> >>> >>> Phone: +49-69-6645-1351 IBM Deutschland >>> (Embedded >>> image moved >>> to file: >>> pic20635.gif) >>> >>> Mobile: +49-163-609-3280 Wilhelm-Fay-Str. >>> 30-34 >>> >>> E-Mail: [hidden email] 65936 Frankfurt >> am >>> Main >>> >>> Germany >>> >>> >>> >>> >>> >>> IBM Deutschland >>> GmbH / >>> Vorsitzender des >>> Aufsichtsrats: >>> Martin Jetter >>> Geschäftsführung: >>> Martina Koederitz >>> (Vorsitzende), >>> Reinhard Reschke, >>> Dieter Scholz, >>> Gregor Pillen, >>> Christian Noll, >>> Ivo Koerner >>> Sitz der >>> Gesellschaft: >>> Ehningen / >>> Registergericht: >>> Amtsgericht >>> Stuttgart, HRB >>> 14562 / >>> WEEE-Reg.-Nr. DE >>> 99369940 >>> >>> >>> >>> >>> >>> >>> From: George Cowie <[hidden email]> >>> To: QuantLib users < [hidden email]> >>> Date: 22/07/2014 14:10 >>> Subject: [Quantlib-users] UK Holiday for >>> USDLibor/PiecewiseYieldCurve >>> >>> >>> >>> Hello, >>> >>> I'm using PiecewiseYieldCurve to build a YieldTermStructure which >>> is >>> ultimately used by BlackScholesMertonProcess in my option pricing. >> I >>> believe I'm running into an issue on days that are holidays in the >> UK >>> (but >>> not the US). Here's the error I'm seeing when trying to run the >> code >>> below >>> for May 5, 2014 (Early May Bank Holiday): >>> >>> terminate called after throwing an instance of 'QuantLib::Error' >>> what(): 1st iteration: failed at 1st alive instrument, maturity >>> May >>> 14th, 2014, reference date May 7th, 2014: Missing no-fix1W >> Actual/360 >>> fixing for May 2nd, 2014 >>> Aborted >>> >>> Everything seems to work fine on other days... Am I doing >>> something >>> wrong with setting up the PiecewiseYieldCurve? >>> >>> Thanks, >>> George >>> >>> #include <ql/quantlib.hpp> >>> >>> using namespace std ; >>> using namespace QuantLib ; >>> >>> int main(int argc, char** argv) >>> { >>> vector<Rate> liborRates ; >>> liborRates.push_back(0.12075 / 100.0) ; //1W >>> liborRates.push_back(0.1515 / 100.0) ; //1M >>> liborRates.push_back(0.1935 / 100.0) ; //2M >>> liborRates.push_back(0.22535 / 100.0) ; //3M >>> liborRates.push_back(0.323 / 100.0) ; //6M >>> liborRates.push_back(0.549 / 100.0) ; //12M >>> >>> vector<Period> periods ; >>> periods.push_back(Period(1,Weeks)) ; >>> periods.push_back(Period(1,Months)) ; >>> periods.push_back(Period(2,Months)) ; >>> periods.push_back(Period(3,Months)) ; >>> periods.push_back(Period(6,Months)) ; >>> periods.push_back(Period(12,Months)) ; >>> >>> vector<boost::shared_ptr<RateHelper> > instruments ; >>> >>> for (vector<int>::size_type i = 0 ; i < liborRates.size () ; i++) >>> { >>> boost::shared_ptr<Quote> liborQuote(new SimpleQuote >> (liborRates >>> [i])) ; >>> Handle<Quote> liborHandle(liborQuote) ; >>> boost::shared_ptr<IborIndex> liborIndex(new USDLibor (periods >>> [i])) ; >>> boost::shared_ptr<RateHelper> rateHelper(new >> DepositRateHelper >>> (liborHandle,liborIndex)) ; >>> instruments.push_back(rateHelper) ; >>> } >>> >>> Calendar calendar = UnitedStates(); >>> Date today (5 , May ,2014); >>> Settings::instance().evaluationDate() = today ; >>> Natural settlementDays = 2; >>> Date settlement = calendar.advance ( today , settlementDays , >>> Days ); >>> DayCounter dc = Actual360 (); >>> >>> Date maturity(20, Jun, 2014) ; >>> double strikePrice = 100.0 ; >>> Option::Type optionType = Option::Call ; >>> double dividendYield = 0.0 ; >>> double impliedVolatility = 0.15 ; >>> double underlyingPrice = 100.0 ; >>> >>> Handle<Quote> underlyingHandle(boost::shared_ptr<Quote> (new >>> SimpleQuote >>> (underlyingPrice))); >>> >>> Handle<YieldTermStructure> rateTermStructure >>> (boost::shared_ptr<YieldTermStructure>(new >>> PiecewiseYieldCurve<ZeroYield,Linear>(settlement, instruments, >>> dc))) ; >>> >>> Handle<YieldTermStructure> >>> dividendTermStructure (boost::shared_ptr<YieldTermStructure>(new >>> FlatForward(today, >>> dividendYield, >>> dc))); >>> Handle<BlackVolTermStructure> >>> volTermStructure (boost::shared_ptr<BlackVolTermStructure>(new >>> BlackConstantVol(today, >>> calendar, >>> impliedVolatility, >>> dc))); >>> >>> boost::shared_ptr<BlackScholesMertonProcess> bsmProcess (new >>> BlackScholesMertonProcess(underlyingHandle, >>> dividendTermStructure, >>> rateTermStructure, >>> volTermStructure)); >>> >>> boost::shared_ptr<Exercise> americanExercise(new AmericanExercise >>> (today, >>> maturity)) ; >>> boost::shared_ptr<StrikedTypePayoff> payoff(new >> PlainVanillaPayoff >>> (optionType, strikePrice)); >>> >>> VanillaOption americanOption(payoff, americanExercise); >>> >>> americanOption.setPricingEngine (boost::shared_ptr<PricingEngine>( >>> new FDAmericanEngine<CrankNicolson>(bsmProcess, >>> 101,100))); >>> >>> cout << americanOption.NPV() << endl ; >>> >>> return 0 ; >>> } >>> >> ------------------------------------------------------------------------------ >> >>> >>> >>> Want fast and easy access to all the code in your enterprise? Index >>> and >>> search up to 200,000 lines of code with a free copy of Black Duck >>> Code Sight - the same software that powers the world's largest code >>> search on Ohloh, the Black Duck Open Hub! Try it now. >>> >> http://p.sf.net/sfu/bds_______________________________________________ >>> >>> QuantLib-users mailing list >>> [hidden email] >>> https://lists.sourceforge.net/lists/listinfo/quantlib-users >>> >>> >> ------------------------------------------------------------------------------ >> >>> Want fast and easy access to all the code in your enterprise? Index and >>> search up to 200,000 lines of code with a free copy of Black Duck >>> Code Sight - the same software that powers the world's largest code >>> search on Ohloh, the Black Duck Open Hub! Try it now. >>> http://p.sf.net/sfu/bds >>> _______________________________________________ >>> QuantLib-users mailing list >>> [hidden email] >>> https://lists.sourceforge.net/lists/listinfo/quantlib-users >>> >> ------------------------------------------------------------------------------ Want fast and easy access to all the code in your enterprise? Index and search up to 200,000 lines of code with a free copy of Black Duck Code Sight - the same software that powers the world's largest code search on Ohloh, the Black Duck Open Hub! Try it now. http://p.sf.net/sfu/bds _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
thanks a lot, Andres and George. I created a pull request to fix the
deposit helpers in this sense: https://github.com/lballabio/quantlib/pull/117 There is only one more little complication I think, namely if we have zero fixing days and are on a holiday in which case we should adjust the start date of the deposit just as it would have been done under the original calendar. The code looks not as neat as in Andres' example above, mainly because I don't know how the hell I can clone a calendar and remove a holiday without impacting all other instances of the same type ... We should think about adding the ignore - fixing options for swaps later on ! kind regards Peter On 24 July 2014 16:06, Andres Hernandez <[hidden email]> wrote: > Hi George, > > as Peter mentioned, you can use another of the constructors. If you want to > use the USDLibor conventions you could use something like the following > inside the loop: > > boost::shared_ptr<IborIndex> liborIndex(new USDLibor(periods[i])) ; > > Calendar calendar = liborIndex->fixingCalendar(); > calendar.removeHoliday(today); > boost::shared_ptr<RateHelper> rateHelper(new DepositRateHelper > ( liborHandle, > liborIndex->tenor(), > liborIndex->fixingDays(), > calendar, > liborIndex-> > businessDayConvention(), > liborIndex->endOfMonth(), > liborIndex->dayCounter > ()) ); > instruments.push_back(rateHelper); > > > @Peter, you are right,no modification would be needed and the behaviour for > the swaps is the correct one. > > cheers, > Andres > > > > From: George Cowie <[hidden email]> > To: Peter Caspers <[hidden email]> > Cc: Andres Hernandez/Germany/IBM@IBMDE, QuantLib users > <[hidden email]> > Date: 24/07/2014 13:52 > Subject: Re: [Quantlib-users] UK Holiday for > USDLibor/PiecewiseYieldCurve > > > > Interesting discussion... sorry to change the subject, but I'm still trying > to figure out how to adapt my code to this situation. How do I force my > YieldTermStructure to bootstrap with a different date? I have to value the > option on May 5th, but as you pointed out, changing the evaluation date to > a holiday has the described consequences. > > > On Thu, Jul 24, 2014 at 6:00 AM, Peter Caspers <[hidden email]> > wrote: > reminding myself of what workaround we actually implemented for swap > helper :o ... and what Murex offers here (always a good reference), > the full set of options would probably be > > default - require historic fixings, take today's fixing if available > ignore today's tixing - require historic fixings, always ignore > today's fixing > ignore all fixings - ignore all fixings (i.e. estimate forward rates > always on the curve - this is technically ok even if the fixing date > is in the past, since only the index estimation period's > start and end date enter the estimation, and these two dates are > always greater or equal today) > > these options to be applied only in the context of yield curve > bootstrapping, ideally to be set on the level of the curve itself. > > > On 24 July 2014 10:26, Peter Caspers <[hidden email]> wrote: > > Hi Andres, > > > > yes, the index in the deposit rate helper seems to be merely a > > convenient way for coding - with the one exception that deposits do > > not (directly) have anything to do with actual index fixings, and > this > > is also where the code breaks. And yes, it gets even worse in your > > example when you use the USD Libor index for USD cash deposits on a > UK > > but non-NY holiday (you could use the index-free constructor though > > and pass the NY calendar directly instead, right, solving half of > the > > problem ?). So just treating the deposit helper's index and its > fixing > > as a computational tool to get the implied Quote seems a reasonable > > solution, in your USD / Libor example yielding the correct > conventions > > even, if I am not mistaken ? I wouldn't introduce any flag or > method > > to activate this behaviour, it should be the only one present > (because > > checking for holidays can easily be done in the user's code if > > necessary at all). > > > > For swaps on the other hand I think the current behaviour is fine - > > what fixing would you take for the first period in a Euribor swap > on a > > TARGET holiday ? Probably the same as you take after the fixing > around > > 11am on a trading day, i.e. the last known fixing. That is exactly > the > > logic applied in the library. I wouldn't change anything here. It > > might be that you get an exception because you just don't provide > the > > historic fixing, but in this case it is a legitimate demand of the > > library and working around this should only be done in the user > code > > imo. > > > > best > > Peter > > > > > > > > > > > > On 24 July 2014 09:23, Andres Hernandez < > [hidden email]> wrote: > >> > >> Hi Peter, > >> > >> I agree that it would be nice to at least have it as an option. We > >> currently do a small workaround, whereby we set in our system a > parameter > >> for the curve specifying the holiday calendar for that curve. The > only use > >> of that calendar is to determine if it is a holiday for the curve > or not > >> and if yes to make a fallback to yesterday's values. In the case > of the EUR > >> curves, this is arguably a good behaviour as the index and the > geographical > >> region have the same calendar, but for the USD case, we are > basically > >> forcing a fallback for a holiday on a different country. The issue > is > >> compounded by the fact that in this case the deposit is traded on > that day, > >> it is just the index that gets no fixing. > >> > >> I took a look and I am almost sure that removing the evaluation > date from > >> the fixing calendar in InterestRate constructor would be enough to > make > >> deposits go through. This could simply be accomplished with an > extra public > >> member function that one would call if one wanted it to go through > on > >> holidays. A more involved and important problem would be to get > the > >> SwapRateHelper to go though on holidays (if desired), as I am > positive that > >> that was the reason for our instituting the fallback. I will see > if I have > >> the time to change it, and would then probably subscribe to the > developers > >> list to get some feedback in how to go about changing it. > >> > >> > >> Mit freundlichen Grüßen / Kind regards > >> > >> Dr. Andres Hernandez > >> > >> Senior Financial Engineer > >> Business Analytics > >> Risk Analytics > >> > >> > >> > >> > >> > >> Phone: +49-69-6645-1351 IBM Deutschland > (Embedded > >> > image moved > >> > to file: > >> > pic02235.gif) > >> > >> Mobile: +49-163-609-3280 Wilhelm-Fay-Str. > 30-34 > >> > >> E-Mail: [hidden email] 65936 Frankfurt > am Main > >> > >> Germany > >> > >> > >> > >> > >> > >> IBM Deutschland > >> GmbH / > >> Vorsitzender des > >> Aufsichtsrats: > >> Martin Jetter > >> Geschäftsführung: > >> Martina Koederitz > >> (Vorsitzende), > >> Reinhard Reschke, > >> Dieter Scholz, > >> Gregor Pillen, > >> Christian Noll, > >> Ivo Koerner > >> Sitz der > >> Gesellschaft: > >> Ehningen / > >> Registergericht: > >> Amtsgericht > >> Stuttgart, HRB > >> 14562 / > >> WEEE-Reg.-Nr. DE > >> 99369940 > >> > >> > >> > >> > >> > >> > >> From: Peter Caspers <[hidden email]> > >> To: Andres Hernandez/Germany/IBM@IBMDE > >> Cc: George Cowie <[hidden email]>, QuantLib users > >> <[hidden email]> > >> Date: 23/07/2014 21:56 > >> Subject: Re: [Quantlib-users] UK Holiday for > >> USDLibor/PiecewiseYieldCurve > >> > >> > >> > >> Hi, > >> > >> I think this question is an older one but I don't remember that it > was > >> finally decided how to handle this situation (?) - which is, > should we > >> allow to bootstrap a curve on a day which is a holiday for the > cash > >> instruments in the curve or not. If negative, we could maybe throw > a > >> different message ( the current one indeed sounds a bit > paradoxical ). > >> If yes ( which would be my personal preference, because you simply > >> want to run your daily processes spitting out numbers even if not > a > >> hundred percent sensible all of them ), one has to define how a > >> deposit which is not traded on that day should be calculated. One > >> obvious way would be to just treat the evaluation date as a > business > >> day when calculating the helper's fixing date. I did not try, but > it > >> may be enough to join the business days of the helper's calendar > with > >> a new one just having one business day (the evaluation date) > before > >> passing it to the no-fix index to make this kind of solution work. > >> What do you think ? > >> > >> Peter > >> > >> > >> On 23 July 2014 15:05, Andres Hernandez < > [hidden email]> > >> wrote: > >>> > >>> Hi George, > >>> > >>> you are still setting the evaluation date to a holiday: > >>> > >>> Date today (5 , May ,2014); > >>> Date liborDate (2, May, 2014) ; > >>> Settings::instance().evaluationDate() = today ; > >>> > >>> > >>> Let's follow the logic: > >>> During bootstrapping, the method impliedQuote() of the rate > helper is > >>> called to compare against the market quote. The DepositRateHelper > simply > >>> returns the fixing corresponding to the fixingDate_ as a return > value. > >>> The fixingDate_ is set during initialization as the return value > of the > >>> function InterestRate::fixingDate(earliestDate_). The function > >>> InterestRate::fixingDate sets back the date given as input > parameter by > >> the > >>> number of fixing days according to the index' calendar. > >>> The parameter earliestDate_ being passed to fixingDate is set > during > >>> initialization to the evaluation date (which you set to the 5th > of May) > >>> moved forward by the number of fixing days according to the > index' > >>> calendar. > >>> Note that if the evaluation date is a holiday you do not end up > with the > >>> same date, but rather with the last business day prior to > evaluation > >> date. > >>> The first act moves the date from the 5th of May to the 7th and > checks > >>> whether it is a business day, which it is. The second move sets > it back > >> two > >>> days to the 5th, and checks whether it is a business day, which > it isn't, > >>> so it sets it back until it finds a business day, i.e. the 2nd of > May. > >>> Since the value is in the past, it requests a historical fixing, > which > >> you > >>> did not provide and so the QL_REQUIRE throws. > >>> > >>> Mit freundlichen Grüßen / Kind regards > >>> > >>> Dr. Andres Hernandez > >>> > >>> Senior Financial Engineer > >>> Business Analytics > >>> Risk Analytics > >>> > >>> > >>> > >>> > >>> > >>> Phone: +49-69-6645-1351 IBM Deutschland > >> (Embedded > >>> > >> image moved > >>> > >> to file: > >>> > >> pic64586.gif) > >>> > >>> Mobile: +49-163-609-3280 > Wilhelm-Fay-Str. 30-34 > >>> > >>> E-Mail: [hidden email] 65936 Frankfurt > am Main > >>> > >>> Germany > >>> > >>> > >>> > >>> > >>> > >>> IBM Deutschland > >>> GmbH / > >>> Vorsitzender des > >>> Aufsichtsrats: > >>> Martin Jetter > >>> Geschäftsführung: > >>> Martina Koederitz > >>> (Vorsitzende), > >>> Reinhard Reschke, > >>> Dieter Scholz, > >>> Gregor Pillen, > >>> Christian Noll, > >>> Ivo Koerner > >>> Sitz der > >>> Gesellschaft: > >>> Ehningen / > >>> Registergericht: > >>> Amtsgericht > >>> Stuttgart, HRB > >>> 14562 / > >>> WEEE-Reg.-Nr. DE > >>> 99369940 > >>> > >>> > >>> > >>> > >>> > >>> > >>> From: George Cowie <[hidden email]> > >>> To: Andres Hernandez/Germany/IBM@IBMDE > >>> Cc: QuantLib users <[hidden email]> > >>> Date: 23/07/2014 11:51 > >>> Subject: Re: [Quantlib-users] UK Holiday for > >>> USDLibor/PiecewiseYieldCurve > >>> > >>> > >>> > >>> > >>> Thank you Andres. What you're describing makes sense, but I > can't seem > >> to > >>> avoid an error when trying to value the option on May 5, 2014. > I've > >> copied > >>> the updated code snippet with changed section highlighted/bolded > below. > >> I > >>> seem to always get an exception of the form: > >>> > >>> terminate called after throwing an instance of 'QuantLib::Error' > >>> what(): 1st iteration: failed at 1st alive instrument, > maturity May > >>> 14th, 2014, reference date May 6th, 2014: Missing no-fix1W > Actual/360 > >>> fixing for May 2nd, 2014 > >>> > >>> Is there something wrong with my approach here? > >>> > >>> Thanks, > >>> George > >>> > >>> > >>> #include <ql/quantlib.hpp> > >>> > >>> using namespace std ; > >>> using namespace QuantLib ; > >>> > >>> int main(int argc, char** argv) > >>> { > >>> vector<Rate> liborRates ; > >>> liborRates.push_back(0.12075 / 100.0) ; //1W > >>> liborRates.push_back(0.1515 / 100.0) ; //1M > >>> liborRates.push_back(0.1935 / 100.0) ; //2M > >>> liborRates.push_back(0.22535 / 100.0) ; //3M > >>> liborRates.push_back(0.323 / 100.0) ; //6M > >>> liborRates.push_back(0.549 / 100.0) ; //12M > >>> > >>> vector<Period> periods ; > >>> periods.push_back(Period(1,Weeks)) ; > >>> periods.push_back(Period(1,Months)) ; > >>> periods.push_back(Period(2,Months)) ; > >>> periods.push_back(Period(3,Months)) ; > >>> periods.push_back(Period(6,Months)) ; > >>> periods.push_back(Period(12,Months)) ; > >>> > >>> vector<boost::shared_ptr<RateHelper> > instruments ; > >>> > >>> for (vector<int>::size_type i = 0 ; i < liborRates.size() ; i+ > +) > >>> { > >>> boost::shared_ptr<Quote> liborQuote(new SimpleQuote > (liborRates > >> [i])) ; > >>> Handle<Quote> liborHandle(liborQuote) ; > >>> boost::shared_ptr<IborIndex> liborIndex(new USDLibor > (periods[i])) ; > >>> boost::shared_ptr<RateHelper> rateHelper(new > DepositRateHelper > >>> (liborHandle,liborIndex)) ; > >>> instruments.push_back(rateHelper) ; > >>> } > >>> > >>> Calendar calendar = UnitedStates(); > >>> Date today (5 , May ,2014); > >>> Date liborDate (2, May, 2014) ; > >>> Settings::instance().evaluationDate() = today ; > >>> Natural settlementDays = 2; > >>> Date settlement = calendar.advance ( liborDate , > settlementDays , > >> Days ); > >>> DayCounter dc = Actual360 (); > >>> > >>> Date maturity(20, Jun, 2014) ; > >>> double strikePrice = 100.0 ; > >>> Option::Type optionType = Option::Call ; > >>> double dividendYield = 0.0 ; > >>> double impliedVolatility = 0.15 ; > >>> double underlyingPrice = 100.0 ; > >>> > >>> Handle<Quote> underlyingHandle(boost::shared_ptr<Quote>(new > SimpleQuote > >>> (underlyingPrice))); > >>> > >>> Handle<YieldTermStructure> rateTermStructure > >>> (boost::shared_ptr<YieldTermStructure>(new > >>> PiecewiseYieldCurve<ZeroYield,Linear>(settlement, instruments, > dc))) ; > >>> > >>> Handle<YieldTermStructure> > >>> dividendTermStructure(boost::shared_ptr<YieldTermStructure> > (new > >>> FlatForward(today, > >>> dividendYield, > >>> dc))); > >>> Handle<BlackVolTermStructure> > >>> volTermStructure(boost::shared_ptr<BlackVolTermStructure>(new > >>> BlackConstantVol(today, > >>> calendar, > >>> impliedVolatility, > >>> dc))); > >>> > >>> boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(new > >>> BlackScholesMertonProcess(underlyingHandle, > >>> dividendTermStructure, > >>> rateTermStructure, > >>> volTermStructure)); > >>> > >>> boost::shared_ptr<Exercise> americanExercise(new > AmericanExercise > >> (today, > >>> maturity)) ; > >>> boost::shared_ptr<StrikedTypePayoff> payoff(new > PlainVanillaPayoff > >>> (optionType, strikePrice)); > >>> > >>> VanillaOption americanOption(payoff, americanExercise); > >>> > >>> americanOption.setPricingEngine > (boost::shared_ptr<PricingEngine>( > >>> new FDAmericanEngine<CrankNicolson>(bsmProcess, > >>> 101,100))); > >>> > >>> cout << americanOption.NPV() << endl ; > >>> > >>> return 0 ; > >>> } > >>> > >>> > >>> > >>> On Tue, Jul 22, 2014 at 7:39 AM, Andres Hernandez < > >>> [hidden email]> wrote: > >>> > >>> Hi George, > >>> > >>> the problem occurs because you are trying to bootstrap on a > >>> UnitedKingdom > >>> holiday, which is implicitly included in the definition of > >> USDLibor. > >>> The > >>> Libor class makes a joint calendar between the given > financial > >> center > >>> calendar and the UK calendar. Since Libor is a London poll, > there > >> are > >>> only > >>> fixings for it on UK business days. If one wants to > bootstrap the > >>> curve on > >>> a holiday, the indice's historical fixings (actually just > the > >> closest > >>> fixing to the given date) need to be provided. > >>> > >>> > >>> Mit freundlichen Grüßen / Kind regards > >>> > >>> Dr. Andres Hernandez > >>> > >>> Senior Financial Engineer > >>> Business Analytics > >>> Risk Analytics > >>> > >>> > >>> > >>> > >>> > >>> Phone: +49-69-6645-1351 IBM > Deutschland > >>> (Embedded > >>> image moved > >>> to file: > >>> pic20635.gif) > >>> > >>> Mobile: +49-163-609-3280 > Wilhelm-Fay-Str. > >>> 30-34 > >>> > >>> E-Mail: [hidden email] 65936 > Frankfurt > >> am > >>> Main > >>> > >>> Germany > >>> > >>> > >>> > >>> > >>> > >>> IBM Deutschland > >>> GmbH / > >>> Vorsitzender des > >>> Aufsichtsrats: > >>> Martin Jetter > >>> Geschäftsführung: > >>> Martina Koederitz > >>> (Vorsitzende), > >>> Reinhard Reschke, > >>> Dieter Scholz, > >>> Gregor Pillen, > >>> Christian Noll, > >>> Ivo Koerner > >>> Sitz der > >>> Gesellschaft: > >>> Ehningen / > >>> Registergericht: > >>> Amtsgericht > >>> Stuttgart, HRB > >>> 14562 / > >>> WEEE-Reg.-Nr. DE > >>> 99369940 > >>> > >>> > >>> > >>> > >>> > >>> > >>> From: George Cowie <[hidden email]> > >>> To: QuantLib users < > [hidden email]> > >>> Date: 22/07/2014 14:10 > >>> Subject: [Quantlib-users] UK Holiday for > >>> USDLibor/PiecewiseYieldCurve > >>> > >>> > >>> > >>> Hello, > >>> > >>> I'm using PiecewiseYieldCurve to build a > YieldTermStructure which > >>> is > >>> ultimately used by BlackScholesMertonProcess in my option > pricing. > >> I > >>> believe I'm running into an issue on days that are holidays > in the > >> UK > >>> (but > >>> not the US). Here's the error I'm seeing when trying to > run the > >> code > >>> below > >>> for May 5, 2014 (Early May Bank Holiday): > >>> > >>> terminate called after throwing an instance of > 'QuantLib::Error' > >>> what(): 1st iteration: failed at 1st alive instrument, > maturity > >>> May > >>> 14th, 2014, reference date May 7th, 2014: Missing no-fix1W > >> Actual/360 > >>> fixing for May 2nd, 2014 > >>> Aborted > >>> > >>> Everything seems to work fine on other days... Am I > doing > >>> something > >>> wrong with setting up the PiecewiseYieldCurve? > >>> > >>> Thanks, > >>> George > >>> > >>> #include <ql/quantlib.hpp> > >>> > >>> using namespace std ; > >>> using namespace QuantLib ; > >>> > >>> int main(int argc, char** argv) > >>> { > >>> vector<Rate> liborRates ; > >>> liborRates.push_back(0.12075 / 100.0) ; //1W > >>> liborRates.push_back(0.1515 / 100.0) ; //1M > >>> liborRates.push_back(0.1935 / 100.0) ; //2M > >>> liborRates.push_back(0.22535 / 100.0) ; //3M > >>> liborRates.push_back(0.323 / 100.0) ; //6M > >>> liborRates.push_back(0.549 / 100.0) ; //12M > >>> > >>> vector<Period> periods ; > >>> periods.push_back(Period(1,Weeks)) ; > >>> periods.push_back(Period(1,Months)) ; > >>> periods.push_back(Period(2,Months)) ; > >>> periods.push_back(Period(3,Months)) ; > >>> periods.push_back(Period(6,Months)) ; > >>> periods.push_back(Period(12,Months)) ; > >>> > >>> vector<boost::shared_ptr<RateHelper> > instruments ; > >>> > >>> for (vector<int>::size_type i = 0 ; i < liborRates.size > () ; i++) > >>> { > >>> boost::shared_ptr<Quote> liborQuote(new SimpleQuote > >> (liborRates > >>> [i])) ; > >>> Handle<Quote> liborHandle(liborQuote) ; > >>> boost::shared_ptr<IborIndex> liborIndex(new USDLibor > (periods > >>> [i])) ; > >>> boost::shared_ptr<RateHelper> rateHelper(new > >> DepositRateHelper > >>> (liborHandle,liborIndex)) ; > >>> instruments.push_back(rateHelper) ; > >>> } > >>> > >>> Calendar calendar = UnitedStates(); > >>> Date today (5 , May ,2014); > >>> Settings::instance().evaluationDate() = today ; > >>> Natural settlementDays = 2; > >>> Date settlement = calendar.advance ( today , > settlementDays , > >>> Days ); > >>> DayCounter dc = Actual360 (); > >>> > >>> Date maturity(20, Jun, 2014) ; > >>> double strikePrice = 100.0 ; > >>> Option::Type optionType = Option::Call ; > >>> double dividendYield = 0.0 ; > >>> double impliedVolatility = 0.15 ; > >>> double underlyingPrice = 100.0 ; > >>> > >>> Handle<Quote> underlyingHandle(boost::shared_ptr<Quote> > (new > >>> SimpleQuote > >>> (underlyingPrice))); > >>> > >>> Handle<YieldTermStructure> rateTermStructure > >>> (boost::shared_ptr<YieldTermStructure>(new > >>> PiecewiseYieldCurve<ZeroYield,Linear>(settlement, > instruments, > >>> dc))) ; > >>> > >>> Handle<YieldTermStructure> > >>> dividendTermStructure > (boost::shared_ptr<YieldTermStructure>(new > >>> FlatForward(today, > >>> dividendYield, > >>> dc))); > >>> Handle<BlackVolTermStructure> > >>> volTermStructure > (boost::shared_ptr<BlackVolTermStructure>(new > >>> BlackConstantVol(today, > >>> calendar, > >>> impliedVolatility, > >>> dc))); > >>> > >>> boost::shared_ptr<BlackScholesMertonProcess> bsmProcess > (new > >>> BlackScholesMertonProcess(underlyingHandle, > >>> dividendTermStructure, > >>> rateTermStructure, > >>> volTermStructure)); > >>> > >>> boost::shared_ptr<Exercise> americanExercise(new > AmericanExercise > >>> (today, > >>> maturity)) ; > >>> boost::shared_ptr<StrikedTypePayoff> payoff(new > >> PlainVanillaPayoff > >>> (optionType, strikePrice)); > >>> > >>> VanillaOption americanOption(payoff, americanExercise); > >>> > >>> americanOption.setPricingEngine > (boost::shared_ptr<PricingEngine>( > >>> new FDAmericanEngine<CrankNicolson>(bsmProcess, > >>> 101,100))); > >>> > >>> cout << americanOption.NPV() << endl ; > >>> > >>> return 0 ; > >>> } > >>> > >> > ------------------------------------------------------------------------------ > > >> > >>> > >>> > >>> Want fast and easy access to all the code in your > enterprise? Index > >>> and > >>> search up to 200,000 lines of code with a free copy of > Black Duck > >>> Code Sight - the same software that powers the world's > largest code > >>> search on Ohloh, the Black Duck Open Hub! Try it now. > >>> > >> > http://p.sf.net/sfu/bds_______________________________________________ > > >>> > >>> QuantLib-users mailing list > >>> [hidden email] > >>> https://lists.sourceforge.net/lists/listinfo/quantlib-users > >>> > >>> > >> > ------------------------------------------------------------------------------ > > >> > >>> Want fast and easy access to all the code in your enterprise? > Index and > >>> search up to 200,000 lines of code with a free copy of Black Duck > >>> Code Sight - the same software that powers the world's largest > code > >>> search on Ohloh, the Black Duck Open Hub! Try it now. > >>> http://p.sf.net/sfu/bds > >>> _______________________________________________ > >>> QuantLib-users mailing list > >>> [hidden email] > >>> https://lists.sourceforge.net/lists/listinfo/quantlib-users > >>> > >> > > ------------------------------------------------------------------------------ Want fast and easy access to all the code in your enterprise? Index and search up to 200,000 lines of code with a free copy of Black Duck Code Sight - the same software that powers the world's largest code search on Ohloh, the Black Duck Open Hub! Try it now. http://p.sf.net/sfu/bds _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
Thanks again guys, I was able to get my example code working with Andres suggestion above. Peter, I'll try pulling in your fix as well when it's available. On Thu, Jul 24, 2014 at 12:54 PM, Peter Caspers <[hidden email]> wrote: thanks a lot, Andres and George. I created a pull request to fix the ------------------------------------------------------------------------------ Want fast and easy access to all the code in your enterprise? Index and search up to 200,000 lines of code with a free copy of Black Duck Code Sight - the same software that powers the world's largest code search on Ohloh, the Black Duck Open Hub! Try it now. http://p.sf.net/sfu/bds _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
Free forum by Nabble | Edit this page |