Esempio n. 1
0
        /*! gaussian-assumption y-th percentile
         */
        /*! \pre percentile must be in range (0%-100%) extremes excluded */
        public double gaussianPercentile(double percentile)
        {
            Utils.QL_REQUIRE(percentile > 0.0 && percentile < 1.0, () => "percentile (" + percentile + ") must be in (0.0, 1.0)");

            InverseCumulativeNormal gInverse = new InverseCumulativeNormal(mean(), standardDeviation());

            return(gInverse.value(percentile));
        }
Esempio n. 2
0
        /*! gaussian-assumption y-th percentile, defined as the value x
         *  such that \f[ y = \frac{1}{\sqrt{2 \pi}}
         *                            \int_{-\infty}^{x} \exp (-u^2/2) du \f]
         */
        /*! \pre percentile must be in range (0%-100%) extremes excluded */
        public double gaussianPercentile(double percentile)
        {
            if (!(percentile > 0.0 && percentile < 1.0))
            {
                throw new ApplicationException("percentile (" + percentile + ") must be in (0.0, 1.0)");
            }

            InverseCumulativeNormal gInverse = new InverseCumulativeNormal(mean(), standardDeviation());

            return(gInverse.value(percentile));
        }
Esempio n. 3
0
        //! gaussian-assumption Expected Shortfall at a given percentile

        /*! Assuming a gaussian distribution it
         *  returns the expected loss in case that the loss exceeded
         *  a VaR threshold,
         *
         *  that is the average of observations below the
         *  given percentile \f$ p \f$.
         *  Also know as conditional value-at-risk.
         *
         *  See Artzner, Delbaen, Eber and Heath,
         *  "Coherent measures of risk", Mathematical Finance 9 (1999)
         */
        public double gaussianExpectedShortfall(double percentile)
        {
            Utils.QL_REQUIRE(percentile < 1.0 && percentile >= 0.9, () => "percentile (" + percentile + ") out of range [0.9, 1)");

            double m   = this.mean();
            double std = this.standardDeviation();
            InverseCumulativeNormal gInverse = new InverseCumulativeNormal(m, std);
            double             var           = gInverse.value(1.0 - percentile);
            NormalDistribution g             = new NormalDistribution(m, std);
            double             result        = m - std * std * g.value(var) / (1.0 - percentile);

            // expectedShortfall must be a loss
            // this means that it has to be MIN(result, 0.0)
            // expectedShortfall must also be a positive quantity, so -MIN(*)
            return(-Math.Min(result, 0.0));
        }
Esempio n. 4
0
        // alternative delta type
        private double strikeFromDelta(double delta, DeltaVolQuote.DeltaType dt)
        {
            double res = 0.0;
            double arg = 0.0;
            InverseCumulativeNormal f = new InverseCumulativeNormal();

            Utils.QL_REQUIRE(delta * phi_ >= 0.0, () => "Option type and delta are incoherent.");

            switch (dt)
            {
            case DeltaVolQuote.DeltaType.Spot:
                Utils.QL_REQUIRE(Math.Abs(delta) <= fDiscount_, () => "Spot delta out of range.");
                arg = -phi_ *f.value(phi_ *delta / fDiscount_) * stdDev_ + 0.5 * stdDev_ * stdDev_;

                res = forward_ * Math.Exp(arg);
                break;

            case DeltaVolQuote.DeltaType.Fwd:
                Utils.QL_REQUIRE(Math.Abs(delta) <= 1.0, () => "Forward delta out of range.");
                arg = -phi_ *f.value(phi_ *delta) * stdDev_ + 0.5 * stdDev_ * stdDev_;

                res = forward_ * Math.Exp(arg);
                break;

            case DeltaVolQuote.DeltaType.PaSpot:
            case DeltaVolQuote.DeltaType.PaFwd:
                // This has to be solved numerically. One of the
                // problems is that the premium adjusted call delta is
                // not monotonic in strike, such that two solutions
                // might occur. The one right to the max of the delta is
                // considered to be the correct strike.  Some proper
                // interval bounds for the strike need to be chosen, the
                // numerics can otherwise be very unreliable and
                // unstable.  I've chosen Brent over Newton, since the
                // interval can be specified explicitly and we can not
                // run into the area on the left of the maximum.  The
                // put delta doesn't have this property and can be
                // solved without any problems, but also numerically.

                BlackDeltaPremiumAdjustedSolverClass f1 = new BlackDeltaPremiumAdjustedSolverClass(
                    ot_, dt, spot_, dDiscount_, fDiscount_, stdDev_, delta);

                Brent solver = new Brent();
                solver.setMaxEvaluations(1000);
                double accuracy = 1.0e-10;

                double rightLimit = 0.0;
                double leftLimit  = 0.0;

                // Strike of not premium adjusted is always to the right of premium adjusted
                if (dt == DeltaVolQuote.DeltaType.PaSpot)
                {
                    rightLimit = strikeFromDelta(delta, DeltaVolQuote.DeltaType.Spot);
                }
                else
                {
                    rightLimit = strikeFromDelta(delta, DeltaVolQuote.DeltaType.Fwd);
                }

                if (phi_ < 0)
                {
                    // if put
                    res = solver.solve(f1, accuracy, rightLimit, 0.0, spot_ * 100.0);
                    break;
                }
                else
                {
                    // find out the left limit which is the strike
                    // corresponding to the value where premium adjusted
                    // deltas have their maximum.

                    BlackDeltaPremiumAdjustedMaxStrikeClass g = new BlackDeltaPremiumAdjustedMaxStrikeClass(
                        ot_, dt, spot_, dDiscount_, fDiscount_, stdDev_);

                    leftLimit = solver.solve(g, accuracy, rightLimit * 0.5, 0.0, rightLimit);

                    double guess = leftLimit + (rightLimit - leftLimit) * 0.5;

                    res = solver.solve(f1, accuracy, guess, leftLimit, rightLimit);
                } // end if phi<0 else

                break;


            default:
                Utils.QL_FAIL("invalid delta type");
                break;
            }

            return(res);
        }