Example #1
0
            public override void validate()
            {
                PercentageStrikePayoff moneyness = payoff as PercentageStrikePayoff;

                Utils.QL_REQUIRE(moneyness != null, () => "wrong payoff type");
                Utils.QL_REQUIRE(moneyness.strike() > 0.0, () => "negative or zero moneyness given");
                Utils.QL_REQUIRE(accruedCoupon == null || accruedCoupon >= 0.0, () => "negative accrued coupon");
                Utils.QL_REQUIRE(localCap == null || localCap >= 0.0, () => "negative local cap");
                Utils.QL_REQUIRE(localFloor == null || localFloor >= 0.0, () => "negative local floor");
                Utils.QL_REQUIRE(globalCap == null || globalCap >= 0.0, () => "negative global cap");
                Utils.QL_REQUIRE(globalFloor == null || globalFloor >= 0.0, () => "negative global floor");
                Utils.QL_REQUIRE(!resetDates.empty(), () => "no reset dates given");
                for (int i = 0; i < resetDates.Count; ++i)
                {
                    Utils.QL_REQUIRE(exercise.lastDate() > resetDates[i], () => "reset date greater or equal to maturity");
                    Utils.QL_REQUIRE(i == 0 || resetDates[i] > resetDates[i - 1], () => "unsorted reset dates");
                }
            }
Example #2
0
 public CliquetOption(PercentageStrikePayoff payoff, EuropeanExercise maturity, List <Date> resetDates)
     : base(payoff, maturity)
 {
     resetDates_ = new List <Date>(resetDates);
 }
        public override void calculate()
        {
            Utils.QL_REQUIRE(arguments_.accruedCoupon == null &&
                             arguments_.lastFixing == null, () =>
                             "this engine cannot price options already started");
            Utils.QL_REQUIRE(arguments_.localCap == null &&
                             arguments_.localFloor == null &&
                             arguments_.globalCap == null &&
                             arguments_.globalFloor == null, () =>
                             "this engine cannot price capped/floored options");

            Utils.QL_REQUIRE(arguments_.exercise.type() == Exercise.Type.European, () => "not an European option");

            PercentageStrikePayoff moneyness = arguments_.payoff as PercentageStrikePayoff;

            Utils.QL_REQUIRE(moneyness != null, () => "wrong payoff given");

            List <Date> resetDates = arguments_.resetDates;

            resetDates.Add(arguments_.exercise.lastDate());

            double underlying = process_.stateVariable().link.value();

            Utils.QL_REQUIRE(underlying > 0.0, () => "negative or null underlying");
            double            strike = underlying * moneyness.strike();
            StrikedTypePayoff payoff = new PlainVanillaPayoff(moneyness.optionType(), strike);

            results_.value = 0.0;
            results_.delta = results_.gamma = 0.0;
            results_.theta = 0.0;
            results_.rho   = results_.dividendRho = 0.0;
            results_.vega  = 0.0;

            for (int i = 1; i < resetDates.Count; i++)
            {
                double weight   = process_.dividendYield().link.discount(resetDates[i - 1]);
                double discount = process_.riskFreeRate().link.discount(resetDates[i]) /
                                  process_.riskFreeRate().link.discount(resetDates[i - 1]);
                double qDiscount = process_.dividendYield().link.discount(resetDates[i]) /
                                   process_.dividendYield().link.discount(resetDates[i - 1]);
                double forward  = underlying * qDiscount / discount;
                double variance = process_.blackVolatility().link.blackForwardVariance(resetDates[i - 1], resetDates[i], strike);

                BlackCalculator black = new BlackCalculator(payoff, forward, Math.Sqrt(variance), discount);

                DayCounter rfdc  = process_.riskFreeRate().link.dayCounter();
                DayCounter divdc = process_.dividendYield().link.dayCounter();
                DayCounter voldc = process_.blackVolatility().link.dayCounter();

                results_.value += weight * black.value();
                results_.delta += weight * (black.delta(underlying) +
                                            moneyness.strike() * discount *
                                            black.beta());
                results_.gamma += 0.0;
                results_.theta += process_.dividendYield().link.forwardRate(
                    resetDates[i - 1], resetDates[i], rfdc, Compounding.Continuous, Frequency.NoFrequency).value() *
                                  weight * black.value();

                double dt = rfdc.yearFraction(resetDates[i - 1], resetDates[i]);
                results_.rho += weight * black.rho(dt);

                double t = divdc.yearFraction(process_.dividendYield().link.referenceDate(), resetDates[i - 1]);
                dt = divdc.yearFraction(resetDates[i - 1], resetDates[i]);
                results_.dividendRho += weight * (black.dividendRho(dt) -
                                                  t * black.value());

                dt             = voldc.yearFraction(resetDates[i - 1], resetDates[i]);
                results_.vega += weight * black.vega(dt);
            }
        }