public static double CalculateImpliedVolCall(double C, double S, double k, double r, double T, double x0 = 0.5, double maxErr = 1e-6, int N = 10000)
        {
            Func <double, double> F = (x) =>
            {
                return(C - BlackScholesFormula.CalculateCallOptionPrice(x, S, k, r, T));
            };
            NewtonSolver s = new NewtonSolver(maxErr, N);

            return(s.Solve(F, null, x0));
        }
        public static double CalculateImpliedVolPut(double P, double S, double k, double r, double T, double x0 = 0.5, double maxErr = 1e-6, int N = 10000)
        {
            double callPrice = BlackScholesFormula.GetCallFromPutPrice(S, k, r, T, P);

            if (callPrice < 0)
            {
                throw new System.ArgumentException("Input arguments violate put/call parity.");
            }

            return(CalculateImpliedVolCall(callPrice, S, k, r, T, x0, maxErr, N));
        }
        public static void RunEurOptionPricing()
        {
            double[] ssviParams = new double[] { Math.Sqrt(0.1), 1, 0.7, 0.2, 0.3 };
            double   r          = 0.025;
            double   S0         = 100;
            double   T          = 1;
            int      N          = 10000;
            int      M          = 128;
            double   K          = 102;
            double   k          = Math.Log(K * Math.Exp(-r * T) / S0);

            MonteCarloPricingLocalVol pricer = new MonteCarloPricingLocalVol(r, N, M, ssviParams);
            double McPriceCall = pricer.CalculateEurPutOptionPrice(S0, K, T);
            Ssvi   SsviSurface = new Ssvi(ssviParams[0], ssviParams[1], ssviParams[2], ssviParams[3], ssviParams[4]);
            double sigmaBs     = Math.Sqrt(SsviSurface.OmegaSsvi(T, k) / T);
            double BsPriceCall = BlackScholesFormula.CalculatePutOptionPrice(sigmaBs, 100, k, r, T);

            Console.WriteLine("Call price: MC: £{0}, BS £{1}", McPriceCall, BsPriceCall);
        }