/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (C) 2005, 2006 Theo Boafo Copyright (C) 2006 StatPro Italia srl This file is part of QuantLib, a free-software/open-source library for financial quantitative analysts and developers - http://quantlib.org/ QuantLib is free software: you can redistribute it and/or modify it under the terms of the QuantLib license. You should have received a copy of the license along with this program; if not, please email . The license is also available online at . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /*! \file binomialconvertibleengine.hpp \brief binomial engine for convertible bonds */ #ifndef quantlib_binomial_convertible_engine_hpp #define quantlib_binomial_convertible_engine_hpp #include #include #include #include #include #include namespace QuantLib { //! Binomial Tsiveriotis-Fernandes engine for convertible bonds /* \ingroup hybridengines \test the correctness of the returned value is tested by checking it against known results in a few corner cases. */ template class BinomialConvertibleEngine : public ConvertibleBond::option::engine { public: BinomialConvertibleEngine(Size timeSteps) : timeSteps_(timeSteps) {} void calculate() const; private: Size timeSteps_; }; template void BinomialConvertibleEngine::calculate() const { boost::shared_ptr process = boost::dynamic_pointer_cast( this->arguments_.stochasticProcess); QL_REQUIRE(process, "Black-Scholes process required"); DayCounter rfdc = process->riskFreeRate()->dayCounter(); DayCounter divdc = process->dividendYield()->dayCounter(); DayCounter voldc = process->blackVolatility()->dayCounter(); Real s0 = process->stateVariable()->value(); Volatility v = process->blackVolatility()->blackVol( arguments_.exercise->lastDate(), s0); Date maturityDate = arguments_.exercise->lastDate(); Rate riskFreeRate = process->riskFreeRate()->zeroRate( maturityDate, rfdc, Continuous, NoFrequency); Rate q = process->dividendYield()->zeroRate( maturityDate, divdc, Continuous, NoFrequency); Date referenceDate = process->riskFreeRate()->referenceDate(); // subtract dividends Size i; for (i=0; idate() >= referenceDate) s0 -= arguments_.dividends[i]->amount() * process->riskFreeRate()->discount( arguments_.dividends[i]->date()); } QL_REQUIRE(s0 > 0.0, "negative value after subtracting dividends"); // binomial trees with constant coefficient Handle underlying(boost::shared_ptr(new SimpleQuote(s0))); Handle flatRiskFree( boost::shared_ptr( new FlatForward(referenceDate, riskFreeRate, rfdc))); Handle flatDividends( boost::shared_ptr( new FlatForward(referenceDate, q, divdc))); Handle flatVol( boost::shared_ptr( new BlackConstantVol(referenceDate, v, voldc))); boost::shared_ptr payoff = boost::dynamic_pointer_cast(arguments_.payoff); QL_REQUIRE(payoff, "non-plain payoff given"); Time maturity = rfdc.yearFraction(arguments_.settlementDate, maturityDate); boost::shared_ptr bs( new GeneralizedBlackScholesProcess(underlying, flatDividends, flatRiskFree, flatVol)); boost::shared_ptr tree(new T(bs, maturity, timeSteps_, payoff->strike())); Real creditSpread = arguments_.creditSpread->value(); boost::shared_ptr lattice( new TsiveriotisFernandesLattice(tree,riskFreeRate,maturity, timeSteps_,creditSpread,v,q)); // adjust times to grid TimeGrid grid(maturity, timeSteps_); for (i=0; i