|
View:
New views
5 Messages
—
Rating Filter:
Alert me
|
|
|
Update version of experimental/mcbasketHi,
After almost 2 year I would like to post an updated version of mcbasket experimental. The idea is still the same as the initial version: i.e. have one single engine (here MCAmericanPathEngine or MCPathBasketEngine) and to only have to write a new option/payoff (PathMultiAssetOption/PathPayoff) Here the biggest new feature is the support of American Options. The key feature is this virtual method of PathPayoff virtual void value(const Matrix & path, Array & payments, Array & exercises, std::vector<Array> & states) const = 0; which has to return all information needed to value a payoff with early exercise (for a single path) path: is the path of all assets/times payments: all payments made exercises: if the option is exercised at time i, all payment up to (and including i) are preserved and the others cancelled states: a vector of financial coordinates used in LS I have attached a diff wrt the most recent svn and an example of an American Lookback. I can go through all the code in details if people are interested. I don't think it makes much sense to compare it to the 1st version, since it was very limited in features and hardly usable at all. TODO, problems, bugs: - I had to copy&paste a lot of classes/templates already used in QL (e.g.: EarlyExercisePathPricer, LongstaffSchwartzPathPricer). My problem is that the existing EarlyExercisePathPricer only seems to handle an option which pays only once (i.e. at exercise), while I wanted to allow an option that pays many times and that I can cancel at some point - allow for non 1-1 mapping between paths and assets (e.g. stoch vol) - allow for non deterministic interest rates (i.e. replace the discount factors with 1/numeraire) - find nicer names [example.cpp] /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ // the only header you need to use QuantLib #define BOOST_LIB_DIAGNOSTIC # include <ql/quantlib.hpp> #undef BOOST_LIB_DIAGNOSTIC #include <boost/timer.hpp> #include <iostream> #include <iomanip> using namespace QuantLib; #if defined(QL_ENABLE_SESSIONS) namespace QuantLib { Integer sessionId() { return 0; } } #endif // The payoff class AmericanLookback : public AdaptedPathPayoff { public: virtual std::string name() const; virtual std::string description() const; virtual void operator()(ValuationData & data) const; virtual Size basisSystemDimension() const; virtual Real lowerBoundContinuationValue() const; }; std::string AmericanLookback::name() const { return "AmericanLookback"; } std::string AmericanLookback::description() const { return name(); } Size AmericanLookback::basisSystemDimension() const { return 2; } Real AmericanLookback::lowerBoundContinuationValue() const { return 0.0; } void AmericanLookback::operator()(ValuationData & data) const { Real sum = 0.0; const Size numberOfTimes = data.numberOfTimes(); const Size numberOfAssets = data.numberOfAssets(); double runningMaximum = 1.0; for (Size i = 0; i < numberOfTimes; ++i) { double thisSum = 0.0; for (Size j = 0; j < numberOfAssets; ++j) thisSum += data.getAssetValue(i, j); thisSum /= numberOfAssets; runningMaximum = std::max(runningMaximum, thisSum); Array financialCoordinates(basisSystemDimension()); const double payoff = runningMaximum - thisSum; financialCoordinates[0] = runningMaximum / thisSum; financialCoordinates[1] = thisSum; double exercise = payoff; double payment = 0.0; // this is only to be able to price the european version. if (i == numberOfTimes - 1) std::swap(exercise, payment); data.setPayoffValue(i, payment); data.setExerciseData(i, exercise, financialCoordinates); } } // The option class AmericanLookbackOption : public PathMultiAssetOption { public: AmericanLookbackOption(boost::shared_ptr<PathPayoff> &, std::vector<Date> &, const boost::shared_ptr<PricingEngine>& engine = boost::shared_ptr<PricingEngine>() ); virtual boost::shared_ptr<PathPayoff> pathPayoff() const; virtual std::vector<Date> fixingDates() const; private: boost::shared_ptr<PathPayoff> pathPayoff_; std::vector<Date> fixingDates_; }; AmericanLookbackOption::AmericanLookbackOption(boost::shared_ptr<PathPayoff> & pathPayoff, std::vector<Date> & fixingDates, const boost::shared_ptr<PricingEngine> & engine) : PathMultiAssetOption(engine), pathPayoff_(pathPayoff), fixingDates_(fixingDates) { } boost::shared_ptr<PathPayoff> AmericanLookbackOption::pathPayoff() const { return pathPayoff_; } std::vector<Date> AmericanLookbackOption::fixingDates() const { return fixingDates_; } int main(int, char* []) { QL_TRACE_ENABLE; try { boost::timer timer; std::cout << std::endl; // our options Calendar calendar = TARGET(); Real underlying = 1.0; Spread dividendYield = 0.00; Rate riskFreeRate = 0.05; Volatility volatility = 0.20; Date todaysDate(15, May, 1998); Date settlementDate(17, May, 1998); Settings::instance().evaluationDate() = todaysDate; DayCounter dayCounter = Actual365Fixed(); std::cout << "Underlying price = " << underlying << std::endl; std::cout << "Risk-free interest rate = " << io::rate(riskFreeRate) << std::endl; std::cout << "Dividend yield = " << io::rate(dividendYield) << std::endl; std::cout << "Volatility = " << io::volatility(volatility) << std::endl; std::cout << std::endl; std::string method; std::cout << std::endl ; Handle<Quote> underlyingH( boost::shared_ptr<Quote>(new SimpleQuote(underlying))); // bootstrap the yield/dividend/vol curves Handle<YieldTermStructure> flatTermStructure( boost::shared_ptr<YieldTermStructure>( new FlatForward(settlementDate, riskFreeRate, dayCounter))); Handle<YieldTermStructure> flatDividendTS( boost::shared_ptr<YieldTermStructure>( new FlatForward(settlementDate, dividendYield, dayCounter))); Handle<BlackVolTermStructure> flatVolTS( boost::shared_ptr<BlackVolTermStructure>(new BlackConstantVol(settlementDate, calendar, volatility, dayCounter))); boost::shared_ptr<StochasticProcess1D> stochasticProcess( new BlackScholesMertonProcess(underlyingH, flatDividendTS, flatTermStructure, flatVolTS)); std::vector<boost::shared_ptr<StochasticProcess1D> > arrayOfProcesses; arrayOfProcesses.push_back(stochasticProcess); Matrix corr(1, 1); corr[0][0] = 1; boost::shared_ptr<StochasticProcessArray> mdProcess(new StochasticProcessArray(arrayOfProcesses, corr)); // options boost::shared_ptr<PathPayoff> lookbackPayoff(new AmericanLookback()); std::vector<Date> fixings; Date firstFixing(17, May, 2000); fixings.push_back(firstFixing); Period annual(Annual); for (Size i = 0; i < 5; ++i) fixings.push_back(fixings.back() + annual); AmericanLookbackOption lookbackOption(lookbackPayoff, fixings); // Monte Carlo Method Size timeSteps = 10; method = "MC (Sobol)"; Size nSamples = 1 << 17; Size calibSamples = 1 << 17; boost::shared_ptr<PricingEngine> mcengine; mcengine = MakeMCPathBasketEngine<LowDiscrepancy>(mdProcess).withSteps(timeSteps).withSamples(nSamples); lookbackOption.setPricingEngine(mcengine); std::cout << method << " E " << nSamples << " iterations: " << lookbackOption.NPV() << std::endl; mcengine = MakeMCAmericanPathEngine<LowDiscrepancy>(mdProcess).withSteps(timeSteps).withSamples(nSamples).withCalibrationSamples(calibSamples); lookbackOption.setPricingEngine(mcengine); std::cout << method << " A " << nSamples << " iterations: " << lookbackOption.NPV() << std::endl; return 0; } catch (Error& err) { std::cout << "QuantLib::Error: " << err.what() << std::endl; return 1; } catch (std::exception& e) { std::cout << "std::exception: " << e.what() << std::endl; return 2; } catch (...) { std::cout << "unknown error" << std::endl; return 3; } } ------------------------------------------------------------------------------ Come build with us! The BlackBerry(R) Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9 - 12, 2009. Register now! http://p.sf.net/sfu/devconference _______________________________________________ QuantLib-dev mailing list QuantLib-dev@... https://lists.sourceforge.net/lists/listinfo/quantlib-dev |
|
|
Re: Update version of experimental/mcbasketHi Andrea
do you see a change to replace the original version of the classes EarlyExercisePathPricer and LongstaffSchwartzPathPricer in ql/methods/montecarlo by your version? best regards Klaus ------------------------------------------------------------------------------ Come build with us! The BlackBerry(R) Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9 - 12, 2009. Register now! http://p.sf.net/sfu/devconference _______________________________________________ QuantLib-dev mailing list QuantLib-dev@... https://lists.sourceforge.net/lists/listinfo/quantlib-dev |
|
|
Re: Update version of experimental/mcbasketOn 10/10/09 20:53, Klaus Spanderen wrote:
> Hi Andrea > > do you see a change to replace the original version of the classes > > EarlyExercisePathPricer and LongstaffSchwartzPathPricer > > in ql/methods/montecarlo by your version? Ideally yes. The reasons I did not use the EarlyExercisePathPricer are: 1) it only provides a method to get the exercise payment (i.e. operator()) and the state, while I would like to get the value of payments that are made until the option is cancelled 2) I first added this 3rd virtual method. but then I realized that what the LongstaffSchwartzPathPricer caches is not optimal. it caches the paths, while I found much better to cache a triplet of vectors (exercise payments, payments, states) so that I process a single path only once. For a trivial case (i.e. the american call option) it is the same, but if each payment or state is path dependent, then if I only cache the path, I have to reprocess the whole path each time I need a new "time". 3) so I decided that it was better for the LongstaffSchwartzPathPricer to have access to the payoff directly and store the relevant information for each path (and not the path itself) I have not seen how the current implementation of EarlyExercisePathPricer & LongstaffSchwartzPathPricer are used in a complex path dependent case, so maybe there is a more "standard" way of doing it. Then I added to LongstaffSchwartzPathPricer 2 extra things (which are easily ported to the main version) 1) it currently skips all paths that give a non positive exercise value. this because it assumes the continuation value will always be positive, and there is no point to accept a negative exercise. it might not be the case always and it is hard to dynamically detect this lower bound (0.0). so the payoff has a function to return the lower bound of the continuation value or -INF if absent 2) it checks if the 2 trivial exercise strategies (exercise for all paths or never) are better than the LS algorithm. if this is the case, then we override the decision with 2 special vectors of coefficients (empty => never, too big => always). I noticed that if the states are chosen badly, the LS algorithm can be trivially wrong. This might be bad for sensitivities since the whole "function" has a discontinuity. And it prints the result of this check using QL_TRACE Andrea ------------------------------------------------------------------------------ Come build with us! The BlackBerry(R) Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9 - 12, 2009. Register now! http://p.sf.net/sfu/devconference _______________________________________________ QuantLib-dev mailing list QuantLib-dev@... https://lists.sourceforge.net/lists/listinfo/quantlib-dev |
|
|
Re: Update version of experimental/mcbasketOn 11/10/09 19:46, Andrea wrote:
> 1) it currently skips all paths that give a non positive exercise value. this because it assumes the > continuation value will always be positive, and there is no point to accept a negative exercise. > it might not be the case always and it is hard to dynamically detect this lower bound (0.0). so the > payoff has a function to return the lower bound of the continuation value or -INF if absent It is actually possible to dynamically detect what an out of the money option is. Since we go backward, we just remember what the lowest payoff is, and never exercise if the early termination value is less or equal to that value. In this updated version of the mcbasket experimental patch, I've implemented it. In my (simple) tests it worked properly. ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ QuantLib-dev mailing list QuantLib-dev@... https://lists.sourceforge.net/lists/listinfo/quantlib-dev |
|
|
Re: Update version of experimental/mcbasketHi
can you do me a favour and send me your ql/experimental/mcbasket directory as a tar-ball? (the diff doesn't work out on my machine here.). thanks Klaus On Monday 09 November 2009 14:34:24 Andrea wrote: > On 11/10/09 19:46, Andrea wrote: > > 1) it currently skips all paths that give a non positive exercise value. > > this because it assumes the continuation value will always be positive, > > and there is no point to accept a negative exercise. it might not be the > > case always and it is hard to dynamically detect this lower bound (0.0). > > so the payoff has a function to return the lower bound of the > > continuation value or -INF if absent > > It is actually possible to dynamically detect what an out of the money > option is. Since we go backward, we just remember what the lowest payoff > is, and never exercise if the early termination value is less or equal to > that value. > > In this updated version of the mcbasket experimental patch, I've > implemented it. In my (simple) tests it worked properly. ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ QuantLib-dev mailing list QuantLib-dev@... https://lists.sourceforge.net/lists/listinfo/quantlib-dev |
| Free embeddable forum powered by Nabble | Forum Help |