public double weight(double strike, double forward, double stdDev, List <double?> addParams) { if (Convert.ToDouble(addParams[1]) == 0.0) { return(Utils.blackFormulaStdDevDerivative(strike, forward, stdDev, 1.0, addParams[0].Value)); } else { return(Utils.bachelierBlackFormulaStdDevDerivative(strike, forward, stdDev, 1.0)); } }
public double vega(double strike, double atmForward, double stdDev, double exerciseTime, double annuity, double displacement = 0.0) { return(Math.Sqrt(exerciseTime) * Utils.blackFormulaStdDevDerivative(strike, atmForward, stdDev, annuity, displacement)); }
public override void calculate() { double value = 0.0; double vega = 0.0; int optionlets = arguments_.startDates.Count; List <double> values = new InitializedList <double>(optionlets); List <double> vegas = new InitializedList <double>(optionlets); List <double> stdDevs = new InitializedList <double>(optionlets); CapFloorType type = arguments_.type; Date today = vol_.link.referenceDate(); Date settlement = discountCurve_.link.referenceDate(); for (int i = 0; i < optionlets; ++i) { Date paymentDate = arguments_.endDates[i]; if (paymentDate > settlement) { // discard expired caplets double d = arguments_.nominals[i] * arguments_.gearings[i] * discountCurve_.link.discount(paymentDate) * arguments_.accrualTimes[i]; double?forward = arguments_.forwards[i]; Date fixingDate = arguments_.fixingDates[i]; double sqrtTime = 0.0; if (fixingDate > today) { sqrtTime = Math.Sqrt(vol_.link.timeFromReference(fixingDate)); } if (type == CapFloorType.Cap || type == CapFloorType.Collar) { double?strike = arguments_.capRates[i]; if (sqrtTime > 0.0) { stdDevs[i] = Math.Sqrt(vol_.link.blackVariance(fixingDate, strike.Value)); vegas[i] = Utils.blackFormulaStdDevDerivative(strike.Value, forward.Value, stdDevs[i], d, displacement_) * sqrtTime; } // include caplets with past fixing date values[i] = Utils.blackFormula(Option.Type.Call, strike.Value, forward.Value, stdDevs[i], d, displacement_); } if (type == CapFloorType.Floor || type == CapFloorType.Collar) { double?strike = arguments_.floorRates[i]; double floorletVega = 0.0; if (sqrtTime > 0.0) { stdDevs[i] = Math.Sqrt(vol_.link.blackVariance(fixingDate, strike.Value)); floorletVega = Utils.blackFormulaStdDevDerivative(strike.Value, forward.Value, stdDevs[i], d, displacement_) * sqrtTime; } double floorlet = Utils.blackFormula(Option.Type.Put, strike.Value, forward.Value, stdDevs[i], d, displacement_); if (type == CapFloorType.Floor) { values[i] = floorlet; vegas[i] = floorletVega; } else { // a collar is long a cap and short a floor values[i] -= floorlet; vegas[i] -= floorletVega; } } value += values[i]; vega += vegas[i]; } } results_.value = value; results_.additionalResults["vega"] = vega; results_.additionalResults["optionletsPrice"] = values; results_.additionalResults["optionletsVega"] = vegas; results_.additionalResults["optionletsAtmForward"] = arguments_.forwards; if (type != CapFloorType.Collar) { results_.additionalResults["optionletsStdDev"] = stdDevs; } }
public override void calculate() { double basisPoint = 1.0e-4; Date exerciseDate = arguments_.exercise.date(0); // the part of the swap preceding exerciseDate should be truncated // to avoid taking into account unwanted cashflows VanillaSwap swap = arguments_.swap; double strike = swap.fixedRate; // using the forecasting curve swap.setPricingEngine(new DiscountingSwapEngine(swap.iborIndex().forwardingTermStructure())); double atmForward = swap.fairRate(); // Volatilities are quoted for zero-spreaded swaps. // Therefore, any spread on the floating leg must be removed // with a corresponding correction on the fixed leg. if (swap.spread != 0.0) { double correction = swap.spread * Math.Abs(swap.floatingLegBPS() / swap.fixedLegBPS()); strike -= correction; atmForward -= correction; results_.additionalResults["spreadCorrection"] = correction; } else { results_.additionalResults["spreadCorrection"] = 0.0; } results_.additionalResults["strike"] = strike; results_.additionalResults["atmForward"] = atmForward; // using the discounting curve swap.setPricingEngine(new DiscountingSwapEngine(termStructure_)); double annuity; switch (arguments_.settlementType) { case Settlement.Type.Physical: { annuity = Math.Abs(swap.fixedLegBPS()) / basisPoint; break; } case Settlement.Type.Cash: { List <CashFlow> fixedLeg = swap.fixedLeg(); FixedRateCoupon firstCoupon = (FixedRateCoupon)fixedLeg[0]; DayCounter dayCount = firstCoupon.dayCounter(); double fixedLegCashBPS = CashFlows.bps(fixedLeg, new InterestRate(atmForward, dayCount, QLNet.Compounding.Compounded, Frequency.Annual), false, termStructure_.link.referenceDate()); annuity = Math.Abs(fixedLegCashBPS / basisPoint); break; } default: throw new ApplicationException("unknown settlement type"); } results_.additionalResults["annuity"] = annuity; // the swap length calculation might be improved using the value date // of the exercise date double swapLength = volatility_.link.swapLength(exerciseDate, arguments_.floatingPayDates.Last()); results_.additionalResults["swapLength"] = swapLength; double variance = volatility_.link.blackVariance(exerciseDate, swapLength, strike); double stdDev = Math.Sqrt(variance); results_.additionalResults["stdDev"] = stdDev; Option.Type w = (arguments_.type == VanillaSwap.Type.Payer) ? Option.Type.Call : Option.Type.Put; results_.value = Utils.blackFormula(w, strike, atmForward, stdDev, annuity); double exerciseTime = volatility_.link.timeFromReference(exerciseDate); results_.additionalResults["vega"] = Math.Sqrt(exerciseTime) * Utils.blackFormulaStdDevDerivative(strike, atmForward, stdDev, annuity); }
public double weight(double strike, double forward, double stdDev, List <double?> addParams) { return(Utils.blackFormulaStdDevDerivative(strike, forward, stdDev, 1.0)); }
public override void update() { this.coeff_.updateModelInstance(); // we should also check that y contains positive values only // we must update weights if it is vegaWeighted if (vegaWeighted_) { coeff_.weights_.Clear(); double weightsSum = 0.0; for (int i = 0; i < xBegin_.Count; i++) { double stdDev = Math.Sqrt((yBegin_[i]) * (yBegin_[i]) * this.coeff_.t_); coeff_.weights_.Add(Utils.blackFormulaStdDevDerivative(xBegin_[i], forward_, stdDev)); weightsSum += coeff_.weights_.Last(); } // weight normalization for (int i = 0; i < coeff_.weights_.Count; i++) { coeff_.weights_[i] /= weightsSum; } } // there is nothing to optimize if (coeff_.paramIsFixed_.Aggregate((a, b) => b & a)) { coeff_.error_ = interpolationError(); coeff_.maxError_ = interpolationMaxError(); coeff_.XABREndCriteria_ = EndCriteria.Type.None; return; } else { XABRError costFunction = new XABRError(this); Vector guess = new Vector(coeff_.model_.dimension()); for (int i = 0; i < guess.size(); ++i) { guess[i] = coeff_.params_[i].Value; } int iterations = 0; int freeParameters = 0; double bestError = double.MaxValue; Vector bestParameters = new Vector(); for (int i = 0; i < coeff_.model_.dimension(); ++i) { if (!coeff_.paramIsFixed_[i]) { ++freeParameters; } } HaltonRsg halton = new HaltonRsg(freeParameters, 42); EndCriteria.Type tmpEndCriteria; double tmpInterpolationError; do { if (iterations > 0) { Sample <List <double> > s = halton.nextSequence(); coeff_.model_.guess(guess, coeff_.paramIsFixed_, forward_, coeff_.t_, s.value); for (int i = 0; i < coeff_.paramIsFixed_.Count; ++i) { if (coeff_.paramIsFixed_[i]) { guess[i] = coeff_.params_[i].Value; } } } Vector inversedTransformatedGuess = new Vector(coeff_.model_.inverse(guess, coeff_.paramIsFixed_, coeff_.params_, forward_)); ProjectedCostFunction rainedXABRError = new ProjectedCostFunction(costFunction, inversedTransformatedGuess, coeff_.paramIsFixed_); Vector projectedGuess = new Vector(rainedXABRError.project(inversedTransformatedGuess)); NoConstraint raint = new NoConstraint(); Problem problem = new Problem(rainedXABRError, raint, projectedGuess); tmpEndCriteria = optMethod_.minimize(problem, endCriteria_); // TEST // coeff_.params_[3] = 0.0099999966589763966; // TEST Vector projectedResult = new Vector(problem.currentValue()); Vector transfResult = new Vector(rainedXABRError.include(projectedResult)); //transfResult[3] = 0.0099999966589763966; ; Vector result = coeff_.model_.direct(transfResult, coeff_.paramIsFixed_, coeff_.params_, forward_); //result[3] = 0.0099999966589763966; tmpInterpolationError = useMaxError_ ? interpolationMaxError() : interpolationError(); if (tmpInterpolationError < bestError) { bestError = tmpInterpolationError; bestParameters = result; coeff_.XABREndCriteria_ = tmpEndCriteria; } } while (++iterations < maxGuesses_ && tmpInterpolationError > errorAccept_); for (int i = 0; i < bestParameters.size(); ++i) { coeff_.params_[i] = bestParameters[i]; } coeff_.error_ = interpolationError(); coeff_.maxError_ = interpolationMaxError(); } }