def calculate_zero_rates(evaluation_date, zero_rate, sorted_forward_rates, forward_period_days):
    forward_days = timedelta(days=forward_period_days)
    # set first zero_rate to overnight rate
    zero_rates = [ZeroRatePoint(date=evaluation_date, rate=zero_rate), ]

    for (prev_zero_pos, forward_point) in enumerate(sorted_forward_rates):
        prev_zero_rate = zero_rates[prev_zero_pos].rate
        forward_date = forward_point.forward_date
        forward_rate = forward_point.forward_rate
        zero_rate = (forward_rate * years(forward_days) + prev_zero_rate * years(forward_date - evaluation_date)) / years(forward_date + forward_days - evaluation_date)
        zero_rates.append(ZeroRatePoint(date=forward_date + forward_days, rate=zero_rate))
    return zero_rates
def interpolate_zero_rate(evaluation_date, sorted_zero_rates):
    # find index of first zero_rate with forward_date >= evaluation date
    # return final zero_rate if no zero_rate satisfies this condition
    zero_rates = (i for i, zero_rate in enumerate(sorted_zero_rates) if zero_rate.date >= evaluation_date)
    i2 = next(zero_rates, len(sorted_zero_rates) - 1)

    if i2 == 0:
        # if looking for forward rate for today, use overnight zero rate
        return sorted_zero_rates[0].rate
    else:
        # else linearly interpolate between zero_rate points
        # other zero_rate point specified as the zero_rate point previous to the one specified by i2
        i1 = i2 - 1
        forward_date_1 = sorted_zero_rates[i1].date
        zero_rate_1 = sorted_zero_rates[i1].rate
        forward_date_2 = sorted_zero_rates[i2].date
        zero_rate_2 = sorted_zero_rates[i2].rate
        interpolated_zero = zero_rate_1 + years(evaluation_date - forward_date_1) * (zero_rate_2 - zero_rate_1) / years(forward_date_2 - forward_date_1)
        return interpolated_zero