Beispiel #1
0
        public MersenneTwisterUniformRng(List <ulong> seeds)
        {
            mt = new InitializedList <ulong>(N);

            seedInitialization(19650218UL);
            int i = 1, j = 0, k = (N > seeds.Count ? N : seeds.Count);

            for (; k != 0; k--)
            {
                mt[i]  = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525UL)) + seeds[j] + (ulong)j; /* non linear */
                mt[i] &= 0xffffffffUL;                                                                  /* for WORDSIZE > 32 machines */
                i++; j++;
                if (i >= N)
                {
                    mt[0] = mt[N - 1];
                    i     = 1;
                }
                if (j >= seeds.Count)
                {
                    j = 0;
                }
            }
            for (k = N - 1; k != 0; k--)
            {
                mt[i]  = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1566083941UL)) - (ulong)i; /* non linear */
                mt[i] &= 0xffffffffUL;                                                          /* for WORDSIZE > 32 machines */
                i++;
                if (i >= N)
                {
                    mt[0] = mt[N - 1];
                    i     = 1;
                }
            }

            mt[0] = 0x80000000UL; /*MSB is 1; assuring non-zero initial array*/
        }
Beispiel #2
0
        public InterpolatedSmileSection(Date d,
                                        List <double> strikes,
                                        List <Handle <Quote> > stdDevHandles,
                                        Handle <Quote> atmLevel,
                                        DayCounter dc             = null, //Actual365Fixed(),
                                        Interpolator interpolator = default(Interpolator),
                                        Date referenceDate        = null,
                                        double shift = 0.0)
            : base(d, dc, referenceDate, VolatilityType.ShiftedLognormal, shift)
        {
            exerciseTimeSquareRoot_ = Math.Sqrt(exerciseTime());
            strikes_       = strikes;
            stdDevHandles_ = stdDevHandles;
            atmLevel_      = atmLevel;
            vols_          = new InitializedList <double>(stdDevHandles.Count);

            for (int i = 0; i < stdDevHandles_.Count; ++i)
            {
                stdDevHandles_[i].registerWith(update);
            }
            atmLevel_.registerWith(update);
            // check strikes!!!!!!!!!!!!!!!!!!!!
            interpolation_ = interpolator.interpolate(strikes_, strikes_.Count, vols_);
        }
Beispiel #3
0
        //! fixed reference date, fixed market data
        public CapFloorTermVolCurve(Date settlementDate,
                                    Calendar calendar,
                                    BusinessDayConvention bdc,
                                    List <Period> optionTenors,
                                    List <double> vols,
                                    DayCounter dc = null) // Actual365Fixed()
            : base(settlementDate, calendar, bdc, dc ?? new Actual365Fixed())
        {
            nOptionTenors_ = optionTenors.Count;
            optionTenors_  = optionTenors;
            optionDates_   = new InitializedList <Date>(nOptionTenors_);
            optionTimes_   = new InitializedList <double>(nOptionTenors_);
            volHandles_    = new InitializedList <Handle <Quote> >(vols.Count);
            vols_          = vols; // do not initialize with nOptionTenors_

            checkInputs();
            initializeOptionDatesAndTimes();
            // fill dummy handles to allow generic handle-based computations later
            for (int i = 0; i < nOptionTenors_; ++i)
            {
                volHandles_[i] = new Handle <Quote>(new SimpleQuote(vols_[i]));
            }
            interpolate();
        }
        public InterpolatedSmileSection(Date d,
                                        List <double> strikes,
                                        List <double> stdDevs,
                                        double atmLevel,
                                        DayCounter dc             = null, // Actual365Fixed(),
                                        Interpolator interpolator = default(Interpolator),
                                        Date referenceDate        = null,
                                        double shift = 0.0)
            : base(d, dc ?? new Actual365Fixed(), referenceDate, VolatilityType.ShiftedLognormal, shift)
        {
            strikes_       = strikes;
            stdDevHandles_ = new InitializedList <Handle <Quote> >(stdDevs.Count);
            vols_          = new InitializedList <double>(stdDevs.Count);

            //fill dummy handles to allow generic handle-based
            // computations later on
            for (int i = 0; i < stdDevs.Count; ++i)
            {
                stdDevHandles_[i] = new Handle <Quote>(new SimpleQuote(stdDevs[i]));
            }
            atmLevel_ = new Handle <Quote>(new SimpleQuote(atmLevel));
            // check strikes!!!!!!!!!!!!!!!!!!!!
            interpolation_ = interpolator.interpolate(strikes_, strikes_.Count, vols_);
        }
Beispiel #5
0
        public InterpolatedSmileSection(double timeToExpiry,
                                        List <double> strikes,
                                        List <double> stdDevs,
                                        double atmLevel,
                                        Interpolator interpolator = default(Interpolator),
                                        DayCounter dc             = null, //Actual365Fixed(),
                                        double shift = 0.0)
            : base(timeToExpiry, dc, VolatilityType.ShiftedLognormal, shift)
        {
            exerciseTimeSquareRoot_ = Math.Sqrt(exerciseTime());
            strikes_       = strikes;
            stdDevHandles_ = new InitializedList <Handle <Quote> >(stdDevs.Count);
            vols_          = new InitializedList <double>(stdDevs.Count);

            // fill dummy handles to allow generic handle-based
            // computations later on
            for (int i = 0; i < stdDevs.Count; ++i)
            {
                stdDevHandles_[i] = new Handle <Quote>(new SimpleQuote(stdDevs[i]));
            }
            atmLevel_ = new Handle <Quote>(new SimpleQuote(atmLevel));
            // check strikes!!!!!!!!!!!!!!!!!!!!
            interpolation_ = interpolator.interpolate(strikes_, strikes_.Count, vols_);
        }
Beispiel #6
0
        // Multi leg constructor.
        public Swap(List <List <CashFlow> > legs, List <bool> payer)
        {
            legs_            = (InitializedList <List <CashFlow> >)legs;
            payer_           = new InitializedList <double>(legs.Count, 1.0);
            legNPV_          = new InitializedList <double?>(legs.Count, 0.0);
            legBPS_          = new InitializedList <double?>(legs.Count, 0.0);
            startDiscounts_  = new InitializedList <double?>(legs.Count, 0.0);
            endDiscounts_    = new InitializedList <double?>(legs.Count, 0.0);
            npvDateDiscount_ = 0.0;

            Utils.QL_REQUIRE(payer.Count == legs_.Count, () => "size mismatch between payer (" + payer.Count +
                             ") and legs (" + legs_.Count + ")");
            for (int i = 0; i < legs_.Count; ++i)
            {
                if (payer[i])
                {
                    payer_[i] = -1;
                }
                for (int j = 0; j < legs_[i].Count; j++)
                {
                    legs_[i][j].registerWith(update);
                }
            }
        }
Beispiel #7
0
            public Fj_Helper(Handle <PiecewiseTimeDependentHestonModel> model, double term, double strike, int j)
            {
                j_        = j;
                term_     = term;
                v0_       = model.link.v0();
                x_        = Math.Log(model.link.s0());
                sx_       = Math.Log(strike);
                r_        = new InitializedList <double>(model.link.timeGrid().size() - 1);
                q_        = new InitializedList <double>(model.link.timeGrid().size() - 1);
                model_    = model;
                timeGrid_ = model.link.timeGrid();

                for (int i = 0; i < timeGrid_.size() - 1; ++i)
                {
                    double begin = Math.Min(term_, timeGrid_[i]);
                    double end   = Math.Min(term_, timeGrid_[i + 1]);
                    r_[i] = model.link.riskFreeRate().link.forwardRate(begin, end,
                                                                       Compounding.Continuous, Frequency.NoFrequency).rate();
                    q_[i] = model.link.dividendYield().link.forwardRate(begin, end,
                                                                        Compounding.Continuous, Frequency.NoFrequency).rate();
                }

                Utils.QL_REQUIRE(term_ < model_.link.timeGrid().Last(), () => "maturity is too large");
            }
Beispiel #8
0
        public override void fetchResults(IPricingEngineResults r)
        {
            base.fetchResults(r);

            Swap.Results results = r as Swap.Results;
            if (results == null)
            {
                throw new ArgumentException("wrong result type");
            }

            if (results.legNPV.Count != 0)
            {
                if (results.legNPV.Count != legNPV_.Count)
                {
                    throw new ArgumentException("wrong number of leg NPV returned");
                }
                legNPV_ = results.legNPV;
            }
            else
            {
                legNPV_ = new InitializedList <double?>(legNPV_.Count);
            }

            if (results.legBPS.Count != 0)
            {
                if (results.legBPS.Count != legBPS_.Count)
                {
                    throw new ArgumentException("wrong number of leg BPS returned");
                }
                legBPS_ = results.legBPS;
            }
            else
            {
                legBPS_ = new InitializedList <double?>(legBPS_.Count);
            }
        }
        public override void calculate()
        {
            double        value      = 0.0;
            double        vega       = 0.0;
            int           optionlets = arguments_.startDates.Count;
            List <double> values     = new InitializedList <double>(optionlets);
            List <double> vegas      = new InitializedList <double>(optionlets);
            List <double> stdDevs    = new InitializedList <double>(optionlets);
            CapFloorType  type       = arguments_.type;
            Date          today      = vol_.link.referenceDate();
            Date          settlement = discountCurve_.link.referenceDate();

            for (int i = 0; i < optionlets; ++i)
            {
                Date paymentDate = arguments_.endDates[i];
                if (paymentDate > settlement)
                {
                    // discard expired caplets
                    double d = arguments_.nominals[i] *
                               arguments_.gearings[i] *
                               discountCurve_.link.discount(paymentDate) *
                               arguments_.accrualTimes[i];

                    double?forward = arguments_.forwards[i];

                    Date   fixingDate = arguments_.fixingDates[i];
                    double sqrtTime   = 0.0;
                    if (fixingDate > today)
                    {
                        sqrtTime = Math.Sqrt(vol_.link.timeFromReference(fixingDate));
                    }

                    if (type == CapFloorType.Cap || type == CapFloorType.Collar)
                    {
                        double?strike = arguments_.capRates[i];
                        if (sqrtTime > 0.0)
                        {
                            stdDevs[i] = Math.Sqrt(vol_.link.blackVariance(fixingDate, strike.Value));
                            vegas[i]   = Utils.blackFormulaStdDevDerivative(strike.Value, forward.Value, stdDevs[i], d, displacement_) * sqrtTime;
                        }
                        // include caplets with past fixing date
                        values[i] = Utils.blackFormula(Option.Type.Call, strike.Value,
                                                       forward.Value, stdDevs[i], d, displacement_);
                    }
                    if (type == CapFloorType.Floor || type == CapFloorType.Collar)
                    {
                        double?strike       = arguments_.floorRates[i];
                        double floorletVega = 0.0;

                        if (sqrtTime > 0.0)
                        {
                            stdDevs[i]   = Math.Sqrt(vol_.link.blackVariance(fixingDate, strike.Value));
                            floorletVega = Utils.blackFormulaStdDevDerivative(strike.Value, forward.Value, stdDevs[i], d, displacement_) * sqrtTime;
                        }
                        double floorlet = Utils.blackFormula(Option.Type.Put, strike.Value,
                                                             forward.Value, stdDevs[i], d, displacement_);
                        if (type == CapFloorType.Floor)
                        {
                            values[i] = floorlet;
                            vegas[i]  = floorletVega;
                        }
                        else
                        {
                            // a collar is long a cap and short a floor
                            values[i] -= floorlet;
                            vegas[i]  -= floorletVega;
                        }
                    }
                    value += values[i];
                    vega  += vegas[i];
                }
            }
            results_.value = value;
            results_.additionalResults["vega"] = vega;

            results_.additionalResults["optionletsPrice"]      = values;
            results_.additionalResults["optionletsVega"]       = vegas;
            results_.additionalResults["optionletsAtmForward"] = arguments_.forwards;
            if (type != CapFloorType.Collar)
            {
                results_.additionalResults["optionletsStdDev"] = stdDevs;
            }
        }
Beispiel #10
0
        public SobolRsg(int dimensionality, ulong seed, DirectionIntegers directionIntegers)
        {
            dimensionality_  = dimensionality;
            sequenceCounter_ = 0;
            firstDraw_       = true;

            sequence_        = new Sample <List <double> >(new InitializedList <double>(dimensionality), 1.0);
            integerSequence_ = new InitializedList <ulong>(dimensionality);

            directionIntegers_ = new InitializedList <List <ulong> >(dimensionality);
            for (int i = 0; i < dimensionality; i++)
            {
                directionIntegers_[i] = new InitializedList <ulong>(bits_);
            }

            if (!(dimensionality > 0))
            {
                throw new Exception("dimensionality must be greater than 0");
            }
            if (!(dimensionality <= PPMT_MAX_DIM))
            {
                throw new Exception("dimensionality " + dimensionality + " exceeds the number of available "
                                    + "primitive polynomials modulo two (" + PPMT_MAX_DIM + ")");
            }

            // initializes coefficient array of the k-th primitive polynomial
            // and degree of the k-th primitive polynomial
            List <uint> degree = new InitializedList <uint>(dimensionality_);
            List <long> ppmt   = new InitializedList <long>(dimensionality_);

            bool useAltPolynomials = false;

            if (directionIntegers == DirectionIntegers.Kuo || directionIntegers == DirectionIntegers.Kuo2 ||
                directionIntegers == DirectionIntegers.Kuo3 || directionIntegers == DirectionIntegers.SobolLevitan ||
                directionIntegers == DirectionIntegers.SobolLevitanLemieux)
            {
                useAltPolynomials = true;
            }

            // degree 0 is not used
            ppmt[0]   = 0;
            degree[0] = 0;
            int  k, index;
            uint currentDegree = 1;

            k     = 1;
            index = 0;

            uint altDegree = useAltPolynomials ? maxAltDegree : 0;

            for ( ; k < Math.Min(dimensionality_, altDegree); k++, index++)
            {
                ppmt[k] = AltPrimitivePolynomials[currentDegree - 1][index];
                if (ppmt[k] == -1)
                {
                    ++currentDegree;
                    index   = 0;
                    ppmt[k] = AltPrimitivePolynomials[currentDegree - 1][index];
                }

                degree[k] = currentDegree;
            }

            for ( ; k < dimensionality_; k++, index++)
            {
                ppmt[k] = PrimitivePolynomials[currentDegree - 1][index];
                if (ppmt[k] == -1)
                {
                    ++currentDegree;
                    index   = 0;
                    ppmt[k] = PrimitivePolynomials[currentDegree - 1][index];
                }
                degree[k] = currentDegree;
            }

            // initializes bits_ direction integers for each dimension
            // and store them into directionIntegers_[dimensionality_][bits_]
            //
            // In each dimension k with its associated primitive polynomial,
            // the first degree_[k] direction integers can be chosen freely
            // provided that only the l leftmost bits can be non-zero, and
            // that the l-th leftmost bit must be set

            // degenerate (no free direction integers) first dimension
            int j;

            for (j = 0; j < bits_; j++)
            {
                directionIntegers_[0][j] = (1UL << (bits_ - j - 1));
            }

            int maxTabulated = 0;

            // dimensions from 2 (k=1) to maxTabulated (k=maxTabulated-1) included
            // are initialized from tabulated coefficients
            switch (directionIntegers)
            {
            case DirectionIntegers.Unit:
                maxTabulated = dimensionality_;
                for (k = 1; k < maxTabulated; k++)
                {
                    for (int l = 1; l <= degree[k]; l++)
                    {
                        directionIntegers_[k][l - 1]   = 1UL;
                        directionIntegers_[k][l - 1] <<= (bits_ - l);
                    }
                }
                break;

            case DirectionIntegers.Jaeckel:
                // maxTabulated=32
                maxTabulated = initializers.Length + 1;
                for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++)
                {
                    j = 0;
                    // 0UL marks coefficients' end for a given dimension
                    while (initializers[k - 1][j] != 0UL)
                    {
                        directionIntegers_[k][j]   = initializers[k - 1][j];
                        directionIntegers_[k][j] <<= (bits_ - j - 1);
                        j++;
                    }
                }
                break;

            case DirectionIntegers.SobolLevitan:
                // maxTabulated=40
                maxTabulated = SLinitializers.Length + 1;
                for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++)
                {
                    j = 0;
                    // 0UL marks coefficients' end for a given dimension
                    while (SLinitializers[k - 1][j] != 0UL)
                    {
                        directionIntegers_[k][j]   = SLinitializers[k - 1][j];
                        directionIntegers_[k][j] <<= (bits_ - j - 1);
                        j++;
                    }
                }
                break;

            case DirectionIntegers.SobolLevitanLemieux:
                // maxTabulated=360
                maxTabulated = Linitializers.Length + 1;
                for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++)
                {
                    j = 0;
                    // 0UL marks coefficients' end for a given dimension
                    while (Linitializers[k - 1][j] != 0UL)
                    {
                        directionIntegers_[k][j]   = Linitializers[k - 1][j];
                        directionIntegers_[k][j] <<= (bits_ - j - 1);
                        j++;
                    }
                }
                break;

            case DirectionIntegers.JoeKuoD5:
                // maxTabulated=1898
                maxTabulated = JoeKuoD5initializers.Length + 1;
                for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++)
                {
                    j = 0;
                    // 0UL marks coefficients' end for a given dimension
                    while (JoeKuoD5initializers[k - 1][j] != 0UL)
                    {
                        directionIntegers_[k][j]   = JoeKuoD5initializers[k - 1][j];
                        directionIntegers_[k][j] <<= (bits_ - j - 1);
                        j++;
                    }
                }
                break;

            case DirectionIntegers.JoeKuoD6:
                // maxTabulated=1799
                maxTabulated = JoeKuoD6initializers.Length + 1;
                for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++)
                {
                    j = 0;
                    // 0UL marks coefficients' end for a given dimension
                    while (JoeKuoD6initializers[k - 1][j] != 0UL)
                    {
                        directionIntegers_[k][j]   = JoeKuoD6initializers[k - 1][j];
                        directionIntegers_[k][j] <<= (bits_ - j - 1);
                        j++;
                    }
                }
                break;

            case DirectionIntegers.JoeKuoD7:
                // maxTabulated=1898
                maxTabulated = JoeKuoD7initializers.Length + 1;
                for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++)
                {
                    j = 0;
                    // 0UL marks coefficients' end for a given dimension
                    while (JoeKuoD7initializers[k - 1][j] != 0UL)
                    {
                        directionIntegers_[k][j]   = JoeKuoD7initializers[k - 1][j];
                        directionIntegers_[k][j] <<= (bits_ - j - 1);
                        j++;
                    }
                }
                break;



            case DirectionIntegers.Kuo:
                // maxTabulated=4925
                maxTabulated = Kuoinitializers.Length + 1;
                for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++)
                {
                    j = 0;
                    // 0UL marks coefficients' end for a given dimension
                    while (Kuoinitializers[k - 1][j] != 0UL)
                    {
                        directionIntegers_[k][j]   = Kuoinitializers[k - 1][j];
                        directionIntegers_[k][j] <<= (bits_ - j - 1);
                        j++;
                    }
                }
                break;

            case DirectionIntegers.Kuo2:
                // maxTabulated=3946
                maxTabulated = Kuo2initializers.Length + 1;
                for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++)
                {
                    j = 0;
                    // 0UL marks coefficients' end for a given dimension
                    while (Kuo2initializers[k - 1][j] != 0UL)
                    {
                        directionIntegers_[k][j]   = Kuo2initializers[k - 1][j];
                        directionIntegers_[k][j] <<= (bits_ - j - 1);
                        j++;
                    }
                }
                break;

            case DirectionIntegers.Kuo3:
                // maxTabulated=4585
                maxTabulated = Kuo3initializers.Length + 1;
                for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++)
                {
                    j = 0;
                    // 0UL marks coefficients' end for a given dimension
                    while (Kuo3initializers[k - 1][j] != 0UL)
                    {
                        directionIntegers_[k][j]   = Kuo3initializers[k - 1][j];
                        directionIntegers_[k][j] <<= (bits_ - j - 1);
                        j++;
                    }
                }
                break;

            default:
                break;
            }

            // random initialization for higher dimensions
            if (dimensionality_ > maxTabulated)
            {
                MersenneTwisterUniformRng uniformRng = new MersenneTwisterUniformRng(seed);
                for (k = maxTabulated; k < dimensionality_; k++)
                {
                    for (int l = 1; l <= degree[k]; l++)
                    {
                        do
                        {
                            // u is in (0,1)
                            double u = uniformRng.next().value;
                            // the direction integer has at most the
                            // rightmost l bits non-zero
                            directionIntegers_[k][l - 1] = (ulong)(u * (1UL << l));
                        } while (!((directionIntegers_[k][l - 1] & 1UL) != 0));
                        // iterate until the direction integer is odd
                        // that is it has the rightmost bit set

                        // shifting bits_-l bits to the left
                        // we are guaranteed that the l-th leftmost bit
                        // is set, and only the first l leftmost bit
                        // can be non-zero
                        directionIntegers_[k][l - 1] <<= (bits_ - l);
                    }
                }
            }

            // computation of directionIntegers_[k][l] for l>=degree_[k]
            // by recurrence relation
            for (k = 1; k < dimensionality_; k++)
            {
                uint gk = degree[k];
                for (int l = (int)gk; l < bits_; l++)
                {
                    // eq. 8.19 "Monte Carlo Methods in Finance" by P. Jдckel
                    ulong n = (directionIntegers_[k][(int)(l - gk)] >> (int)gk);
                    // a[k][j] are the coefficients of the monomials in ppmt[k]
                    // The highest order coefficient a[k][0] is not actually
                    // used in the recurrence relation, and the lowest order
                    // coefficient a[k][gk] is always set: this is the reason
                    // why the highest and lowest coefficient of
                    // the polynomial ppmt[k] are not included in its encoding,
                    // provided that its degree is known.
                    // That is: a[k][j] = ppmt[k] >> (gk-j-1)
                    for (uint z = 1; z < gk; z++)
                    {
                        // XORed with a selection of (unshifted) direction
                        // integers controlled by which of the a[k][j] are set
                        if ((((ulong)ppmt[k] >> (int)(gk - z - 1)) & 1UL) != 0)
                        {
                            n ^= directionIntegers_[k][(int)(l - z)];
                        }
                    }
                    // a[k][gk] is always set, so directionIntegers_[k][l-gk]
                    // will always enter
                    n ^= directionIntegers_[k][(int)(l - gk)];
                    directionIntegers_[k][l] = n;
                }
            }

            // in case one needs to check the directionIntegers used

            /* bool printDirectionIntegers = false;
             * if (printDirectionIntegers) {
             *     std::ofstream outStream("directionIntegers.txt");
             *     for (k=0; k<std::min(32UL,dimensionality_); k++) {
             *         outStream << std::endl << k+1       << "\t"
             *                                << degree[k] << "\t"
             *                                << ppmt[k]   << "\t";
             *         for (j=0; j<10; j++) {
             *             outStream << io::power_of_two(
             *                 directionIntegers_[k][j]) << "\t";
             *         }
             *     }
             *     outStream.close();
             * }
             */

            // initialize the Sobol integer/double vectors
            // first draw
            for (k = 0; k < dimensionality_; k++)
            {
                integerSequence_[k] = directionIntegers_[k][0];
            }
        }
Beispiel #11
0
 public MersenneTwisterUniformRng(ulong seed)
 {
     mt = new InitializedList <ulong>(N);
     seedInitialization(seed);
 }
Beispiel #12
0
        public Concentrating1dMesher(double start, double end, int size,
                                     List <Tuple <double?, double?, bool> > cPoints,
                                     double tol = 1e-8)
            : base(size)
        {
            Utils.QL_REQUIRE(end > start, () => "end must be larger than start");

            List <double?> points = new List <double?>(), betas = new List <double?>();

            foreach (Tuple <double?, double?, bool> iter in cPoints)
            {
                points.Add(iter.Item1);
                betas.Add((iter.Item2 * (end - start)) * (iter.Item2 * (end - start)));
            }

            // get scaling factor a so that y(1) = end
            double aInit = 0.0;

            for (int i = 0; i < points.Count; ++i)
            {
                double c1 = Utils.Asinh((start - points[i].GetValueOrDefault()) / betas[i].GetValueOrDefault());
                double c2 = Utils.Asinh((end - points[i].GetValueOrDefault()) / betas[i].GetValueOrDefault());
                aInit += (c2 - c1) / points.Count;
            }

            OdeIntegrationFct fct = new OdeIntegrationFct(points, betas, tol);
            double            a   = new Brent().solve(
                new OdeSolver(fct, start, 0.0, 1.0, end),
                tol, aInit, 0.1 * aInit);

            // solve ODE for all grid points
            Vector x = new Vector(size), y = new Vector(size);

            x[0] = 0.0;
            y[0] = start;
            double dx = 1.0 / (size - 1);

            for (int i = 1; i < size; ++i)
            {
                x[i] = i * dx;
                y[i] = fct.solve(a, y[i - 1], x[i - 1], x[i]);
            }

            // eliminate numerical noise and ensure y(1) = end
            double dy = y[y.Count - 1] - end;

            for (int i = 1; i < size; ++i)
            {
                y[i] -= i * dx * dy;
            }

            LinearInterpolation odeSolution = new LinearInterpolation(x, x.Count, y);

            // ensure required points are part of the grid
            List <Pair <double?, double?> > w =
                new InitializedList <Pair <double?, double?> >(1, new Pair <double?, double?>(0.0, 0.0));

            for (int i = 0; i < points.Count; ++i)
            {
                if (cPoints[i].Item3 && points[i] > start && points[i] < end)
                {
                    int j = y.distance(y[0], y.BinarySearch(points[i].Value));

                    double e = new Brent().solve(
                        new OdeSolver2(odeSolution.value, points[i].Value),
                        Const.QL_EPSILON, x[j], 0.5 / size);

                    w.Add(new Pair <double?, double?>(Math.Min(x[size - 2], x[j]), e));
                }
            }
            w.Add(new Pair <double?, double?>(1.0, 1.0));
            w = w.OrderBy(xx => xx.first).Distinct(new equal_on_first()).ToList();

            List <double> u = new List <double>(w.Count), z = new List <double>(w.Count);

            for (int i = 0; i < w.Count; ++i)
            {
                u[i] = w[i].first.GetValueOrDefault();
                z[i] = w[i].second.GetValueOrDefault();
            }
            LinearInterpolation transform = new LinearInterpolation(u, u.Count, z);

            for (int i = 0; i < size; ++i)
            {
                locations_[i] = odeSolution.value(transform.value(i * dx));
            }

            for (int i = 0; i < size - 1; ++i)
            {
                dplus_[i] = dminus_[i + 1] = locations_[i + 1] - locations_[i];
            }
            dplus_[dplus_.Count] = null;
            dminus_[0]           = null;
        }
        public override void calculate()
        {
            Utils.QL_REQUIRE(arguments_.settlementType == Settlement.Type.Physical, () =>
                             "cash-settled swaptions not priced by Jamshidian engine");

            Utils.QL_REQUIRE(arguments_.exercise.type() == Exercise.Type.European, () =>
                             "cannot use the Jamshidian decomposition on exotic swaptions");

            Utils.QL_REQUIRE(arguments_.swap.spread.IsEqual(0.0), () =>
                             "non zero spread (" + arguments_.swap.spread + ") not allowed");

            Date       referenceDate;
            DayCounter dayCounter;

            ITermStructureConsistentModel tsmodel = (ITermStructureConsistentModel)base.model_.link;

            try
            {
                if (tsmodel != null)
                {
                    referenceDate = tsmodel.termStructure().link.referenceDate();
                    dayCounter    = tsmodel.termStructure().link.dayCounter();
                }
                else
                {
                    referenceDate = termStructure_.link.referenceDate();
                    dayCounter    = termStructure_.link.dayCounter();
                }
            }
            catch
            {
                referenceDate = termStructure_.link.referenceDate();
                dayCounter    = termStructure_.link.dayCounter();
            }

            List <double> amounts = new InitializedList <double>(arguments_.fixedCoupons.Count);

            for (int i = 0; i < amounts.Count; i++)
            {
                amounts[i] = arguments_.fixedCoupons[i];
            }
            amounts[amounts.Count - 1] = amounts.Last() + arguments_.nominal;

            double maturity = dayCounter.yearFraction(referenceDate,
                                                      arguments_.exercise.date(0));

            List <double> fixedPayTimes = new InitializedList <double>(arguments_.fixedPayDates.Count);

            for (int i = 0; i < fixedPayTimes.Count; i++)
            {
                fixedPayTimes[i] =
                    dayCounter.yearFraction(referenceDate,
                                            arguments_.fixedPayDates[i]);
            }

            rStarFinder finder = new rStarFinder(model_, arguments_.nominal, maturity,
                                                 fixedPayTimes, amounts);
            Brent  s1d       = new Brent();
            double minStrike = -10.0;
            double maxStrike = 10.0;

            s1d.setMaxEvaluations(10000);
            s1d.setLowerBound(minStrike);
            s1d.setUpperBound(maxStrike);
            double rStar = s1d.solve(finder, 1e-8, 0.05, minStrike, maxStrike);

            Option.Type w = arguments_.type == VanillaSwap.Type.Payer ?
                            Option.Type.Put : Option.Type.Call;
            int size = arguments_.fixedCoupons.Count;

            double value = 0.0;

            for (int i = 0; i < size; i++)
            {
                double fixedPayTime =
                    dayCounter.yearFraction(referenceDate,
                                            arguments_.fixedPayDates[i]);
                double strike = model_.link.discountBond(maturity,
                                                         fixedPayTime,
                                                         rStar);
                double dboValue = model_.link.discountBondOption(
                    w, strike, maturity,
                    fixedPayTime);
                value += amounts[i] * dboValue;
            }
            results_.value = value;
        }
Beispiel #14
0
        public void recalibration(double beta, Period swapTenor)
        {
            List <double> betaVector = new InitializedList <double>(nOptionTenors_, beta);

            recalibration(betaVector, swapTenor);
        }
        public override void update()
        {
            sectionHelpers_.Clear();
            if (size_ == 2)   //single period
            {
                ISectionHelper singleHelper = new EverywhereConstantHelper(yBegin_[1], 0.0, xBegin_[0]);
                sectionHelpers_.Add(xBegin_[1], singleHelper);
                extrapolationHelper_ = singleHelper;
                return;
            }

            List <double> f = new InitializedList <double>(size_);

            sectionHelpers_ = new Dictionary <double, ISectionHelper>(preSectionHelpers_);
            int startPoint = sectionHelpers_.Count + 1;

            //first derive the boundary forwards.
            for (int i = startPoint; i < size_ - 1; ++i)
            {
                double dxPrev = xBegin_[i] - xBegin_[i - 1];
                double dx     = xBegin_[i + 1] - xBegin_[i];
                f[i] = dxPrev / (dx + dxPrev) * yBegin_[i]
                       + dx / (dx + dxPrev) * yBegin_[i + 1];
            }

            if (startPoint > 1)
            {
                f[startPoint - 1] = preSectionHelpers_.Last().Value.fNext();
            }
            if (startPoint == 1)
            {
                f[0] = 1.5 * yBegin_[1] - 0.5 * f[1];
            }

            f[size_ - 1] = 1.5 * yBegin_[size_ - 1] - 0.5 * f[size_ - 2];

            if (forcePositive_)
            {
                if (f[0] < 0)
                {
                    f[0] = 0.0;
                }
                if (f[size_ - 1] < 0.0)
                {
                    f[size_ - 1] = 0.0;
                }
            }

            double primitive = 0.0;

            for (int i = 0; i < startPoint - 1; ++i)
            {
                primitive += yBegin_[i + 1] * (xBegin_[i + 1] - xBegin_[i]);
            }

            int endPoint = size_;

            //constantLastPeriod_ = false;
            if (constantLastPeriod_)
            {
                endPoint = endPoint - 1;
            }

            for (int i = startPoint; i < endPoint; ++i)
            {
                double gPrev = f[i - 1] - yBegin_[i];
                double gNext = f[i] - yBegin_[i];
                //first deal with the zero gradient case
                if (Math.Abs(gPrev) < 1.0E-14 && Math.Abs(gNext) < 1.0E-14)
                {
                    ISectionHelper singleHelper = new ConstantGradHelper(f[i - 1], primitive,
                                                                         xBegin_[i - 1],
                                                                         xBegin_[i],
                                                                         f[i]);
                    sectionHelpers_.Add(xBegin_[i], singleHelper);
                }
                else
                {
                    double         quadraticity       = quadraticity_;
                    ISectionHelper quadraticHelper    = null;
                    ISectionHelper convMonotoneHelper = null;
                    if (quadraticity_ > 0.0)
                    {
                        if (gPrev >= -2.0 * gNext && gPrev > -0.5 * gNext && forcePositive_)
                        {
                            quadraticHelper = new QuadraticMinHelper(xBegin_[i - 1],
                                                                     xBegin_[i],
                                                                     f[i - 1], f[i],
                                                                     yBegin_[i],
                                                                     primitive);
                        }
                        else
                        {
                            quadraticHelper = new QuadraticHelper(xBegin_[i - 1],
                                                                  xBegin_[i],
                                                                  f[i - 1], f[i],
                                                                  yBegin_[i],
                                                                  primitive);
                        }
                    }
                    if (quadraticity_ < 1.0)
                    {
                        if ((gPrev > 0.0 && -0.5 * gPrev >= gNext && gNext >= -2.0 * gPrev) ||
                            (gPrev < 0.0 && -0.5 * gPrev <= gNext && gNext <= -2.0 * gPrev))
                        {
                            quadraticity = 1.0;
                            if (quadraticity_ == 0)
                            {
                                if (forcePositive_)
                                {
                                    quadraticHelper = new QuadraticMinHelper(
                                        xBegin_[i - 1],
                                        xBegin_[i],
                                        f[i - 1], f[i],
                                        yBegin_[i],
                                        primitive);
                                }
                                else
                                {
                                    quadraticHelper = new QuadraticHelper(
                                        xBegin_[i - 1],
                                        xBegin_[i],
                                        f[i - 1], f[i],
                                        yBegin_[i],
                                        primitive);
                                }
                            }
                        }
                        else if ((gPrev < 0.0 && gNext > -2.0 * gPrev) ||
                                 (gPrev > 0.0 && gNext < -2.0 * gPrev))
                        {
                            double eta = (gNext + 2.0 * gPrev) / (gNext - gPrev);
                            double b2  = (1.0 + monotonicity_) / 2.0;
                            if (eta < b2)
                            {
                                convMonotoneHelper = new ConvexMonotone2Helper(
                                    xBegin_[i - 1],
                                    xBegin_[i],
                                    gPrev, gNext,
                                    yBegin_[i],
                                    eta, primitive);
                            }
                            else
                            {
                                if (forcePositive_)
                                {
                                    convMonotoneHelper = new ConvexMonotone4MinHelper(
                                        xBegin_[i - 1],
                                        xBegin_[i],
                                        gPrev, gNext,
                                        yBegin_[i],
                                        b2, primitive);
                                }
                                else
                                {
                                    convMonotoneHelper = new ConvexMonotone4Helper(
                                        xBegin_[i - 1],
                                        xBegin_[i],
                                        gPrev, gNext,
                                        yBegin_[i],
                                        b2, primitive);
                                }
                            }
                        }
                        else if ((gPrev > 0.0 && gNext < 0.0 && gNext > -0.5 * gPrev) ||
                                 (gPrev < 0.0 && gNext > 0.0 && gNext < -0.5 * gPrev))
                        {
                            double eta = gNext / (gNext - gPrev) * 3.0;
                            double b3  = (1.0 - monotonicity_) / 2.0;
                            if (eta > b3)
                            {
                                convMonotoneHelper = new ConvexMonotone3Helper(
                                    xBegin_[i - 1],
                                    xBegin_[i],
                                    gPrev, gNext,
                                    yBegin_[i],
                                    eta, primitive);
                            }
                            else
                            {
                                if (forcePositive_)
                                {
                                    convMonotoneHelper = new ConvexMonotone4MinHelper(
                                        xBegin_[i - 1],
                                        xBegin_[i],
                                        gPrev, gNext,
                                        yBegin_[i],
                                        b3, primitive);
                                }
                                else
                                {
                                    convMonotoneHelper = new ConvexMonotone4Helper(
                                        xBegin_[i - 1],
                                        xBegin_[i],
                                        gPrev, gNext,
                                        yBegin_[i],
                                        b3, primitive);
                                }
                            }
                        }
                        else
                        {
                            double eta = gNext / (gPrev + gNext);
                            double b2  = (1.0 + monotonicity_) / 2.0;
                            double b3  = (1.0 - monotonicity_) / 2.0;
                            if (eta > b2)
                            {
                                eta = b2;
                            }
                            if (eta < b3)
                            {
                                eta = b3;
                            }
                            if (forcePositive_)
                            {
                                convMonotoneHelper = new ConvexMonotone4MinHelper(
                                    xBegin_[i - 1],
                                    xBegin_[i],
                                    gPrev, gNext,
                                    yBegin_[i],
                                    eta, primitive);
                            }
                            else
                            {
                                convMonotoneHelper = new ConvexMonotone4Helper(
                                    xBegin_[i - 1],
                                    xBegin_[i],
                                    gPrev, gNext,
                                    yBegin_[i],
                                    eta, primitive);
                            }
                        }
                    }

                    if (quadraticity == 1.0)
                    {
                        sectionHelpers_.Add(xBegin_[i], quadraticHelper);
                    }
                    else if (quadraticity == 0.0)
                    {
                        sectionHelpers_.Add(xBegin_[i], convMonotoneHelper);
                    }
                    else
                    {
                        sectionHelpers_.Add(xBegin_[i], new ComboHelper(quadraticHelper, convMonotoneHelper, quadraticity));
                    }
                }
                primitive += yBegin_[i] * (xBegin_[i] - xBegin_[i - 1]);
            }

            if (constantLastPeriod_)
            {
                sectionHelpers_.Add(xBegin_[size_ - 1], new EverywhereConstantHelper(yBegin_[size_ - 1], primitive, xBegin_[size_ - 2]));
                extrapolationHelper_ = sectionHelpers_[xBegin_[size_ - 1]];
            }
            else
            {
                extrapolationHelper_ = new EverywhereConstantHelper((sectionHelpers_.Last()).Value.value(xBegin_.Last()),
                                                                    primitive, xBegin_.Last());
            }
        }
Beispiel #16
0
 public FdmLinearOpIterator(List <int> dim)
 {
     index_       = 0;
     dim_         = dim;
     coordinates_ = new InitializedList <int>(dim.Count, 0);
 }
Beispiel #17
0
        public override EndCriteria.Type minimize(Problem P, EndCriteria endCriteria)
        {
            // set up of the problem
            //double ftol = endCriteria.functionEpsilon();    // end criteria on f(x) (see Numerical Recipes in C++, p.410)
            double xtol = endCriteria.rootEpsilon(); // end criteria on x (see GSL v. 1.9, http://www.gnu.org/software/gsl/)
            int    maxStationaryStateIterations_ = endCriteria.maxStationaryStateIterations();

            EndCriteria.Type ecType = EndCriteria.Type.None;
            P.reset();
            Vector x_ = P.currentValue();
            int    iterationNumber_ = 0;

            // Initialize vertices of the simplex
            bool end = false;
            int  n   = x_.Count;

            vertices_ = new InitializedList <Vector>(n + 1, x_);
            for (int i = 0; i < n; i++)
            {
                Vector direction = new Vector(n, 0.0);
                Vector vertice   = vertices_[i + 1];
                direction[i] = 1.0;
                P.constraint().update(ref vertice, direction, lambda_);
                vertices_[i + 1] = vertice;
            }
            // Initialize function values at the vertices of the simplex
            values_ = new Vector(n + 1, 0.0);
            for (int i = 0; i <= n; i++)
            {
                values_[i] = P.value(vertices_[i]);
            }
            // Loop looking for minimum
            do
            {
                sum_ = new Vector(n, 0.0);
                for (int i = 0; i <= n; i++)
                {
                    sum_ += vertices_[i];
                }
                // Determine the best (iLowest), worst (iHighest)
                // and 2nd worst (iNextHighest) vertices
                int iLowest = 0;
                int iHighest;
                int iNextHighest;
                if (values_[0] < values_[1])
                {
                    iHighest     = 1;
                    iNextHighest = 0;
                }
                else
                {
                    iHighest     = 0;
                    iNextHighest = 1;
                }
                for (int i = 1; i <= n; i++)
                {
                    if (values_[i] > values_[iHighest])
                    {
                        iNextHighest = iHighest;
                        iHighest     = i;
                    }
                    else
                    {
                        if ((values_[i] > values_[iNextHighest]) && i != iHighest)
                        {
                            iNextHighest = i;
                        }
                    }
                    if (values_[i] < values_[iLowest])
                    {
                        iLowest = i;
                    }
                }
                // Now compute accuracy, update iteration number and check end criteria
                //// Numerical Recipes exit strategy on fx (see NR in C++, p.410)
                //double low = values_[iLowest];
                //double high = values_[iHighest];
                //double rtol = 2.0*std::fabs(high - low)/
                //    (std::fabs(high) + std::fabs(low) + QL_EPSILON);
                //++iterationNumber_;
                //if (rtol < ftol ||
                //    endCriteria.checkMaxIterations(iterationNumber_, ecType)) {
                // GSL exit strategy on x (see GSL v. 1.9, http://www.gnu.org/software/gsl
                double simplexSize = Utils.computeSimplexSize(vertices_);
                ++iterationNumber_;
                if (simplexSize < xtol || endCriteria.checkMaxIterations(iterationNumber_, ref ecType))
                {
                    endCriteria.checkStationaryPoint(0.0, 0.0, ref maxStationaryStateIterations_, ref ecType);
                    endCriteria.checkMaxIterations(iterationNumber_, ref ecType);
                    x_ = vertices_[iLowest];
                    double low = values_[iLowest];
                    P.setFunctionValue(low);
                    P.setCurrentValue(x_);
                    return(ecType);
                }
                // If end criteria is not met, continue
                double factor = -1.0;
                double vTry   = extrapolate(ref P, iHighest, ref factor);
                if ((vTry <= values_[iLowest]) && (factor == -1.0))
                {
                    factor = 2.0;
                    extrapolate(ref P, iHighest, ref factor);
                }
                else if (Math.Abs(factor) > Const.QL_EPSILON)
                {
                    if (vTry >= values_[iNextHighest])
                    {
                        double vSave = values_[iHighest];
                        factor = 0.5;
                        vTry   = extrapolate(ref P, iHighest, ref factor);
                        if (vTry >= vSave && Math.Abs(factor) > Const.QL_EPSILON)
                        {
                            for (int i = 0; i <= n; i++)
                            {
                                if (i != iLowest)
                                {
#if QL_ARRAY_EXPRESSIONS
                                    vertices_[i] = 0.5 * (vertices_[i] + vertices_[iLowest]);
#else
                                    vertices_[i] += vertices_[iLowest];
                                    vertices_[i] *= 0.5;
#endif
                                    values_[i] = P.value(vertices_[i]);
                                }
                            }
                        }
                    }
                }
                // If can't extrapolate given the constraints, exit
                if (Math.Abs(factor) <= Const.QL_EPSILON)
                {
                    x_ = vertices_[iLowest];
                    double low = values_[iLowest];
                    P.setFunctionValue(low);
                    P.setCurrentValue(x_);
                    return(EndCriteria.Type.StationaryFunctionValue);
                }
            } while (end == false);
            throw new Exception("optimization failed: unexpected behaviour");
        }
        public override void calculate()
        {
            // copy black version then adapt to others

            double        value      = 0.0;
            int           optionlets = arguments_.startDates.Count;
            List <double> values     = new InitializedList <double>(optionlets, 0.0);
            List <double> stdDevs    = new InitializedList <double>(optionlets, 0.0);
            List <double> forwards   = new InitializedList <double> (optionlets, 0.0);
            CapFloorType  type       = arguments_.type;

            Handle <YoYInflationTermStructure> yoyTS
                = index().yoyInflationTermStructure();
            Handle <YieldTermStructure> nominalTS
                = yoyTS.link.nominalTermStructure();
            Date settlement = nominalTS.link.referenceDate();


            for (int i = 0; i < optionlets; ++i)
            {
                Date paymentDate = arguments_.payDates[i];
                if (paymentDate > settlement)
                {
                    // discard expired caplets
                    double d = arguments_.nominals[i] *
                               arguments_.gearings[i] *
                               nominalTS.link.discount(paymentDate) *
                               arguments_.accrualTimes[i];

                    // We explicitly have the index and assume that
                    // the fixing is natural, i.e. no convexity adjustment.
                    // If that was required then we would also need
                    // nominal vols in the pricing engine, i.e. a different engine.
                    // This also means that we do not need the coupon to have
                    // a pricing engine to return the swaplet rate and then
                    // the adjusted fixing in the instrument.
                    forwards[i] = yoyTS.link.yoyRate(arguments_.fixingDates[i], new Period(0, TimeUnit.Days));
                    double forward = forwards[i];

                    Date   fixingDate = arguments_.fixingDates[i];
                    double sqrtTime   = 0.0;
                    if (fixingDate > volatility_.link.baseDate())
                    {
                        sqrtTime = Math.Sqrt(volatility_.link.timeFromBase(fixingDate));
                    }

                    if (type == CapFloorType.Cap || type == CapFloorType.Collar)
                    {
                        double strike = arguments_.capRates[i].Value;
                        if (sqrtTime > 0.0)
                        {
                            stdDevs[i] = Math.Sqrt(volatility_.link.totalVariance(fixingDate, strike, new Period(0, TimeUnit.Days)));
                        }

                        // sttDev=0 for already-fixed dates so everything on forward
                        values[i] = optionletImpl(Option.Type.Call, strike, forward, stdDevs[i], d);
                    }
                    if (type == CapFloorType.Floor || type == CapFloorType.Collar)
                    {
                        double strike = arguments_.floorRates[i].Value;
                        if (sqrtTime > 0.0)
                        {
                            stdDevs[i] = Math.Sqrt(volatility_.link.totalVariance(fixingDate, strike, new Period(0, TimeUnit.Days)));
                        }
                        double floorlet = optionletImpl(Option.Type.Put, strike, forward, stdDevs[i], d);
                        if (type == CapFloorType.Floor)
                        {
                            values[i] = floorlet;
                        }
                        else
                        {
                            // a collar is long a cap and short a floor
                            values[i] -= floorlet;
                        }
                    }
                    value += values[i];
                }
            }
            results_.value = value;

            results_.additionalResults["optionletsPrice"]      = values;
            results_.additionalResults["optionletsAtmForward"] = forwards;
            if (type != CapFloorType.Collar)
            {
                results_.additionalResults["optionletsStdDev"] = stdDevs;
            }
        }
Beispiel #19
0
        protected List <double> spreadVolInterpolation(Date atmOptionDate, Period atmSwapTenor)
        {
            double atmOptionTime = timeFromReference(atmOptionDate);
            double atmTimeLength = swapLength(atmSwapTenor);

            List <double> result      = new List <double>();
            List <double> optionTimes = sparseParameters_.optionTimes();
            List <double> swapLengths = sparseParameters_.swapLengths();
            List <Date>   optionDates = sparseParameters_.optionDates();
            List <Period> swapTenors  = sparseParameters_.swapTenors();

            double optionTimesPreviousNode, swapLengthsPreviousNode;

            optionTimesPreviousNode = optionTimes_.First(x => x >= atmOptionTime);
            int optionTimesPreviousIndex = optionTimes_.IndexOf(optionTimesPreviousNode);

            swapLengthsPreviousNode = swapLengths_.First(x => x >= atmTimeLength);
            int swapLengthsPreviousIndex = swapLengths_.IndexOf(swapLengthsPreviousNode);

            if (optionTimesPreviousIndex > 0)
            {
                optionTimesPreviousIndex--;
            }

            if (swapLengthsPreviousIndex > 0)
            {
                swapLengthsPreviousIndex--;
            }

            List <List <SmileSection> > smiles = new List <List <SmileSection> >();
            List <SmileSection>         smilesOnPreviousExpiry = new List <SmileSection>();
            List <SmileSection>         smilesOnNextExpiry     = new List <SmileSection>();

            Utils.QL_REQUIRE(optionTimesPreviousIndex + 1 < sparseSmiles_.Count, () =>
                             "optionTimesPreviousIndex+1 >= sparseSmiles_.size()");
            Utils.QL_REQUIRE(swapLengthsPreviousIndex + 1 < sparseSmiles_[0].Count, () =>
                             "swapLengthsPreviousIndex+1 >= sparseSmiles_[0].size()");
            smilesOnPreviousExpiry.Add(sparseSmiles_[optionTimesPreviousIndex][swapLengthsPreviousIndex]);
            smilesOnPreviousExpiry.Add(sparseSmiles_[optionTimesPreviousIndex][swapLengthsPreviousIndex + 1]);
            smilesOnNextExpiry.Add(sparseSmiles_[optionTimesPreviousIndex + 1][swapLengthsPreviousIndex]);
            smilesOnNextExpiry.Add(sparseSmiles_[optionTimesPreviousIndex + 1][swapLengthsPreviousIndex + 1]);

            smiles.Add(smilesOnPreviousExpiry);
            smiles.Add(smilesOnNextExpiry);

            List <double> optionsNodes = new InitializedList <double>(2);

            optionsNodes[0] = optionTimes[optionTimesPreviousIndex];
            optionsNodes[1] = optionTimes[optionTimesPreviousIndex + 1];

            List <Date> optionsDateNodes = new InitializedList <Date>(2);

            optionsDateNodes[0] = optionDates[optionTimesPreviousIndex];
            optionsDateNodes[1] = optionDates[optionTimesPreviousIndex + 1];

            List <double> swapLengthsNodes = new InitializedList <double>(2);

            swapLengthsNodes[0] = swapLengths[swapLengthsPreviousIndex];
            swapLengthsNodes[1] = swapLengths[swapLengthsPreviousIndex + 1];

            List <Period> swapTenorNodes = new InitializedList <Period>(2);

            swapTenorNodes[0] = swapTenors[swapLengthsPreviousIndex];
            swapTenorNodes[1] = swapTenors[swapLengthsPreviousIndex + 1];

            double atmForward = atmStrike(atmOptionDate, atmSwapTenor);
            double shift      = atmVol_.link.shift(atmOptionTime, atmTimeLength);

            Matrix atmForwards = new Matrix(2, 2, 0.0);
            Matrix atmShifts   = new Matrix(2, 2, 0.0);
            Matrix atmVols     = new Matrix(2, 2, 0.0);

            for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    atmForwards[i, j] = atmStrike(optionsDateNodes[i], swapTenorNodes[j]);
                    atmShifts[i, j]   = atmVol_.link.shift(optionsNodes[i], swapLengthsNodes[j]);
                    atmVols[i, j]     = atmVol_.link.volatility(optionsDateNodes[i], swapTenorNodes[j], atmForwards[i, j]);

                    /* With the old implementation the interpolated spreads on ATM
                     * volatilities were null even if the spreads on ATM volatilities to be
                     * interpolated were non-zero. The new implementation removes
                     * this behaviour, but introduces a small ERROR in the cube:
                     * even if no spreads are applied on any cube ATM volatility corresponding
                     * to quoted smile sections (that is ATM volatilities in sparse cube), the
                     * cube ATM volatilities corresponding to not quoted smile sections (that
                     * is ATM volatilities in dense cube) are no more exactly the quoted values,
                     * but that ones PLUS the linear interpolation of the fit errors on the ATM
                     * volatilities in sparse cube whose spreads are used in the calculation.
                     * A similar imprecision is introduced to the volatilities in dense cube
                     * whith moneyness near to 1.
                     * (See below how spreadVols are calculated).
                     * The extent of this error depends on the quality of the fit: in case of
                     * good fits it is negligibile.
                     */
                }
            }

            for (int k = 0; k < nStrikes_; k++)
            {
                double strike    = Math.Max(atmForward + strikeSpreads_[k], cutoffStrike_ - shift);
                double moneyness = (atmForward + shift) / (strike + shift);

                Matrix strikes    = new Matrix(2, 2, 0.0);
                Matrix spreadVols = new Matrix(2, 2, 0.0);
                for (int i = 0; i < 2; i++)
                {
                    for (int j = 0; j < 2; j++)
                    {
                        strikes[i, j]    = (atmForwards[i, j] + atmShifts[i, j]) / moneyness - atmShifts[i, j];
                        spreadVols[i, j] = smiles[i][j].volatility(strikes[i, j]) - atmVols[i, j];
                    }
                }
                Cube localInterpolator = new Cube(optionsDateNodes, swapTenorNodes, optionsNodes, swapLengthsNodes, 1);
                localInterpolator.setLayer(0, spreadVols);
                localInterpolator.updateInterpolators();

                result.Add(localInterpolator.value(atmOptionTime, atmTimeLength)[0]);
            }
            return(result);
        }
Beispiel #20
0
        protected Cube sabrCalibration(Cube marketVolCube)
        {
            List <double> optionTimes = marketVolCube.optionTimes();
            List <double> swapLengths = marketVolCube.swapLengths();
            List <Date>   optionDates = marketVolCube.optionDates();
            List <Period> swapTenors  = marketVolCube.swapTenors();
            Matrix        alphas      = new Matrix(optionTimes.Count, swapLengths.Count, 0.0);
            Matrix        betas       = new Matrix(alphas);
            Matrix        nus         = new Matrix(alphas);
            Matrix        rhos        = new Matrix(alphas);
            Matrix        forwards    = new Matrix(alphas);
            Matrix        errors      = new Matrix(alphas);
            Matrix        maxErrors   = new Matrix(alphas);
            Matrix        endCriteria = new Matrix(alphas);

            List <Matrix> tmpMarketVolCube = marketVolCube.points();

            List <double> strikes      = new InitializedList <double>(strikeSpreads_.Count);
            List <double> volatilities = new InitializedList <double>(strikeSpreads_.Count);

            for (int j = 0; j < optionTimes.Count; j++)
            {
                for (int k = 0; k < swapLengths.Count; k++)
                {
                    double atmForward = atmStrike(optionDates[j], swapTenors[k]);
                    double shiftTmp   = atmVol_.link.shift(optionTimes[j], swapLengths[k]);
                    strikes.Clear();
                    volatilities.Clear();
                    for (int i = 0; i < nStrikes_; i++)
                    {
                        double strike = atmForward + strikeSpreads_[i];
                        if (strike + shiftTmp >= cutoffStrike_)
                        {
                            strikes.Add(strike);
                            Matrix matrix = tmpMarketVolCube[i];
                            volatilities.Add(matrix[j, k]);
                        }
                    }

                    List <double> guess = parametersGuess_.value(optionTimes[j], swapLengths[k]);


                    SABRInterpolation sabrInterpolation = new SABRInterpolation(strikes, strikes.Count,
                                                                                volatilities,
                                                                                optionTimes[j], atmForward,
                                                                                guess[0], guess[1],
                                                                                guess[2], guess[3],
                                                                                isParameterFixed_[0],
                                                                                isParameterFixed_[1],
                                                                                isParameterFixed_[2],
                                                                                isParameterFixed_[3],
                                                                                vegaWeightedSmileFit_,
                                                                                endCriteria_,
                                                                                optMethod_,
                                                                                errorAccept_,
                                                                                useMaxError_,
                                                                                maxGuesses_
                                                                                );// shiftTmp
                    sabrInterpolation.update();

                    double rmsError = sabrInterpolation.rmsError();
                    double maxError = sabrInterpolation.maxError();
                    alphas     [j, k] = sabrInterpolation.alpha();
                    betas      [j, k] = sabrInterpolation.beta();
                    nus        [j, k] = sabrInterpolation.nu();
                    rhos       [j, k] = sabrInterpolation.rho();
                    forwards   [j, k] = atmForward;
                    errors     [j, k] = rmsError;
                    maxErrors  [j, k] = maxError;
                    endCriteria[j, k] = (double)sabrInterpolation.endCriteria();

                    Utils.QL_REQUIRE(endCriteria[j, k].IsNotEqual((double)EndCriteria.Type.MaxIterations), () =>
                                     "global swaptions calibration failed: " +
                                     "MaxIterations reached: " + "\n" +
                                     "option maturity = " + optionDates[j] + ", \n" +
                                     "swap tenor = " + swapTenors[k] + ", \n" +
                                     "error = " + (errors[j, k]) + ", \n" +
                                     "max error = " + (maxErrors[j, k]) + ", \n" +
                                     "   alpha = " + alphas[j, k] + "n" +
                                     "   beta = " + betas[j, k] + "\n" +
                                     "   nu = " + nus[j, k] + "\n" +
                                     "   rho = " + rhos[j, k] + "\n"
                                     );

                    Utils.QL_REQUIRE(useMaxError_ ? maxError > 0 : rmsError < maxErrorTolerance_, () =>
                                     "global swaptions calibration failed: " +
                                     "option tenor " + optionDates[j] +
                                     ", swap tenor " + swapTenors[k] +
                                     (useMaxError_ ? ": max error " : ": error") +
                                     (useMaxError_ ? maxError : rmsError) +
                                     "   alpha = " + alphas[j, k] + "\n" +
                                     "   beta = " + betas[j, k] + "\n" +
                                     "   nu = " + nus[j, k] + "\n" +
                                     "   rho = " + rhos[j, k] + "\n" +
                                     (useMaxError_ ? ": error" : ": max error ") +
                                     (useMaxError_ ? rmsError :maxError)

                                     );
                }
            }
            Cube sabrParametersCube = new Cube(optionDates, swapTenors, optionTimes, swapLengths, 8, true, backwardFlat_);

            sabrParametersCube.setLayer(0, alphas);
            sabrParametersCube.setLayer(1, betas);
            sabrParametersCube.setLayer(2, nus);
            sabrParametersCube.setLayer(3, rhos);
            sabrParametersCube.setLayer(4, forwards);
            sabrParametersCube.setLayer(5, errors);
            sabrParametersCube.setLayer(6, maxErrors);
            sabrParametersCube.setLayer(7, endCriteria);

            return(sabrParametersCube);
        }
Beispiel #21
0
 public EuropeanExercise(Date date) : base(Type.European)
 {
     dates_ = new InitializedList <Date>(1, date);
 }
Beispiel #22
0
        public static List <Func <Vector, double> > multiPathBasisSystem(int dim, int order, PolynomType polynomType)
        {
            List <Func <double, double> > b = pathBasisSystem(order, polynomType);

            List <Func <Vector, double> > ret = new List <Func <Vector, double> >();

            ret.Add((xx) => 1.0);

            for (int i = 1; i <= order; ++i)
            {
                List <Func <Vector, double> > a = w(dim, i, polynomType, b);

                foreach (var iter in a)
                {
                    ret.Add(iter);
                }
            }

            // remove-o-zap: now remove redundant functions.
            // usually we do have a lot of them due to the construction schema.
            // We use a more "hands on" method here.
            List <bool> rm = new InitializedList <bool>(ret.Count, true);

            Vector x = new Vector(dim), v = new Vector(ret.Count);
            MersenneTwisterUniformRng rng = new MersenneTwisterUniformRng(1234UL);

            for (int i = 0; i < 10; ++i)
            {
                int k;

                // calculate random x vector
                for (k = 0; k < dim; ++k)
                {
                    x[k] = rng.next().value;
                }

                // get return values for all basis functions
                for (k = 0; k < ret.Count; ++k)
                {
                    v[k] = ret[k](x);
                }

                // find duplicates
                for (k = 0; k < ret.Count; ++k)
                {
                    if (v.First(xx => (Math.Abs(v[k] - xx) <= 10 * v[k] * Const.QL_EPSILON)) == v.First() + k)
                    {
                        // don't remove this item, it's unique!
                        rm[k] = false;
                    }
                }
            }

            int iter2 = 0;

            for (int i = 0; i < rm.Count; ++i)
            {
                if (rm[i])
                {
                    ret.RemoveAt(iter2);
                }
                else
                {
                    ++iter2;
                }
            }

            return(ret);
        }
Beispiel #23
0
 public AmericanExercise(Date latest, bool payoffAtExpiry = false) : base(Type.American, payoffAtExpiry)
 {
     dates_    = new InitializedList <Date>(2);
     dates_[0] = Date.minDate();
     dates_[1] = latest;
 }
Beispiel #24
0
        //@}
        public override void calculate()
        {
            if (!(base.arguments_.settlementType == Settlement.Type.Physical))
            {
                throw new ArgumentException("cash-settled swaptions not priced with tree engine");
            }
            if (base.model_ == null)
            {
                throw new ArgumentException("no model specified");
            }

            Date       referenceDate;
            DayCounter dayCounter;

            ITermStructureConsistentModel tsmodel =
                (ITermStructureConsistentModel)base.model_.link;

            try {
                if (tsmodel != null)
                {
                    referenceDate = tsmodel.termStructure().link.referenceDate();
                    dayCounter    = tsmodel.termStructure().link.dayCounter();
                }
                else
                {
                    referenceDate = termStructure_.link.referenceDate();
                    dayCounter    = termStructure_.link.dayCounter();
                }
            }
            catch {
                referenceDate = termStructure_.link.referenceDate();
                dayCounter    = termStructure_.link.dayCounter();
            }

            DiscretizedSwaption swaption = new DiscretizedSwaption(arguments_, referenceDate, dayCounter);
            Lattice             lattice;

            if (lattice_ != null)
            {
                lattice = lattice_;
            }
            else
            {
                List <double> times    = swaption.mandatoryTimes();
                TimeGrid      timeGrid = new TimeGrid(times, times.Count, timeSteps_);
                lattice = model_.link.tree(timeGrid);
            }

            List <double> stoppingTimes = new InitializedList <double>(arguments_.exercise.dates().Count);

            for (int i = 0; i < stoppingTimes.Count; ++i)
            {
                stoppingTimes[i] =
                    dayCounter.yearFraction(referenceDate,
                                            arguments_.exercise.date(i));
            }

            swaption.initialize(lattice, stoppingTimes.Last());

            double nextExercise;

            /*std::find_if(stoppingTimes.begin(),
             *            stoppingTimes.end(),
             *            std::bind2nd(std::greater_equal<Time>(), 0.0));*/

            List <double> listExercise = new List <double>();

            listExercise.AddRange(stoppingTimes.FindAll(x => x >= 0));
            nextExercise = listExercise[0];
            swaption.rollback(nextExercise);

            results_.value = swaption.presentValue();
        }
Beispiel #25
0
        // calculating swaption volatility matrix using
        // Rebonatos approx. formula. Be aware that this
        // matrix is valid only for regular fixings and
        // assumes that the fix and floating leg have the
        // same frequency
        public SwaptionVolatilityMatrix getSwaptionVolatilityMatrix()
        {
            if (swaptionVola != null)
            {
                return(swaptionVola);
            }

            IborIndex index = process_.index();
            Date      today = process_.fixingDates()[0];

            int    size         = process_.size() / 2;
            Matrix volatilities = new Matrix(size, size);

            List <Date> exercises = new InitializedList <Date>(size);

            for (int i = 0; i < size; ++i)
            {
                exercises[i] = process_.fixingDates()[i + 1];
            }

            List <Period> lengths = new InitializedList <Period>(size);

            for (int i = 0; i < size; ++i)
            {
                lengths[i] = (i + 1) * index.tenor();
            }

            Vector f = process_.initialValues();

            for (int k = 0; k < size; ++k)
            {
                int    alpha   = k;
                double t_alpha = process_.fixingTimes()[alpha + 1];

                Matrix var = new Matrix(size, size);
                for (int i = alpha + 1; i <= k + size; ++i)
                {
                    for (int j = i; j <= k + size; ++j)
                    {
                        var[i - alpha - 1, j - alpha - 1] = var[j - alpha - 1, i - alpha - 1] =
                            covarProxy_.integratedCovariance(i, j, t_alpha, null);
                    }
                }

                for (int l = 1; l <= size; ++l)
                {
                    int    beta = l + k;
                    Vector w    = w_0(alpha, beta);

                    double sum = 0.0;
                    for (int i = alpha + 1; i <= beta; ++i)
                    {
                        for (int j = alpha + 1; j <= beta; ++j)
                        {
                            sum += w[i] * w[j] * f[i] * f[j] * var[i - alpha - 1, j - alpha - 1];
                        }
                    }
                    volatilities[k, l - 1] =
                        Math.Sqrt(sum / t_alpha) / S_0(alpha, beta);
                }
            }

            return(swaptionVola = new SwaptionVolatilityMatrix(today, exercises, lengths,
                                                               volatilities, index.dayCounter()));
        }
Beispiel #26
0
        public void sabrCalibrationSection(Cube marketVolCube, Cube parametersCube, Period swapTenor)
        {
            List <double> optionTimes = marketVolCube.optionTimes();
            List <double> swapLengths = marketVolCube.swapLengths();
            List <Date>   optionDates = marketVolCube.optionDates();
            List <Period> swapTenors  = marketVolCube.swapTenors();

            int k = swapTenors.IndexOf(swapTenors.First(x => x == swapTenor));

            Utils.QL_REQUIRE(k != swapTenors.Count, () => "swap tenor not found");

            List <double> calibrationResult = new InitializedList <double>(8, 0.0);
            List <Matrix> tmpMarketVolCube  = marketVolCube.points();

            List <double> strikes      = new List <double>(strikeSpreads_.Count);
            List <double> volatilities = new List <double>(strikeSpreads_.Count);

            for (int j = 0; j < optionTimes.Count; j++)
            {
                double atmForward = atmStrike(optionDates[j], swapTenors[k]);
                double shiftTmp   = atmVol_.link.shift(optionTimes[j], swapLengths[k]);
                strikes.Clear();
                volatilities.Clear();
                for (int i = 0; i < nStrikes_; i++)
                {
                    double strike = atmForward + strikeSpreads_[i];
                    if (strike + shiftTmp >= cutoffStrike_)
                    {
                        strikes.Add(strike);
                        volatilities.Add(tmpMarketVolCube[i][j, k]);
                    }
                }

                List <double> guess = parametersGuess_.value(optionTimes[j], swapLengths[k]);

                var sabrInterpolation = new SABRInterpolation(strikes,
                                                              strikes.Count,
                                                              volatilities,
                                                              optionTimes[j], atmForward,
                                                              guess[0], guess[1],
                                                              guess[2], guess[3],
                                                              isParameterFixed_[0],
                                                              isParameterFixed_[1],
                                                              isParameterFixed_[2],
                                                              isParameterFixed_[3],
                                                              vegaWeightedSmileFit_,
                                                              endCriteria_,
                                                              optMethod_,
                                                              errorAccept_,
                                                              useMaxError_,
                                                              maxGuesses_
                                                              );//shiftTmp

                sabrInterpolation.update();
                double interpolationError = sabrInterpolation.rmsError();
                calibrationResult[0] = sabrInterpolation.alpha();
                calibrationResult[1] = sabrInterpolation.beta();
                calibrationResult[2] = sabrInterpolation.nu();
                calibrationResult[3] = sabrInterpolation.rho();
                calibrationResult[4] = atmForward;
                calibrationResult[5] = interpolationError;
                calibrationResult[6] = sabrInterpolation.maxError();
                calibrationResult[7] = (double)sabrInterpolation.endCriteria();

                Utils.QL_REQUIRE(calibrationResult[7].IsNotEqual((double)EndCriteria.Type.MaxIterations), () =>
                                 "section calibration failed: " +
                                 "option tenor " + optionDates[j] +
                                 ", swap tenor " + swapTenors[k] +
                                 ": max iteration (" +
                                 endCriteria_.maxIterations() + ")" +
                                 ", alpha " + calibrationResult[0] +
                                 ", beta " + calibrationResult[1] +
                                 ", nu " + calibrationResult[2] +
                                 ", rho " + calibrationResult[3] +
                                 ", max error " + calibrationResult[6] +
                                 ", error " + calibrationResult[5]
                                 );

                Utils.QL_REQUIRE(useMaxError_ ? calibrationResult[6] > 0 : calibrationResult[5] < maxErrorTolerance_, () =>
                                 "section calibration failed: " +
                                 "option tenor " + optionDates[j] +
                                 ", swap tenor " + swapTenors[k] +
                                 (useMaxError_ ? ": max error " : ": error ") +
                                 (useMaxError_ ? calibrationResult[6] : calibrationResult[5]) +
                                 ", alpha " + calibrationResult[0] +
                                 ", beta " + calibrationResult[1] +
                                 ", nu " + calibrationResult[2] +
                                 ", rho " + calibrationResult[3] +
                                 (useMaxError_ ? ": error" : ": max error ") +
                                 (useMaxError_ ? calibrationResult[5] : calibrationResult[6])
                                 );

                parametersCube.setPoint(optionDates[j], swapTenors[k], optionTimes[j], swapLengths[k], calibrationResult);
                parametersCube.updateInterpolators();
            }
        }
Beispiel #27
0
 protected override void setupExpired()
 {
     base.setupExpired();
     legNPV_ = new InitializedList <double?>(legNPV_.Count);
 }
Beispiel #28
0
        public override List <SparseMatrix> toMatrixDecomp()
        {
            List <SparseMatrix> retVal = new InitializedList <SparseMatrix>(1, mapT_.toMatrix());

            return(retVal);
        }
Beispiel #29
0
 public LinearInterpolationImpl(List <double> xBegin, int size, List <double> yBegin)
     : base(xBegin, size, yBegin)
 {
     primitiveConst_ = new InitializedList <double>(size_);
     s_ = new InitializedList <double>(size_);
 }
        public override void calculate()
        {
            /* this engine cannot really check for the averageType==Geometric
             * since it can be used as control variate for the Arithmetic version
             *  QL_REQUIRE(arguments_.averageType == Average::Geometric,
             *             "not a geometric average option");
             */

            if (!(arguments_.exercise.type() == Exercise.Type.European))
            {
                throw new ApplicationException("not an European Option");
            }

            double runningLog;
            int    pastFixings;

            if (arguments_.averageType == Average.Type.Geometric)
            {
                if (!(arguments_.runningAccumulator > 0.0))
                {
                    throw new ApplicationException("positive running product required: "
                                                   + arguments_.runningAccumulator + " not allowed");
                }
                runningLog =
                    Math.Log(arguments_.runningAccumulator.GetValueOrDefault());
                pastFixings = arguments_.pastFixings.GetValueOrDefault();
            }
            else      // it is being used as control variate
            {
                runningLog  = 1.0;
                pastFixings = 0;
            }

            PlainVanillaPayoff payoff = (PlainVanillaPayoff)(arguments_.payoff);

            if (payoff == null)
            {
                throw new ApplicationException("non-plain payoff given");
            }

            Date          referenceDate = process_.riskFreeRate().link.referenceDate();
            DayCounter    rfdc          = process_.riskFreeRate().link.dayCounter();
            DayCounter    divdc         = process_.dividendYield().link.dayCounter();
            DayCounter    voldc         = process_.blackVolatility().link.dayCounter();
            List <double> fixingTimes   = new InitializedList <double>(arguments_.fixingDates.Count());
            int           i;

            for (i = 0; i < arguments_.fixingDates.Count(); i++)
            {
                if (arguments_.fixingDates[i] >= referenceDate)
                {
                    double t = voldc.yearFraction(referenceDate,
                                                  arguments_.fixingDates[i]);
                    fixingTimes.Add(t);
                }
            }

            int    remainingFixings = fixingTimes.Count();
            int    numberOfFixings  = pastFixings + remainingFixings;
            double N = numberOfFixings;

            double pastWeight   = pastFixings / N;
            double futureWeight = 1.0 - pastWeight;

            /*double timeSum = std::accumulate(fixingTimes.begin(),
             *                             fixingTimes.end(), 0.0);*/
            double timeSum = 0;

            fixingTimes.ForEach((ii, vv) => timeSum += fixingTimes[ii]);

            double vola = process_.blackVolatility().link.blackVol(
                arguments_.exercise.lastDate(),
                payoff.strike());
            double temp = 0.0;

            for (i = pastFixings + 1; i < numberOfFixings; i++)
            {
                temp += fixingTimes[i - pastFixings - 1] * (N - i);
            }
            double variance   = vola * vola / N / N * (timeSum + 2.0 * temp);
            double dsigG_dsig = Math.Sqrt((timeSum + 2.0 * temp)) / N;
            double sigG       = vola * dsigG_dsig;
            double dmuG_dsig  = -(vola * timeSum) / N;

            Date   exDate       = arguments_.exercise.lastDate();
            double dividendRate = process_.dividendYield().link.
                                  zeroRate(exDate, divdc, Compounding.Continuous, Frequency.NoFrequency).rate();
            double riskFreeRate = process_.riskFreeRate().link.
                                  zeroRate(exDate, rfdc, Compounding.Continuous, Frequency.NoFrequency).rate();
            double nu = riskFreeRate - dividendRate - 0.5 * vola * vola;

            double s = process_.stateVariable().link.value();

            if (!(s > 0.0))
            {
                throw new ApplicationException("positive underlying value required");
            }

            int    M   = (pastFixings == 0 ? 1 : pastFixings);
            double muG = pastWeight * runningLog / M +
                         futureWeight * Math.Log(s) + nu * timeSum / N;
            double forwardPrice = Math.Exp(muG + variance / 2.0);

            double riskFreeDiscount = process_.riskFreeRate().link.discount(
                arguments_.exercise.lastDate());

            BlackCalculator black = new BlackCalculator(payoff, forwardPrice, Math.Sqrt(variance),
                                                        riskFreeDiscount);

            results_.value = black.value();
            results_.delta = futureWeight * black.delta(forwardPrice) * forwardPrice / s;
            results_.gamma = forwardPrice * futureWeight / (s * s)
                             * (black.gamma(forwardPrice) * futureWeight * forwardPrice
                                - pastWeight * black.delta(forwardPrice));

            double Nx_1, nx_1;
            CumulativeNormalDistribution CND = new CumulativeNormalDistribution();
            NormalDistribution           ND  = new NormalDistribution();

            if (sigG > Const.QL_Epsilon)
            {
                double x_1 = (muG - Math.Log(payoff.strike()) + variance) / sigG;
                Nx_1 = CND.value(x_1);
                nx_1 = ND.value(x_1);
            }
            else
            {
                Nx_1 = (muG > Math.Log(payoff.strike()) ? 1.0 : 0.0);
                nx_1 = 0.0;
            }
            results_.vega = forwardPrice * riskFreeDiscount *
                            ((dmuG_dsig + sigG * dsigG_dsig) * Nx_1 + nx_1 * dsigG_dsig);

            if (payoff.optionType() == Option.Type.Put)
            {
                results_.vega -= riskFreeDiscount * forwardPrice *
                                 (dmuG_dsig + sigG * dsigG_dsig);
            }

            double tRho = rfdc.yearFraction(process_.riskFreeRate().link.referenceDate(),
                                            arguments_.exercise.lastDate());

            results_.rho = black.rho(tRho) * timeSum / (N * tRho)
                           - (tRho - timeSum / N) * results_.value;

            double tDiv = divdc.yearFraction(
                process_.dividendYield().link.referenceDate(),
                arguments_.exercise.lastDate());

            results_.dividendRho = black.dividendRho(tDiv) * timeSum / (N * tDiv);

            results_.strikeSensitivity = black.strikeSensitivity();

            results_.theta = Utils.blackScholesTheta(process_,
                                                     results_.value.GetValueOrDefault(),
                                                     results_.delta.GetValueOrDefault(),
                                                     results_.gamma.GetValueOrDefault());
        }