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 == 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_++; } throw new ApplicationException("maximum number of function evaluations (" + maxEvaluations_ + ") exceeded"); }
//! Internal rate of return. /*! The IRR is the interest rate at which the NPV of the cash flows equals the given market price. The function verifies * the theoretical existance of an IRR and numerically establishes the IRR to the desired precision. */ public static double irr(List <CashFlow> cashflows, double marketPrice, DayCounter dayCounter, Compounding compounding, Frequency frequency, Date settlementDate, double accuracy, int maxIterations, double guess) { if (settlementDate == null) { settlementDate = Settings.evaluationDate(); } // depending on the sign of the market price, check that cash flows of the opposite sign have been specified (otherwise // IRR is nonsensical.) int lastSign = Math.Sign(-marketPrice), signChanges = 0; foreach (CashFlow cf in cashflows.Where(cf => !cf.hasOccurred(settlementDate))) { int thisSign = Math.Sign(cf.amount()); if (lastSign * thisSign < 0) // sign change { signChanges++; } if (thisSign != 0) { lastSign = thisSign; } } if (!(signChanges > 0)) { throw new ApplicationException("the given cash flows cannot result in the given market price due to their sign"); } /* The following is commented out due to the lack of a QL_WARN macro * if (signChanges > 1) { // Danger of non-unique solution * // Check the aggregate cash flows (Norstrom) * Real aggregateCashFlow = marketPrice; * signChanges = 0; * for (Size i = 0; i < cashflows.size(); ++i) { * Real nextAggregateCashFlow = * aggregateCashFlow + cashflows[i]->amount(); * * if (aggregateCashFlow * nextAggregateCashFlow < 0.0) * signChanges++; * * aggregateCashFlow = nextAggregateCashFlow; * } * if (signChanges > 1) * QL_WARN( "danger of non-unique solution"); * }; */ //Brent solver; NewtonSafe solver = new NewtonSafe(); solver.setMaxEvaluations(maxIterations); return(solver.solve(new IrrFinder(cashflows, marketPrice, dayCounter, compounding, frequency, settlementDate), accuracy, guess, guess / 10.0)); }
//! 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) { calculate(); if (isExpired()) { throw new ArgumentException("instrument expired"); } SwaptionImpliedVolatilityHelper f = new SwaptionImpliedVolatilityHelper(this, discountCurve, targetValue); //Brent solver; NewtonSafe solver = new NewtonSafe(); solver.setMaxEvaluations(maxEvaluations); return(solver.solve(f, accuracy, guess, minVol, maxVol)); }
//! 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)); }
//! 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); }
/*! 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); }
//! Internal rate of return. /*! The IRR is the interest rate at which the NPV of the cash flows equals the given market price. The function verifies the theoretical existance of an IRR and numerically establishes the IRR to the desired precision. */ public static double irr(List<CashFlow> cashflows, double marketPrice, DayCounter dayCounter, Compounding compounding, Frequency frequency, Date settlementDate, double accuracy, int maxIterations, double guess) { if (settlementDate == null) settlementDate = Settings.evaluationDate(); // depending on the sign of the market price, check that cash flows of the opposite sign have been specified (otherwise // IRR is nonsensical.) int lastSign = Math.Sign(-marketPrice), signChanges = 0; foreach (CashFlow cf in cashflows.Where(cf => !cf.hasOccurred(settlementDate))) { int thisSign = Math.Sign(cf.amount()); if (lastSign * thisSign < 0) // sign change signChanges++; if (thisSign != 0) lastSign = thisSign; } if (!(signChanges > 0)) throw new ApplicationException("the given cash flows cannot result in the given market price due to their sign"); /* The following is commented out due to the lack of a QL_WARN macro if (signChanges > 1) { // Danger of non-unique solution // Check the aggregate cash flows (Norstrom) Real aggregateCashFlow = marketPrice; signChanges = 0; for (Size i = 0; i < cashflows.size(); ++i) { Real nextAggregateCashFlow = aggregateCashFlow + cashflows[i]->amount(); if (aggregateCashFlow * nextAggregateCashFlow < 0.0) signChanges++; aggregateCashFlow = nextAggregateCashFlow; } if (signChanges > 1) QL_WARN( "danger of non-unique solution"); }; */ //Brent solver; NewtonSafe solver = new NewtonSafe(); solver.setMaxEvaluations(maxIterations); return solver.solve(new IrrFinder(cashflows, marketPrice, dayCounter, compounding, frequency, settlementDate), accuracy, guess, guess / 10.0); }