/// <summary> /// Format the y parameter so it can be made compatible with <see cref="Pelsser.Bond"/>. /// </summary> /// <param name="y">The y parameter wanted inside Bond.</param> /// <param name="process">The Pelsser process which will be used.</param> /// <returns>The Matrix to pass to Bond.</returns> private Matrix DynamicParam(double y, SquaredGaussianModel process) { double alphaT = process.F(process.CacheDates[0], process.CacheDates[1] - process.CacheDates[0]) + 2 * Math.Exp(-process.a1.V() * process.CacheDates[0]) * process.Int(0, process.CacheDates[0]); return(new Matrix(new double[] { Math.Pow(y + alphaT, 2) })); }
public static void Calculate(double t1, double t2, double simEnd, int numSim, int numSteps, out double val, out double stDev) { 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); // To be changed to 350000. int n_sim = numSim; int n_steps = numSteps; 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); // Set the discounting. RiskFreeInfo rfi = rov.GetDiscountingModel() as RiskFreeInfo; rfi.ActualizationType = EActualizationType.RiskFree; rfi.m_deterministicRF = 0.0; OptionTree op = new OptionTree(rov); op.PayoffInfo.PayoffExpression = "bond(" + t1.ToString() + ";" + t2.ToString() + ";@v1)"; // Here we put the simulation maturity. op.PayoffInfo.Timing.EndingTime.m_Value = (RightValue)simEnd; 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]); } ResultItem price = rov.m_ResultList[0] as ResultItem; val = price.value; stDev = price.stdDev / Math.Sqrt((double)numSim); }
public void Test() { 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 = 5000; int n_steps = 900; SquaredGaussianModel process = new SquaredGaussianModel(); process.a1 = (ModelParameter)0.0704877770928728; process.sigma1 = (ModelParameter)0.116251516678772; process.zr = (ModelParameter)"@zr"; StochasticProcessExtendible s = new StochasticProcessExtendible(rov, process); rov.Processes.AddProcess(s); OptionTree op = new OptionTree(rov); op.PayoffInfo.PayoffExpression = "bond(t;10;@v1)"; // Set the simulation maturity. op.PayoffInfo.Timing.EndingTime.m_Value = (RightValue)2.0; 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); }
/// <summary> /// Constructor to create a new instance of the PelsserCache. /// </summary> /// <param name="t">The first date parameter this element is referenced to.</param> /// <param name="s">The second date parameter this element is referenced to.</param> /// <param name="p_instance"> /// The instance to the <see cref="SquaredGaussianModel"/> this cache references to. /// </param> public PelsserCache(double t, double s, SquaredGaussianModel p_instance) { this.instance = p_instance; double[] btT; // Integral calculation is always done with daily intervals. int ipy = 252; double cached_dt = this.instance.CacheDates[1] - this.instance.CacheDates[0]; // Indices representing t and s on the mDates discretization. if (this.instance.CacheDates[this.instance.CacheDates.Length - 1] < s || 1.0 / cached_dt < ipy) { double dt = 1.0 / ipy; double[] newDates = new double[(int)(1 + s * ipy)]; for (int j = 0; j < newDates.Length; j++) { newDates[j] = j * dt; } this.instance.CalculateValueForCache(newDates); } int ti = DVPLDOM.AdaptiveTimeDiscretization.DiscreteTime(t, this.instance.CacheDates); int si = DVPLDOM.AdaptiveTimeDiscretization.DiscreteTime(s, this.instance.CacheDates); double delta = this.instance.CacheDates[1] - this.instance.CacheDates[0]; btT = this.instance.B(ti, si, delta); this.A = this.instance.A(ti, si, delta, btT); if (btT.Length > 0) { this.B = btT[0]; } this.CtT0 = this.instance.C(s - t); }
/// <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; }
/// <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> /// Constructor to create a new instance of the PelsserCache. /// </summary> /// <param name="t">The first date parameter this element is referenced to.</param> /// <param name="s">The second date parameter this element is referenced to.</param> /// <param name="p_instance"> /// The instance to the <see cref="SquaredGaussianModel"/> this cache references to. /// </param> public PelsserCache(double t, double s, SquaredGaussianModel p_instance) { this.instance = p_instance; double[] btT; // Integral calculation is always done with daily intervals. int ipy = 252; double cached_dt = this.instance.CacheDates[1] - this.instance.CacheDates[0]; // Indices representing t and s on the mDates discretization. if (this.instance.CacheDates[this.instance.CacheDates.Length - 1] < s || 1.0 / cached_dt < ipy) { double dt = 1.0 / ipy; double[] newDates = new double[(int)(1 + s * ipy)]; for (int j = 0; j < newDates.Length; j++) newDates[j] = j * dt; this.instance.CalculateValueForCache(newDates); } int ti = DVPLDOM.AdaptiveTimeDiscretization.DiscreteTime(t, this.instance.CacheDates); int si = DVPLDOM.AdaptiveTimeDiscretization.DiscreteTime(s, this.instance.CacheDates); double delta = this.instance.CacheDates[1] - this.instance.CacheDates[0]; btT = this.instance.B(ti, si, delta); this.A = this.instance.A(ti, si, delta, btT); if (btT.Length > 0) { this.B = btT[0]; } this.CtT0 = this.instance.C(s - t); }
/// <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; }
/// <summary> /// Format the y parameter so it can be made compatible with <see cref="Pelsser.Bond"/>. /// </summary> /// <param name="y">The y parameter wanted inside Bond.</param> /// <param name="process">The Pelsser process which will be used.</param> /// <returns>The Matrix to pass to Bond.</returns> private Matrix DynamicParam(double y, SquaredGaussianModel process) { double alphaT = process.F(process.CacheDates[0], process.CacheDates[1] - process.CacheDates[0]) + 2 * Math.Exp(-process.a1.V() * process.CacheDates[0]) * process.Int(0, process.CacheDates[0]); return new Matrix(new double[] { Math.Pow(y + alphaT, 2) }); }
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 = 5000; int n_steps = 900; 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); // Set the discounting. RiskFreeInfo rfi = rov.GetDiscountingModel() as RiskFreeInfo; rfi.ActualizationType = EActualizationType.RiskFree; rfi.m_deterministicRF = 0.0; OptionTree op = new OptionTree(rov); op.PayoffInfo.PayoffExpression = "bond(t;10;@v1)"; // Set the simulation maturity. op.PayoffInfo.Timing.EndingTime.m_Value = (RightValue)2.0; 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; Console.WriteLine("Bond Test Value = " + price.value.ToString()); Assert.LessOrEqual(Math.Abs(0.6702 - price.value), .01); // Try to do some simple tests and check the results. double b0_10 = process.Bond(DynamicParam(0, process), process.CacheDates, 0, 0, 10); Console.WriteLine("Bond(0,10) = " + b0_10); Assert.LessOrEqual(Math.Abs(b0_10 - 0.606513), .001); double b7_10 = process.Bond(DynamicParam(0.00427631, process), process.CacheDates, 0, 7, 10); Console.WriteLine("Bond(7,10) = " + b7_10); Assert.LessOrEqual(Math.Abs(b7_10 - 0.856374), .001); double b7_30 = process.Bond(DynamicParam(0.00427631, process), process.CacheDates, 0, 7, 30); }