예제 #1
0
        public void Test()
        {
            ProjectROV r = HullAndWhite1("bond(t;2;@V1)", 1, 1, .05);

            r.Container.NMethods.Technology = ETechType.T_SIMULATION;
            r.Container.NMethods.m_UseRepeatableSequence = true;
            r.Initialize();

            AnalysisValuation valuator = new AnalysisValuation();

            valuator.BindToProject(r);
            valuator.RunAnalysis(-1);

            if (r.HasErrors)
            {
                r.DisplayErrors();
            }

            Assert.IsFalse(r.HasErrors);

            double v = r.m_ResultList[0].value;

            Console.WriteLine("v = " + v.ToString());

            Assert.AreEqual(0.9134, v, 0.0001);
        }
예제 #2
0
        public void TestCalibration()
        {
            InterestRateMarketData IData = InterestRateMarketData.FromFile("../../TestData/IRMD-sample.xml");
            CallPriceMarketData    HData = CallPriceMarketData.FromFile("../../TestData/CallData-sample.xml");
            //InterestRateMarketData IData = InterestRateMarketData.FromFile("../../../EquityModels.Tests/TestData/IRMD-EU-30102012-close.xml");
            //CallPriceMarketData HData = CallPriceMarketData.FromFile("../../../EquityModels.Tests/TestData/30102012-SX5E_Index-HestonData.xml");
            //CallPriceMarketData HData = ObjectSerialization.ReadFromXMLFile("../../../EquityModels.Tests/TestData/FTSE.xml") as CallPriceMarketData;


            List <object> l = new List <object>();

            l.Add(IData.DiscountingCurve);
            l.Add(HData);

            DupireEstimator           DE       = new DupireEstimator();
            DupireCalibrationSettings settings = new DupireCalibrationSettings();

            settings.LocalVolatilityCalculation = LocalVolatilityCalculation.Method1;


            //settings.LocalVolatilityCalculation = LocalVolatilityCalculation.QuantLib;
            EstimationResult res = DE.Estimate(l, settings);
            //int nmat = HData.Maturity.Length;
            //int nstrike = HData.Strike.Length;

            int i = 5; // Maturity.
            int j = 4; // Strike.

            Engine.MultiThread = true;

            Document   doc = new Document();
            ProjectROV rov = new ProjectROV(doc);

            doc.Part.Add(rov);
            doc.DefaultProject.NMethods.m_UseAntiteticPaths = true;
            int    n_sim   = 10000;
            int    n_steps = 500;
            double strike  = HData.Strike[j];
            //double volatility = HData.Volatility[i, j];

            /*
             * PFunction2D.PFunction2D impvolfunc = new PFunction2D.PFunction2D(rov);
             * impvolfunc = res.Objects[3] as PFunction2D.PFunction2D;
             * impvolfunc.VarName = "impvol";
             * rov.Symbols.Add(impvolfunc);
             * double volatility = impvolfunc.Evaluate(HData.Maturity[i], HData.Strike[j]);
             */
            double volatility = 0.2;
            double maturity   = HData.Maturity[i];

            ModelParameter Pstrike = new ModelParameter(strike, string.Empty, "strike");

            rov.Symbols.Add(Pstrike);
            AFunction payoff = new AFunction(rov);

            payoff.VarName = "payoff";
            payoff.m_IndependentVariables = 1;
            payoff.m_Value = (RightValue)("max(x1 - strike ; 0)");
            rov.Symbols.Add(payoff);

            bool           found;
            double         S0  = PopulateHelper.GetValue("S0", res.Names, res.Values, out found);
            ModelParameter PS0 = new ModelParameter(S0, string.Empty, "S0");

            rov.Symbols.Add(PS0);
            PFunction rfunc = new PFunction(rov);

            rfunc         = res.Objects[0] as PFunction;
            rfunc.VarName = "r";
            rov.Symbols.Add(rfunc);

            PFunction qfunc = new PFunction(rov);

            qfunc         = res.Objects[1] as PFunction;
            qfunc.VarName = "q";
            rov.Symbols.Add(qfunc);

            PFunction2D.PFunction2D volfunc = new PFunction2D.PFunction2D(rov);
            volfunc         = res.Objects[2] as PFunction2D.PFunction2D;
            volfunc.VarName = "localvol";
            rov.Symbols.Add(volfunc);
            DupireProcess process = new DupireProcess();

            process.s0       = (ModelParameter)"S0";
            process.r        = (ModelParameter)"@r";
            process.q        = (ModelParameter)"@q";
            process.localVol = (ModelParameter)"@localvol";
            double rate = rfunc.Evaluate(maturity);
            double dy   = qfunc.Evaluate(maturity);

            StochasticProcessExtendible s = new StochasticProcessExtendible(rov, process);

            rov.Processes.AddProcess(s);

            // Set the discounting.
            RiskFreeInfo rfi = rov.GetDiscountingModel() as RiskFreeInfo;

            rfi.ActualizationType = EActualizationType.RiskFree;
            rfi.m_deterministicRF = rate;
            OptionTree op = new OptionTree(rov);

            op.PayoffInfo.PayoffExpression          = "payoff(v1)";
            op.PayoffInfo.Timing.EndingTime.m_Value = (RightValue)maturity;
            op.PayoffInfo.European = true;
            rov.Map.Root           = op;

            rov.NMethods.Technology      = ETechType.T_SIMULATION;
            rov.NMethods.PathsNumber     = n_sim;
            rov.NMethods.SimulationSteps = n_steps;
            ROVSolver solver = new ROVSolver();

            solver.BindToProject(rov);
            solver.DoValuation(-1);
            if (rov.HasErrors)
            {
                rov.DisplayErrors();
            }

            Assert.IsFalse(rov.HasErrors);
            ResultItem price       = rov.m_ResultList[0] as ResultItem;
            double     samplePrice = price.value;
            double     sampleDevSt = price.stdDev / Math.Sqrt((double)n_sim);

            Console.WriteLine("Surf = " + volfunc.Expr);

            // Calculation of the theoretical value of the call.
            double theoreticalPrice = BlackScholes.Call(rate, S0, strike, volatility, maturity, dy);

            Console.WriteLine("Theoretical Price  = " + theoreticalPrice.ToString());
            Console.WriteLine("Monte Carlo Price  = " + samplePrice);
            Console.WriteLine("Standard Deviation = " + sampleDevSt.ToString());
            double tol = 4.0 * sampleDevSt;

            doc.WriteToXMLFile("Dupire.fair");
            Assert.LessOrEqual(Math.Abs(theoreticalPrice - samplePrice), tol);
        }
예제 #3
0
        public void TestSimulation()
        {
            Engine.MultiThread = true;

            Document doc = new Document();
            ProjectROV rov = new ProjectROV(doc);
            doc.Part.Add(rov);
            doc.DefaultProject.NMethods.m_UseAntiteticPaths = true;
            int n_sim = 10000;
            int n_steps = 512;
            double strike = 90.0;
            double maturity = 2.0;
            double rate = 0.1;
            double dy = 0.05;
            double volatility = 0.2;
            double S0 = 100;

            ModelParameter Pstrike = new ModelParameter(strike, string.Empty, "strike");
            rov.Symbols.Add(Pstrike);

            ModelParameter PS0 = new ModelParameter(S0, string.Empty, "S0");
            rov.Symbols.Add(PS0);

            AFunction payoff = new AFunction(rov);
            payoff.VarName = "payoff";
            payoff.m_IndependentVariables = 1;
            payoff.m_Value = (RightValue)("max(x1 - strike ; 0)");
            rov.Symbols.Add(payoff);

            AFunction rfunc = new AFunction(rov);
            rfunc.VarName = "r";
            rfunc.m_IndependentVariables = 1;
            rfunc.m_Value = (RightValue)rate;
            rov.Symbols.Add(rfunc);

            AFunction qfunc = new AFunction(rov);
            qfunc.VarName = "q";
            qfunc.m_IndependentVariables = 1;
            qfunc.m_Value = (RightValue)dy;
            rov.Symbols.Add(qfunc);

            AFunction volfunc = new AFunction(rov);
            volfunc.VarName = "localvol";
            volfunc.m_IndependentVariables = 2;
            volfunc.m_Value = (RightValue)volatility;
            rov.Symbols.Add(volfunc);

            DupireProcess process = new DupireProcess();
            process.s0 = (ModelParameter)"S0";
            process.r = (ModelParameter)"@r";
            process.q = (ModelParameter)"@q";
            process.localVol = (ModelParameter)"@localvol";

            StochasticProcessExtendible s = new StochasticProcessExtendible(rov, process);
            rov.Processes.AddProcess(s);

            // Set the discounting.
            RiskFreeInfo rfi = rov.GetDiscountingModel() as RiskFreeInfo;
            rfi.ActualizationType = EActualizationType.RiskFree;
            rfi.m_deterministicRF = rate;
            OptionTree op = new OptionTree(rov);
            op.PayoffInfo.PayoffExpression = "payoff(v1)";
            op.PayoffInfo.Timing.EndingTime.m_Value = (RightValue)maturity;
            op.PayoffInfo.European = true;
            rov.Map.Root = op;

            rov.NMethods.Technology = ETechType.T_SIMULATION;
            rov.NMethods.PathsNumber = n_sim;
            rov.NMethods.SimulationSteps = n_steps;

            ROVSolver solver = new ROVSolver();
            solver.BindToProject(rov);
            solver.DoValuation(-1);
            if (rov.HasErrors)
            {
                rov.DisplayErrors();
            }

            Assert.IsFalse(rov.HasErrors);
            ResultItem price = rov.m_ResultList[0] as ResultItem;
            double samplePrice = price.value;
            double sampleDevSt = price.stdDev / Math.Sqrt((double)n_sim);

            // Calculation of the theoretical value of the call.
            double theoreticalPrice = BlackScholes.Call(rate, S0, strike, volatility, maturity, dy);
            Console.WriteLine("Theoretical Price  = " + theoreticalPrice.ToString());
            Console.WriteLine("Monte Carlo Price  = " + samplePrice);
            Console.WriteLine("Standard Deviation = " + sampleDevSt.ToString());
            double tol = 4.0 * sampleDevSt;
            Assert.LessOrEqual(Math.Abs(theoreticalPrice - samplePrice), tol);
        }
예제 #4
0
        public void Test()
        {
            double nu = 0.6;
            double theta = -0.2;
            double sigma = 0.2;
            double rate = 0.02;
            double dy = 0.01;
            double s0 = 1;
            double maturity = 2.0;
            double strike = 1.2;
            Vector mat = new Vector(1) + maturity;
            Vector k = new Vector(1) + strike;

            // Calculates the theoretical value of the call.
            double theoreticalPrice = VarianceGammaOptionsCalibration.VGCall(theta, sigma, nu,
                                                                             maturity, strike,
                                                                             dy, s0, rate);

            Engine.MultiThread = true;
            Document doc = new Document();
            ProjectROV rov = new ProjectROV(doc);
            doc.Part.Add(rov);
            doc.DefaultProject.NMethods.m_UseAntiteticPaths = true;

            int n_sim = 50000;
            int n_steps = 512;

            ModelParameter paramStrike = new ModelParameter(strike, "strike");
            paramStrike.VarName = "strike";
            rov.Symbols.Add(paramStrike);

            ModelParameter paramRate = new ModelParameter(rate, "rfrate");
            paramRate.VarName = "rfrate";
            rov.Symbols.Add(paramRate);

            AFunction payoff = new AFunction(rov);
            payoff.VarName = "payoff";
            payoff.m_IndependentVariables = 1;
            payoff.m_Value = (RightValue)("max(x1 - strike ; 0)");
            rov.Symbols.Add(payoff);

            VarianceGamma process = new VarianceGamma(s0, theta, sigma, nu, rate, dy);

            StochasticProcessExtendible s = new StochasticProcessExtendible(rov, process);
            rov.Processes.AddProcess(s);

            // Set the discounting.
            RiskFreeInfo rfi = rov.GetDiscountingModel() as RiskFreeInfo;
            rfi.ActualizationType = EActualizationType.RiskFree;
            rfi.m_deterministicRF = rate;

            OptionTree op = new OptionTree(rov);
            op.PayoffInfo.PayoffExpression = "payoff(v1)";
            op.PayoffInfo.Timing.EndingTime.m_Value = (RightValue)maturity;
            op.PayoffInfo.European = true;
            rov.Map.Root = op;

            rov.NMethods.Technology = ETechType.T_SIMULATION;
            rov.NMethods.PathsNumber = n_sim;
            rov.NMethods.SimulationSteps = n_steps;

            ROVSolver solver = new ROVSolver();
            solver.BindToProject(rov);
            solver.DoValuation(-1);

            if (rov.HasErrors)
            {
                rov.DisplayErrors();
            }

            Assert.IsFalse(rov.HasErrors);

            ResultItem price = rov.m_ResultList[0] as ResultItem;

            double samplePrice = price.value;
            double sampleDevSt = price.stdDev / Math.Sqrt((double)n_sim);

            Console.WriteLine("Theoretical Price = " + theoreticalPrice);
            Console.WriteLine("Monte Carlo Price = " + samplePrice);
            Console.WriteLine("Standard Deviation = " + sampleDevSt.ToString());
            double tol = 4.0 * sampleDevSt;
            Assert.Less(Math.Abs(theoreticalPrice - samplePrice), tol);
        }
        public void Test()
        {
            Engine.MultiThread = true;

            Document   doc = new Document();
            ProjectROV rov = new ProjectROV(doc);

            doc.Part.Add(rov);

            AFunction zerorate = new AFunction(rov);

            zerorate.VarName = "zr";
            zerorate.m_IndependentVariables = 1;
            zerorate.m_Value = (RightValue)0.05;

            rov.Symbols.Add(zerorate);

            int    n_sim       = 4000;
            double maturityOpt = 6.5;

            // Simulation steps for a year. With stepPerYear = 150 the test will be passed.
            // But notice that the price calculated through Monte Carlo is unstable when
            // changing this value, even till 1000 steps per year.
            int    stepsPerYear = 150;
            int    n_steps      = stepsPerYear * ((int)maturityOpt);
            double strike       = 0.01;
            double tau          = 0.5;

            SquaredGaussianModel process = new SquaredGaussianModel();

            process.a1     = (ModelParameter)0.1;
            process.sigma1 = (ModelParameter)0.01;
            process.zr     = (ModelParameter)"@zr";

            StochasticProcessExtendible s = new StochasticProcessExtendible(rov, process);

            rov.Processes.AddProcess(s);

            ModelParameter PT = new ModelParameter(maturityOpt, "TT");

            PT.VarName = "TT";
            rov.Symbols.Add(PT);

            ModelParameter Ptau = new ModelParameter(tau, "tau");

            Ptau.VarName = "tau";
            rov.Symbols.Add(Ptau);

            ModelParameter Pstrike = new ModelParameter(strike, "strike");

            Pstrike.VarName = "strike";
            rov.Symbols.Add(Pstrike);

            // Set the discounting.
            RiskFreeInfo rfi = rov.GetDiscountingModel() as RiskFreeInfo;

            rfi.ActualizationType = EActualizationType.Stochastic;
            rfi.m_deterministicRF = (ModelParameter)"@V1";

            // Set the payoff.
            OptionTree op = new OptionTree(rov);

            op.PayoffInfo.PayoffExpression          = "tau*max(rate(TT;tau;@v1) - strike; 0)";
            op.PayoffInfo.Timing.EndingTime.m_Value = (RightValue)(maturityOpt + tau);
            op.PayoffInfo.European = true;
            rov.Map.Root           = op;

            rov.NMethods.Technology      = ETechType.T_SIMULATION;
            rov.NMethods.PathsNumber     = n_sim;
            rov.NMethods.SimulationSteps = n_steps;

            ROVSolver solver = new ROVSolver();

            solver.BindToProject(rov);
            solver.DoValuation(-1);

            if (rov.HasErrors)
            {
                rov.DisplayErrors();
            }

            Assert.IsFalse(rov.HasErrors);

            ResultItem price   = rov.m_ResultList[0] as ResultItem;
            double     mcPrice = price.value;
            double     mcDevST = price.stdDev / Math.Sqrt((double)n_sim);

            Caplet cplt = new Caplet();
            Vector Mat, fwd, Rk;
            Vector capMatV;
            double delta_k;
            double capMat;

            delta_k = 0.5;
            capMat  = maturityOpt + tau;
            int nmat = 2 * ((int)capMat) + 1;

            Mat    = new Vector(nmat);
            fwd    = new Vector(nmat);
            Mat[0] = 0;
            fwd[0] = zerorate.Evaluate(0);
            for (int k = 1; k < nmat; k++)
            {
                Mat[k] = tau * ((double)k);
                fwd[k] = zerorate.Evaluate(Mat[k]) * Mat[k] - zerorate.Evaluate(Mat[k - 1]) * Mat[k - 1];
            }

            fwd        = fwd / tau;
            Rk         = new Vector(1);
            Rk[0]      = strike;
            capMatV    = new Vector(2);
            capMatV[0] = maturityOpt;
            capMatV[1] = maturityOpt + tau;
            Matrix caplet = cplt.PGSMCaplets(process, Mat, fwd, Rk, delta_k, capMatV);

            double theoreticalPrice = caplet[1, 0] - caplet[0, 0];

            Console.WriteLine("\nTheoretical Price = " + theoreticalPrice.ToString());
            Console.WriteLine("Monte Carlo Price = " + mcPrice);
            Console.WriteLine("Standard Deviation = " + mcDevST);

            double tol = 4.0 * mcDevST;

            Assert.Less(Math.Abs(theoreticalPrice - mcPrice), tol);
        }
예제 #6
0
        public void TestSimulation()
        {
            Engine.MultiThread = true;

            Document   doc = new Document();
            ProjectROV rov = new ProjectROV(doc);

            doc.Part.Add(rov);
            doc.DefaultProject.NMethods.m_UseAntiteticPaths = true;
            int    n_sim      = 10000;
            int    n_steps    = 512;
            double strike     = 90.0;
            double maturity   = 2.0;
            double rate       = 0.1;
            double dy         = 0.05;
            double volatility = 0.2;
            double S0         = 100;

            ModelParameter Pstrike = new ModelParameter(strike, string.Empty, "strike");

            rov.Symbols.Add(Pstrike);

            ModelParameter PS0 = new ModelParameter(S0, string.Empty, "S0");

            rov.Symbols.Add(PS0);

            AFunction payoff = new AFunction(rov);

            payoff.VarName = "payoff";
            payoff.m_IndependentVariables = 1;
            payoff.m_Value = (RightValue)("max(x1 - strike ; 0)");
            rov.Symbols.Add(payoff);

            AFunction rfunc = new AFunction(rov);

            rfunc.VarName = "r";
            rfunc.m_IndependentVariables = 1;
            rfunc.m_Value = (RightValue)rate;
            rov.Symbols.Add(rfunc);

            AFunction qfunc = new AFunction(rov);

            qfunc.VarName = "q";
            qfunc.m_IndependentVariables = 1;
            qfunc.m_Value = (RightValue)dy;
            rov.Symbols.Add(qfunc);

            AFunction volfunc = new AFunction(rov);

            volfunc.VarName = "localvol";
            volfunc.m_IndependentVariables = 2;
            volfunc.m_Value = (RightValue)volatility;
            rov.Symbols.Add(volfunc);

            DupireProcess process = new DupireProcess();

            process.s0       = (ModelParameter)"S0";
            process.r        = (ModelParameter)"@r";
            process.q        = (ModelParameter)"@q";
            process.localVol = (ModelParameter)"@localvol";

            StochasticProcessExtendible s = new StochasticProcessExtendible(rov, process);

            rov.Processes.AddProcess(s);

            // Set the discounting.
            RiskFreeInfo rfi = rov.GetDiscountingModel() as RiskFreeInfo;

            rfi.ActualizationType = EActualizationType.RiskFree;
            rfi.m_deterministicRF = rate;
            OptionTree op = new OptionTree(rov);

            op.PayoffInfo.PayoffExpression          = "payoff(v1)";
            op.PayoffInfo.Timing.EndingTime.m_Value = (RightValue)maturity;
            op.PayoffInfo.European = true;
            rov.Map.Root           = op;

            rov.NMethods.Technology      = ETechType.T_SIMULATION;
            rov.NMethods.PathsNumber     = n_sim;
            rov.NMethods.SimulationSteps = n_steps;

            ROVSolver solver = new ROVSolver();

            solver.BindToProject(rov);
            solver.DoValuation(-1);
            if (rov.HasErrors)
            {
                rov.DisplayErrors();
            }

            Assert.IsFalse(rov.HasErrors);
            ResultItem price       = rov.m_ResultList[0] as ResultItem;
            double     samplePrice = price.value;
            double     sampleDevSt = price.stdDev / Math.Sqrt((double)n_sim);

            // Calculation of the theoretical value of the call.
            double theoreticalPrice = BlackScholes.Call(rate, S0, strike, volatility, maturity, dy);

            Console.WriteLine("Theoretical Price  = " + theoreticalPrice.ToString());
            Console.WriteLine("Monte Carlo Price  = " + samplePrice);
            Console.WriteLine("Standard Deviation = " + sampleDevSt.ToString());
            double tol = 4.0 * sampleDevSt;

            Assert.LessOrEqual(Math.Abs(theoreticalPrice - samplePrice), tol);
        }
예제 #7
0
        public void Test()
        {
            double nu       = 0.6;
            double theta    = -0.2;
            double sigma    = 0.2;
            double rate     = 0.02;
            double dy       = 0.01;
            double s0       = 1;
            double maturity = 2.0;
            double strike   = 1.2;
            Vector mat      = new Vector(1) + maturity;
            Vector k        = new Vector(1) + strike;

            // Calculates the theoretical value of the call.
            double theoreticalPrice = VarianceGammaOptionsCalibration.VGCall(theta, sigma, nu,
                                                                             maturity, strike,
                                                                             dy, s0, rate);

            Engine.MultiThread = true;
            Document   doc = new Document();
            ProjectROV rov = new ProjectROV(doc);

            doc.Part.Add(rov);
            doc.DefaultProject.NMethods.m_UseAntiteticPaths = true;

            int n_sim   = 50000;
            int n_steps = 512;

            ModelParameter paramStrike = new ModelParameter(strike, "strike");

            paramStrike.VarName = "strike";
            rov.Symbols.Add(paramStrike);

            ModelParameter paramRate = new ModelParameter(rate, "rfrate");

            paramRate.VarName = "rfrate";
            rov.Symbols.Add(paramRate);

            AFunction payoff = new AFunction(rov);

            payoff.VarName = "payoff";
            payoff.m_IndependentVariables = 1;
            payoff.m_Value = (RightValue)("max(x1 - strike ; 0)");
            rov.Symbols.Add(payoff);

            VarianceGamma process = new VarianceGamma(s0, theta, sigma, nu, rate, dy);

            StochasticProcessExtendible s = new StochasticProcessExtendible(rov, process);

            rov.Processes.AddProcess(s);

            // Set the discounting.
            RiskFreeInfo rfi = rov.GetDiscountingModel() as RiskFreeInfo;

            rfi.ActualizationType = EActualizationType.RiskFree;
            rfi.m_deterministicRF = rate;

            OptionTree op = new OptionTree(rov);

            op.PayoffInfo.PayoffExpression          = "payoff(v1)";
            op.PayoffInfo.Timing.EndingTime.m_Value = (RightValue)maturity;
            op.PayoffInfo.European = true;
            rov.Map.Root           = op;

            rov.NMethods.Technology      = ETechType.T_SIMULATION;
            rov.NMethods.PathsNumber     = n_sim;
            rov.NMethods.SimulationSteps = n_steps;

            ROVSolver solver = new ROVSolver();

            solver.BindToProject(rov);
            solver.DoValuation(-1);

            if (rov.HasErrors)
            {
                rov.DisplayErrors();
            }

            Assert.IsFalse(rov.HasErrors);

            ResultItem price = rov.m_ResultList[0] as ResultItem;

            double samplePrice = price.value;
            double sampleDevSt = price.stdDev / Math.Sqrt((double)n_sim);

            Console.WriteLine("Theoretical Price = " + theoreticalPrice);
            Console.WriteLine("Monte Carlo Price = " + samplePrice);
            Console.WriteLine("Standard Deviation = " + sampleDevSt.ToString());
            double tol = 4.0 * sampleDevSt;

            Assert.Less(Math.Abs(theoreticalPrice - samplePrice), tol);
        }
        public void Test()
        {
            Engine.MultiThread = true;

            Document doc = new Document();
            ProjectROV rov = new ProjectROV(doc);
            doc.Part.Add(rov);

            AFunction zerorate = new AFunction(rov);
            zerorate.VarName = "zr";
            zerorate.m_IndependentVariables = 1;
            zerorate.m_Value = (RightValue)0.05;

            rov.Symbols.Add(zerorate);

            int n_sim = 4000;
            double maturityOpt = 6.5;

            // Simulation steps for a year. With stepPerYear = 150 the test will be passed.
            // But notice that the price calculated through Monte Carlo is unstable when
            // changing this value, even till 1000 steps per year.
            int stepsPerYear = 150;
            int n_steps = stepsPerYear * ((int)maturityOpt);
            double strike = 0.01;
            double tau = 0.5;

            SquaredGaussianModel process = new SquaredGaussianModel();
            process.a1 = (ModelParameter)0.1;
            process.sigma1 = (ModelParameter)0.01;
            process.zr = (ModelParameter)"@zr";

            StochasticProcessExtendible s = new StochasticProcessExtendible(rov, process);
            rov.Processes.AddProcess(s);

            ModelParameter PT = new ModelParameter(maturityOpt, "TT");
            PT.VarName = "TT";
            rov.Symbols.Add(PT);

            ModelParameter Ptau = new ModelParameter(tau, "tau");
            Ptau.VarName = "tau";
            rov.Symbols.Add(Ptau);

            ModelParameter Pstrike = new ModelParameter(strike, "strike");
            Pstrike.VarName = "strike";
            rov.Symbols.Add(Pstrike);

            // Set the discounting.
            RiskFreeInfo rfi = rov.GetDiscountingModel() as RiskFreeInfo;
            rfi.ActualizationType = EActualizationType.Stochastic;
            rfi.m_deterministicRF = (ModelParameter)"@V1";

            // Set the payoff.
            OptionTree op = new OptionTree(rov);
            op.PayoffInfo.PayoffExpression = "tau*max(rate(TT;tau;@v1) - strike; 0)";
            op.PayoffInfo.Timing.EndingTime.m_Value = (RightValue)(maturityOpt + tau);
            op.PayoffInfo.European = true;
            rov.Map.Root = op;

            rov.NMethods.Technology = ETechType.T_SIMULATION;
            rov.NMethods.PathsNumber = n_sim;
            rov.NMethods.SimulationSteps = n_steps;

            ROVSolver solver = new ROVSolver();
            solver.BindToProject(rov);
            solver.DoValuation(-1);

            if (rov.HasErrors)
            {
                rov.DisplayErrors();
            }

            Assert.IsFalse(rov.HasErrors);

            ResultItem price = rov.m_ResultList[0] as ResultItem;
            double mcPrice = price.value;
            double mcDevST = price.stdDev / Math.Sqrt((double)n_sim);

            Caplet cplt = new Caplet();
            Vector Mat, fwd, Rk;
            Vector capMatV;
            double delta_k;
            double capMat;
            delta_k = 0.5;
            capMat = maturityOpt + tau;
            int nmat = 2 * ((int)capMat) + 1;
            Mat = new Vector(nmat);
            fwd = new Vector(nmat);
            Mat[0] = 0;
            fwd[0] = zerorate.Evaluate(0);
            for (int k = 1; k < nmat; k++)
            {
                Mat[k] = tau * ((double)k);
                fwd[k] = zerorate.Evaluate(Mat[k]) * Mat[k] - zerorate.Evaluate(Mat[k - 1]) * Mat[k - 1];
            }

            fwd = fwd / tau;
            Rk = new Vector(1);
            Rk[0] = strike;
            capMatV = new Vector(2);
            capMatV[0] = maturityOpt;
            capMatV[1] = maturityOpt + tau;
            Matrix caplet = cplt.PGSMCaplets(process, Mat, fwd, Rk, delta_k, capMatV);

            double theoreticalPrice = caplet[1, 0] - caplet[0, 0];

            Console.WriteLine("\nTheoretical Price = " + theoreticalPrice.ToString());
            Console.WriteLine("Monte Carlo Price = " + mcPrice);
            Console.WriteLine("Standard Deviation = " + mcDevST);

            double tol = 4.0 * mcDevST;
            Assert.Less(Math.Abs(theoreticalPrice - mcPrice), tol);
        }