/// <summary> /// This method is unused but part of the interface. /// </summary> /// <param name="x">The parameter is not used.</param> /// <returns>Nothing the function always throws a NotImplementedException.</returns> public DVPLI.Vector Grad(DVPLI.Vector x) { throw new NotImplementedException(); }
/// <summary> /// Calibration objective function. /// </summary> /// <param name='x'> /// The vector of parameters. /// </param> /// <returns> /// Objective function value. /// </returns> public virtual double Obj(DVPLI.Vector x) { double sum = 0; if(Engine.MultiThread && !displayObjInfo) { // Instantiate parallel computation if enabled. List<Task> tl = new List<Task>(); // Context contains both input parameters and outputs. List<HestonCall> context = new List<HestonCall>(); for (int r = 0; r < this.callMarketPrice.R; r++) { if (this.maturity[r] >= this.matBound[0]) { HestonCall hc = new HestonCall(this, x, this.s0); context.Add(hc); hc.T = this.maturity[r]; hc.rate = this.rate[r]; if (HestonConstantDriftEstimator.impliedDividends) hc.dividend = x[Range.End]; else hc.dividend = this.dividendYield[r]; hc.row = r; tl.Add(Task.Factory.StartNew(this.CalculateSingleRow, hc)); } } tsScheduler.WaitTaskList(tl); for (int r = 0; r < tl.Count; r++) sum += context[r].sum; } else { // Sequential version of the code, used when parallel computation is disabled. HestonCall hc = new HestonCall(this, x, this.s0); for (int r = 0; r < this.callMarketPrice.R; r++) { if (this.maturity[r] >= this.matBound[0]) { hc.T = this.maturity[r]; hc.rate = this.rate[r]; if (HestonConstantDriftEstimator.impliedDividends) hc.dividend = x[Range.End]; else hc.dividend = this.dividendYield[r]; hc.row = r; hc.sum = 0; this.CalculateSingleRow(hc); sum += hc.sum; } } var pricingErrors = hc.hestonCallPrice - this.callMarketPrice; if (displayObjInfo) { avgPricingError = 0; for (int r = 0; r < this.callMarketPrice.R; r++) if (this.maturity[r] >= this.matBound[0]) { for (int c = 0; c < this.callMarketPrice.C; c++) { if (this.callMarketPrice[r, c] > s0 * optionThreshold && this.cpmd.CallVolume[r, c] > 0) avgPricingError += Math.Abs(pricingErrors[r, c]); //if (this.cpmd.PutPrice[r, c] > s0 * optionThreshold && this.cpmd.PutVolume[r, c] > 0) // avgPricingError += Math.Abs(pricingErrors[r, c]); } } avgPricingError /= numCall; int RR = Math.Min(12, this.callMarketPrice.R - 1); int CC = Math.Min(12, this.callMarketPrice.C - 1); Console.WriteLine("Mkt Price"); Console.WriteLine(this.callMarketPrice[Range.New(0,RR),Range.New(0,CC)]); Console.WriteLine("Pricing Errors"); Console.WriteLine(pricingErrors[Range.New(0, RR), Range.New(0, CC)]); } objCount++; } //Calculate average distance... sum = Math.Sqrt( sum /this.totalVolume); if (this.useBoundPenalty) sum += this.BoundPenalty(x); if (this.useFellerPenalty) sum +=this.FellerPenalty(x); return sum; }
/// <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> /// This method is unused but part of the interface. /// </summary> /// <param name="x">The parameter is not used.</param> /// <returns>Null as it's unused.</returns> public DVPLI.Vector G(DVPLI.Vector x) { return null; }
/// <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> /// Calibration objective function: /// squared difference between black swaptions and HW swaptions. /// </summary> /// <param name='x'> /// The tested [alpha, sigma] vector. /// </param> /// <returns> /// A double containing the squared difference between /// black swaptions and the HW swaptions. /// </returns> public double Obj(DVPLI.Vector x) { Matrix hwSWMatrix = this.shw1.HWSwaptionMatrix(this.swaptionMaturity, this.swapDuration, x[0], x[1], this.deltaK); double sum = 0; int count = this.swaptionMaturity.Length * this.swapDuration.Length; for (int r = 0; r < this.swaptionMaturity.Length; r++) for (int c = 0; c < this.swapDuration.Length; c++) if (this.blackSwaption[r, c] != 0.0) sum += Math.Pow(hwSWMatrix[r, c] - this.blackSwaption[r, c], 2); double bias = 0; double k = 25000; /* f.zr = this.shw1.zeroRateCurve; f.a = x[0]; f.sigma = x[1]; List<double> simDates, fR, avgR; f.Simulate(40, out simDates, out fR, out avgR); bias += Math.Abs(avgR[avgR.Count - 1] - f.zr.Evaluate(simDates[avgR.Count - 1])); Console.WriteLine(f.zr.Evaluate(simDates[avgR.Count - 1]) + "\t" + avgR[avgR.Count - 1] + "\t" + x[0] + "\t" + x[1] + "\t" + Math.Sqrt(sum / count)); */ return Math.Sqrt(sum / count )+k*bias; }
public override double Obj(DVPLI.Vector x) { double kappa = x[0]; double theta = x[1]; double sigma = x[2]; double rho = x[3]; double v0 = x[4]; if (displayObjInfo) { Console.WriteLine("."); } var paths = SimulateScenariosMT(s0, v0, kappa, theta, sigma, rho,Math.Min(this.matBound[1],this.cpmd.Maturity[Range.End])); if(displayObjInfo) { Console.WriteLine("Average Underlying Scenario"); int Z=paths.Length;// number of time steps int J = paths[0].Length;//number of realizations. //display average path for (int z = 0; z < Z; z++) { double avg = 0; for (int j = 0; j < J; j++) avg += paths[z][j]; avg /= J; Console.WriteLine((z * dt) + "\t" + avg); } } double sum = 0; int count = 0; for (int i = 0; i < this.cpmd.Maturity.Length; i++) { double maturity = this.cpmd.Maturity[i]; if (maturity < matBound[0]|| maturity>matBound[1]) continue; for (int j = 0; j < this.cpmd.Strike.Length; j++) { double strike = this.cpmd.Strike[j]; if (strike < strikeBound[0] * s0 || strike > strikeBound[1] * s0) continue; if(calibrateOnCallOptions) if (this.cpmd.CallPrice[i, j] > s0 * optionThreshold) if (cpmd.CallVolume[i, j] > 0) { double call = CallPrice(paths, strike, maturity); sum += this.callWeight[i,j] * System.Math.Pow(this.cpmd.CallPrice[i, j] - call, 2.0); count++; } if(calibrateOnPutOptions) if (cpmd.PutPrice != null) if (cpmd.PutPrice[i, j] > s0 * optionThreshold) if (cpmd.PutVolume[i, j] > 0) { double put = PutPrice(paths, strike, maturity); sum += this.putWeight[i, j] * System.Math.Pow(cpmd.PutPrice[i, j] - put, 2.0); count++; } } } double p = 0; //Frees memory for (int i = 0; i < paths.Length; i++) paths[i].Dispose(); if (this.useFellerPenalty) p += this.FellerPenalty(x); if (double.IsNaN(sum) || double.IsInfinity(sum)) return p+10e5 * x.Norm(); return p + Math.Sqrt(sum / this.totalVolume)/s0*100; }
/// <summary> /// Calibration objective function: /// squared difference between black caps and hw caps. /// </summary> /// <param name='x'> /// The tested [alpha, sigma] vector. /// </param> /// <returns> /// A double containing the squared difference between /// black Caps and the HW Caps. /// </returns> public double Obj(DVPLI.Vector x) { Matrix hwCapsMatrix = this.hw1Caps.HWMatrixCaps(this.capMaturity, this.capRate, x[0], x[1], this.deltaK); double sum = 0; for (int r = 0; r < hwCapsMatrix.R; r++) { for (int c = 0; c < hwCapsMatrix.C; c++) { if (this.blackCaps[r, c] != 0.0) sum += Math.Pow(hwCapsMatrix[r, c] - this.blackCaps[r, c], 2); } } double bias = 0; /* f.zr = hw1Caps.zeroRateCurve; f.a = x[0]; f.sigma = x[1]; List<double> simDates, fR, avgR; f.Simulate(40, out simDates, out fR, out avgR); //double bias=f.ExpectedAverageRate(50) - hw1Caps.zeroRateCurve.Evaluate(50); for (int z = 0; z < simDates.Count; z++) bias += Math.Abs(avgR[z] - hw1Caps.zeroRateCurve.Evaluate(simDates[z])); Console.WriteLine(bias); */ double k = 25000; return Math.Sqrt(sum ) + k * bias; }
/// <summary> /// Calibration objective function: /// squared difference between black caps and Cox-Ingersoll-Ross caps. /// </summary> /// <param name='x'> /// The tested [kappa, theta, sigma] vector. /// </param> /// <returns> /// The distance (using the L2 norm) between /// black Caps and the Cox-Ingersoll-Ross Caps. /// </returns> public double Obj(DVPLI.Vector x) { Matrix cirCapMatrix = CIRCap.CIRCapMatrix(this.capMaturity, this.capRate, this.tau, this.r0, x); double sum = 0; for (int r = 0; r < cirCapMatrix.R; r++) { for (int c = 0; c < cirCapMatrix.C; c++) { if (this.blackCaps[r, c] != 0.0) sum += Math.Pow(cirCapMatrix[r, c] - this.blackCaps[r, c], 2); } } return Math.Sqrt(sum); }