/// <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)); } }
/// <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); }
/// <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); }
/// <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); }
/// <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); }