void FDEuropeanEngine<Scheme>::calculate() const { setupArguments(&arguments_); setGridLimits(); initializeInitialCondition(); initializeOperator(); initializeBoundaryConditions(); FiniteDifferenceModel<Scheme<TridiagonalOperator> > model( finiteDifferenceOperator_, BCs_); prices_ = intrinsicValues_; model.rollback(prices_.values(), getResidualTime(), 0, timeSteps_); results_.value = prices_.valueAtCenter(); results_.delta = prices_.firstDerivativeAtCenter(); results_.gamma = prices_.secondDerivativeAtCenter(); results_.theta = blackScholesTheta(process_, results_.value, results_.delta, results_.gamma); results_.additionalResults["priceCurve"] = prices_; }
void BinomialVanillaEngine<T>::calculate() const { DayCounter rfdc = process_->riskFreeRate()->dayCounter(); DayCounter divdc = process_->dividendYield()->dayCounter(); DayCounter voldc = process_->blackVolatility()->dayCounter(); Calendar volcal = process_->blackVolatility()->calendar(); Real s0 = process_->stateVariable()->value(); QL_REQUIRE(s0 > 0.0, "negative or null underlying given"); Volatility v = process_->blackVolatility()->blackVol( arguments_.exercise->lastDate(), s0); Date maturityDate = arguments_.exercise->lastDate(); Rate r = process_->riskFreeRate()->zeroRate(maturityDate, rfdc, Continuous, NoFrequency); Rate q = process_->dividendYield()->zeroRate(maturityDate, divdc, Continuous, NoFrequency); Date referenceDate = process_->riskFreeRate()->referenceDate(); // binomial trees with constant coefficient Handle<YieldTermStructure> flatRiskFree( boost::shared_ptr<YieldTermStructure>( new FlatForward(referenceDate, r, rfdc))); Handle<YieldTermStructure> flatDividends( boost::shared_ptr<YieldTermStructure>( new FlatForward(referenceDate, q, divdc))); Handle<BlackVolTermStructure> flatVol( boost::shared_ptr<BlackVolTermStructure>( new BlackConstantVol(referenceDate, volcal, v, voldc))); boost::shared_ptr<PlainVanillaPayoff> payoff = boost::dynamic_pointer_cast<PlainVanillaPayoff>(arguments_.payoff); QL_REQUIRE(payoff, "non-plain payoff given"); Time maturity = rfdc.yearFraction(referenceDate, maturityDate); boost::shared_ptr<StochasticProcess1D> bs( new GeneralizedBlackScholesProcess( process_->stateVariable(), flatDividends, flatRiskFree, flatVol)); TimeGrid grid(maturity, timeSteps_); boost::shared_ptr<T> tree(new T(bs, maturity, timeSteps_, payoff->strike())); boost::shared_ptr<BlackScholesLattice<T> > lattice( new BlackScholesLattice<T>(tree, r, maturity, timeSteps_)); DiscretizedVanillaOption option(arguments_, *process_, grid); option.initialize(lattice, maturity); // Partial derivatives calculated from various points in the // binomial tree (Odegaard) // Rollback to third-last step, and get underlying price (s2) & // option values (p2) at this point option.rollback(grid[2]); Array va2(option.values()); QL_ENSURE(va2.size() == 3, "Expect 3 nodes in grid at second step"); Real p2h = va2[2]; // high-price Real s2 = lattice->underlying(2, 2); // high price // Rollback to second-last step, and get option value (p1) at // this point option.rollback(grid[1]); Array va(option.values()); QL_ENSURE(va.size() == 2, "Expect 2 nodes in grid at first step"); Real p1 = va[1]; // Finally, rollback to t=0 option.rollback(0.0); Real p0 = option.presentValue(); Real s1 = lattice->underlying(1, 1); // Calculate partial derivatives Real delta0 = (p1-p0)/(s1-s0); // dp/ds Real delta1 = (p2h-p1)/(s2-s1); // dp/ds // Store results results_.value = p0; results_.delta = delta0; results_.gamma = 2.0*(delta1-delta0)/(s2-s0); //d(delta)/ds results_.theta = blackScholesTheta(process_, results_.value, results_.delta, results_.gamma); }