protected override double optionletPriceImp(Option.Type optionType, double effStrike, double forward, double stdDev) { return(Utils.bachelierBlackFormula(optionType, effStrike, forward, stdDev)); }
public virtual double optionPrice(double strike, Option.Type type = Option.Type.Call, double discount = 1.0) { double?atm = atmLevel(); Utils.QL_REQUIRE(atm != null, () => "smile section must provide atm level to compute option price"); // if lognormal or shifted lognormal, // for strike at -shift, return option price even if outside // minstrike, maxstrike interval if (volatilityType() == VolatilityType.ShiftedLognormal) { return(Utils.blackFormula(type, strike, atm.Value, Math.Abs(strike + shift()) < Const.QL_EPSILON ? 0.2 : Math.Sqrt(variance(strike)), discount, shift())); } else { return(Utils.bachelierBlackFormula(type, strike, atm.Value, Math.Sqrt(variance(strike)), discount)); } }
protected double optionletPrice(Option.Type optionType, double effStrike) { Date fixingDate = coupon_.fixingDate(); if (fixingDate <= Settings.evaluationDate()) { // the amount is determined double a; double b; if (optionType == Option.Type.Call) { a = coupon_.indexFixing(); b = effStrike; } else { a = effStrike; b = coupon_.indexFixing(); } return(Math.Max(a - b, 0.0) * accrualPeriod_ * discount_); } else { // not yet determined, use Black model Utils.QL_REQUIRE(!capletVolatility().empty(), () => "missing optionlet volatility"); double stdDev = Math.Sqrt(capletVolatility().link.blackVariance(fixingDate, effStrike)); double shift = capletVolatility().link.displacement(); bool shiftedLn = capletVolatility().link.volatilityType() == VolatilityType.ShiftedLognormal; double fixing = shiftedLn ? Utils.blackFormula(optionType, effStrike, adjustedFixing(), stdDev, 1.0, shift) : Utils.bachelierBlackFormula(optionType, effStrike, adjustedFixing(), stdDev, 1.0); return(fixing * accrualPeriod_ * discount_); } }
public double value(Option.Type type, double strike, double atmForward, double stdDev, double annuity, double displacement = 0.0) { return(Utils.bachelierBlackFormula(type, strike, atmForward, stdDev, annuity)); }
protected override double optionletImpl(Option.Type type, double strike, double forward, double stdDev, double d) { return(Utils.bachelierBlackFormula(type, strike, forward, stdDev, d)); }
public override void calculate() { double value = 0.0; double vega = 0.0; int optionlets = arguments_.startDates.Count; List <double> values = new InitializedList <double>(optionlets, 0.0); List <double> vegas = new InitializedList <double>(optionlets, 0.0); List <double> stdDevs = new InitializedList <double>(optionlets, 0.0); 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]; // handling of settlementDate, npvDate and includeSettlementFlows // should be implemented. // For the double being just discard expired caplets if (paymentDate > settlement) { double d = arguments_.nominals[i] * arguments_.gearings[i] * discountCurve_.link.discount(paymentDate) * arguments_.accrualTimes[i]; double forward = arguments_.forwards[i].Value; 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].Value; if (sqrtTime > 0.0) { stdDevs[i] = Math.Sqrt(vol_.link.blackVariance(fixingDate, strike)); vegas[i] = Utils.bachelierBlackFormulaStdDevDerivative(strike, forward, stdDevs[i], d) * sqrtTime; } // include caplets with past fixing date values[i] = Utils.bachelierBlackFormula(Option.Type.Call, strike, forward, stdDevs[i], d); } if (type == CapFloorType.Floor || type == CapFloorType.Collar) { double strike = arguments_.floorRates[i].Value; double floorletVega = 0.0; if (sqrtTime > 0.0) { stdDevs[i] = Math.Sqrt(vol_.link.blackVariance(fixingDate, strike)); floorletVega = Utils.bachelierBlackFormulaStdDevDerivative(strike, forward, stdDevs[i], d) * sqrtTime; } double floorlet = Utils.bachelierBlackFormula(Option.Type.Put, strike, forward, stdDevs[i], d); 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; } }