public double discountBondOption(Option.Type type,
double strike, double maturity,
double bondMaturity)
{
List <double> accrualStartTimes
= process_.accrualStartTimes();
List <double> accrualEndTimes
= process_.accrualEndTimes();
if (!(accrualStartTimes.First() <= maturity && accrualStartTimes.Last() >= maturity))
{
throw new Exception("capet maturity does not fit to the process");
}
int i = accrualStartTimes.BinarySearch(maturity);
if (i < 0)
{
// The lower_bound() algorithm finds the first position in a sequence that value can occupy
// without violating the sequence's ordering
// if BinarySearch does not find value the value, the index of the prev minor item is returned
i = ~i + 1;
}
// impose limits. we need the one before last at max or the first at min
i = Math.Max(Math.Min(i, accrualStartTimes.Count - 1), 0);
if (!(i < process_.size() &&
Math.Abs(maturity - accrualStartTimes[i]) < 100 * Const.QL_EPSILON &&
Math.Abs(bondMaturity - accrualEndTimes[i]) < 100 * Const.QL_EPSILON))
{
throw new Exception("irregular fixings are not (yet) supported");
}
double tenor = accrualEndTimes[i] - accrualStartTimes[i];
double forward = process_.initialValues()[i];
double capRate = (1.0 / strike - 1.0) / tenor;
double var = covarProxy_.integratedCovariance(i, i, process_.fixingTimes()[i]);
double dis = process_.index().forwardingTermStructure().link.discount(bondMaturity);
double black = Utils.blackFormula(
(type == Option.Type.Put ? Option.Type.Call : Option.Type.Put),
capRate, forward, Math.Sqrt(var));
double npv = dis * tenor * black;
return(npv / (1.0 + capRate * tenor));
}