Example #1
0
        // LazyObject interface
        protected override void performCalculations()
        {
            //// optionletStripper data
            optionletDates_          = new List <Date>(stripper1_.optionletFixingDates());
            optionletPaymentDates_   = new List <Date>(stripper1_.optionletPaymentDates());
            optionletAccrualPeriods_ = new List <double>(stripper1_.optionletAccrualPeriods());
            optionletTimes_          = new List <double>(stripper1_.optionletFixingTimes());
            atmOptionletRate_        = new List <double>(stripper1_.atmOptionletRates());
            for (int i = 0; i < optionletTimes_.Count; ++i)
            {
                optionletStrikes_[i]      = new List <double>(stripper1_.optionletStrikes(i));
                optionletVolatilities_[i] = new List <double>(stripper1_.optionletVolatilities(i));
            }

            // atmCapFloorTermVolCurve data
            List <Period> optionExpiriesTenors = new List <Period>(atmCapFloorTermVolCurve_.link.optionTenors());
            List <double> optionExpiriesTimes  = new List <double>(atmCapFloorTermVolCurve_.link.optionTimes());

            for (int j = 0; j < nOptionExpiries_; ++j)
            {
                double atmOptionVol        = atmCapFloorTermVolCurve_.link.volatility(optionExpiriesTimes[j], 33.3333); // dummy strike
                BlackCapFloorEngine engine = new BlackCapFloorEngine(iborIndex_.forwardingTermStructure(), atmOptionVol, dc_);
                CapFloor            test   = new MakeCapFloor(CapFloorType.Cap, optionExpiriesTenors[j], iborIndex_, null,
                                                              new Period(0, TimeUnit.Days)).withPricingEngine(engine).value();
                caps_.Add(test);
                atmCapFloorStrikes_[j] = caps_[j].atmRate(iborIndex_.forwardingTermStructure());
                atmCapFloorPrices_[j]  = caps_[j].NPV();
            }

            spreadsVolImplied_ = spreadsVolImplied();

            StrippedOptionletAdapter adapter = new StrippedOptionletAdapter(stripper1_);

            double unadjustedVol, adjustedVol;

            for (int j = 0; j < nOptionExpiries_; ++j)
            {
                for (int i = 0; i < optionletVolatilities_.Count; ++i)
                {
                    if (i <= caps_[j].floatingLeg().Count)
                    {
                        unadjustedVol = adapter.volatility(optionletTimes_[i], atmCapFloorStrikes_[j]);
                        adjustedVol   = unadjustedVol + spreadsVolImplied_[j];

                        var previous    = optionletStrikes_[i].FindIndex(x => x >= atmCapFloorStrikes_[j]);
                        int insertIndex = previous;

                        optionletStrikes_[i].Insert(insertIndex, atmCapFloorStrikes_[j]);
                        optionletVolatilities_[i].Insert(insertIndex, adjustedVol);
                    }
                }
            }
        }
Example #2
0
        // LazyObject interface
        protected override void performCalculations()
        {
            // update dates
            Date                referenceDate = termVolSurface_.referenceDate();
            DayCounter          dc            = termVolSurface_.dayCounter();
            BlackCapFloorEngine dummy         = new BlackCapFloorEngine( // discounting does not matter here
                iborIndex_.forwardingTermStructure(), 0.20, dc);

            for (int i = 0; i < nOptionletTenors_; ++i)
            {
                CapFloor temp = new MakeCapFloor(CapFloorType.Cap,
                                                 capFloorLengths_[i],
                                                 iborIndex_,
                                                 0.04, // dummy strike
                                                 new Period(0, TimeUnit.Days))
                                .withPricingEngine(dummy);
                FloatingRateCoupon lFRC = temp.lastFloatingRateCoupon();
                optionletDates_[i]          = lFRC.fixingDate();
                optionletPaymentDates_[i]   = lFRC.date();
                optionletAccrualPeriods_[i] = lFRC.accrualPeriod();
                optionletTimes_[i]          = dc.yearFraction(referenceDate,
                                                              optionletDates_[i]);
                atmOptionletRate_[i] = lFRC.indexFixing();
            }

            if (floatingSwitchStrike_ && capFlooMatrixNotInitialized_)
            {
                double averageAtmOptionletRate = 0.0;
                for (int i = 0; i < nOptionletTenors_; ++i)
                {
                    averageAtmOptionletRate += atmOptionletRate_[i];
                }
                switchStrike_ = averageAtmOptionletRate / nOptionletTenors_;
            }

            Handle <YieldTermStructure> discountCurve = discount_.empty()
                                                    ? iborIndex_.forwardingTermStructure()
                                                    : discount_;

            List <double> strikes = new List <double>(termVolSurface_.strikes());

            // initialize CapFloorMatrix
            if (capFlooMatrixNotInitialized_)
            {
                for (int i = 0; i < nOptionletTenors_; ++i)
                {
                    capFloors_[i] = new List <CapFloor>(nStrikes_);
                }
                // construction might go here
                for (int j = 0; j < nStrikes_; ++j)
                {
                    // using out-of-the-money options
                    CapFloorType capFloorType = strikes[j] < switchStrike_
                                           ? CapFloorType.Floor
                                           : CapFloorType.Cap;
                    for (int i = 0; i < nOptionletTenors_; ++i)
                    {
                        if (volatilityType_ == VolatilityType.ShiftedLognormal)
                        {
                            BlackCapFloorEngine engine = new BlackCapFloorEngine(discountCurve,
                                                                                 new Handle <Quote>(volQuotes_[i][j]), dc, displacement_);
                            capFloors_[i].Add(new MakeCapFloor(capFloorType, capFloorLengths_[i], iborIndex_, strikes[j],
                                                               new Period(0, TimeUnit.Days)).withPricingEngine(engine));
                        }
                        else if (volatilityType_ == VolatilityType.Normal)
                        {
                            BachelierCapFloorEngine engine = new BachelierCapFloorEngine(discountCurve,
                                                                                         new Handle <Quote>(volQuotes_[i][j]), dc);
                            capFloors_[i].Add(new MakeCapFloor(capFloorType, capFloorLengths_[i], iborIndex_, strikes[j],
                                                               new Period(0, TimeUnit.Days)).withPricingEngine(engine));
                        }
                        else
                        {
                            Utils.QL_FAIL("unknown volatility type: " + volatilityType_);
                        }
                    }
                }
                capFlooMatrixNotInitialized_ = false;
            }

            for (int j = 0; j < nStrikes_; ++j)
            {
                Option.Type optionletType = strikes[j] < switchStrike_ ? Option.Type.Put : Option.Type.Call;

                double previousCapFloorPrice = 0.0;
                for (int i = 0; i < nOptionletTenors_; ++i)
                {
                    capFloorVols_[i, j] = termVolSurface_.volatility(capFloorLengths_[i], strikes[j], true);
                    volQuotes_[i][j].setValue(capFloorVols_[i, j]);

                    capFloorPrices_[i, j]  = capFloors_[i][j].NPV();
                    optionletPrices_[i, j] = capFloorPrices_[i, j] - previousCapFloorPrice;
                    previousCapFloorPrice  = capFloorPrices_[i, j];
                    double d = discountCurve.link.discount(optionletPaymentDates_[i]);
                    double optionletAnnuity = optionletAccrualPeriods_[i] * d;
                    try
                    {
                        if (volatilityType_ == VolatilityType.ShiftedLognormal)
                        {
                            optionletStDevs_[i, j] = Utils.blackFormulaImpliedStdDev(optionletType, strikes[j], atmOptionletRate_[i],
                                                                                     optionletPrices_[i, j], optionletAnnuity, displacement_, optionletStDevs_[i, j], accuracy_,
                                                                                     maxIter_);
                        }
                        else if (volatilityType_ == VolatilityType.Normal)
                        {
                            optionletStDevs_[i, j] = Math.Sqrt(optionletTimes_[i]) *
                                                     Utils.bachelierBlackFormulaImpliedVol(
                                optionletType, strikes[j], atmOptionletRate_[i],
                                optionletTimes_[i], optionletPrices_[i, j],
                                optionletAnnuity);
                        }
                        else
                        {
                            Utils.QL_FAIL("Unknown volatility type: " + volatilityType_);
                        }
                    }
                    catch (Exception e)
                    {
                        if (dontThrow_)
                        {
                            optionletStDevs_[i, j] = 0.0;
                        }
                        else
                        {
                            Utils.QL_FAIL("could not bootstrap optionlet:" +
                                          "\n type:    " + optionletType +
                                          "\n strike:  " + (strikes[j]) +
                                          "\n atm:     " + (atmOptionletRate_[i]) +
                                          "\n price:   " + optionletPrices_[i, j] +
                                          "\n annuity: " + optionletAnnuity +
                                          "\n expiry:  " + optionletDates_[i] +
                                          "\n error:   " + e.Message);
                        }
                    }
                    optionletVolatilities_[i][j] = optionletStDevs_[i, j] / Math.Sqrt(optionletTimes_[i]);
                }
            }
        }