Example #1
0
        public Fdm1DimSolver(FdmSolverDesc solverDesc,
                             FdmSchemeDesc schemeDesc,
                             FdmLinearOpComposite op)
        {
            solverDesc_     = solverDesc;
            schemeDesc_     = schemeDesc;
            op_             = op;
            thetaCondition_ = new FdmSnapshotCondition(
                0.99 * Math.Min(1.0 / 365.0,
                                solverDesc.condition.stoppingTimes().empty()
                            ? solverDesc.maturity
                            : solverDesc.condition.stoppingTimes().First()));

            conditions_ = FdmStepConditionComposite.joinConditions(thetaCondition_,
                                                                   solverDesc.condition);
            x_             = new InitializedList <double>(solverDesc.mesher.layout().size());
            initialValues_ = new InitializedList <double>(solverDesc.mesher.layout().size());
            resultValues_  = new Vector(solverDesc.mesher.layout().size());

            FdmMesher         mesher = solverDesc.mesher;
            FdmLinearOpLayout layout = mesher.layout();

            FdmLinearOpIterator endIter = layout.end();

            for (FdmLinearOpIterator iter = layout.begin(); iter != endIter;
                 ++iter)
            {
                initialValues_[iter.index()]
                    = solverDesc_.calculator.avgInnerValue(iter,
                                                           solverDesc.maturity);
                x_[iter.index()] = mesher.location(iter, 0);
            }
        }
 public FdmBackwardSolver(FdmLinearOpComposite map,
                          FdmBoundaryConditionSet bcSet,
                          FdmStepConditionComposite condition,
                          FdmSchemeDesc schemeDesc)
 {
     map_        = map;
     bcSet_      = bcSet;
     condition_  = condition;
     schemeDesc_ = schemeDesc;
 }
Example #3
0
        public static FdmStepConditionComposite joinConditions(FdmSnapshotCondition c1,
                                                               FdmStepConditionComposite c2)
        {
            List <List <double> > stoppingTimes = new List <List <double> >();

            stoppingTimes.Add(c2.stoppingTimes());
            stoppingTimes.Add(new InitializedList <double>(1, c1.getTime()));

            List <IStepCondition <Vector> > conditions = new List <IStepCondition <Vector> >();

            conditions.Add(c2);
            conditions.Add(c1);

            return(new FdmStepConditionComposite(stoppingTimes, conditions));
        }
Example #4
0
        public override void calculate()
        {
            // 1. Mesher
            HestonProcess process  = model_.currentLink().process();
            double        maturity = process.time(arguments_.exercise.lastDate());

            // 1.1 The variance mesher
            int tGridMin      = 5;
            int tGridAvgSteps = Math.Max(tGridMin, tGrid_ / 50);
            FdmHestonLocalVolatilityVarianceMesher varianceMesher
                = new FdmHestonLocalVolatilityVarianceMesher(vGrid_, process, leverageFct_, maturity, tGridAvgSteps);

            // 1.2 the equity mesher
            StrikedTypePayoff payoff = arguments_.payoff as StrikedTypePayoff;

            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_,
                                          FdmBlackScholesMesher.processHelper(process.s0(),
                                                                              process.dividendYield(),
                                                                              process.riskFreeRate(),
                                                                              varianceMesher.volaEstimate()),
                                          maturity,
                                          payoff.strike(),
                                          xMin,
                                          xMax,
                                          0.0001,
                                          1.5,
                                          new Pair <double?, double?>(),
                                          arguments_.cashFlow);

            FdmMesher mesher =
                new FdmMesherComposite(equityMesher, varianceMesher);

            // 2. Calculator
            StrikedTypePayoff rebatePayoff =
                new CashOrNothingPayoff(Option.Type.Call, 0.0, arguments_.rebate.Value);
            FdmInnerValueCalculator calculator =
                new FdmLogInnerValue(rebatePayoff, mesher, 0);

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

            FdmStepConditionComposite conditions =
                FdmStepConditionComposite.vanillaComposite(
                    arguments_.cashFlow, arguments_.exercise,
                    mesher, calculator,
                    process.riskFreeRate().currentLink().referenceDate(),
                    process.riskFreeRate().currentLink().dayCounter());

            // 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_;

            FdmHestonSolver solver =
                new FdmHestonSolver(
                    new Handle <HestonProcess>(process),
                    solverDesc, schemeDesc_,
                    new Handle <FdmQuantoHelper>(),
                    leverageFct_);

            double spot = process.s0().currentLink().value();

            results_.value = solver.valueAt(spot, process.v0());
            results_.delta = solver.deltaAt(spot, process.v0());
            results_.gamma = solver.gammaAt(spot, process.v0());
            results_.theta = solver.thetaAt(spot, process.v0());
        }
        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;
            }
        }
        public FdmSolverDesc getSolverDesc(double x)
        {
            // 1. Mesher
            HestonProcess process  = model_.currentLink().process();
            double        maturity = process.time(arguments_.exercise.lastDate());

            // 1.1 The variance mesher
            int tGridMin = 5;
            FdmHestonVarianceMesher varianceMesher =
                new FdmHestonVarianceMesher(vGrid_, process,
                                            maturity, Math.Max(tGridMin, tGrid_ / 50));

            // 1.2 The equity mesher
            StrikedTypePayoff payoff = arguments_.payoff as StrikedTypePayoff;

            Fdm1dMesher equityMesher;

            if (strikes_.empty())
            {
                equityMesher = new FdmBlackScholesMesher(
                    xGrid_,
                    FdmBlackScholesMesher.processHelper(
                        process.s0(), process.dividendYield(),
                        process.riskFreeRate(), varianceMesher.volaEstimate()),
                    maturity, payoff.strike(),
                    null, null, 0.0001, x,
                    new Pair <double?, double?>(payoff.strike(), 0.1),
                    arguments_.cashFlow);
            }
            else
            {
                Utils.QL_REQUIRE(arguments_.cashFlow.empty(), () => "multiple strikes engine "
                                 + "does not work with discrete dividends");
                equityMesher = new FdmBlackScholesMultiStrikeMesher(
                    xGrid_,
                    FdmBlackScholesMesher.processHelper(
                        process.s0(), process.dividendYield(),
                        process.riskFreeRate(), varianceMesher.volaEstimate()),
                    maturity, strikes_, 0.0001, x,
                    new Pair <double?, double?>(payoff.strike(), 0.075));
            }

            FdmMesher mesher = new FdmMesherComposite(equityMesher, varianceMesher);

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

            // 3. Step conditions
            FdmStepConditionComposite conditions =
                FdmStepConditionComposite.vanillaComposite(
                    arguments_.cashFlow, arguments_.exercise,
                    mesher, calculator,
                    process.riskFreeRate().currentLink().referenceDate(),
                    process.riskFreeRate().currentLink().dayCounter());

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

            // 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_;

            return(solverDesc);
        }
Example #7
0
        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
            StrikedTypePayoff rebatePayoff =
                new CashOrNothingPayoff(Option.Type.Call, 0.0, arguments_.rebate.Value);
            FdmInnerValueCalculator calculator =
                new FdmLogInnerValue(rebatePayoff, mesher, 0);

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

            FdmStepConditionComposite conditions =
                FdmStepConditionComposite.vanillaComposite(
                    arguments_.cashFlow, arguments_.exercise,
                    mesher, calculator,
                    process_.riskFreeRate().currentLink().referenceDate(),
                    process_.riskFreeRate().currentLink().dayCounter());

            // 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);
        }
        public override void calculate()
        {
            // 1. Term structure
            Handle <YieldTermStructure> ts = model_.currentLink().termStructure();

            // 2. Mesher
            DayCounter dc            = ts.currentLink().dayCounter();
            Date       referenceDate = ts.currentLink().referenceDate();
            double     maturity      = dc.yearFraction(referenceDate,
                                                       arguments_.exercise.lastDate());


            OrnsteinUhlenbeckProcess process = new OrnsteinUhlenbeckProcess(model_.currentLink().a(), model_.currentLink().sigma());

            Fdm1dMesher shortRateMesher =
                new FdmSimpleProcess1DMesher(xGrid_, process, maturity, 1, invEps_);

            FdmMesher mesher = new FdmMesherComposite(shortRateMesher);

            // 3. Inner Value Calculator
            List <Date> exerciseDates     = arguments_.exercise.dates();
            Dictionary <double, Date> t2d = new Dictionary <double, Date>();

            for (int i = 0; i < exerciseDates.Count; ++i)
            {
                double t = dc.yearFraction(referenceDate, exerciseDates[i]);
                Utils.QL_REQUIRE(t >= 0, () => "exercise dates must not contain past date");

                t2d.Add(t, exerciseDates[i]);
            }

            Handle <YieldTermStructure> disTs = model_.currentLink().termStructure();
            Handle <YieldTermStructure> fwdTs
                = arguments_.swap.iborIndex().forwardingTermStructure();

            Utils.QL_REQUIRE(fwdTs.currentLink().dayCounter() == disTs.currentLink().dayCounter(),
                             () => "day counter of forward and discount curve must match");
            Utils.QL_REQUIRE(fwdTs.currentLink().referenceDate() == disTs.currentLink().referenceDate(),
                             () => "reference date of forward and discount curve must match");

            HullWhite fwdModel =
                new HullWhite(fwdTs, model_.currentLink().a(), model_.currentLink().sigma());

            FdmInnerValueCalculator calculator =
                new FdmAffineModelSwapInnerValue <HullWhite>(
                    model_.currentLink(), fwdModel,
                    arguments_.swap, t2d, mesher, 0);

            // 4. Step conditions
            FdmStepConditionComposite conditions =
                FdmStepConditionComposite.vanillaComposite(
                    new DividendSchedule(), arguments_.exercise,
                    mesher, calculator, referenceDate, dc);

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

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

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

            FdmHullWhiteSolver solver =
                new FdmHullWhiteSolver(model_, solverDesc, schemeDesc_);

            results_.value = solver.valueAt(0.0);
        }
Example #9
0
        public override void calculate()
        {
            // 0. Cash dividend model
            Date   exerciseDate   = arguments_.exercise.lastDate();
            double maturity       = process_.time(exerciseDate);
            Date   settlementDate = process_.riskFreeRate().currentLink().referenceDate();

            double           spotAdjustment   = 0.0;
            DividendSchedule dividendSchedule = new DividendSchedule();

            switch (cashDividendModel_)
            {
            case CashDividendModel.Spot:
                dividendSchedule = arguments_.cashFlow;
                break;

            case CashDividendModel.Escrowed:
                foreach (Dividend divIter in dividendSchedule)
                {
                    Date divDate = divIter.date();

                    if (divDate <= exerciseDate && divDate >= settlementDate)
                    {
                        double divAmount = divIter.amount();
                        double discount  =
                            process_.riskFreeRate().currentLink().discount(divDate) /
                            process_.dividendYield().currentLink().discount(divDate);

                        spotAdjustment -= divAmount * discount;
                    }
                }

                Utils.QL_REQUIRE(process_.x0() + spotAdjustment > 0.0,
                                 () => "spot minus dividends becomes negative");
                break;

            default:
                Utils.QL_FAIL("unknwon cash dividend model");
                break;
            }

            // 1. Mesher
            StrikedTypePayoff payoff = arguments_.payoff as StrikedTypePayoff;

            Fdm1dMesher equityMesher =
                new FdmBlackScholesMesher(
                    xGrid_, process_, maturity, payoff.strike(),
                    null, null, 0.0001, 1.5,
                    new Pair <double?, double?>(payoff.strike(), 0.1),
                    dividendSchedule, quantoHelper_,
                    spotAdjustment);

            FdmMesher mesher =
                new FdmMesherComposite(equityMesher);

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

            // 3. Step conditions
            FdmStepConditionComposite conditions = FdmStepConditionComposite.vanillaComposite(
                arguments_.cashFlow, arguments_.exercise,
                mesher, calculator,
                process_.riskFreeRate().currentLink().referenceDate(),
                process_.riskFreeRate().currentLink().dayCounter());

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

            // 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);
        }