예제 #1
0
        /// <summary>
        /// Calibration objective function:
        /// squared difference between black caps and Pelsser caps.
        /// </summary>
        /// <param name='x'>
        /// The tested [alpha, sigma] vector.
        /// </param>
        /// <returns>
        /// A scalar containing the sum of squared differences between
        /// black Caps and the Pelsser Caps.
        /// </returns>
        public double Obj(DVPLI.Vector x)
        {
            SquaredGaussianModel model = Assign(this.project, x);

            try
            {
                Matrix caps = this.caplet.PGSMCaplets(model, this.capMaturity, this.fwd, this.capK, this.deltaK, this.capMat);
                double sum  = 0;
                for (int r = 0; r < caps.R; r++)
                {
                    for (int c = 0; c < caps.C; c++)
                    {
                        if (this.blackCaps[r, c] != 0.0)
                        {
                            sum += Math.Pow(caps[r, c] - this.blackCaps[r, c], 2);
                        }
                    }
                }

                double penalty = 100 * PelsserConstraint(this.project, x, 50).Norm();

                return(Math.Sqrt(sum / (caps.R * caps.C)) + penalty);
            }
            catch (Exception)
            {
                return(1000 * x.Norm(NormType.L2));
            }
        }
예제 #2
0
        /// <summary>
        /// Creates a representation of the Pelsser constraints.
        /// </summary>
        /// <remarks>
        /// The method is static in order to be used by other classes.
        /// </remarks>
        /// <param name="project">The project where to evaluate the constraints.</param>
        /// <param name="x">The vector of x values.</param>
        /// <param name="maturity">The cap maturity to use to evaluate the constraints.</param>
        /// <returns>
        /// A vector with the representation of the Pelsser constraints.
        /// </returns>
        public static DVPLI.Vector PelsserConstraint(ProjectROV project, DVPLI.Vector x, double maturity)
        {
            // This is modeled as a one-dimensional bound.
            SquaredGaussianModel model = Assign(project, x);
            Vector res = new Vector(1);

            double dt = 1.0 / (252);

            for (double t = 0; t <= maturity; t += dt)
            {
                res[0] += Math.Max(0, -model.F2(t, dt)); // The square of F.
            }

            /*
             * dt = .1317;
             * for (double t = 0; t <= 2; t += dt)
             *  res[0] +=Math.Max(0,-model.F2(t, dt)); // The square of F.
             *
             *
             * dt = .25;
             * for (double t = 0; t <= 2; t += dt)
             *  res[0] +=Math.Max(0,-model.F2(t, dt)); // The square of F.
             */

            return(res);
        }
예제 #3
0
        /// <summary>
        /// Calculates the integral C(t, T) function with T taking
        /// every element of the parameter mat.
        /// </summary>
        /// <param name="model">The model instance.</param>
        /// <param name="t">The starting point of the integral.</param>
        /// <param name="mat">The vector of ending interval points T.</param>
        /// <returns>The vector of pre-calculated C(t,T).</returns>
        private Vector CtT(SquaredGaussianModel model, double t, Vector mat)
        {
            Vector C = new Vector(mat.Length);

            for (int i = 0; i < mat.Length; i++)
            {
                C[i] = model.C(mat[i] - t);
            }
            return(C);
        }
예제 #4
0
        /// <summary>
        /// Assigns new trial values for x in order to use it
        /// for the evaluation of the constraints and the objective function.
        /// </summary>
        /// <param name="project">The project where to evaluate.</param>
        /// <param name="x">The vector of x values.</param>
        /// <returns>A <see cref="SquaredGaussianModel"/> set with the values.</returns>
        internal static SquaredGaussianModel Assign(ProjectROV project, Vector x)
        {
            Engine.Parser.NewContext();

            SquaredGaussianModel model = project.Processes[0].Plugin as SquaredGaussianModel;

            // Assign the new values.
            ModelParameter a1 = model.a1 as ModelParameter;
            ModelParameter s1 = model.sigma1 as ModelParameter;

            a1.m_Value = (RightValue)x[0];
            s1.m_Value = (RightValue)x[1];

            bool errors = model.Parse(null);

            if (errors)
            {
                throw new Exception("Cannot Assing model");
            }

            return(model);
        }
        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);
        }
예제 #7
0
        /// <summary>
        /// Caplet prices calculated as a put on a zero coupon bond.
        /// </summary>
        /// <param name="model">The model to use to execute the calculation.</param>
        /// <param name="mat">
        /// Caplet maturity. This vector starts from zero and increases
        /// of step DeltaK each element till the last one.
        /// </param>
        /// <param name="fwd">Forward with the deltaK step.</param>
        /// <param name="rk">Strike vector (columns).</param>
        /// <param name="deltaK">Amount to use as increase factor.</param>
        /// <param name="tOss">The Maturities.</param>
        /// <returns>A <see cref="Matrix"/> with the caplet prices.</returns>
        public Matrix PGSMCaplets(SquaredGaussianModel model, Vector mat, Vector fwd, Vector rk, double deltaK, Vector tOss)
        {
            double s   = model.sigma1.fV();
            int    col = rk.Length;

            int NP = (int)(1 + tOss[tOss.Length - 1] * 252);

            double[] dates = new double[NP];
            double   step  = mat[mat.Length - 1] / (NP - 1);

            for (int z = 0; z < NP; z++)
            {
                dates[z] = step * z;
            }

            DateTime t0 = DateTime.Now;

            model.Setup(dates);
            DateTime t1 = DateTime.Now;

            Vector K       = 1.0 / (1 + rk * deltaK);
            double cCost   = model.C(deltaK);
            Vector sigma0s = Math.Pow(s, 2) * CtT(model, 0, mat);

            Matrix caplets = new Matrix(mat.Length - 1, rk.Length);
            Matrix caps    = new Matrix(tOss.Length, rk.Length);

            // Pre-calculate values.
            Vector logK = Vector.Log(K);

            // Parallel version.
            List <Task> tl = new List <Task>();

            Context context = new Context();

            context.Model    = model;
            context.Mat      = mat;
            context.Fwd      = fwd;
            context.RK       = rk;
            context.DeltaK   = deltaK;
            context.TOss     = tOss;
            context.K        = K;
            context.LogK     = logK;
            context.Caplets  = caplets;
            context.Sigma0s  = sigma0s;
            context.CCost    = cCost;
            context.RowStart = 0;
            context.RowEnd   = (mat.Length - 2) / 2;
            tl.Add(Task.Factory.StartNew(Context.CalculateRowP, context));

            context          = new Context();
            context.Model    = model;
            context.Mat      = mat;
            context.Fwd      = fwd;
            context.RK       = rk;
            context.DeltaK   = deltaK;
            context.TOss     = tOss;
            context.K        = K;
            context.LogK     = logK;
            context.Caplets  = caplets;
            context.Sigma0s  = sigma0s;
            context.CCost    = cCost;
            context.RowStart = (mat.Length - 2) / 2 + 1;
            context.RowEnd   = mat.Length - 2 - 1;
            tl.Add(Task.Factory.StartNew(Context.CalculateRowP, context));

            tsScheduler.WaitTaskList(tl);

            // Sequential version.

            /*
             * Context Context = new Context();
             * Context.Model = Model;
             * Context.Mat = Mat;
             * Context.Fwd = Fwd;
             * Context.RK = RK;
             * Context.DeltaK = DeltaK;
             * Context.TOss = TOss;
             * Context.K = K;
             * Context.LogK = LogK;
             * Context.Caplets = Caplets;
             * Context.Sigma0s = Sigma0s;
             * Context.CCost = CCost;
             *
             * for (int r = 0; r < Mat.Length - 2; r++)
             * Context.CalculateRow(r);
             */

            // Calculate the caps from the caplets.
            for (int r = 0; r < tOss.Length; r++)
            {
                for (int c = 0; c < rk.Length; c++)
                {
                    double current = 0;
                    for (int ci = 0; ci < (int)(tOss[r] / deltaK) - 1; ci++)
                    {
                        current += caplets[ci, c];
                    }
                    caps[r, c] = current;
                }
            }

            return(caps);
        }