Source:
<code>public double rate( PricingEnvironment env, OvernightAveragedRateObservation observation, LocalDate startDate, LocalDate endDate) { OvernightIndex index = observation.getIndex(); int publicationOffset = index.getPublicationDateOffset(); int cutoffOffset = observation.getRateCutOffDays() > 1 ? observation.getRateCutOffDays() : 1; LocalDate startFixingDate = observation.getStartDate(); LocalDate endFixingDate = observation.getEndDate(); List<LocalDate> fixingDates = new ArrayList<>(); <START> List<LocalDate> publicationDates = new ArrayList<>(); END> List<Double> accrualFactors = new ArrayList<>(); LocalDate currentFixing = startFixingDate; double accrualFactorTotal = 0.0d; while (currentFixing.isBefore(endFixingDate)) { LocalDate currentOnRateStart = index.calculateEffectiveFromFixing(currentFixing); LocalDate currentOnRateEnd = index.calculateMaturityFromEffective(currentOnRateStart); fixingDates.add(currentFixing); publicationDates.add(publicationOffset == 0 ? currentFixing : index.getFixingCalendar().next(currentFixing)); double accrualFactor = index.getDayCount().yearFraction(currentOnRateStart, currentOnRateEnd); accrualFactors.add(accrualFactor); currentFixing = index.getFixingCalendar().next(currentFixing); accrualFactorTotal += accrualFactor; } int nbPeriods = accrualFactors.size(); for (int i = 0; i < cutoffOffset - 1; i++) { fixingDates.set(nbPeriods - 1 - i, fixingDates.get(nbPeriods - cutoffOffset)); publicationDates.set(nbPeriods - 1 - i, publicationDates.get(nbPeriods - cutoffOffset)); } double accruedUnitNotional = 0d; for (int i = 0; i < nbPeriods; i++) { double forwardRate = env.overnightIndexRate(index, fixingDates.get(i)); accruedUnitNotional += accrualFactors.get(i) * forwardRate; } return accruedUnitNotional / accrualFactorTotal; }</code><technical_language>publicationDates built</technical_language>

Target:
public double rate( PricingEnvironment env, OvernightAveragedRateObservation observation, LocalDate startDate, LocalDate endDate) { OvernightIndex index = observation.getIndex(); LocalDate lastNonCutoffFixing = observation.getEndDate(); int cutoffOffset = observation.getRateCutOffDays() > 1 ? observation.getRateCutOffDays() : 1; double accumulatedInterest = 0.0d; double accrualFactorTotal = 0.0d; double cutoffAccrualFactor = 0.0; for (int i = 0; i < cutoffOffset; i++) { lastNonCutoffFixing = index.getFixingCalendar().previous(lastNonCutoffFixing); LocalDate cutoffEffectiveDate = index.calculateEffectiveFromFixing(lastNonCutoffFixing); LocalDate cutoffMaturityDate = index.calculateMaturityFromEffective(cutoffEffectiveDate); double accrualFactor = index.getDayCount().yearFraction(cutoffEffectiveDate, cutoffMaturityDate); accrualFactorTotal += accrualFactor; cutoffAccrualFactor += accrualFactor; } double forwardRateCutOff = env.overnightIndexRate(index, lastNonCutoffFixing); accumulatedInterest += cutoffAccrualFactor * forwardRateCutOff; LocalDate currentFixingNonCutoff = observation.getStartDate(); while (currentFixingNonCutoff.isBefore(lastNonCutoffFixing)) { LocalDate currentOnRateStart = index.calculateEffectiveFromFixing(currentFixingNonCutoff); LocalDate currentOnRateEnd = index.calculateMaturityFromEffective(currentOnRateStart); double accrualFactor = index.getDayCount().yearFraction(currentOnRateStart, currentOnRateEnd); double forwardRate = env.overnightIndexRate(index, currentFixingNonCutoff); accrualFactorTotal += accrualFactor; accumulatedInterest += accrualFactor * forwardRate; currentFixingNonCutoff = index.getFixingCalendar().next(currentFixingNonCutoff); } return accumulatedInterest / accrualFactorTotal; }