Caplet prices using Pelsser Squared Gaussian model.
Example #1
0
 /// <summary>
 /// Constructor for the Pelsser Calibration Problem based on caps matrices.
 /// </summary>
 /// <param name="project">The project where this calibration is being done.</param>
 /// <param name="caplet">The Pelsser Caplet object to use.</param>
 /// <param name="capMaturity">Vector of cap maturities.</param>
 /// <param name="fwd">Forward with the deltaK step.</param>
 /// <param name="capK">The caplet strike vector (columns).</param>
 /// <param name="deltaK">Interval between caplets expressed in year.</param>
 /// <param name="capMat">The caplet maturities.</param>
 /// <param name="blackCaps">A Blacks caps matrix to use.</param>
 internal PelsserCappletOptimizationProblem(ProjectROV project, Caplet caplet, Vector capMaturity, Vector fwd, Vector capK, double deltaK, Vector capMat, Matrix blackCaps)
 {
     this.project     = project;
     this.caplet      = caplet;
     this.capMaturity = capMaturity;
     this.fwd         = fwd;
     this.capK        = capK;
     this.deltaK      = deltaK;
     this.capMat      = capMat;
     this.blackCaps   = blackCaps;
     Console.WriteLine("Pelsser Caps problem on " + this.capMaturity.Length + " x " + this.capK.Length + " elements");
 }
        /// <summary>
        /// Attempts a calibration through <see cref="PelsserCappletOptimizationProblem"/>
        /// using caps matrices.
        /// </summary>
        /// <param name="data">The data to be used in order to perform the calibration.</param>
        /// <param name="settings">The parameter is not used.</param>
        /// <param name="controller">The controller which may be used to cancel the process.</param>
        /// <returns>The results of the calibration.</returns>
        public EstimationResult Estimate(List <object> data, IEstimationSettings settings = null, IController controller = null, Dictionary <string, object> properties = null)
        {
            InterestRateMarketData dataset   = data[0] as InterestRateMarketData;
            MatrixMarketData       normalVol = null;

            if (data.Count > 1)
            {
                normalVol = (MatrixMarketData)data[1];
            }
            EstimationResult result;

            if ((dataset.ZRMarket == null) || (dataset.CapVolatility == null))
            {
                result = new EstimationResult();
                result.ErrorMessage = "Not enough data to calibrate.\n" +
                                      "The estimator needs a ZRMarket and a CapVolatility " +
                                      "defined inside InterestRateMarketData";
                return(result);
            }

            // Backup the dates
            DateTime effectiveDate = DateTime.Now.Date;
            DateTime valuationDate = DateTime.Now.Date;

            if (Document.ActiveDocument != null)
            {
                effectiveDate = Document.ActiveDocument.ContractDate;
                valuationDate = Document.ActiveDocument.SimulationStartDate;
            }

            // Creates the Context.
            Document   doc = new Document();
            ProjectROV prj = new ProjectROV(doc);

            doc.Part.Add(prj);

            Function zr = new PFunction(null);

            zr.VarName = "zr";
            // Load the zr.
            double[,] zrvalue = (double[, ])ArrayHelper.Concat(dataset.ZRMarketDates.ToArray(), dataset.ZRMarket.ToArray());
            zr.Expr           = zrvalue;

            prj.Symbols.Add(zr);


            var bm = BlackModelFactory(zr);

            if (bm is BachelierNormalModel)
            {
                (bm as BachelierNormalModel).Tenor = dataset.CapTenor;
            }

            double deltak = dataset.CapTenor;


            Matrix capVol = normalVol != null ? normalVol.Values:dataset.CapVolatility;
            Vector capMat = normalVol != null ? normalVol.RowValues: dataset.CapMaturity;
            Vector capK   = normalVol != null ? normalVol.ColumnValues: dataset.CapRate;

            var preferences = settings as Fairmat.Calibration.CapVolatilityFiltering;

            // Matrix calculated with black.
            var blackCaps = new Matrix(capMat.Length, capK.Length);

            for (int m = 0; m < capMat.Length; m++)
            {
                for (int s = 0; s < capK.Length; s++)
                {
                    bool skip = false;
                    if (preferences != null)
                    {
                        if (capK[s] < preferences.MinCapRate || capK[s] > preferences.MaxCapRate ||
                            capMat[m] < preferences.MinCapMaturity || capMat[m] > preferences.MaxCapMaturity)
                        {
                            skip = true;
                        }
                    }

                    if (capVol[m, s] == 0 || skip)
                    {
                        blackCaps[m, s] = 0;
                    }
                    else
                    {
                        blackCaps[m, s] = bm.Cap(capK[s], capVol[m, s], deltak, capMat[m]);
                    }
                }
            }

            if (blackCaps.IsNaN())
            {
                Console.WriteLine("Black caps matrix has non real values:");
                Console.WriteLine(blackCaps);
                throw new Exception("Cannot calculate Black caps");
            }

            // Maturity goes from 0 to the last item with step deltaK.
            Vector maturity = new Vector((int)(1.0 + capMat[capMat.Length - 1] / deltak));

            for (int l = 0; l < maturity.Length; l++)
            {
                maturity[l] = deltak * l;
            }

            Vector fwd = new Vector(maturity.Length - 1);

            for (int i = 0; i < fwd.Length; i++)
            {
                fwd[i] = bm.Fk(maturity[i + 1], deltak);
            }

            // Creates a default Pelsser model.
            Pelsser.SquaredGaussianModel model = new Pelsser.SquaredGaussianModel();
            model.a1     = (ModelParameter)0.014;
            model.sigma1 = (ModelParameter)0.001;
            model.zr     = (ModelParameter)"@zr";
            StochasticProcessExtendible iex = new StochasticProcessExtendible(prj, model);

            prj.Processes.AddProcess(iex);

            prj.Parse();

            DateTime t0 = DateTime.Now;
            Caplet   cp = new Caplet();

            PelsserCappletOptimizationProblem problem = new PelsserCappletOptimizationProblem(prj, cp, maturity, fwd, capK, deltak, capMat, blackCaps);

            IOptimizationAlgorithm solver  = new QADE();
            IOptimizationAlgorithm solver2 = new SteepestDescent();

            DESettings o = new DESettings();

            o.NP         = 35;
            o.TargetCost = 0.0025;
            o.MaxIter    = 10;
            o.Verbosity  = Math.Max(1, Engine.Verbose);
            o.controller = controller;
            // Parallel evaluation is not supported for this calibration.
            o.Parallel = false;
            o.Debug    = true;
            SolutionInfo solution = null;

            Vector x0 = (Vector) new double[] { 0.1, 0.1 };

            solution = solver.Minimize(problem, o, x0);
            if (solution.errors)
            {
                return(new EstimationResult(solution.message));
            }

            o.epsilon   = 10e-7;
            o.h         = 10e-7;
            o.MaxIter   = 1000;
            o.Debug     = true;
            o.Verbosity = Math.Max(1, Engine.Verbose);

            if (solution != null)
            {
                solution = solver2.Minimize(problem, o, solution.x);
            }
            else
            {
                solution = solver2.Minimize(problem, o, x0);
            }

            if (solution.errors)
            {
                return(new EstimationResult(solution.message));
            }

            Console.WriteLine(solution);

            string[] names = new string[] { "alpha1", "sigma1" };
            result = new EstimationResult(names, solution.x);

            result.ZRX        = (double[])dataset.ZRMarketDates.ToArray();
            result.ZRY        = (double[])dataset.ZRMarket.ToArray();
            result.Objects    = new object[1];
            result.Objects[0] = solution.obj;
            //result.Fit = solution.obj;//Uncomment in 1.6
            // Restore the dates
            if (Document.ActiveDocument != null)
            {
                Document.ActiveDocument.ContractDate        = effectiveDate;
                Document.ActiveDocument.SimulationStartDate = valuationDate;
            }

            return(result);
        }
 /// <summary>
 /// Constructor for the Pelsser Calibration Problem based on caps matrices.
 /// </summary>
 /// <param name="project">The project where this calibration is being done.</param>
 /// <param name="caplet">The Pelsser Caplet object to use.</param>
 /// <param name="capMaturity">Vector of cap maturities.</param>
 /// <param name="fwd">Forward with the deltaK step.</param>
 /// <param name="capK">The caplet strike vector (columns).</param>
 /// <param name="deltaK">Interval between caplets expressed in year.</param>
 /// <param name="capMat">The caplet maturities.</param>
 /// <param name="blackCaps">A Blacks caps matrix to use.</param>
 internal PelsserCappletOptimizationProblem(ProjectROV project, Caplet caplet, Vector capMaturity, Vector fwd, Vector capK, double deltaK, Vector capMat, Matrix blackCaps)
 {
     this.project = project;
     this.caplet = caplet;
     this.capMaturity = capMaturity;
     this.fwd = fwd;
     this.capK = capK;
     this.deltaK = deltaK;
     this.capMat = capMat;
     this.blackCaps = blackCaps;
     Console.WriteLine("Pelsser Caps problem on " + this.capMaturity.Length + " x " + this.capK.Length + " elements");
 }
        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);
        }
        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 = 10000;
            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 = 500;
            int n_steps = stepsPerYear * ((int)maturityOpt);
            double strike = 100.0;
            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 = "max(strike - Bond(TT;TT+tau;@v1); 0)";
            op.PayoffInfo.Timing.EndingTime.m_Value = (RightValue)maturityOpt;
            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)
            {
                Console.WriteLine(rov.m_RuntimeErrorList[0]);
            }

            Assert.IsFalse(rov.HasErrors);

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

            Caplet cplt = new Caplet();
            Vector Mat;
            Vector fwd;
            Vector Rk;
            Vector capMatV;
            double deltaK;
            double capMat;
            deltaK = 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] = (1 / strike - 1.0) / tau;
            capMatV = new Vector(2);
            capMatV[0] = maturityOpt;
            capMatV[1] = maturityOpt + tau;
            Matrix caplet = cplt.PGSMCaplets(process, Mat, fwd, Rk, deltaK, capMatV);
            Console.WriteLine("rows = " + caplet.R);
            Console.WriteLine("columns = " + caplet.C);

            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);
        }
        /// <summary>
        /// Attempts a calibration through <see cref="PelsserCappletOptimizationProblem"/>
        /// using caps matrices.
        /// </summary>
        /// <param name="data">The data to be used in order to perform the calibration.</param>
        /// <param name="settings">The parameter is not used.</param>
        /// <param name="controller">The controller which may be used to cancel the process.</param>
        /// <returns>The results of the calibration.</returns>
        public EstimationResult Estimate(List<object> data, IEstimationSettings settings = null, IController controller = null, Dictionary<string, object> properties = null)
        {
            InterestRateMarketData dataset = data[0] as InterestRateMarketData;
            EstimationResult result;
            if ((dataset.ZRMarket == null) || (dataset.CapVolatility == null))
            {
                result = new EstimationResult();
                result.ErrorMessage = "Not enough data to calibrate.\n" +
                    "The estimator needs a ZRMarket and a CapVolatility " +
                    "defined inside InterestRateMarketData";
                return result;
            }

            // Backup the dates
            DateTime effectiveDate = DateTime.Now.Date;
            DateTime valuationDate = DateTime.Now.Date;
            if (Document.ActiveDocument != null)
            {
                effectiveDate = Document.ActiveDocument.ContractDate;
                valuationDate = Document.ActiveDocument.SimulationStartDate;
            }

            // Creates the Context.
            Document doc = new Document();
            ProjectROV prj = new ProjectROV(doc);
            doc.Part.Add(prj);

            Function zr = new PFunction(null);
            zr.VarName = "zr";
            // Load the zr.
            double[,] zrvalue = (double[,])ArrayHelper.Concat(dataset.ZRMarketDates.ToArray(), dataset.ZRMarket.ToArray());
            zr.Expr = zrvalue;

            prj.Symbols.Add(zr);

            BlackModel bm = new BlackModel(zr);

            double deltak = dataset.CapTenor;

            Matrix capVol = dataset.CapVolatility;
            Vector capMat = dataset.CapMaturity;
            Vector capK = dataset.CapRate;

            var preferences = settings as Fairmat.Calibration.CapVolatilityFiltering;

            // Matrix calculated with black.
            Matrix blackCaps = new Matrix(capMat.Length, capK.Length);
            for (int m = 0; m < capMat.Length; m++)
            {
                for (int s = 0; s < capK.Length; s++)
                {
                    bool skip = false;
                    if (preferences != null)
                    {
                        if (capK[s] < preferences.MinCapRate || capK[s] > preferences.MaxCapRate ||
                           capMat[m] < preferences.MinCapMaturity || capMat[m] > preferences.MaxCapMaturity)
                                {skip = true; }
                    }

                    if (capVol[m, s] == 0 || skip)
                        blackCaps[m, s] = 0;
                    else
                        blackCaps[m, s] = bm.Cap(capK[s], capVol[m, s], deltak, capMat[m]);
                }
            }

            if (blackCaps.IsNAN())
            {
                Console.WriteLine("Black caps matrix has non real values:");
                Console.WriteLine(blackCaps);
                throw new Exception("Cannot calculate Black caps");
            }

            // Maturity goes from 0 to the last item with step deltaK.
            Vector maturity = new Vector((int)(1.0 + capMat[capMat.Length - 1] / deltak));
            for (int l = 0; l < maturity.Length; l++)
                maturity[l] = deltak * l;

            Vector fwd = new Vector(maturity.Length - 1);
            for (int i = 0; i < fwd.Length; i++)
            {
                fwd[i] = bm.Fk(maturity[i + 1], deltak);
            }

            // Creates a default Pelsser model.
            Pelsser.SquaredGaussianModel model = new Pelsser.SquaredGaussianModel();
            model.a1 = (ModelParameter)0.014;
            model.sigma1 = (ModelParameter)0.001;
            model.zr = (ModelParameter)"@zr";
            StochasticProcessExtendible iex = new StochasticProcessExtendible(prj, model);
            prj.Processes.AddProcess(iex);

            prj.Parse();

            DateTime t0 = DateTime.Now;
            Caplet cp = new Caplet();

            PelsserCappletOptimizationProblem problem = new PelsserCappletOptimizationProblem(prj, cp, maturity, fwd, capK, deltak, capMat, blackCaps);

            IOptimizationAlgorithm solver = new QADE();
            IOptimizationAlgorithm solver2 = new SteepestDescent();

            DESettings o = new DESettings();
            o.NP = 35;
            o.TargetCost = 0.0025;
            o.MaxIter = 10;
            o.Verbosity = Math.Max(1, Engine.Verbose);
            o.controller = controller;
            // Parallel evaluation is not supported for this calibration.
            o.Parallel = false;
            o.Debug = true;
            SolutionInfo solution = null;

            Vector x0 = (Vector)new double[] { 0.1, 0.1 };

            solution = solver.Minimize(problem, o, x0);
            if (solution.errors)
                return new EstimationResult(solution.message);

            o.epsilon = 10e-7;
            o.h = 10e-7;
            o.MaxIter = 1000;
            o.Debug = true;
            o.Verbosity = Math.Max(1, Engine.Verbose);

            if (solution != null)
                solution = solver2.Minimize(problem, o, solution.x);
            else
                solution = solver2.Minimize(problem, o, x0);

            if (solution.errors)
                return new EstimationResult(solution.message);

            Console.WriteLine(solution);

            string[] names = new string[] { "alpha1", "sigma1" };
            result = new EstimationResult(names, solution.x);

            result.ZRX = (double[])dataset.ZRMarketDates.ToArray();
            result.ZRY = (double[])dataset.ZRMarket.ToArray();
            result.Objects = new object[1];
            result.Objects[0] = solution.obj;
            //result.Fit = solution.obj;//Uncomment in 1.6
            // Restore the dates
            if (Document.ActiveDocument != null)
            {
                Document.ActiveDocument.ContractDate = effectiveDate;
                Document.ActiveDocument.SimulationStartDate = valuationDate;
            }

            return result;
        }