public double CalculateIVByOptionPrice(double stockPrice, int dayLefts)
        {
            var blackNScholesCaculator = new BlackNScholesCaculator()
            {
                DayLefts = dayLefts,

                RiskFreeInterestRate = RiskFreeInterestRate,
                StockPrice           = stockPrice,
                Strike = StrikePrice
            };
            double iv = 0;

            try
            {
                iv = OptionType == EOptionType.Call
                       ? blackNScholesCaculator.GetCallIVBisections(BaseOptionPrice)
                       : blackNScholesCaculator.GetPutIVBisections(BaseOptionPrice);
            }
            catch (Exception ex)
            {
                Logger.Error(ex.Message + ": wrong calculation, ImpliedVolatilitiesBase = 0 !!!!", ex);
            }

            ImpliedVolatilitiesBase = iv;
            return(iv);
        }
        public void Calculate()
        {
            var blackNScholesCaculator = new BlackNScholesCaculator
            {
                DayLefts             = DayLefts,
                ImpliedVolatilities  = ImpliedVolatilities,
                RiskFreeInterestRate = RiskFreeInterestRate,
                StockPrice           = StockPrice,
                Strike     = StrikePrice,
                Multiplier = Multiplier
            };

            blackNScholesCaculator.CalculateAll();
            if (OptionType == EOptionType.Call)
            {
                ResultDataValues.OptionPrice = Double.IsNaN(blackNScholesCaculator.CallValue) ? 0 : blackNScholesCaculator.CallValue;
                ResultDataValues.Delta       = blackNScholesCaculator.DeltaCall;
                ResultDataValues.Gamma       = blackNScholesCaculator.GamaCall;
                ResultDataValues.Theta       = blackNScholesCaculator.ThetaCall;
                ResultDataValues.Vega        = blackNScholesCaculator.VegaCall;
            }
            else
            {
                ResultDataValues.OptionPrice = Double.IsNaN(blackNScholesCaculator.PutValue) ? 0 : blackNScholesCaculator.PutValue;
                //ResultDataValues.OptionPrice = blackNScholesCaculator.PutValue;
                ResultDataValues.Delta = blackNScholesCaculator.DeltaPut;
                ResultDataValues.Gamma = blackNScholesCaculator.GamaPut;
                ResultDataValues.Theta = blackNScholesCaculator.ThetaPut;
                ResultDataValues.Vega  = blackNScholesCaculator.VegaPut;
            }
        }
        public static bool TestPutCalculation()
        {
            var o = new BlackNScholesCaculator
            {
                DayLefts             = 90,
                ImpliedVolatilities  = 0.2,
                OptionType           = EOptionType.Call,
                RiskFreeInterestRate = 0.1,
                StockPrice           = 50,
                Strike = 40
            };
            var putValue = o.CalculatePutValue();

            return(!(Abs(putValue - 0.078) > 0.001));
        }
        //public double CalculateImpliedVolatilityBNSNewton(double callOptionPrice)
        //{
        //    double impliedVolatility = OptionPriceImpliedVolatilityCallBlackScholesNewton(StockPrice, Strike,
        //        RiskFreeInterestRate, ExpiryTime, callOptionPrice);
        //    return impliedVolatility;
        //}
        /// <summary>
        /// Calculates implied volatility for the Black Scholes formula using
        /// the Newton-Raphson formula
        ///
        /// Converted to C# from "Financial Numerical Recipes in C" by:
        /// Bernt Arne Odegaard
        /// http://finance.bi.no/~bernt/gcc_prog/index.html
        ///
        /// (NOTE: In the original code a large negative number was used as an
        /// exception handling mechanism.  This has been replace with a generic
        /// 'Exception' that is thrown.  The original code is in place and commented
        /// if you want to use the pure version of this code)
        /// </summary>
        /// <param name="spot">spot (underlying) price</param>
        /// <param name="strike">strike (exercise) price</param>
        /// <param name="interestRate">interest rate</param>
        /// <param name="time">time to maturity</param>
        /// <param name="optionPrice">The price of the option</param>
        /// <returns>Sigma (implied volatility)</returns>
        public double OptionPriceImpliedVolatilityCallBlackScholesNewton(double spot, double strike, double interestRate,
                                                                         double time, double optionPrice)
        {
            // check for arbitrage violations. Option price is too low if this happens
            if (optionPrice < 0.99 * (spot - strike * Exp(-time * interestRate)))
            {
                return(0.0);
            }

            const int    MAX_ITERATIONS = 100;
            const double ACCURACY       = 1.0e-5;
            double       tSqrt          = Sqrt(time);

            var blackNScholesCaculator = new BlackNScholesCaculator
            {
                ExpiryTime           = time,
                RiskFreeInterestRate = interestRate,
                StockPrice           = spot,
                Strike = strike,
                //ImpliedVolatilities = sigmaHigh
            };

            double sigma = (optionPrice / spot) / (0.398 * tSqrt);    // find initial value

            for (int i = 0; i < MAX_ITERATIONS; i++)
            {
                blackNScholesCaculator.ImpliedVolatilities = sigma;
                blackNScholesCaculator.CalculateAll();
                double price = blackNScholesCaculator.CallValue;
                // price = OptionPriceCallBlackScholes(spot, strike, interestRate, sigma, time);
                double diff = optionPrice - price;
                if (Abs(diff) < ACCURACY)
                {
                    return(sigma);
                }
                double d1 = (Log(spot / strike) + interestRate * time) / (sigma * tSqrt) + 0.5 * sigma * tSqrt;

                double vega = spot * tSqrt * CumulativeNormDist(d1);
                sigma = sigma + diff / vega;
            }
            //return -99e10;  // something screwy happened, should throw exception  // <--- original code
            throw new Exception("An error occurred"); // Comment this line if you uncomment the line above
        }
        public static bool TestCallCalculation()
        {
            var o = new BlackNScholesCaculator
            {
                //ExpiryTime = 0.25,
                DayLefts             = 90,
                ImpliedVolatilities  = 0.2,
                OptionType           = EOptionType.Call,
                RiskFreeInterestRate = 0.1,
                StockPrice           = 50,
                Strike = 40
            };
            double callValue = o.CalculateCallValue();

            if (Abs(callValue - 11.01) > 0.1)
            {
                return(false);
            }

            return(true);
        }
        /// <summary>
        /// Calculates implied volatility for the Black Scholes formula using
        /// binomial search algorithm
        ///
        /// Converted to C# from "Financial Numerical Recipes in C" by:
        /// Bernt Arne Odegaard
        /// http://finance.bi.no/~bernt/gcc_prog/index.html
        ///
        /// (NOTE: In the original code a large negative number was used as an
        /// exception handling mechanism.  This has been replace with a generic
        /// 'Exception' that is thrown.  The original code is in place and commented
        /// if you want to use the pure version of this code)
        /// </summary>
        /// <param name="spot">spot (underlying) price</param>
        /// <param name="strike">strike (exercise) price</param>
        /// <param name="interestRate">interest rate</param>
        /// <param name="time">time to maturity</param>
        /// <param name="optionPrice">The price of the option</param>
        /// <returns>Sigma (implied volatility)</returns>
        public double PutOptionPriceIVBisections(double spot, double strike, double interestRate,
                                                 double time, double optionPrice)
        {
            // check for arbitrage violations.
            if (optionPrice < 0.99 * (spot - strike * Exp(-time * interestRate)))
            {
                return(0.0);   // Option price is too low if this happens
            }

            // simple binomial search for the implied volatility.
            // relies on the value of the option increasing in volatility
            const double ACCURACY       = 1.0e-5; // make this smaller for higher accuracy
            const int    MAX_ITERATIONS = 100;
            const double HIGH_VALUE     = 1e10;
            //const double ERROR = -1e40;  // <--- original code

            // want to bracket sigma. first find a maximum sigma by finding a sigma
            // with a estimated price higher than the actual price.
            double sigmaLow  = 1e-5;
            double sigmaHigh = 0.3;

            var blackNScholesCaculator = new BlackNScholesCaculator
            {
                ExpiryTime           = time,
                RiskFreeInterestRate = interestRate,
                StockPrice           = spot,
                Strike = strike,
                ImpliedVolatilities = sigmaHigh
            };

            blackNScholesCaculator.CalculateAll();
            double price = blackNScholesCaculator.PutValue;

            while (price < optionPrice)
            {
                sigmaHigh = 2.0 * sigmaHigh; // keep doubling.
                blackNScholesCaculator.ImpliedVolatilities = sigmaHigh;
                blackNScholesCaculator.CalculateAll();
                price = blackNScholesCaculator.PutValue;

                if (sigmaHigh > HIGH_VALUE)
                {
                    //return ERROR; // panic, something wrong.     // <--- original code
                    throw new Exception("panic, something wrong."); // Comment this line if you uncomment the line above
                }
            }
            for (int i = 0; i < MAX_ITERATIONS; i++)
            {
                double sigma = (sigmaLow + sigmaHigh) * 0.5;

                blackNScholesCaculator.ImpliedVolatilities = sigma;
                blackNScholesCaculator.CalculateAll();
                price = blackNScholesCaculator.PutValue;

                double test = (price - optionPrice);
                if (Abs(test) < ACCURACY)
                {
                    IterationCounter = i;
                    return(sigma);
                }
                if (test < 0.0)
                {
                    sigmaLow = sigma;
                }
                else
                {
                    sigmaHigh = sigma;
                }
            }
            //return ERROR;      // <--- original code
            throw new Exception("An error occurred"); // Comment this line if you uncomment the line above
        }