protected override double optionletPrice(Option.Type optionType, double strike) { ConundrumIntegrand integrand = new ConundrumIntegrand(vanillaOptionPricer_, rateCurve_, gFunction_, fixingDate_, paymentDate_, annuity_, swapRateValue_, strike, optionType); stdDeviationsForUpperLimit_ = requiredStdDeviations_; double a; double b; double integralValue; if (optionType == Option.Type.Call) { upperLimit_ = resetUpperLimit(stdDeviationsForUpperLimit_); // while(upperLimit_ <= strike){ // stdDeviationsForUpperLimit_ += 1.; // upperLimit_ = resetUpperLimit(stdDeviationsForUpperLimit_); // } integralValue = integrate(strike, upperLimit_, integrand); //refineIntegration(integralValue, *integrand); } else { a = Math.Min(strike, lowerLimit_); b = strike; integralValue = integrate(a, b, integrand); } double dFdK = integrand.firstDerivativeOfF(strike); double swaptionPrice = vanillaOptionPricer_.value(strike, optionType, annuity_); // v. HAGAN, Conundrums..., formule 2.17a, 2.18a return(coupon_.accrualPeriod() * (discount_ / annuity_) * ((1 + dFdK) * swaptionPrice + ((int)optionType) * integralValue)); }
public double integrate(double a, double b, ConundrumIntegrand integrand) { double result = .0; //double abserr =.0; //double alpha = 1.0; //double epsabs = precision_; //double epsrel = 1.0; // we are interested only in absolute precision //size_t neval =0; // we use the non adaptive algorithm only for semi infinite interval if (a > 0) { // we estimate the actual boudary by testing integrand values double upperBoundary = 2 * a; while (integrand.value(upperBoundary) > precision_) { upperBoundary *= 2.0; } // sometimes b < a because of a wrong estimation of b based on stdev if (b > a) { upperBoundary = Math.Min(upperBoundary, b); } GaussKronrodNonAdaptive gaussKronrodNonAdaptive = new GaussKronrodNonAdaptive(precision_, 1000000, 1.0); // if the integration intervall is wide enough we use the // following change variable x -> a + (b-a)*(t/(a-b))^3 upperBoundary = Math.Max(a, Math.Min(upperBoundary, hardUpperLimit_)); if (upperBoundary > 2 * a) { VariableChange variableChange = new VariableChange(integrand.value, a, upperBoundary, 3); result = gaussKronrodNonAdaptive.value(variableChange.value, .0, 1.0); } else { result = gaussKronrodNonAdaptive.value(integrand.value, a, upperBoundary); } // if the expected precision has not been reached we use the old algorithm if (!gaussKronrodNonAdaptive.integrationSuccess()) { GaussKronrodAdaptive integrator = new GaussKronrodAdaptive(precision_, 100000); b = Math.Max(a, Math.Min(b, hardUpperLimit_)); result = integrator.value(integrand.value, a, b); } } // if a < b we use the old algorithm else { b = Math.Max(a, Math.Min(b, hardUpperLimit_)); GaussKronrodAdaptive integrator = new GaussKronrodAdaptive(precision_, 100000); result = integrator.value(integrand.value, a, b); } return(result); }
public double refineIntegration(double integralValue, ConundrumIntegrand integrand) { double percDiff = 1000.0; while (Math.Abs(percDiff) < refiningIntegrationTolerance_) { stdDeviationsForUpperLimit_ += 1.0; double lowerLimit = upperLimit_; upperLimit_ = resetUpperLimit(stdDeviationsForUpperLimit_); double diff = integrate(lowerLimit, upperLimit_, integrand); percDiff = diff / integralValue; integralValue += diff; } return(integralValue); }
public double refineIntegration(double integralValue, ConundrumIntegrand integrand) { double percDiff = 1000.0; while (Math.Abs(percDiff) < refiningIntegrationTolerance_) { stdDeviationsForUpperLimit_ += 1.0; double lowerLimit = upperLimit_; upperLimit_ = resetUpperLimit(stdDeviationsForUpperLimit_); double diff = integrate(lowerLimit, upperLimit_, integrand); percDiff = diff / integralValue; integralValue += diff; } return integralValue; }
public double integrate(double a, double b, ConundrumIntegrand integrand) { double result = .0; //double abserr =.0; //double alpha = 1.0; //double epsabs = precision_; //double epsrel = 1.0; // we are interested only in absolute precision //size_t neval =0; // we use the non adaptive algorithm only for semi infinite interval if (a > 0) { // we estimate the actual boudary by testing integrand values double upperBoundary = 2 * a; while (integrand.value(upperBoundary) > precision_) upperBoundary *= 2.0; // sometimes b < a because of a wrong estimation of b based on stdev if (b > a) upperBoundary = Math.Min(upperBoundary, b); GaussKronrodNonAdaptive gaussKronrodNonAdaptive = new GaussKronrodNonAdaptive(precision_, 1000000, 1.0); // if the integration intervall is wide enough we use the // following change variable x -> a + (b-a)*(t/(a-b))^3 if (upperBoundary > 2 * a) { VariableChange variableChange = new VariableChange(integrand.value, a, upperBoundary, 3); result = gaussKronrodNonAdaptive.value(variableChange.value, .0, 1.0); } else { result = gaussKronrodNonAdaptive.value(integrand.value, a, upperBoundary); } // if the expected precision has not been reached we use the old algorithm if (!gaussKronrodNonAdaptive.integrationSuccess()) { GaussKronrodAdaptive integrator = new GaussKronrodAdaptive(precision_, 1000000); result = integrator.value(integrand.value, a, b); } } // if a < b we use the old algorithm else { GaussKronrodAdaptive integrator = new GaussKronrodAdaptive(precision_, 1000000); result = integrator.value(integrand.value, a, b); } return result; }
protected override double optionletPrice(Option.Type optionType, double strike) { ConundrumIntegrand integrand = new ConundrumIntegrand(vanillaOptionPricer_, rateCurve_, gFunction_, fixingDate_, paymentDate_, annuity_, swapRateValue_, strike, optionType); stdDeviationsForUpperLimit_ = requiredStdDeviations_; double a; double b; double integralValue; if (optionType == Option.Type.Call) { upperLimit_ = resetUpperLimit(stdDeviationsForUpperLimit_); // while(upperLimit_ <= strike){ // stdDeviationsForUpperLimit_ += 1.; // upperLimit_ = resetUpperLimit(stdDeviationsForUpperLimit_); // } integralValue = integrate(strike, upperLimit_, integrand); //refineIntegration(integralValue, *integrand); } else { a = Math.Min(strike, lowerLimit_); b = strike; integralValue = integrate(a, b, integrand); } double dFdK = integrand.firstDerivativeOfF(strike); double swaptionPrice = vanillaOptionPricer_.value(strike, optionType, annuity_); // v. HAGAN, Conundrums..., formule 2.17a, 2.18a return coupon_.accrualPeriod() * (discount_ / annuity_) * ((1 + dFdK) * swaptionPrice + ((int)optionType) * integralValue); }