//! Implied internal rate of return. // The function verifies // the theoretical existance of an IRR and numerically // establishes the IRR to the desired precision. public static double yield(Leg leg, double npv, DayCounter dayCounter, Compounding compounding, Frequency frequency, bool includeSettlementDateFlows, Date settlementDate = null, Date npvDate = null, double accuracy = 1.0e-10, int maxIterations = 100, double guess = 0.05) { NewtonSafe solver = new NewtonSafe(); solver.setMaxEvaluations(maxIterations); IrrFinder objFunction = new IrrFinder(leg, npv, dayCounter, compounding, frequency, includeSettlementDateFlows, settlementDate, npvDate); return(solver.solve(objFunction, accuracy, guess, guess / 10.0)); }
//! implied volatility public double impliedVolatility(double targetValue, Handle <YieldTermStructure> discountCurve, double guess, double accuracy = 1.0e-4, int maxEvaluations = 100, double minVol = 1.0e-7, double maxVol = 4.0, VolatilityType type = VolatilityType.ShiftedLognormal, double?displacement = 0.0) { calculate(); if (isExpired()) { throw new ArgumentException("instrument expired"); } ImpliedVolHelper_ f = new ImpliedVolHelper_(this, discountCurve, targetValue, displacement, type); NewtonSafe solver = new NewtonSafe(); solver.setMaxEvaluations(maxEvaluations); return(solver.solve(f, accuracy, guess, minVol, maxVol)); }
protected override double solveImpl(ISolver1d f, double xAccuracy) { /* The implementation of the algorithm was inspired by Press, Teukolsky, Vetterling, and Flannery, * "Numerical Recipes in C", 2nd edition, Cambridge University Press */ double froot, dfroot, dx; froot = f.value(root_); dfroot = f.derivative(root_); if (dfroot.IsEqual(default(double))) { throw new ArgumentException("Newton requires function's derivative"); } ++evaluationNumber_; while (evaluationNumber_ <= maxEvaluations_) { dx = froot / dfroot; root_ -= dx; // jumped out of brackets, switch to NewtonSafe if ((xMin_ - root_) * (root_ - xMax_) < 0.0) { NewtonSafe s = new NewtonSafe(); s.setMaxEvaluations(maxEvaluations_ - evaluationNumber_); return(s.solve(f, xAccuracy, root_ + dx, xMin_, xMax_)); } if (Math.Abs(dx) < xAccuracy) { return(root_); } froot = f.value(root_); dfroot = f.derivative(root_); evaluationNumber_++; } Utils.QL_FAIL("maximum number of function evaluations (" + maxEvaluations_ + ") exceeded", QLNetExceptionEnum.MaxNumberFuncEvalExceeded); return(0); }
public double impliedVolatility( double targetValue, Handle <YieldTermStructure> discountCurve, double guess, double accuracy, int maxEvaluations, double minVol, double maxVol, VolatilityType type, double displacement) { calculate(); if (isExpired()) { throw new ArgumentException("instrument expired"); } ImpliedVolHelper f = new ImpliedVolHelper(this, discountCurve, targetValue, displacement, type); NewtonSafe solver = new NewtonSafe(); solver.setMaxEvaluations(maxEvaluations); return(solver.solve(f, accuracy, guess, minVol, maxVol)); }
/*! Black 1976 implied standard deviation, * i.e. volatility*sqrt(timeToMaturity) */ public static double blackFormulaImpliedStdDev(Option.Type optionType, double strike, double forward, double blackPrice, double discount = 1.0, double displacement = 0.0, double?guess = null, double accuracy = 1.0e-6, int maxIterations = 100) { checkParameters(strike, forward, displacement); QL_REQUIRE(discount > 0.0, () => "discount (" + discount + ") must be positive"); QL_REQUIRE(blackPrice >= 0.0, () => "option price (" + blackPrice + ") must be non-negative"); // check the price of the "other" option implied by put-call paity double otherOptionPrice = blackPrice - (int)optionType * (forward - strike) * discount; QL_REQUIRE(otherOptionPrice >= 0.0, () => "negative " + (-1 * (int)optionType) + " price (" + otherOptionPrice + ") implied by put-call parity. No solution exists for " + optionType + " strike " + strike + ", forward " + forward + ", price " + blackPrice + ", deflator " + discount); // solve for the out-of-the-money option which has // greater vega/price ratio, i.e. // it is numerically more robust for implied vol calculations if (optionType == Option.Type.Put && strike > forward) { optionType = Option.Type.Call; blackPrice = otherOptionPrice; } if (optionType == Option.Type.Call && strike < forward) { optionType = Option.Type.Put; blackPrice = otherOptionPrice; } strike = strike + displacement; forward = forward + displacement; if (guess == null) { guess = blackFormulaImpliedStdDevApproximation(optionType, strike, forward, blackPrice, discount, displacement); } else { QL_REQUIRE(guess >= 0.0, () => "stdDev guess (" + guess + ") must be non-negative"); } BlackImpliedStdDevHelper f = new BlackImpliedStdDevHelper(optionType, strike, forward, blackPrice / discount); NewtonSafe solver = new NewtonSafe(); solver.setMaxEvaluations(maxIterations); double minSdtDev = 0.0, maxStdDev = 24.0; // 24 = 300% * sqrt(60) double stdDev = solver.solve(f, accuracy, guess.Value, minSdtDev, maxStdDev); QL_REQUIRE(stdDev >= 0.0, () => "stdDev (" + stdDev + ") must be non-negative"); return(stdDev); }