/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (C) 2004 Ferdinando Ametrano Copyright (C) 2007 StatPro Italia srl This file is part of QuantLib, a free-software/open-source library for financial quantitative analysts and developers - http://quantlib.org/ QuantLib is free software: you can redistribute it and/or modify it under the terms of the QuantLib license. You should have received a copy of the license along with this program; if not, please email . 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. */ #include #include #include #include #include #include namespace QuantLib { JumpDiffusionEngine::JumpDiffusionEngine( const boost::shared_ptr& baseEngine, Real relativeAccuracy, Size maxIterations) : baseEngine_(baseEngine), relativeAccuracy_(relativeAccuracy), maxIterations_(maxIterations) { QL_REQUIRE(baseEngine_, "null base engine"); } void JumpDiffusionEngine::calculate() const { boost::shared_ptr jdProcess = boost::dynamic_pointer_cast( arguments_.stochasticProcess); QL_REQUIRE(jdProcess, "not a jump diffusion process"); Real jumpSquareVol = jdProcess->logJumpVolatility()->value() * jdProcess->logJumpVolatility()->value(); Real muPlusHalfSquareVol = jdProcess->logMeanJump()->value() + 0.5*jumpSquareVol; // mean jump size Real k = std::exp(muPlusHalfSquareVol) - 1.0; Real lambda = (k+1.0) * jdProcess->jumpIntensity()->value(); // dummy strike Real variance = jdProcess->blackVolatility()->blackVariance( arguments_.exercise->lastDate(), 1.0); DayCounter voldc = jdProcess->blackVolatility()->dayCounter(); Date volRefDate = jdProcess->blackVolatility()->referenceDate(); Time t = voldc.yearFraction(volRefDate, arguments_.exercise->lastDate()); Rate riskFreeRate = -std::log(jdProcess->riskFreeRate()->discount( arguments_.exercise->lastDate()))/t; Date rateRefDate = jdProcess->riskFreeRate()->referenceDate(); PoissonDistribution p(lambda*t); baseEngine_->reset(); VanillaOption::arguments* baseArguments = dynamic_cast( baseEngine_->getArguments()); baseArguments->payoff = arguments_.payoff; baseArguments->exercise = arguments_.exercise; Handle stateVariable = jdProcess->stateVariable(); Handle dividendTS = jdProcess->dividendYield(); RelinkableHandle riskFreeTS( jdProcess->riskFreeRate().currentLink()); RelinkableHandle volTS( jdProcess->blackVolatility().currentLink()); baseArguments->stochasticProcess = boost::shared_ptr( new GeneralizedBlackScholesProcess(stateVariable, dividendTS, riskFreeTS, volTS)); baseArguments->validate(); const VanillaOption::results* baseResults = dynamic_cast( baseEngine_->getResults()); results_.value = 0.0; results_.delta = 0.0; results_.gamma = 0.0; results_.theta = 0.0; results_.vega = 0.0; results_.rho = 0.0; results_.dividendRho = 0.0; Real r, v, weight, lastContribution = 1.0; Size i; Real theta_correction; // Haug arbitrary criterium is: //for (i=0; i<11; i++) { for (i=0; lastContribution>relativeAccuracy_ && ijumpIntensity()->value()*k + i*muPlusHalfSquareVol/t; riskFreeTS.linkTo(boost::shared_ptr( new FlatForward(rateRefDate, r, voldc))); volTS.linkTo(boost::shared_ptr( new BlackConstantVol(rateRefDate, v, voldc))); baseArguments->validate(); baseEngine_->calculate(); weight = p(Size(i)); results_.value += weight * baseResults->value; results_.delta += weight * baseResults->delta; results_.gamma += weight * baseResults->gamma; results_.vega += weight * (std::sqrt(variance/t)/v)* baseResults->vega; // theta modified theta_correction = baseResults->vega*((i*jumpSquareVol)/ (2.0*v*t*t)) + baseResults->rho*i*muPlusHalfSquareVol/(t*t); results_.theta += weight *(baseResults->theta + theta_correction + lambda*baseResults->value); if(i != 0){ results_.theta -= (p(Size(i-1))*lambda* baseResults->value); } //end theta calculation results_.rho += weight * baseResults->rho; results_.dividendRho += weight * baseResults->dividendRho; lastContribution = std::fabs(baseResults->value / (std::fabs(results_.value)>QL_EPSILON ? results_.value : 1.0)); lastContribution = std::max(lastContribution, std::fabs(baseResults->delta / (std::fabs(results_.delta)>QL_EPSILON ? results_.delta : 1.0))); lastContribution = std::max(lastContribution, std::fabs(baseResults->gamma / (std::fabs(results_.gamma)>QL_EPSILON ? results_.gamma : 1.0))); lastContribution = std::max(lastContribution, std::fabs(baseResults->theta / (std::fabs(results_.theta)>QL_EPSILON ? results_.theta : 1.0))); lastContribution = std::max(lastContribution, std::fabs(baseResults->vega / (std::fabs(results_.vega)>QL_EPSILON ? results_.vega : 1.0))); lastContribution = std::max(lastContribution, std::fabs(baseResults->rho / (std::fabs(results_.rho)>QL_EPSILON ? results_.rho : 1.0))); lastContribution = std::max(lastContribution, std::fabs(baseResults->dividendRho / (std::fabs(results_.dividendRho)>QL_EPSILON ? results_.dividendRho : 1.0))); lastContribution *= weight; } QL_ENSURE(i