/**
* Reports the error of the arithmetic average approximation by the log of the compounded rate.
*/
public void averageApproximation() {
final MulticurveProviderDiscount multicurvesCst = new MulticurveProviderDiscount();
YieldAndDiscountCurve curveCst = YieldCurve.from(ConstantDoublesCurve.from(0.0, "CST"));
multicurvesCst.setCurve(FEDFUND, curveCst);
final double[] rateLevel = {0.01, 0.05, 0.10 };
final int nbLevel = rateLevel.length;
final int nbStart = 36;
final Period step = Period.ofMonths(1);
final ZonedDateTime[] effectiveDate = new ZonedDateTime[nbStart];
effectiveDate[0] = ScheduleCalculator.getAdjustedDate(REFERENCE_DATE, GENERATOR_SWAP_EONIA.getSpotLag(), NYC);
final double[][] payComp = new double[nbLevel][nbStart];
final double[][] payAA = new double[nbLevel][nbStart];
final double[][] payAAApprox = new double[nbLevel][nbStart];
final double[][] rateComp = new double[nbLevel][nbStart];
final double[][] rateAA = new double[nbLevel][nbStart];
final double[][] rateAAApprox = new double[nbLevel][nbStart];
for (int looplevel = 0; looplevel < nbLevel; looplevel++) {
curveCst = YieldCurve.from(ConstantDoublesCurve.from(rateLevel[looplevel], "CST"));
multicurvesCst.replaceCurve(FEDFUND, curveCst);
for (int loopstart = 0; loopstart < nbStart; loopstart++) {
effectiveDate[loopstart] = ScheduleCalculator.getAdjustedDate(effectiveDate[0], step.multipliedBy(loopstart), USDLIBOR3M, NYC);
final ZonedDateTime endDate = ScheduleCalculator.getAdjustedDate(effectiveDate[loopstart], TENOR_3M, USDLIBOR3M, NYC);
final CouponArithmeticAverageONDefinition cpnONDefinition = CouponArithmeticAverageONDefinition.from(FEDFUND, effectiveDate[loopstart], endDate, NOTIONAL, 0, NYC);
final CouponArithmeticAverageON cpnON = cpnONDefinition.toDerivative(REFERENCE_DATE);
// Compute daily forwards
final int nbON = cpnON.getFixingPeriodAccrualFactors().length;
final double fwdON[] = new double[nbON];
for (int loopon = 0; loopon < nbON; loopon++) {
fwdON[loopon] = multicurvesCst.getForwardRate(FEDFUND, cpnON.getFixingPeriodTimes()[loopon], cpnON.getFixingPeriodTimes()[loopon + 1], cpnON.getFixingPeriodAccrualFactors()[loopon]);
}
// Compounded period forward
payComp[looplevel][loopstart] = multicurvesCst.getForwardRate(FEDFUND, cpnON.getFixingPeriodTimes()[0], cpnON.getFixingPeriodTimes()[nbON], cpnON.getFixingPeriodRemainingAccrualFactor())
* cpnON.getFixingPeriodRemainingAccrualFactor();
payAA[looplevel][loopstart] = 0;
for (int loopon = 0; loopon < nbON; loopon++) {
payAA[looplevel][loopstart] += fwdON[loopon] * cpnON.getFixingPeriodAccrualFactors()[loopon];
}