public double IV(OptionContractType optionType, double S, double K, double T, double r, double q, double optionMarketPrice)
        {
            Func <double, double> f  = sigma => Premium(optionType, S, K, T, sigma, r, q) - optionMarketPrice;
            Func <double, double> df = sigma => Vega(S, K, T, sigma, r, q);

            return(RobustNewtonRaphson.FindRoot(f, df, lowerBound: 0, upperBound: 100, accuracy: 0.001));
        }
        /// <summary>
        /// Computes theta.
        /// </summary>
        /// <param name="optionType">call or put</param>
        /// <param name="S">Underlying price</param>
        /// <param name="K">Strike price</param>
        /// <param name="T">Time to expiration in % of year</param>
        /// <param name="sigma">Volatility</param>
        /// <param name="r">continuously compounded risk-free interest rate</param>
        /// <param name="q">continuously compounded dividend yield</param>
        /// <returns></returns>
        public double Theta(OptionContractType optionType, double S, double K, double T, double sigma, double r, double q)
        {
            double d1 = D1(S, K, T, sigma, r, q);
            double d2 = D2(T, sigma, d1);

            switch (optionType)
            {
            case OptionContractType.Call:
            {
                double theta = -Math.Exp(-q * T) * (S * Normal.PDF(0, 1, d1) * sigma) / (2.0 * Math.Sqrt(T))
                               - (r * K * Math.Exp(-r * T) * Normal.CDF(0, 1, d2))
                               + q * S * Math.Exp(-q * T) * Normal.CDF(0, 1, d1);

                return(theta / 365);
            }

            case OptionContractType.Put:
            {
                double theta = -Math.Exp(-q * T) * (S * Normal.PDF(0, 1, d1) * sigma) / (2.0 * Math.Sqrt(T))
                               + (r * K * Math.Exp(-r * T) * Normal.PDF(0, 1, -d2))
                               - q * S * Math.Exp(-q * T) * Normal.CDF(0, 1, -d1);

                return(theta / 365);
            }

            default:
                throw new NotSupportedException();
            }
        }
        /// <summary>
        /// Computes delta.
        /// </summary>
        /// <param name="optionType">call or put</param>
        /// <param name="S">Underlying price</param>
        /// <param name="K">Strike price</param>
        /// <param name="T">Time to expiration in % of year</param>
        /// <param name="sigma">Volatility</param>
        /// <param name="r">continuously compounded risk-free interest rate</param>
        /// <param name="q">continuously compounded dividend yield</param>
        /// <returns></returns>
        public double Delta(OptionContractType optionType, double S, double K, double T, double sigma, double r, double q)
        {
            double d1 = D1(S, K, T, sigma, r, q);

            switch (optionType)
            {
            case OptionContractType.Call:
                return(Math.Exp(-r * T) * Normal.CDF(0, 1, d1));

            case OptionContractType.Put:
                return(-Math.Exp(-r * T) * Normal.CDF(0, 1, -d1));

            default:
                throw new NotSupportedException();
            }
        }
        /// <summary>
        /// Computes theoretical price.
        /// </summary>
        /// <param name="optionType">call or put</param>
        /// <param name="S">Underlying price</param>
        /// <param name="K">Strike price</param>
        /// <param name="T">Time to expiration in % of year</param>
        /// <param name="sigma">Volatility</param>
        /// <param name="r">continuously compounded risk-free interest rate</param>
        /// <param name="q">continuously compounded dividend yield</param>
        /// <returns></returns>
        public double Premium(OptionContractType optionType, double S, double K, double T, double sigma, double r, double q)
        {
            double d1 = D1(S, K, T, sigma, r, q);
            double d2 = D2(T, sigma, d1);

            switch (optionType)
            {
            case OptionContractType.Call:
                return(S * Math.Exp(-q * T) * Normal.CDF(0, 1, d1) - K * Math.Exp(-r * T) * Normal.CDF(0, 1, d2));

            case OptionContractType.Put:
                return(K * Math.Exp(-r * T) * Normal.CDF(0, 1, -d2) - S * Math.Exp(-q * T) * Normal.CDF(0, 1, -d1));

            default:
                throw new NotSupportedException(" Option Type Error 1 " + optionType + "Type does not exist!");
            }
        }