/// <summary>Gets the volga of the option, i.e. the second partial derivative of the option value formula with respect to the volatility.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The volga of the option, i.e. the second partial derivative of the option value formula with respect to the volatility.</returns>
        public double GetVolga(double volatility)
        {
            if (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon)
            {
                return(0.0);
            }
            double d = (m_Strike - m_Forward) / (volatility * SqrtOfTimeToExpiration);

            return(m_DiscountFactor * StandardNormalDistribution.GetPdfValue(d) * d * (d * d - 2.0) / (volatility * volatility));
        }
Exemple #2
0
        /// <summary>Gets the (forward-)vanna of the option, i.e. the partial derivative of the option value formual with respect
        /// to the forward and with respect to the volatility, i.e. '\partial\sigma \partial F'.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The (forward-)vanna of the option, i.e. the partial derivative of the option value formual with respect
        /// to the forward and with respect to the volatility, i.e. '\partial\sigma \partial F'.
        /// </returns>
        public double GetForwardVanna(double volatility)
        {
            if ((m_Strike < MachineConsts.Epsilon) || (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon))
            {
                return(0.0);
            }
            double dplus = (LogOfMoneyness + 0.5 * volatility * volatility * m_TimeToExpiration) / (volatility * SqrtOfTimeToExpiration);

            return(m_DiscountFactor * StandardNormalDistribution.GetPdfValue(dplus) * (SqrtOfTimeToExpiration - dplus / volatility));
        }
Exemple #3
0
        /// <summary>Gets the strike-delta of the option, i.e. the partial derivative of the option value formula with respect to the strike.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The strike-delta of the option, i.e. the partial derivative of the option value formula with respect to the strike.</returns>
        public double GetStrikeDelta(double volatility)
        {
            if ((m_Strike < MachineConsts.Epsilon) || (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon))
            {
                return(0.0);
            }
            double dminus = (LogOfMoneyness - 0.5 * volatility * volatility * m_TimeToExpiration) / (volatility * SqrtOfTimeToExpiration);

            return(m_DiscountFactor * StandardNormalDistribution.GetCdfValue(-dminus));
        }
Exemple #4
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>
 public ImpliedCalculationResultState TryGetImpliedStrike(double optionValue, double volatility, out double impliedStrike)
 {
     if (m_TimeToExpiration < MachineConsts.Epsilon)
     {
         impliedStrike = m_Forward;
         return(ImpliedCalculationResultState.ProperResult);
     }
     impliedStrike = m_Forward * Math.Exp(-StandardNormalDistribution.GetInverseCdfValue(optionValue / m_DiscountFactor) * volatility * Math.Sqrt(m_TimeToExpiration) - 0.5 * volatility * volatility * m_TimeToExpiration);
     return((Double.IsNaN(impliedStrike) == false) ? ImpliedCalculationResultState.ProperResult : ImpliedCalculationResultState.NoProperResult);
 }
Exemple #5
0
        /// <summary>Gets the forward-delta of the option, i.e. the partial derivative of the option value formula with respect to the forward.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The forward-delta of the option, i.e. the partial derivative of the option value formula with respect to the forward.</returns>
        public double GetForwardDelta(double volatility)
        {
            if ((m_Strike < MachineConsts.Epsilon) || (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon))
            {
                return((m_Strike > m_Forward) ? 1 : 0);
            }
            double dplus = (LogOfMoneyness + 0.5 * volatility * volatility * m_TimeToExpiration) / (volatility * SqrtOfTimeToExpiration);

            return(m_DiscountFactor * (StandardNormalDistribution.GetCdfValue(dplus) - 1.0));
        }
Exemple #6
0
        /// <summary>Gets the forward-gamma of the option, i.e. the second partial derivative of the option value formula with respect to the forward.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The forward-gamma of the option, i.e. the second partial derivative of the option value formula with respect to the forward.
        /// </returns>
        /// <remarks>The initial value of the underlying is equal to the forward times the discount factor.</remarks>
        public double GetForwardGamma(double volatility)
        {
            if ((m_Strike < MachineConsts.Epsilon) || (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon))
            {
                return(0.0);
            }
            double dminus = (LogOfMoneyness - 0.5 * volatility * volatility * m_TimeToExpiration) / (volatility * SqrtOfTimeToExpiration);

            return(m_DiscountFactor * StandardNormalDistribution.GetPdfValue(dminus) / (volatility * m_Forward * m_Forward) * (-dminus / (volatility * m_TimeToExpiration) - 1.0 / (SqrtOfTimeToExpiration)));
        }
Exemple #7
0
        /// <summary>Gets the (forward-)vanna of the option, i.e. the partial derivative of the option value formual with respect
        /// to the forward and with respect to the volatility, i.e. '\partial\sigma \partial F'.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The (forward-)vanna of the option, i.e. the partial derivative of the option value formual with respect
        /// to the forward and with respect to the volatility, i.e. '\partial\sigma \partial F'.
        /// </returns>
        public double GetForwardVanna(double volatility)
        {
            if ((m_Strike < MachineConsts.Epsilon) || (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon))
            {
                return(0);
            }
            double d = (m_Strike - m_Forward) / (volatility * SqrtOfTimeToExpiration);

            return(m_DiscountFactor * d * StandardNormalDistribution.GetPdfValue(d) / volatility);
        }
Exemple #8
0
        /// <summary>Gets the price of the option <c>at time of expiry</c>, i.e. not discounted.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The value of the option <c>at the time of expiry</c>, thus not discounted. To get the price just multiply the return value with the discount factor.</returns>
        public double GetNoneDiscountedValue(double volatility)
        {
            if (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon)
            {
                return(Math.Max(0, m_Strike - m_Forward));
            }
            double d = (m_Strike - m_Forward) / (volatility * SqrtOfTimeToExpiration);

            return((m_Strike - m_Forward) * StandardNormalDistribution.GetCdfValue(d) + volatility * SqrtOfTimeToExpiration * StandardNormalDistribution.GetPdfValue(d));
        }
Exemple #9
0
        /// <summary>Gets the theta of the option, i.e. the partial derivative of the option value formula with respect to the time to maturity.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The theta of the option, i.e. the partial derivative of the option value formula with respect to the time to expiry.
        /// </returns>
        public double GetTheta(double volatility)
        {
            if (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon)
            {
                return(0.0);
            }
            double d = (m_Forward - m_Strike) / (volatility * SqrtOfTimeToExpiration);

            return(m_DiscountFactor * 0.5 * StandardNormalDistribution.GetPdfValue(d) * (-d * (d * volatility / SqrtOfTimeToExpiration + (m_Strike - m_Forward) / m_TimeToExpiration) + volatility / SqrtOfTimeToExpiration));
        }
Exemple #10
0
        /// <summary>Gets the strike-delta of the option, i.e. the partial derivative of the option value formula with respect to the strike.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The strike-delta of the option, i.e. the partial derivative of the option value formula with respect to the strike.</returns>
        public double GetStrikeDelta(double volatility)
        {
            if (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon)
            {
                return(0.0);
            }
            double d = (m_Forward - m_Strike) / (volatility * SqrtOfTimeToExpiration);

            return(m_DiscountFactor * (1.0 - 2.0 * StandardNormalDistribution.GetCdfValue(d)));
        }
Exemple #11
0
        /// <summary>Gets the price of the option <c>at time of expiry</c>, i.e. not discounted.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The value of the option <c>at the time of expiry</c>, thus not discounted. To get the price just multiply the return value with the discount factor.</returns>
        public double GetNoneDiscountedValue(double volatility)
        {
            if ((m_Strike < MachineConsts.Epsilon) || (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon))
            {
                return(Math.Max(0, m_Strike - m_Forward));
            }
            double dplus  = (LogOfMoneyness + 0.5 * volatility * volatility * m_TimeToExpiration) / (volatility * SqrtOfTimeToExpiration);
            double dminus = dplus - volatility * SqrtOfTimeToExpiration;

            return(m_Strike * StandardNormalDistribution.GetCdfValue(-dminus) - m_Forward * StandardNormalDistribution.GetCdfValue(-dplus));
        }
Exemple #12
0
        /// <summary>Gets the price of the option <c>at time of expiry</c>, i.e. not discounted.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The value of the option <c>at the time of expiry</c>, thus not discounted. To get the price just multiply the return value with the discount factor.</returns>
        public double GetNoneDiscountedValue(double volatility)
        {
            if (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon)
            {
                return(Math.Abs(m_Strike - m_Forward));
            }
            // here, we use the fact N(-d) = 1 - N(d):
            double d = (m_Forward - m_Strike) / (volatility * SqrtOfTimeToExpiration);

            return(2.0 * (volatility * SqrtOfTimeToExpiration * StandardNormalDistribution.GetPdfValue(d) + (m_Strike - m_Forward) * (0.5 - StandardNormalDistribution.GetCdfValue(d))));
        }
        /// <summary>Gets the volga of the option, i.e. the second partial derivative of the option value formula with respect to the volatility.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The volga of the option, i.e. the second partial derivative of the option value formula with respect to the volatility.</returns>
        public double GetVolga(double volatility)
        {
            if ((m_Strike < MachineConsts.Epsilon) || (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon))
            {
                return(0.0);
            }
            double dplus  = (LogOfMoneyness + 0.5 * volatility * volatility * m_TimeToExpiration) / (volatility * SqrtOfTimeToExpiration);
            double dminus = dplus - volatility * SqrtOfTimeToExpiration;

            return(2.0 * m_DiscountFactor * m_Forward * SqrtOfTimeToExpiration * StandardNormalDistribution.GetPdfValue(dplus) * dplus * dminus / volatility);
        }
        /// <summary>Gets the price of the option <c>at time of expiry</c>, i.e. not discounted.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The value of the option <c>at the time of expiry</c>, thus not discounted. To get the price just multiply the return value with the discount factor.
        /// </returns>
        public double GetNoneDiscountedValue(double volatility)
        {
            /* mind numerical traps: */
            if ((m_Strike < MachineConsts.Epsilon) || (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon))
            {
                return(m_Forward <= m_Strike ? 1.0 : 0.0);
            }
            double dminus = (LogOfMoneyness - 0.5 * volatility * volatility * m_TimeToExpiration) / (volatility * SqrtOfTimeToExpiration);

            return(StandardNormalDistribution.GetCdfValue(-dminus));
        }
        /// <summary>Gets the forward-gamma of the option, i.e. the second partial derivative of the option value formula with respect to the forward.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The forward-gamma of the option, i.e. the second partial derivative of the option value formula with respect to the forward.</returns>
        /// <remarks>The initial value of the underlying is equal to the forward times the discount factor.</remarks>
        public double GetForwardGamma(double volatility)
        {
            if ((m_Strike < MachineConsts.Epsilon) || (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon))
            {
                return(0.0);
            }
            double dplus = (LogOfMoneyness + 0.5 * volatility * volatility * m_TimeToExpiration) / (volatility * SqrtOfTimeToExpiration);

            // is just two times the gamma of an call/put option
            return(2.0 * m_DiscountFactor * StandardNormalDistribution.GetPdfValue(dplus) / (volatility * SqrtOfTimeToExpiration * m_Forward));
        }
Exemple #16
0
        /// <summary>Gets the price of the option <c>at time of expiry</c>, i.e. not discounted.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The value of the option <c>at the time of expiry</c>, thus not discounted. To get the price just multiply the return value with the discount factor.</returns>
        public double GetNoneDiscountedValue(double volatility)
        {
            /* mind numerical traps: */
            if ((m_Strike < MachineConsts.Epsilon) || (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon))
            {
                return(Math.Max(0, m_Forward - m_Strike));
            }
            double dplus  = LogOfMoneyness / (volatility * SqrtOfTimeToExpiration) + 0.5 * volatility * SqrtOfTimeToExpiration;
            double dminus = dplus - volatility * SqrtOfTimeToExpiration;

            return(m_Forward * StandardNormalDistribution.GetCdfValue(dplus) - m_Strike * StandardNormalDistribution.GetCdfValue(dminus));
        }
        /// <summary>Gets the price of the option <c>at time of expiry</c>, i.e. not discounted.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The value of the option <c>at the time of expiry</c>, thus not discounted. To get the price just multiply the return value with the discount factor.</returns>
        public double GetNoneDiscountedValue(double volatility)
        {
            double forwardMinusStrike = m_Forward - m_Strike;

            if (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon)
            {
                return(Math.Max(0, forwardMinusStrike));
            }
            double d = forwardMinusStrike / (volatility * SqrtOfTimeToExpiration);

            return(forwardMinusStrike * StandardNormalDistribution.GetCdfValue(d) + volatility * SqrtOfTimeToExpiration * StandardNormalDistribution.GetPdfValue(d));
        }
        /// <summary>Gets the theta of the option, i.e. the partial derivative of the option value formula with respect to the time to maturity.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The theta of the option, i.e. the partial derivative of the option value formula with respect to the time to expiry.</returns>
        public double GetTheta(double volatility)
        {
            if ((m_Strike < MachineConsts.Epsilon) || (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon))
            {
                return(0.0);
            }
            double dplus  = (LogOfMoneyness + 0.5 * volatility * volatility * m_TimeToExpiration) / (volatility * SqrtOfTimeToExpiration);
            double dminus = dplus - volatility * SqrtOfTimeToExpiration;

            double tempTerm1 = 0.25 * volatility / SqrtOfTimeToExpiration;
            double tempTerm2 = LogOfMoneyness / (2.0 * volatility * m_TimeToExpiration * SqrtOfTimeToExpiration);

            return(2.0 * m_DiscountFactor * (m_Forward * StandardNormalDistribution.GetPdfValue(dplus) * (tempTerm1 - tempTerm2) + m_Strike * StandardNormalDistribution.GetPdfValue(dminus) * (tempTerm1 + tempTerm2)));
        }
        /// <summary>Gets the volga of the option, i.e. the second partial derivative of the option value formula with respect to the volatility.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The volga of the option, i.e. the second partial derivative of the option value formula with respect to the volatility.</returns>
        public double GetVolga(double volatility)
        {
            if ((m_Strike < MachineConsts.Epsilon) || (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon))
            {
                return(0.0);
            }
            double volaSquare      = volatility * volatility;
            double dminus          = (LogOfMoneyness - 0.5 * volaSquare * m_TimeToExpiration) / (volatility * SqrtOfTimeToExpiration);
            double densityAtDminus = StandardNormalDistribution.GetPdfValue(dminus);

            // compute the derivative of \phi(d_), where \phi is the density of the standard normal distribution:
            double densityDerivativeAtDminus = dminus * densityAtDminus * (0.5 * SqrtOfTimeToExpiration + LogOfMoneyness / (SqrtOfTimeToExpiration * volaSquare));

            return(m_DiscountFactor * (0.5 * SqrtOfTimeToExpiration * densityDerivativeAtDminus + (densityDerivativeAtDminus * volatility - densityAtDminus - densityAtDminus) * LogOfMoneyness / (SqrtOfTimeToExpiration * volaSquare * volatility)));
        }
        /// <summary>Gets the price of the option <c>at time of expiry</c>, i.e. not discounted.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The value of the option <c>at the time of expiry</c>, thus not discounted. To get
        /// the price just multiply the return value with the discount factor.
        /// </returns>
        public double GetNoneDiscountedValue(double volatility)
        {
            if ((m_Strike < MachineConsts.Epsilon) || (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon))
            {
                return(Math.Abs(m_Strike - m_Forward));
            }
            double dplus  = (LogOfMoneyness + 0.5 * volatility * volatility * m_TimeToExpiration) / (volatility * SqrtOfTimeToExpiration);
            double dminus = dplus - volatility * SqrtOfTimeToExpiration;

            /* the value is given by: (K: strike, f: forward), use N(-t) = 1-N(t)
             *   discfactor * [ f * N(d+) - K * N(d-) + K * N(-d-) - f * N(-d+) ], i.e. call + put value
             *   = discfactor * [ f * N(d+) - K * N(d-) + K* (1-N(d-)) - f * (1-N(d+))
             *   = discfactor * [2 * f * N(d+) - 2 * K * N(d-) + K -f] */
            return(m_Strike - m_Forward + 2.0 * m_Forward * StandardNormalDistribution.GetCdfValue(dplus) - 2.0 * m_Strike * StandardNormalDistribution.GetCdfValue(dminus));
        }
Exemple #21
0
            /// <summary>Gets the implied Black volatility of a specific european call option.
            /// </summary>
            /// <param name="strike">The strike.</param>
            /// <param name="forward">The forward.</param>
            /// <param name="timeToExpiry">The time span between valuation date and expiry date in its <see cref="System.Double"/> representation.</param>
            /// <param name="c0">The dimensionless option price, i.e. option price divided by forward and discount factor.</param>
            /// <param name="value">The implied Black volatility (output).</param>
            /// <returns>A value indicating whether <paramref name="value"/> contains valid data.</returns>
            private ImpliedCalculationResultState TryGetImpliedCallVolatility(double strike, double forward, double timeToExpiry, double c0, out double value)
            {
                /* Initial value is taken from rational approximation of a straddle option. The algorithm converges with quaratic order of convergence, therefore
                 * for an arbitrary point for which the algorithm is well-defined. Because of the good initial point, often it is one iteration required only. */

                double v0;
                double sqrtOfTime = Math.Sqrt(timeToExpiry);

                if (RationalApproximation.TryGetStraddleImpliedVolatility(strike - forward, sqrtOfTime, 2.0 * c0 * forward + strike - forward, out value) == ImpliedCalculationResultState.ProperResult)
                {
                    v0 = value * sqrtOfTime / forward;
                }
                else
                {
                    v0 = 0.1 * sqrtOfTime / forward;  // default if approximation fails.
                }

                var x = 1 - strike / forward;

                if (x > 0) // "in-out" duality
                {
                    c0 = c0 - x;
                    x  = -x;
                }
                var oneOverOnePlusW = 1.0 / (1 + m_RelaxationParameter);

                var v = v0;

                for (int j = 0; j < m_MaxNumberOfIterations; j++)
                {
                    var    n = StandardNormalDistribution.GetPdfValue(x / v);
                    var    N = StandardNormalDistribution.GetCdfValue(x / v);
                    double c = v * n + x * N;  // undiscounted normalized option value

                    v = (c0 - x * N + m_RelaxationParameter * v * n) * oneOverOnePlusW / n;

                    if (Math.Abs(c - c0) < m_Tolerance)
                    {
                        value = forward * v / sqrtOfTime;  // here, we assume that the 'new' total volatility estimation is better than the one used for the calculation of 'c'
                        return(ImpliedCalculationResultState.ProperResult);
                    }
                }
                value = v / sqrtOfTime;
                return(ImpliedCalculationResultState.NoProperResult);
            }
Exemple #22
0
 /// <summary>Gets the value of the copula at some point.
 /// </summary>
 /// <param name="x">The argument x.</param>
 /// <param name="y">The argument y.</param>
 /// <returns>
 /// The value of the copula at (<paramref name="x"/>,<paramref name="y"/>).
 /// </returns>
 public double GetValue(double x, double y)
 {
     if ((x < MachineConsts.SuperTinyEpsilon) || (y < MachineConsts.SuperTinyEpsilon))
     {
         return(0.0);
     }
     if (1.0 - x < MachineConsts.SuperTinyEpsilon)
     {
         if (1.0 - y < MachineConsts.SuperTinyEpsilon)
         {
             return(x);
         }
         return(y);
     }
     if (1.0 - y < MachineConsts.SuperTinyEpsilon)
     {
         return(x);
     }
     return(BivariateNormalDistribution.StandardCDFValue(StandardNormalDistribution.GetInverseCdfValue(x), StandardNormalDistribution.GetInverseCdfValue(y), m_Correlation));
 }
        /// <summary>Gets the implied volatility for a specific non-discounted option price.
        /// </summary>
        /// <param name="noneDiscountedValue">The value of the option at the time of expiry, thus the price but <b>not</b> discounted to time 0.</param>
        /// <param name="impliedVolatility">The implied volatility (output).</param>
        /// <returns>A value indicating whether <paramref name="impliedVolatility" /> contains valid data.</returns>
        /// <remarks>This method is the inverse function of <see cref="IConstantVolatilityStandardEuropeanOption.GetNoneDiscountedValue(double)" />.</remarks>
        public ImpliedCalculationResultState TryGetImpliedVolatilityOfNonDiscountedValue(double noneDiscountedValue, out double impliedVolatility)
        {
            double x        = Math.Log(m_Forward / m_Strike);
            double NInverse = StandardNormalDistribution.GetInverseCdfValue(noneDiscountedValue);

            if (NInverse * NInverse + 2 * x >= 0)
            {
                double root = Math.Sqrt(NInverse * NInverse + 2 * x);
                impliedVolatility = NInverse + root;

                if (NInverse - root >= 0)
                {
                    impliedVolatility = NInverse - root;
                }
                impliedVolatility /= Math.Sqrt(m_TimeToExpiration);
                return(ImpliedCalculationResultState.ProperResult);
            }
            impliedVolatility = 0.0;
            return(ImpliedCalculationResultState.NoProperResult);
        }
            /// <summary>Gets the implied Black volatility of a specific european call option.
            /// </summary>
            /// <param name="strike">The strike.</param>
            /// <param name="forward">The forward.</param>
            /// <param name="timeToExpiry">The time span between valuation date and expiry date in its <see cref="System.Double"/> representation.</param>
            /// <param name="c0">The dimensionless option price, i.e. option price divided by forward and discount factor.</param>
            /// <param name="value">The implied Black volatility (output).</param>
            /// <returns>A value indicating whether <paramref name="value"/> contains valid data.</returns>
            private ImpliedCalculationResultState TryGetImpliedCallVolatility(double strike, double forward, double timeToExpiry, double c0, out double value)
            {
                var x           = Math.Log(forward / strike);
                var expOfMinusx = strike / forward;

                if (x > 0) // "in-out" duality
                {
                    x           = -x;
                    expOfMinusx = forward / strike;

                    c0 = expOfMinusx * c0 + 1 - expOfMinusx;  // expOfMinusx = exp( [original] x )
                }
                var v0 = SOR.GetInitialCallOptionTotalVolatility(x, c0);
                var w0 = (v0 * v0 - 2 * Math.Abs(x)) / (v0 * v0 + 2 * Math.Abs(x));

                var oneOverOnePlusW = 1.0 / (1 + w0);

                var v = v0;
                var w = w0;

                for (int j = 0; j < m_MaxNumberOfIterations; j++)
                {
                    var    nPlus  = StandardNormalDistribution.GetCdfValue(x / v + 0.5 * v);
                    var    nMinus = expOfMinusx * StandardNormalDistribution.GetCdfValue(x / v - 0.5 * v);
                    double c      = nPlus - nMinus; // undiscounted normalized option value

                    var temp = StandardNormalDistribution.GetInverseCdfValue((c0 + nMinus + w * nPlus) / (1.0 + w));

                    v = temp + Math.Sqrt(temp * temp + 2.0 * Math.Abs(x));
                    w = (v * v - 2 * Math.Abs(x)) / (v * v + 2 * Math.Abs(x));

                    if (Math.Abs(c - c0) < m_Tolerance)
                    {
                        value = v / Math.Sqrt(timeToExpiry);  // here, we assume that the 'new' total volatility estimation is better than the one used for the calculation of 'c'
                        return(ImpliedCalculationResultState.ProperResult);
                    }
                }
                value = v / Math.Sqrt(timeToExpiry);
                return(ImpliedCalculationResultState.NoProperResult);
            }
        /// <summary>Gets the implied strike for a given value (price) and Black-Scholes volatility of a specific european call or put option.
        /// </summary>
        /// <param name="theta">A value indicating whether a call (=1) or put (=-1) is given.</param>
        /// <param name="forward">The forward.</param>
        /// <param name="timeToExpiry">The time span between valuation date and expiry date in its <see cref="System.Double"/> representation.</param>
        /// <param name="noneDiscountedValue">The value of the option at the time of expiry, thus the price but <b>not</b> discounted to time 0.</param>
        /// <param name="blackVolatility">The Black volatility.</param>
        /// <param name="sqrtOfTime">The square root of <paramref name="timeToExpiry"/>.</param>
        /// <param name="impliedStrike">The implied strike (output).</param>
        /// <returns>Returns a value indicating whether <paramref name="impliedStrike"/> contains valid data.</returns>
        /// <remarks>The implementation is based on the Newton approach.</remarks>
        protected static ImpliedCalculationResultState TryGetPlainVanillaImpliedStrike(int theta, double forward, double timeToExpiry, double noneDiscountedValue, double blackVolatility, double sqrtOfTime, out double impliedStrike)
        {
            /* 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).
             */

            impliedStrike = forward;
            double absOfValueAtExpiry        = Math.Abs(noneDiscountedValue);
            double optionValueForGivenStrike = noneDiscountedValue;

            double dplus, CDFAtThetaTimesdMinus;

            for (int i = 1; i <= MaxNumberIterationImpliedStrike; i++)
            {
                if (impliedStrike < MachineConsts.SuperTinyEpsilon)
                {
                    optionValueForGivenStrike = forward + impliedStrike;
                    impliedStrike             = forward - theta * noneDiscountedValue;
                }
                else
                {
                    dplus = (Math.Log(forward / impliedStrike) + 0.5 * blackVolatility * blackVolatility * timeToExpiry) / (blackVolatility * sqrtOfTime);
                    CDFAtThetaTimesdMinus = StandardNormalDistribution.GetCdfValue(theta * (dplus - blackVolatility * sqrtOfTime));

                    optionValueForGivenStrike = (theta * forward * StandardNormalDistribution.GetCdfValue(theta * dplus) - theta * impliedStrike * CDFAtThetaTimesdMinus);
                    impliedStrike            += theta * optionValueForGivenStrike * Math.Log(optionValueForGivenStrike / noneDiscountedValue) / CDFAtThetaTimesdMinus;
                }
                if (Math.Abs(noneDiscountedValue - optionValueForGivenStrike) < absOfValueAtExpiry * MachineConsts.TinyEpsilon)
                {
                    return(ImpliedCalculationResultState.ProperResult);
                }
            }
            return(ImpliedCalculationResultState.NoProperResult);
        }
        /// <summary>Gets the implied strike for a given value (price) and Bachelier (=Normal Black) volatility of a specific european call or put option.
        /// </summary>
        /// <param name="theta">A value indicating whether a call (=1) or put (=-1) is given.</param>
        /// <param name="forward">The forward.</param>
        /// <param name="undiscountedValue">The value of the option at the time of expiry, thus the price but <b>not</b> discounted to time 0.</param>
        /// <param name="bachelierVolatility">The Bachelier (=Normal Black) volatility.</param>
        /// <param name="sqrtOfTime">The square root of the time span between valuation date and expiry date.</param>
        /// <param name="impliedStrike">The implied strike (output), input represents the initial value of the Newton-Method.</param>
        /// <returns>Returns a value indicating whether <paramref name="impliedStrike"/> contains valid data.
        /// </returns>
        /// <remarks>The implementation is based on the Newton approach and the forward is used as initial guess.</remarks>
        protected static ImpliedCalculationResultState TryGetPlainVanillaImpliedStrike(int theta, double forward, double undiscountedValue, double bachelierVolatility, double sqrtOfTime, ref double impliedStrike)
        {
            /* 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).
             */
            double absOfValueAtExpiry        = Math.Abs(undiscountedValue);
            double optionValueForGivenStrike = undiscountedValue;

            double d, CDF_Theta_d;

            for (int i = 1; i <= MaxNumberIterationImpliedStrike; i++)
            {
                if (impliedStrike < MachineConsts.SuperTinyEpsilon)
                {
                    optionValueForGivenStrike = forward + impliedStrike;
                    impliedStrike             = forward - theta * undiscountedValue;
                }
                else
                {
                    d           = (forward - impliedStrike) / (bachelierVolatility * sqrtOfTime);
                    CDF_Theta_d = StandardNormalDistribution.GetCdfValue(theta * d);
                    optionValueForGivenStrike = theta * (forward - impliedStrike) * CDF_Theta_d + bachelierVolatility * sqrtOfTime * StandardNormalDistribution.GetPdfValue(theta * d);

                    impliedStrike += theta * optionValueForGivenStrike * Math.Log(optionValueForGivenStrike / undiscountedValue) / CDF_Theta_d;
                }
                if (Math.Abs(undiscountedValue - optionValueForGivenStrike) < absOfValueAtExpiry * MachineConsts.TinyEpsilon)
                {
                    return(ImpliedCalculationResultState.ProperResult);
                }
            }
            return(ImpliedCalculationResultState.NoProperResult);
        }
        /// <summary>Gets the implied strike for a specific european straddle.
        /// </summary>
        /// <param name="forward">The forward.</param>
        /// <param name="timeToExpiry">The time span between valuation date and expiry date in its <see cref="System.Double"/> representation.</param>
        /// <param name="undiscountedValue">The value of the option at the time of expiry, thus the price but <b>not</b> discounted to time 0.</param>
        /// <param name="blackVolatility">The Black volatility.</param>
        /// <param name="initialStrike">The initial strike used as initial guess for the Newton method.</param>
        /// <param name="impliedStrike">The implied strike (output).</param>
        /// <returns>
        ///    Returns a value indicating whether <paramref name="impliedStrike"/> contains valid data.
        /// </returns>
        /// <remarks>This method checks some academic conditions and is based on the Newton approach.
        ///    <para>The implied strike is not unique.</para>
        /// </remarks>
        protected static ImpliedCalculationResultState TryGetImpliedStrike(double forward, double timeToExpiry, double undiscountedValue, double blackVolatility, double initialStrike, out double impliedStrike)
        {
            /* the value of a straddle is given by K-F + 2 * CallValue(K) thus we do it in a simular way as in the case of a call option */
            impliedStrike = initialStrike;
            double optionValueForGivenStrike = undiscountedValue;
            double absUndiscountedValue      = Math.Abs(undiscountedValue);
            double sqrtOfTime = Math.Sqrt(timeToExpiry);

            double dplus, CDFAtdMinus;

            for (int i = 1; i <= MaxNumberIterationImpliedStrike; i++)
            {
                if (impliedStrike < MachineConsts.SuperTinyEpsilon)
                {
                    optionValueForGivenStrike = Math.Abs(forward - impliedStrike);
                    impliedStrike             = forward - undiscountedValue;
                }
                else
                {
                    dplus       = (Math.Log(forward / impliedStrike) + 0.5 * blackVolatility * blackVolatility * timeToExpiry) / (blackVolatility * sqrtOfTime);
                    CDFAtdMinus = StandardNormalDistribution.GetCdfValue(dplus - blackVolatility * sqrtOfTime);

                    optionValueForGivenStrike = impliedStrike - forward + 2 * (forward * StandardNormalDistribution.GetCdfValue(dplus) - impliedStrike * CDFAtdMinus);
                    impliedStrike            += optionValueForGivenStrike * Math.Log(optionValueForGivenStrike / undiscountedValue) / (1 + 2.0 * CDFAtdMinus);
                }
                if (Math.Abs(undiscountedValue - optionValueForGivenStrike) < absUndiscountedValue * MachineConsts.TinyEpsilon)
                {
                    return(ImpliedCalculationResultState.ProperResult);
                }
            }
            return(ImpliedCalculationResultState.NoProperResult);
        }
Exemple #28
0
 /// <summary>Gets the implied volatility for a specific non-discounted option price.
 /// </summary>
 /// <param name="noneDiscountedValue">The value of the option at the time of expiry, thus the price but <b>not</b> discounted to time 0.</param>
 /// <param name="impliedVolatility">The implied volatility (output).</param>
 /// <returns>A value indicating whether <paramref name="impliedVolatility" /> contains valid data.</returns>
 /// <remarks>This method is the inverse function of <see cref="IConstantVolatilityStandardEuropeanOption.GetNoneDiscountedValue(double)" />.</remarks>
 public ImpliedCalculationResultState TryGetImpliedVolatilityOfNonDiscountedValue(double noneDiscountedValue, out double impliedVolatility)
 {
     impliedVolatility = (m_Strike - m_Forward) / (SqrtOfTimeToExpiration * StandardNormalDistribution.GetInverseCdfValue(noneDiscountedValue));
     return((Double.IsInfinity(impliedVolatility) || Double.IsNaN(impliedVolatility)) ? ImpliedCalculationResultState.InputError : ImpliedCalculationResultState.ProperResult);
 }
        /// <summary>Gets the strike-delta of the option, i.e. the partial derivative of the option value formula with
        /// respect to the strike.
        /// </summary>
        /// <param name="volatility">The volatility.</param>
        /// <returns>The strike-delta of the option, i.e. the partial derivative of the option value formula with respect to the strike.</returns>
        public double GetStrikeDelta(double volatility)
        {
            if ((m_Strike < MachineConsts.Epsilon) || (volatility * volatility * m_TimeToExpiration < MachineConsts.Epsilon))
            {
                return(0.0);
            }
            double dplus  = (LogOfMoneyness + 0.5 * volatility * volatility * m_TimeToExpiration) / (volatility * SqrtOfTimeToExpiration);
            double dminus = dplus - volatility * SqrtOfTimeToExpiration;

            return(m_DiscountFactor * (-2.0 * m_Forward / (volatility * SqrtOfTimeToExpiration * m_Strike) * StandardNormalDistribution.GetPdfValue(dplus) - (2 * StandardNormalDistribution.GetCdfValue(dminus) - 1) + 2.0 * StandardNormalDistribution.GetPdfValue(dminus) / (volatility * SqrtOfTimeToExpiration)));
        }
Exemple #30
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>
 public ImpliedCalculationResultState TryGetImpliedStrike(double optionValue, double volatility, out double impliedStrike)
 {
     impliedStrike = m_Forward + volatility * SqrtOfTimeToExpiration * StandardNormalDistribution.GetInverseCdfValue(optionValue / m_DiscountFactor);
     return((Double.IsInfinity(impliedStrike) || Double.IsNaN(impliedStrike)) ? ImpliedCalculationResultState.InputError : ImpliedCalculationResultState.ProperResult);
 }