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