public override List<CashFlow> value()
{
if (couponRates_.Count == 0) throw new ArgumentException("no coupon rates given");
if (notionals_.Count == 0) throw new ArgumentException("no nominals given");
List<CashFlow> leg = new List<CashFlow>();
Calendar schCalendar = schedule_.calendar();
// first period might be short or long
Date start = schedule_[0], end = schedule_[1];
Date paymentDate = calendar_.adjust(end, paymentAdjustment_);
InterestRate rate = couponRates_[0];
double nominal = notionals_[0];
if (schedule_.isRegular(1))
{
if (!(firstPeriodDC_ == null || firstPeriodDC_ == rate.dayCounter()))
throw new ArgumentException("regular first coupon does not allow a first-period day count");
leg.Add(new FixedRateCoupon(nominal, paymentDate, rate, start, end, start, end));
}
else
{
Date refer = end - schedule_.tenor();
refer = schCalendar.adjust(refer, schedule_.businessDayConvention());
InterestRate r = new InterestRate(rate.rate(),
(firstPeriodDC_ == null || firstPeriodDC_.IsEmpty) ? rate.dayCounter() : firstPeriodDC_,
rate.compounding(), rate.frequency());
leg.Add(new FixedRateCoupon(nominal, paymentDate, r, start, end, refer, end));
}
// regular periods
for (int i = 2; i < schedule_.Count - 1; ++i)
{
start = end; end = schedule_[i];
paymentDate = calendar_.adjust(end, paymentAdjustment_);
if ((i - 1) < couponRates_.Count) rate = couponRates_[i - 1];
else rate = couponRates_.Last();
if ((i - 1) < notionals_.Count) nominal = notionals_[i - 1];
else nominal = notionals_.Last();
leg.Add(new FixedRateCoupon(nominal, paymentDate, rate, start, end, start, end));
}
if (schedule_.Count > 2)
{
// last period might be short or long
int N = schedule_.Count;
start = end; end = schedule_[N - 1];
paymentDate = calendar_.adjust(end, paymentAdjustment_);
if ((N - 2) < couponRates_.Count) rate = couponRates_[N - 2];
else rate = couponRates_.Last();
if ((N - 2) < notionals_.Count) nominal = notionals_[N - 2];
else nominal = notionals_.Last();
if (schedule_.isRegular(N - 1))
leg.Add(new FixedRateCoupon(nominal, paymentDate, rate, start, end, start, end));
else
{
Date refer = start + schedule_.tenor();
refer = schCalendar.adjust(refer, schedule_.businessDayConvention());
leg.Add(new FixedRateCoupon(nominal, paymentDate, rate, start, end, start, refer));
}
}
return leg;
}