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);
        }
        public double CalcMeanSquareErrorBetweenOmegaAndMarketNonATM(Ssvi m)
        {
            double meanSqErr = 0;
            int    nElements = 0;

            foreach (OptionMarketData option in marketOptionsList)
            {
                double maturity = option.maturity;
                string type     = option.type;
                double strike   = option.strike;
                double k        = Math.Log(strike * Math.Exp(-r0) / S0);
                double omega    = m.OmegaSsvi(maturity, k);
                double bsImpliedVolatility;
                if (option.type == "Call" || option.type == "call" || option.type == "C" || option.type == "c")
                {
                    bsImpliedVolatility = BlackScholesImpliedVolatility.CalculateImpliedVolCall(option.marketPrice, S0, k, r0, maturity);
                }
                else if (option.type == "Put" || option.type == "put" || option.type == "P" || option.type == "p")
                {
                    bsImpliedVolatility = BlackScholesImpliedVolatility.CalculateImpliedVolPut(option.marketPrice, S0, k, r0, maturity);
                }
                else
                {
                    throw new CalibrationFailedException("Option type in marketOptionsList was not Call, call, C, c, Put, put, P or p");
                }
                double difference = omega - bsImpliedVolatility * bsImpliedVolatility * maturity;
                meanSqErr += difference * difference;
                nElements++;
            }
            if (nElements > 0)
            {
                return(meanSqErr / nElements);
            }
            else
            {
                throw new ArgumentNullException("There is no market data to use for error calculation.");
            }
        }