Esempio n. 1
0
        public static FdmStepConditionComposite vanillaComposite(DividendSchedule cashFlow,
                                                                 Exercise exercise,
                                                                 FdmMesher mesher,
                                                                 FdmInnerValueCalculator calculator,
                                                                 Date refDate,
                                                                 DayCounter dayCounter)
        {
            List <List <double> >           stoppingTimes  = new List <List <double> >();
            List <IStepCondition <Vector> > stepConditions = new List <IStepCondition <Vector> >();

            if (!cashFlow.empty())
            {
                FdmDividendHandler dividendCondition =
                    new FdmDividendHandler(cashFlow, mesher,
                                           refDate, dayCounter, 0);

                stepConditions.Add(dividendCondition);
                stoppingTimes.Add(dividendCondition.dividendTimes());
            }

            Utils.QL_REQUIRE(exercise.type() == Exercise.Type.American ||
                             exercise.type() == Exercise.Type.European ||
                             exercise.type() == Exercise.Type.Bermudan,
                             () => "exercise type is not supported");
            if (exercise.type() == Exercise.Type.American)
            {
                stepConditions.Add(new FdmAmericanStepCondition(mesher, calculator));
            }
            else if (exercise.type() == Exercise.Type.Bermudan)
            {
                FdmBermudanStepCondition bermudanCondition =
                    new FdmBermudanStepCondition(exercise.dates(),
                                                 refDate, dayCounter,
                                                 mesher, calculator);
                stepConditions.Add(bermudanCondition);
                stoppingTimes.Add(bermudanCondition.exerciseTimes());
            }

            return(new FdmStepConditionComposite(stoppingTimes, stepConditions));
        }
        public override void calculate()
        {
            // 1. Mesher
            StrikedTypePayoff payoff   = arguments_.payoff as StrikedTypePayoff;
            double            maturity = process_.time(arguments_.exercise.lastDate());

            double?xMin = null;
            double?xMax = null;

            if (arguments_.barrierType == Barrier.Type.DownIn ||
                arguments_.barrierType == Barrier.Type.DownOut)
            {
                xMin = Math.Log(arguments_.barrier.Value);
            }
            if (arguments_.barrierType == Barrier.Type.UpIn ||
                arguments_.barrierType == Barrier.Type.UpOut)
            {
                xMax = Math.Log(arguments_.barrier.Value);
            }

            Fdm1dMesher equityMesher =
                new FdmBlackScholesMesher(xGrid_, process_, maturity,
                                          payoff.strike(), xMin, xMax, 0.0001, 1.5,
                                          new Pair <double?, double?>(),
                                          arguments_.cashFlow);

            FdmMesher mesher =
                new FdmMesherComposite(equityMesher);

            // 2. Calculator
            FdmInnerValueCalculator calculator =
                new FdmLogInnerValue(payoff, mesher, 0);

            // 3. Step conditions
            List <IStepCondition <Vector> > stepConditions = new List <IStepCondition <Vector> >();
            List <List <double> >           stoppingTimes  = new List <List <double> >();

            // 3.1 Step condition if discrete dividends
            FdmDividendHandler dividendCondition =
                new FdmDividendHandler(arguments_.cashFlow, mesher,
                                       process_.riskFreeRate().currentLink().referenceDate(),
                                       process_.riskFreeRate().currentLink().dayCounter(), 0);

            if (!arguments_.cashFlow.empty())
            {
                stepConditions.Add(dividendCondition);
                stoppingTimes.Add(dividendCondition.dividendTimes());
            }

            Utils.QL_REQUIRE(arguments_.exercise.type() == Exercise.Type.European,
                             () => "only european style option are supported");

            FdmStepConditionComposite conditions =
                new FdmStepConditionComposite(stoppingTimes, stepConditions);

            // 4. Boundary conditions
            FdmBoundaryConditionSet boundaries = new FdmBoundaryConditionSet();

            if (arguments_.barrierType == Barrier.Type.DownIn ||
                arguments_.barrierType == Barrier.Type.DownOut)
            {
                boundaries.Add(
                    new FdmDirichletBoundary(mesher, arguments_.rebate.Value, 0,
                                             FdmDirichletBoundary.Side.Lower));
            }

            if (arguments_.barrierType == Barrier.Type.UpIn ||
                arguments_.barrierType == Barrier.Type.UpOut)
            {
                boundaries.Add(
                    new FdmDirichletBoundary(mesher, arguments_.rebate.Value, 0,
                                             FdmDirichletBoundary.Side.Upper));
            }

            // 5. Solver
            FdmSolverDesc solverDesc = new FdmSolverDesc();

            solverDesc.mesher       = mesher;
            solverDesc.bcSet        = boundaries;
            solverDesc.condition    = conditions;
            solverDesc.calculator   = calculator;
            solverDesc.maturity     = maturity;
            solverDesc.dampingSteps = dampingSteps_;
            solverDesc.timeSteps    = tGrid_;

            FdmBlackScholesSolver solver =
                new FdmBlackScholesSolver(
                    new Handle <GeneralizedBlackScholesProcess>(process_),
                    payoff.strike(), solverDesc, schemeDesc_,
                    localVol_, illegalLocalVolOverwrite_);

            double spot = process_.x0();

            results_.value = solver.valueAt(spot);
            results_.delta = solver.deltaAt(spot);
            results_.gamma = solver.gammaAt(spot);
            results_.theta = solver.thetaAt(spot);

            // 6. Calculate vanilla option and rebate for in-barriers
            if (arguments_.barrierType == Barrier.Type.DownIn ||
                arguments_.barrierType == Barrier.Type.UpIn)
            {
                // Cast the payoff
                StrikedTypePayoff castedPayoff = arguments_.payoff as StrikedTypePayoff;

                // Calculate the vanilla option
                DividendVanillaOption vanillaOption =
                    new DividendVanillaOption(castedPayoff, arguments_.exercise,
                                              dividendCondition.dividendDates(),
                                              dividendCondition.dividends());

                vanillaOption.setPricingEngine(
                    new FdBlackScholesVanillaEngine(
                        process_, tGrid_, xGrid_,
                        0, // dampingSteps
                        schemeDesc_, localVol_, illegalLocalVolOverwrite_));

                // Calculate the rebate value
                DividendBarrierOption rebateOption =
                    new DividendBarrierOption(arguments_.barrierType,
                                              arguments_.barrier.Value,
                                              arguments_.rebate.Value,
                                              castedPayoff, arguments_.exercise,
                                              dividendCondition.dividendDates(),
                                              dividendCondition.dividends());

                int min_grid_size = 50;
                int rebateDampingSteps
                    = (dampingSteps_ > 0) ? Math.Min(1, dampingSteps_ / 2) : 0;

                rebateOption.setPricingEngine(new FdBlackScholesRebateEngine(
                                                  process_, tGrid_, Math.Max(min_grid_size, xGrid_ / 5),
                                                  rebateDampingSteps, schemeDesc_, localVol_,
                                                  illegalLocalVolOverwrite_));

                results_.value = vanillaOption.NPV() + rebateOption.NPV()
                                 - results_.value;
                results_.delta = vanillaOption.delta() + rebateOption.delta()
                                 - results_.delta;
                results_.gamma = vanillaOption.gamma() + rebateOption.gamma()
                                 - results_.gamma;
                results_.theta = vanillaOption.theta() + rebateOption.theta()
                                 - results_.theta;
            }
        }