public override void partialRollback(DiscretizedAsset asset, double to)
        {
            double from = asset.time();

            if (Utils.close(from, to))
            {
                return;
            }

            Utils.QL_REQUIRE(from > to, () => " cannot roll the asset back to tile to it is already at time from ");

            DiscretizedConvertible convertible = asset as DiscretizedConvertible;

            int iFrom = t_.index(from);
            int iTo   = t_.index(to);

            for (var i = iFrom - 1; i >= iTo; --i)
            {
                Vector newValues                = new Vector(size(i));
                Vector newSpreadAdjustedRate    = new Vector(size(i));
                Vector newConversionProbability = new Vector(size(i));

                stepback(i, convertible.values(), convertible.conversionProbability(), convertible.spreadAdjustedRate(),
                         newValues, newConversionProbability, newSpreadAdjustedRate);
                convertible.setTime(t_[i]);
                convertible.setValues(newValues);
                convertible.spreadAdjustedRate_    = newSpreadAdjustedRate;
                convertible.conversionProbability_ = newConversionProbability;

                // skip the very last adjustement
                if (i != iTo)
                {
                    convertible.adjustValues();
                }
            }
        }
Beispiel #2
0
        public override void calculate()
        {
            DayCounter rfdc   = process_.riskFreeRate().link.dayCounter();
            DayCounter divdc  = process_.dividendYield().link.dayCounter();
            DayCounter voldc  = process_.blackVolatility().link.dayCounter();
            Calendar   volcal = process_.blackVolatility().link.calendar();

            double s0 = process_.x0();

            Utils.QL_REQUIRE(s0 > 0.0, () => "negative or null underlying");
            double v             = process_.blackVolatility().link.blackVol(arguments_.exercise.lastDate(), s0);
            Date   maturityDate  = arguments_.exercise.lastDate();
            double riskFreeRate  = process_.riskFreeRate().link.zeroRate(maturityDate, rfdc, Compounding.Continuous, Frequency.NoFrequency).value();
            double q             = process_.dividendYield().link.zeroRate(maturityDate, divdc, Compounding.Continuous, Frequency.NoFrequency).value();
            Date   referenceDate = process_.riskFreeRate().link.referenceDate();

            // substract dividends

            ConvertibleBond.option.Arguments args = arguments_ as ConvertibleBond.option.Arguments;

            for (int i = 0; i < args.dividends.Count; i++)
            {
                if (args.dividends[i].date() >= referenceDate)
                {
                    s0 -= args.dividends[i].amount() * process_.riskFreeRate().link.discount(args.dividends[i].date());
                }

                Utils.QL_REQUIRE(s0 > 0.0, () => "negative value after substracting dividends");
            }

            // binomial trees with constant coefficient

            Handle <Quote> underlying = new Handle <Quote>(new SimpleQuote(s0));
            Handle <YieldTermStructure> flatRiskFree =
                new Handle <YieldTermStructure>(new FlatForward(referenceDate, riskFreeRate, rfdc));
            Handle <YieldTermStructure> flatDividends =
                new Handle <YieldTermStructure>(new FlatForward(referenceDate, q, divdc));
            Handle <BlackVolTermStructure> flatVol =
                new Handle <BlackVolTermStructure>(new BlackConstantVol(referenceDate, volcal, v, voldc));
            PlainVanillaPayoff payoff = args.payoff as PlainVanillaPayoff;

            Utils.QL_REQUIRE(payoff != null, () => " non-plain payoff given ");

            double maturity = rfdc.yearFraction(args.settlementDate, maturityDate);
            GeneralizedBlackScholesProcess bs =
                new GeneralizedBlackScholesProcess(underlying, flatDividends, flatRiskFree, flatVol);

            T Tree = new T().factory(bs, maturity, timeSteps_, payoff.strike());

            double creditSpread = args.creditSpread.link.value();

            TsiveriotisFernandesLattice <T> lattice = new TsiveriotisFernandesLattice <T>(Tree, riskFreeRate,
                                                                                          maturity, timeSteps_, creditSpread, v, q);
            DiscretizedConvertible convertible = new DiscretizedConvertible(args, bs, new TimeGrid(maturity, timeSteps_));

            convertible.initialize(lattice, maturity);
            convertible.rollback(0.0);
            results_.value = convertible.presentValue();

            Utils.QL_REQUIRE(results_.value < double.MaxValue, () => "floating-point overflow on tree grid");
        }