Пример #1
0
    public static ResolvedIborCapFloorLeg[][] ReturnRectangularResolvedIborCapFloorLegArray(int size1, int size2)
    {
        ResolvedIborCapFloorLeg[][] newArray = new ResolvedIborCapFloorLeg[size1][];
        for (int array1 = 0; array1 < size1; array1++)
        {
            newArray[array1] = new ResolvedIborCapFloorLeg[size2];
        }

        return(newArray);
    }
        //-------------------------------------------------------------------------
        // price and vega function
        private System.Func <double, double[]> getValueVegaFunction(ResolvedIborCapFloorLeg cap, RatesProvider ratesProvider, IborCapletFloorletVolatilities vols, ZonedDateTime prevExpiry, int nodeIndex)
        {
            VolatilityIborCapletFloorletPeriodPricer periodPricer = LegPricer.PeriodPricer;

            System.Func <double, double[]> priceAndVegaFunction = (double?x) =>
            {
                IborCapletFloorletVolatilities newVols = vols.withParameter(nodeIndex, x.Value);
                double                         price   = cap.CapletFloorletPeriods.Where(p => p.FixingDateTime.isAfter(prevExpiry)).Select(p => periodPricer.presentValue(p, ratesProvider, newVols).Amount).Sum();
                PointSensitivities             point   = cap.CapletFloorletPeriods.Where(p => p.FixingDateTime.isAfter(prevExpiry)).Select(p => periodPricer.presentValueSensitivityModelParamsVolatility(p, ratesProvider, newVols)).Aggregate((c1, c2) => c1.combinedWith(c2)).get().build();
                CurrencyParameterSensitivities sensi   = newVols.parameterSensitivity(point);
                double                         vega    = sensi.Sensitivities.get(0).Sensitivity.get(nodeIndex);
                return(new double[] { price, vega });
            };
            return(priceAndVegaFunction);
        }
        //-------------------------------------------------------------------------
        // create complete lists of caps, volatilities, strikes, expiries
        protected internal virtual void reduceRawData(IborCapletFloorletVolatilityDefinition definition, RatesProvider ratesProvider, DoubleArray strikes, DoubleArray volatilityData, DoubleArray errors, LocalDate startDate, LocalDate endDate, SurfaceMetadata metadata, System.Func <Surface, IborCapletFloorletVolatilities> volatilityFunction, IList <double> timeList, IList <double> strikeList, IList <double> volList, IList <ResolvedIborCapFloorLeg> capList, IList <double> priceList, IList <double> errorList)
        {
            int nStrikes = strikes.size();

            for (int i = 0; i < nStrikes; ++i)
            {
                if (Double.isFinite(volatilityData.get(i)))
                {
                    ResolvedIborCapFloorLeg capFloor = definition.createCap(startDate, endDate, strikes.get(i)).resolve(referenceData);
                    capList.Add(capFloor);
                    strikeList.Add(strikes.get(i));
                    volList.Add(volatilityData.get(i));
                    ConstantSurface constVolSurface     = ConstantSurface.of(metadata, volatilityData.get(i));
                    IborCapletFloorletVolatilities vols = volatilityFunction(constVolSurface);
                    timeList.Add(vols.relativeTime(capFloor.FinalFixingDateTime));
                    priceList.Add(pricer.presentValue(capFloor, ratesProvider, vols).Amount);
                    errorList.Add(errors.get(i));
                }
            }
        }
Пример #4
0
        //-------------------------------------------------------------------------
        // computes initial guess for each time step
        private DoubleArray computeInitialValues(RatesProvider ratesProvider, Curve betaCurve, Curve shiftCurve, IList <double> timeList, IList <double> volList, IList <ResolvedIborCapFloorLeg> capList, int[] startIndex, int postion, bool betaFixed, ValueType valueType)
        {
            IList <double>          vols = volList.subList(startIndex[postion], startIndex[postion + 1]);
            ResolvedIborCapFloorLeg cap  = capList[startIndex[postion]];
            double         fwd           = ratesProvider.iborIndexRates(cap.Index).rate(cap.FinalPeriod.IborRate.Observation);
            double         shift         = shiftCurve.yValue(timeList[startIndex[postion]]);
            double         factor        = valueType.Equals(ValueType.BLACK_VOLATILITY) ? 1d : 1d / (fwd + shift);
            IList <double> volsEquiv     = vols.Select(v => v * factor).ToList();
            double         nuFirst;
            double         betaInitial  = betaFixed ? betaCurve.yValue(timeList[startIndex[postion]]) : 0.5d;
            double         alphaInitial = DoubleArray.copyOf(volsEquiv).min() * Math.Pow(fwd, 1d - betaInitial);

            if (alphaInitial == volsEquiv[0] || alphaInitial == volsEquiv[volsEquiv.Count - 1])
            {
                nuFirst       = 0.1d;
                alphaInitial *= 0.95d;
            }
            else
            {
                nuFirst = 1d;
            }
            return(DoubleArray.of(alphaInitial, betaInitial, -0.5 * betaInitial + 0.5 * (1d - betaInitial), nuFirst));
        }
Пример #5
0
        //-------------------------------------------------------------------------
        public override IborCapletFloorletVolatilityCalibrationResult calibrate(IborCapletFloorletVolatilityDefinition definition, ZonedDateTime calibrationDateTime, RawOptionData capFloorData, RatesProvider ratesProvider)
        {
            ArgChecker.isTrue(ratesProvider.ValuationDate.Equals(calibrationDateTime.toLocalDate()), "valuationDate of ratesProvider should be coherent to calibrationDateTime");
            ArgChecker.isTrue(definition is DirectIborCapletFloorletVolatilityDefinition, "definition should be DirectIborCapletFloorletVolatilityDefinition");
            DirectIborCapletFloorletVolatilityDefinition directDefinition = (DirectIborCapletFloorletVolatilityDefinition)definition;
            // unpack cap data, create node caps
            IborIndex index           = directDefinition.Index;
            LocalDate calibrationDate = calibrationDateTime.toLocalDate();
            LocalDate baseDate        = index.EffectiveDateOffset.adjust(calibrationDate, ReferenceData);
            LocalDate startDate       = baseDate.plus(index.Tenor);

            System.Func <Surface, IborCapletFloorletVolatilities> volatilitiesFunction = this.volatilitiesFunction(directDefinition, calibrationDateTime, capFloorData);
            SurfaceMetadata metadata   = directDefinition.createMetadata(capFloorData);
            IList <Period>  expiries   = capFloorData.Expiries;
            DoubleArray     strikes    = capFloorData.Strikes;
            int             nExpiries  = expiries.Count;
            IList <double>  timeList   = new List <double>();
            IList <double>  strikeList = new List <double>();
            IList <double>  volList    = new List <double>();
            IList <ResolvedIborCapFloorLeg> capList = new List <ResolvedIborCapFloorLeg>();
            IList <double> priceList   = new List <double>();
            IList <double> errorList   = new List <double>();
            DoubleMatrix   errorMatrix = capFloorData.Error.orElse(DoubleMatrix.filled(nExpiries, strikes.size(), 1d));

            int[] startIndex = new int[nExpiries + 1];
            for (int i = 0; i < nExpiries; ++i)
            {
                LocalDate   endDate           = baseDate.plus(expiries[i]);
                DoubleArray volatilityForTime = capFloorData.Data.row(i);
                DoubleArray errorForTime      = errorMatrix.row(i);
                reduceRawData(directDefinition, ratesProvider, capFloorData.Strikes, volatilityForTime, errorForTime, startDate, endDate, metadata, volatilitiesFunction, timeList, strikeList, volList, capList, priceList, errorList);
                startIndex[i + 1] = volList.Count;
                ArgChecker.isTrue(startIndex[i + 1] > startIndex[i], "no valid option data for {}", expiries[i]);
            }
            // create caplet nodes and initial caplet vol surface
            ResolvedIborCapFloorLeg cap = capList[capList.Count - 1];
            int         nCaplets        = cap.CapletFloorletPeriods.size();
            DoubleArray capletExpiries  = DoubleArray.of(nCaplets, n => directDefinition.DayCount.relativeYearFraction(calibrationDate, cap.CapletFloorletPeriods.get(n).FixingDateTime.toLocalDate()));
            Triple <DoubleArray, DoubleArray, DoubleArray> capletNodes;
            DoubleArray initialVols = DoubleArray.copyOf(volList);

            if (directDefinition.ShiftCurve.Present)
            {
                metadata = Surfaces.blackVolatilityByExpiryStrike(directDefinition.Name.Name, directDefinition.DayCount);
                Curve shiftCurve = directDefinition.ShiftCurve.get();
                if (capFloorData.DataType.Equals(NORMAL_VOLATILITY))
                {
                    initialVols = DoubleArray.of(capList.Count, n => volList[n] / (ratesProvider.iborIndexRates(index).rate(capList[n].FinalPeriod.IborRate.Observation) + shiftCurve.yValue(timeList[n])));
                }
                InterpolatedNodalSurface capVolSurface = InterpolatedNodalSurface.of(metadata, DoubleArray.copyOf(timeList), DoubleArray.copyOf(strikeList), initialVols, INTERPOLATOR);
                capletNodes          = createCapletNodes(capVolSurface, capletExpiries, strikes, directDefinition.ShiftCurve.get());
                volatilitiesFunction = createShiftedBlackVolatilitiesFunction(index, calibrationDateTime, shiftCurve);
            }
            else
            {
                InterpolatedNodalSurface capVolSurface = InterpolatedNodalSurface.of(metadata, DoubleArray.copyOf(timeList), DoubleArray.copyOf(strikeList), initialVols, INTERPOLATOR);
                capletNodes = createCapletNodes(capVolSurface, capletExpiries, strikes);
            }
            InterpolatedNodalSurface baseSurface   = InterpolatedNodalSurface.of(metadata, capletNodes.First, capletNodes.Second, capletNodes.Third, INTERPOLATOR);
            DoubleMatrix             penaltyMatrix = directDefinition.computePenaltyMatrix(strikes, capletExpiries);
            // solve least square
            LeastSquareResults       res        = solver.solve(DoubleArray.copyOf(priceList), DoubleArray.copyOf(errorList), getPriceFunction(capList, ratesProvider, volatilitiesFunction, baseSurface), getJacobianFunction(capList, ratesProvider, volatilitiesFunction, baseSurface), capletNodes.Third, penaltyMatrix, POSITIVE);
            InterpolatedNodalSurface resSurface = InterpolatedNodalSurface.of(metadata, capletNodes.First, capletNodes.Second, res.FitParameters, directDefinition.Interpolator);

            return(IborCapletFloorletVolatilityCalibrationResult.ofLeastSquare(volatilitiesFunction(resSurface), res.ChiSq));
        }
        // sum of caplet prices which are already fixed
        private double priceFixed(ResolvedIborCapFloorLeg cap, RatesProvider ratesProvider, IborCapletFloorletVolatilities vols, ZonedDateTime prevExpiry)
        {
            VolatilityIborCapletFloorletPeriodPricer periodPricer = LegPricer.PeriodPricer;

            return(cap.CapletFloorletPeriods.Where(p => !p.FixingDateTime.isAfter(prevExpiry)).Select(p => periodPricer.presentValue(p, ratesProvider, vols).Amount).Sum());
        }