Ejemplo n.º 1
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the raw data sensitivities from SABR parameter sensitivity.
        /// <para>
        /// The SABR parameter sensitivities to data are stored in some optional data in the
        /// <seealso cref="SabrParametersSwaptionVolatilities"/>.
        /// The sensitivities to the SABR parameters passed in should be compatible with the SABR parameters in term of data order.
        /// </para>
        /// <para>
        /// Only the sensitivity to the SABR parameters for which there is a data sensitivity are taken into account.
        /// At least one of the four parameter must have such sensitivities.
        ///
        /// </para>
        /// </summary>
        /// <param name="paramSensitivities">  the curve SABR parameter sensitivities </param>
        /// <param name="volatilities">  the SABR parameters, including the data sensitivity metadata </param>
        /// <returns> the raw data sensitivities </returns>
        public virtual CurrencyParameterSensitivity parallelSensitivity(CurrencyParameterSensitivities paramSensitivities, SabrParametersSwaptionVolatilities volatilities)
        {
            IList <IList <DoubleArray> >            sensitivityToRawData = new List <IList <DoubleArray> >(4);
            Optional <ImmutableList <DoubleArray> > alphaInfo            = volatilities.DataSensitivityAlpha;

            sensitivityToRawData.Add(alphaInfo.orElse(null));
            Optional <ImmutableList <DoubleArray> > betaInfo = volatilities.DataSensitivityBeta;

            sensitivityToRawData.Add(betaInfo.orElse(null));
            Optional <ImmutableList <DoubleArray> > rhoInfo = volatilities.DataSensitivityRho;

            sensitivityToRawData.Add(rhoInfo.orElse(null));
            Optional <ImmutableList <DoubleArray> > nuInfo = volatilities.DataSensitivityNu;

            sensitivityToRawData.Add(nuInfo.orElse(null));
            ArgChecker.isTrue(alphaInfo.Present || betaInfo.Present || rhoInfo.Present || nuInfo.Present, "at least one sensitivity to raw data must be available");
            checkCurrency(paramSensitivities);
            int nbSurfaceNode = sensitivityToRawData[0].Count;

            double[] sensitivityRawArray = new double[nbSurfaceNode];
            Currency ccy = null;
            IList <ParameterMetadata> metadataResult = null;

            foreach (CurrencyParameterSensitivity s in paramSensitivities.Sensitivities)
            {
                ccy = s.Currency;
//JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET:
//ORIGINAL LINE: com.opengamma.strata.data.MarketDataName<?> name = s.getMarketDataName();
                MarketDataName <object> name = s.MarketDataName;
                if (name is SurfaceName)
                {
                    if (volatilities.Parameters.AlphaSurface.Name.Equals(name) && alphaInfo.Present)
                    {
                        updateSensitivity(s, sensitivityToRawData[0], sensitivityRawArray);
                        metadataResult = s.ParameterMetadata;
                    }
                    if (volatilities.Parameters.BetaSurface.Name.Equals(name) && betaInfo.Present)
                    {
                        updateSensitivity(s, sensitivityToRawData[1], sensitivityRawArray);
                        metadataResult = s.ParameterMetadata;
                    }
                    if (volatilities.Parameters.RhoSurface.Name.Equals(name) && rhoInfo.Present)
                    {
                        updateSensitivity(s, sensitivityToRawData[2], sensitivityRawArray);
                        metadataResult = s.ParameterMetadata;
                    }
                    if (volatilities.Parameters.NuSurface.Name.Equals(name) && nuInfo.Present)
                    {
                        updateSensitivity(s, sensitivityToRawData[3], sensitivityRawArray);
                        metadataResult = s.ParameterMetadata;
                    }
                }
            }
            DoubleArray sensitivityRaw = DoubleArray.ofUnsafe(sensitivityRawArray);

            return(CurrencyParameterSensitivity.of(SurfaceName.of("RawDataParallelSensitivity"), metadataResult, ccy, sensitivityRaw));
        }
Ejemplo n.º 2
0
        static BlackBondFutureOptionMarginedProductPricerTest()
        {
            IList <GenericVolatilitySurfaceYearFractionParameterMetadata> list = new List <GenericVolatilitySurfaceYearFractionParameterMetadata>();
            int nData = TIME.size();

            for (int i = 0; i < nData; ++i)
            {
                GenericVolatilitySurfaceYearFractionParameterMetadata parameterMetadata = GenericVolatilitySurfaceYearFractionParameterMetadata.of(TIME.get(i), LogMoneynessStrike.of(MONEYNESS.get(i)));
                list.Add(parameterMetadata);
            }
            METADATA = DefaultSurfaceMetadata.builder().surfaceName(SurfaceName.of("GOVT1-BOND-FUT-VOL")).xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.LOG_MONEYNESS).zValueType(ValueType.BLACK_VOLATILITY).parameterMetadata(list).dayCount(ACT_365F).build();
        }
 public virtual void test_findData()
 {
     assertEquals(VOLS.findData(SURFACE.Name), SURFACE);
     assertEquals(VOLS.findData(SurfaceName.of("Rubbish")), null);
 }
        public virtual DeformedSurface localVolatilityFromPrice(Surface callPriceSurface, double spot, System.Func <double, double> interestRate, System.Func <double, double> dividendRate)
        {
            System.Func <DoublesPair, ValueDerivatives> func = (DoublesPair x) =>
            {
                double      t          = x.First;
                double      k          = x.Second;
                double      r          = interestRate(t);
                double      q          = dividendRate(t);
                double      price      = callPriceSurface.zValue(t, k);
                DoubleArray priceSensi = callPriceSurface.zValueParameterSensitivity(t, k).Sensitivity;
                double      divT       = FIRST_DERIV.differentiate(u => callPriceSurface.zValue(u, k)).apply(t);
                DoubleArray divTSensi  = FIRST_DERIV_SENSI.differentiate(u => callPriceSurface.zValueParameterSensitivity(u.get(0), k).Sensitivity).apply(DoubleArray.of(t)).column(0);
                double      divK       = FIRST_DERIV.differentiate(l => callPriceSurface.zValue(t, l)).apply(k);
                DoubleArray divKSensi  = FIRST_DERIV_SENSI.differentiate(l => callPriceSurface.zValueParameterSensitivity(t, l.get(0)).Sensitivity).apply(DoubleArray.of(k)).column(0);
                double      divK2      = SECOND_DERIV.differentiate(l => callPriceSurface.zValue(t, l)).apply(k);
                DoubleArray divK2Sensi = SECOND_DERIV_SENSI.differentiateNoCross(l => callPriceSurface.zValueParameterSensitivity(t, l.get(0)).Sensitivity).apply(DoubleArray.of(k)).column(0);
                double      var        = 2d * (divT + q * price + (r - q) * k * divK) / (k * k * divK2);
                if (var < 0d)
                {
                    throw new System.ArgumentException("Negative variance");
                }
                double      localVol      = Math.Sqrt(var);
                double      factor        = 1d / (localVol * k * k * divK2);
                DoubleArray localVolSensi = divTSensi.multipliedBy(factor).plus(divKSensi.multipliedBy((r - q) * k * factor)).plus(priceSensi.multipliedBy(q * factor)).plus(divK2Sensi.multipliedBy(-0.5 * localVol / divK2));
                return(ValueDerivatives.of(localVol, localVolSensi));
            };
            SurfaceMetadata metadata = DefaultSurfaceMetadata.builder().xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.STRIKE).zValueType(ValueType.LOCAL_VOLATILITY).surfaceName(SurfaceName.of("localVol_" + callPriceSurface.Name)).build();

            return(DeformedSurface.of(metadata, callPriceSurface, func));
        }
        public virtual DeformedSurface localVolatilityFromImpliedVolatility(Surface impliedVolatilitySurface, double spot, System.Func <double, double> interestRate, System.Func <double, double> dividendRate)
        {
            System.Func <DoublesPair, ValueDerivatives> func = (DoublesPair x) =>
            {
                double      t         = x.First;
                double      k         = x.Second;
                double      r         = interestRate(t);
                double      q         = dividendRate(t);
                double      vol       = impliedVolatilitySurface.zValue(t, k);
                DoubleArray volSensi  = impliedVolatilitySurface.zValueParameterSensitivity(t, k).Sensitivity;
                double      divT      = FIRST_DERIV.differentiate(u => impliedVolatilitySurface.zValue(u, k)).apply(t);
                DoubleArray divTSensi = FIRST_DERIV_SENSI.differentiate(u => impliedVolatilitySurface.zValueParameterSensitivity(u.get(0), k).Sensitivity).apply(DoubleArray.of(t)).column(0);
                double      localVol;
                DoubleArray localVolSensi = DoubleArray.of();
                if (k < SMALL)
                {
                    localVol      = Math.Sqrt(vol * vol + 2 * vol * t * (divT));
                    localVolSensi = volSensi.multipliedBy((vol + t * divT) / localVol).plus(divTSensi.multipliedBy(vol * t / localVol));
                }
                else
                {
                    double      divK       = FIRST_DERIV.differentiate(l => impliedVolatilitySurface.zValue(t, l)).apply(k);
                    DoubleArray divKSensi  = FIRST_DERIV_SENSI.differentiate(l => impliedVolatilitySurface.zValueParameterSensitivity(t, l.get(0)).Sensitivity).apply(DoubleArray.of(k)).column(0);
                    double      divK2      = SECOND_DERIV.differentiate(l => impliedVolatilitySurface.zValue(t, l)).apply(k);
                    DoubleArray divK2Sensi = SECOND_DERIV_SENSI.differentiateNoCross(l => impliedVolatilitySurface.zValueParameterSensitivity(t, l.get(0)).Sensitivity).apply(DoubleArray.of(k)).column(0);
                    double      rq         = r - q;
                    double      h1         = (Math.Log(spot / k) + (rq + 0.5 * vol * vol) * t) / vol;
                    double      h2         = h1 - vol * t;
                    double      den        = 1d + 2d * h1 * k * divK + k * k * (h1 * h2 * divK * divK + t * vol * divK2);
                    double      var        = (vol * vol + 2d * vol * t * (divT + k * rq * divK)) / den;
                    if (var < 0d)
                    {
                        throw new System.ArgumentException("Negative variance");
                    }
                    localVol      = Math.Sqrt(var);
                    localVolSensi = volSensi.multipliedBy(localVol * k * h2 * divK * (1d + 0.5 * k * h2 * divK) / vol / den + 0.5 * localVol * Math.Pow(k * h1 * divK, 2) / vol / den + (vol + divT * t + rq * t * k * divK) / (localVol * den) - 0.5 * divK2 * localVol * k * k * t / den).plus(divKSensi.multipliedBy((vol * t * rq * k / localVol - localVol * k * h1 * (1d + k * h2 * divK)) / den)).plus(divTSensi.multipliedBy(vol * t / (localVol * den))).plus(divK2Sensi.multipliedBy(-0.5 * vol * localVol * k * k * t / den));
                }
                return(ValueDerivatives.of(localVol, localVolSensi));
            };
            SurfaceMetadata metadata = DefaultSurfaceMetadata.builder().xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.STRIKE).zValueType(ValueType.LOCAL_VOLATILITY).surfaceName(SurfaceName.of("localVol_" + impliedVolatilitySurface.Name)).build();

            return(DeformedSurface.of(metadata, impliedVolatilitySurface, func));
        }
Ejemplo n.º 6
0
        public virtual InterpolatedNodalSurface localVolatilityFromPrice(Surface callPriceSurface, double spot, System.Func <double, double> interestRate, System.Func <double, double> dividendRate)
        {
            double[][]           stateValue  = new double[nSteps + 1][];
            double[]             df          = new double[nSteps];
            IList <DoubleMatrix> probability = new List <DoubleMatrix>(nSteps);
            int nTotal = (nSteps - 1) * (nSteps - 1) + 1;

            double[] timeRes = new double[nTotal];
            double[] spotRes = new double[nTotal];
            double[] volRes  = new double[nTotal];
            // uniform grid based on TrigeorgisLatticeSpecification, using reference values
            double refPrice      = callPriceSurface.zValue(maxTime, spot) * Math.Exp(interestRate(maxTime) * maxTime);
            double refForward    = spot * Math.Exp((interestRate(maxTime) - dividendRate(maxTime)) * maxTime);
            double refVolatility = BlackFormulaRepository.impliedVolatility(refPrice, refForward, spot, maxTime, true);
            double dt            = maxTime / nSteps;
            double dx            = refVolatility * Math.Sqrt(3d * dt);
            double upFactor      = Math.Exp(dx);
            double downFactor    = Math.Exp(-dx);

            double[] adSec      = new double[2 * nSteps + 1];
            double[] assetPrice = new double[2 * nSteps + 1];
            for (int i = nSteps; i > -1; --i)
            {
                if (i == 0)
                {
                    resolveFirstLayer(interestRate, dividendRate, nTotal, dt, spot, adSec, assetPrice, timeRes, spotRes, volRes, df, stateValue, probability);
                }
                else
                {
                    double   time             = dt * i;
                    double   zeroRate         = interestRate(time);
                    double   zeroDividendRate = dividendRate(time);
                    int      nNodes           = 2 * i + 1;
                    double[] assetPriceLocal  = new double[nNodes];
                    double[] callOptionPrice  = new double[nNodes];
                    double[] putOptionPrice   = new double[nNodes];
                    int      position         = i - 1;
                    double   assetTmp         = spot * Math.Pow(upFactor, i);
                    // call options for upper half nodes
                    for (int j = nNodes - 1; j > position - 1; --j)
                    {
                        assetPriceLocal[j] = assetTmp;
                        callOptionPrice[j] = callPriceSurface.zValue(time, assetPriceLocal[j]);
                        assetTmp          *= downFactor;
                    }
                    // put options for lower half nodes
                    assetTmp = spot * Math.Pow(downFactor, i);
                    for (int j = 0; j < position + 2; ++j)
                    {
                        assetPriceLocal[j] = assetTmp;
                        putOptionPrice[j]  = callPriceSurface.zValue(time, assetPriceLocal[j]) - spot * Math.Exp(-zeroDividendRate * time) + Math.Exp(-zeroRate * time) * assetPriceLocal[j];
                        assetTmp          *= upFactor;
                    }
                    resolveLayer(interestRate, dividendRate, i, nTotal, position, dt, zeroRate, zeroDividendRate, callOptionPrice, putOptionPrice, adSec, assetPrice, assetPriceLocal, timeRes, spotRes, volRes, df, stateValue, probability);
                }
            }
            SurfaceMetadata metadata = DefaultSurfaceMetadata.builder().xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.STRIKE).zValueType(ValueType.LOCAL_VOLATILITY).surfaceName(SurfaceName.of("localVol_" + callPriceSurface.Name)).build();

            return(InterpolatedNodalSurface.ofUnsorted(metadata, DoubleArray.ofUnsafe(timeRes), DoubleArray.ofUnsafe(spotRes), DoubleArray.ofUnsafe(volRes), interpolator));
        }
Ejemplo n.º 7
0
        //-------------------------------------------------------------------------
        public virtual InterpolatedNodalSurface localVolatilityFromImpliedVolatility(Surface impliedVolatilitySurface, double spot, System.Func <double, double> interestRate, System.Func <double, double> dividendRate)
        {
            System.Func <DoublesPair, double> surface = (DoublesPair tk) =>
            {
                return(impliedVolatilitySurface.zValue(tk));
            };
            ImmutableList <double[]> localVolData = calibrate(surface, spot, interestRate, dividendRate).First;
            SurfaceMetadata          metadata     = DefaultSurfaceMetadata.builder().xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.STRIKE).zValueType(ValueType.LOCAL_VOLATILITY).surfaceName(SurfaceName.of("localVol_" + impliedVolatilitySurface.Name)).build();

            return(InterpolatedNodalSurface.ofUnsorted(metadata, DoubleArray.ofUnsafe(localVolData.get(0)), DoubleArray.ofUnsafe(localVolData.get(1)), DoubleArray.ofUnsafe(localVolData.get(2)), interpolator));
        }