/// <summary> /// Calculates the value of a Bond under the Pelsser model. /// </summary> /// <param name='dynamic'> /// The simulated process. /// </param> /// <param name='dates'> /// The vector of reference dates. /// </param> /// <param name='i'> /// The index at which the state variables must be sampled. /// </param> /// <param name='t'> /// The date in years/fractions at at which the state variables must be sampled. /// </param> /// <param name='s'> /// The maturity of the bond. /// </param> /// <returns>The value of the bound at index i using the Pelsser model.</returns> public double Bond(IReadOnlyMatrixSlice dynamic, double[] dates, int i, double t, double s) { // Handles special case. if (t == s) { return(1); } // Get the value of the short rate. double y = Math.Sqrt(dynamic[i, 0]) - this.alphaT0[i]; PelsserKey k = new PelsserKey(t, s); PelsserCache cachedValue = null; lock (this.cache) { if (this.cache.ContainsKey(k)) { cachedValue = this.cache[k]; } else { cachedValue = new PelsserCache(t, s, this); // Insert the value in the cache. this.cache.Add(k, cachedValue); } } double v = Math.Exp(cachedValue.A - y * cachedValue.B - (y * y) * cachedValue.CtT0); return(v); }
/// <summary> /// Calculates an entire caplets matrix row using Pelsser's model. /// </summary> /// <param name="r">The row index.</param> internal void CalculateRow(int r) { double T = this.Mat[r + 1] + this.DeltaK; PelsserCache pc = new PelsserCache(this.Mat[r + 1], T, this.Model); double MU0 = this.Model.Mu0(this.Mat[r + 1]); int rm = r + 1; double nu = MU0 - pc.B * this.Sigma0s[rm]; double phi = 1 + 2 * this.CCost * this.Sigma0s[rm]; PelsserCache pc0t = new PelsserCache(0, this.Mat[r + 1], this.Model); PelsserCache pc0tau = new PelsserCache(0, T, this.Model); // Discount factor double p0tau = Math.Exp(pc0tau.A); double p0t = Math.Exp(pc0t.A); double sqrtSigmaRm = Math.Sqrt(this.Sigma0s[rm]); // Execute the subsequent operations on all caplets. for (int c = 0; c < this.K.Length; c++) { double d = Math.Pow(pc.B, 2) + 4 * this.CCost * (pc.A - this.LogK[c]); // Exclude the negative values of the discriminant. d = Math.Max(0, d); double el = (-pc.B - Math.Sqrt(d)) / (2 * this.CCost); double eic = (-pc.B + Math.Sqrt(d)) / (2 * this.CCost); double nP1 = SpecialFunctions.NormCdf(-(eic * phi - nu) / Math.Sqrt(phi * this.Sigma0s[rm])) + SpecialFunctions.NormCdf((el * phi - nu) / Math.Sqrt(phi * this.Sigma0s[rm])); double nP2 = SpecialFunctions.NormCdf(-(eic - MU0) / sqrtSigmaRm) + SpecialFunctions.NormCdf((el - MU0) / sqrtSigmaRm); double put_zc = -p0tau * nP1 + p0t * this.K[c] * nP2; this.Caplets[r, c] = put_zc; } }
/// <summary> /// Calculates the value of a Bond under the Pelsser model. /// </summary> /// <param name='dynamic'> /// The simulated process. /// </param> /// <param name='dates'> /// The vector of reference dates. /// </param> /// <param name='i'> /// The index at which the state variables must be sampled. /// </param> /// <param name='t'> /// The date in years/fractions at at which the state variables must be sampled. /// </param> /// <param name='s'> /// The maturity of the bond. /// </param> /// <returns>The value of the bound at index i using the Pelsser model.</returns> public double Bond(IReadOnlyMatrixSlice dynamic, double[] dates, int i, double t, double s) { // Handles special case. if (t == s) return 1; // Get the value of the short rate. double y = Math.Sqrt(dynamic[i, 0]) - this.alphaT0[i]; PelsserKey k = new PelsserKey(t, s); PelsserCache cachedValue = null; lock (this.cache) { if (this.cache.ContainsKey(k)) cachedValue = this.cache[k]; else { cachedValue = new PelsserCache(t, s, this); // Insert the value in the cache. this.cache.Add(k, cachedValue); } } double v = Math.Exp(cachedValue.A - y * cachedValue.B - (y * y) * cachedValue.CtT0); return v; }