Beispiel #1
0
        /// <summary>Initializes a new instance of the <see cref="LambertWFunctionFritsch" /> class.
        /// </summary>
        internal LambertWFunctionFritsch()
        {
            m_PolynomialA1 = Polynomial.Real.Create(1.0, 5.931375839364438, 11.39220550532913, 7.33888339911111, 0.653449016991959);
            m_PolynomialB1 = Polynomial.Real.Create(1.0, 6.931373689597704, 16.82349461388016, 16.43072324143226, 5.115235195211697);

            m_PolynomialA2 = Polynomial.Real.Create(1.0, 2.445053070726557, 1.343664225958226, 0.148440055397592, 0.0008047501729130);
            m_PolynomialB2 = Polynomial.Real.Create(1.0, 3.444708986486002, 3.292489857371952, 0.916460018803122, 0.0530686404483322);

            m_InitialValueCoefficients = new double[] { -1.0, 1.0, -1.0 / 3.0, 11.0 / 72.0, -43.0 / 540.0, 769.0 / 17280.0, -221.0 / 8505.0, 680863.0 / 43545600.0, -1963.0 / 204120.0, 226287557.0 / 37623398400.0 };
        }
Beispiel #2
0
        };                                 // e^(-27^2)*2^64
        #endregion

        #region public constructors

        /// <summary>Initializes a new instance of the <see cref="ErrorFunctionCoarseAlgorithm" /> class.
        /// </summary>
        public ErrorFunctionCoarseAlgorithm()
        {
            m_ErfP = Polynomial.Real.Create(1.12837916709551256, 1.35894887627277916e-1, 4.03259488531795274e-2, 1.20339380863079457e-3, 6.49254556481904354e-5);
            m_ErfQ = Polynomial.Real.Create(1, 4.53767041780002545e-1, 8.69936222615385890e-2, 8.49717371168693357e-3, 3.64915280629351082e-4);

            m_ErfcP1 = Polynomial.Real.Create(9.99999992049799098e-1, 1.33154163936765307, 8.78115804155881782e-1, 3.31899559578213215e-1, 7.14193832506776067e-2, 7.06940843763253131e-3);
            m_ErfcQ1 = Polynomial.Real.Create(1, 2.45992070144245533, 2.65383972869775752, 1.61876655543871376, 5.94651311286481502e-1, 1.26579413030177940e-1, 1.25304936549413393e-2);


            m_ErfcP2 = Polynomial.Real.Create(9.99921140009714409e-1, 1.62356584489366647, 1.26739901455873222, 5.81528574177741135e-1, 1.57289620742838702e-1, 2.25716982919217555e-2);
            m_ErfcQ2 = Polynomial.Real.Create(1, 2.75143870676376208, 3.37367334657284535, 2.38574194785344389, 1.05074004614827206, 2.78788439273628983e-1, 4.00072964526861362e-2);

            m_ErfcP3 = Polynomial.Real.Create(5.64189583547756078e-1, 8.80253746105525775, 3.84683103716117320e+1, 4.77209965874436377e+1, 8.08040729052301677);
            m_ErfcQ3 = Polynomial.Real.Create(1, 1.61020914205869003e+1, 7.54843505665954743e+1, 1.12123870801026015e+2, 3.73997570145040850e+1);
        }
Beispiel #3
0
        /// <summary>Gets the implied strike for a specific option price.
        /// </summary>
        /// <param name="optionValue">The value of the option.</param>
        /// <param name="volatility">The volatility.</param>
        /// <param name="impliedStrike">The implied strike (output).</param>
        /// <returns>A value indicating whether <paramref name="impliedStrike"/> contains valid data.
        /// </returns>
        /// <remarks>This method is based on Newtons method where the initial guess is equal to the approximation given in
        ///   <para>How close are the option pricing formulas of Bachelier and Black-Merton-Scholes, W. Schachermayer, J. Teichmann.</para>
        /// <para>The implied strike is not unique for straddle options.</para>
        /// </remarks>
        public ImpliedCalculationResultState TryGetImpliedStrike(double optionValue, double volatility, out double impliedStrike)
        {
            double undiscountedValue = optionValue / m_DiscountFactor;

            if (m_TimeToExpiration < MachineConsts.Epsilon)
            {
                impliedStrike = m_Forward - undiscountedValue;
                return(ImpliedCalculationResultState.ProperResult);
            }

            /* compute initial guess:
             *    Straddle(m) = C(m) + P(m) \approx 2 * a + m^2/( 2 pi * a),
             * see eqn.(3.4)&(3.5), where the left hand side is already given.
             */
            double a = volatility * SqrtOfTimeToExpiration / MathConsts.SqrtTwoPi;
            double m = Math.Sqrt(Math.Abs((undiscountedValue - 2 * a) * MathConsts.TwoPi * a));

            impliedStrike = m_Forward + m;

            /* we apply Newtons method to the function
             *     H(K) = ln( f(K) / c),
             * where f(K) is the (undiscounted) value of the option and c is the given undiscounted value
             * of the option. It holds H'(K) = f'(K)/f(K) and Newtons method gives
             *
             *      K_{n+1} = K_n - H(K_n)/H'(K_n) = K_n - ln(f(K)/c) * f(K) / f'(K),
             *
             * here f'(K) = 1 - 2 * N(d) which will be equal to 0, if K=forward.
             */

            double absOfValueAtExpiry        = Math.Abs(undiscountedValue);
            double optionValueForGivenStrike = undiscountedValue;
            double sqrtOfTime = SqrtOfTimeToExpiration;

            double d, CDF_d;

            for (int i = 1; i <= MaxNumberIterationImpliedStrike; i++)
            {
                d     = (m_Forward - impliedStrike) / (volatility * sqrtOfTime);
                CDF_d = StandardNormalDistribution.GetCdfValue(d);
                optionValueForGivenStrike = 2.0 * (volatility * sqrtOfTime * StandardNormalDistribution.GetPdfValue(d) + (impliedStrike - m_Forward) * (0.5 - CDF_d));

                if (Math.Abs(d) < MachineConsts.Epsilon) // forward = strike and f'(K) = 0, i.e. denominator = 0
                {
                    if (Math.Abs(undiscountedValue - optionValueForGivenStrike) < absOfValueAtExpiry * MachineConsts.TinyEpsilon)
                    {
                        return(ImpliedCalculationResultState.ProperResult);
                    }

                    /* here, we do a better approximation for the initial guess of the implied strike,
                     * i.e. straddle = C(m) + P(m) = 2 a + m^2/(2Pi a) - m^4/(48 * Pi^2 a^3), we use
                     * a root-finding approach the these polynomials and we use the root 'm' (= strike - forward)
                     * where Straddle(m) - undiscountedValue is minimal with respect to each root.
                     */
                    IRealPolynomial polynomial = Polynomial.Real.Create(2 * a, 0, 1.0 / (a * MathConsts.TwoPi), 0, -1.0 / (a * a * a * 48 * MathConsts.PiSquared));
                    List <double>   roots      = new List <double>();
                    polynomial.GetRealRoots(roots, Polynomial.RootFinder.LaguerreApproach.StandardPolishing);

                    if (roots.Count == 0)
                    {
                        throw new ArithmeticException("Straddle approximation polynomial of degree 4 has no real root.");
                    }
                    else
                    {
                        impliedStrike = m_Forward + roots[0];
                        double minDistance = Math.Abs(undiscountedValue - GetUndiscountedOptionValue(roots[0], volatility, sqrtOfTime));
                        for (int j = 1; j < roots.Count; j++)
                        {
                            double distance = Math.Abs(undiscountedValue - GetUndiscountedOptionValue(roots[j], volatility, sqrtOfTime));
                            if (distance < minDistance)
                            {
                                impliedStrike = m_Forward + roots[j];
                                minDistance   = distance;
                            }
                        }
                    }
                }
                else
                {
                    impliedStrike -= optionValueForGivenStrike * Math.Log(optionValueForGivenStrike / undiscountedValue) / (1 - 2 * CDF_d);
                }
                if (Math.Abs(undiscountedValue - optionValueForGivenStrike) < absOfValueAtExpiry * MachineConsts.TinyEpsilon)
                {
                    return(ImpliedCalculationResultState.ProperResult);
                }
            }
            return(ImpliedCalculationResultState.NoProperResult);
        }