Exemple #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");
                }
            }
Exemple #2
0
        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");

            StrikedTypePayoff payoff = new PlainVanillaPayoff(moneyness.optionType(), 1.0);

            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 discount  = process_.riskFreeRate().link.discount(resetDates[i - 1]);
                double rDiscount = 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  = (1.0 / moneyness.strike()) * qDiscount / rDiscount;
                double variance = process_.blackVolatility().link.blackForwardVariance(
                    resetDates[i - 1], resetDates[i],
                    underlying * moneyness.strike());

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

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

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

                double dt = rfdc.yearFraction(resetDates[i - 1], resetDates[i]);
                double t  = rfdc.yearFraction(process_.riskFreeRate().link.referenceDate(), resetDates[i - 1]);
                results_.rho += discount * moneyness.strike() * (black.rho(dt) - t * black.value());

                dt = divdc.yearFraction(resetDates[i - 1], resetDates[i]);
                results_.dividendRho += discount * moneyness.strike() * black.dividendRho(dt);

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