def values_of_series_of_invest(
    rates_between_periods,
    invest_amounts=None,
    final_only=True,
    invest_at_begining_of_period=False,
):
    """
    Total values after investing each of the values in invest_values, the running total increasing
    by the percentage in rate_between_values from one investment to the next.
    By default invest_at_begining_of_period is set to False meaning that each investment is made
    at the begining of the period and thus is not subject to the period growth.

    :param: invest_values, an iterable of invested values
    :param: rate_between_values, an iterable of rate of growth for the periods from one
                                 investment to the next
    :param: invest_at_begining_of_period, boolean, whether to invest at the begining of a period
            or the end.

    # no growth, the result is just the sum of the amounts
    >>> rates_between_periods = (0, 0)
    >>> invest_amounts = (1, 1)
    >>> values_of_series_of_invest(rates_between_periods, invest_amounts)
    2

    Final_only controls whether to get the intermediate values

    >>> values_of_series_of_invest(rates_between_periods, invest_amounts, final_only=False)
    [1, 2]

    The first rate is not used by default, since the amounts are invested at the END of the period

    >>> invest_amounts = (1, 1)
    >>> rates_between_periods = (0.05, 0)
    >>> values_of_series_of_invest(rates_between_periods, invest_amounts, final_only=False)
    [1.0, 2.0]

    This can be changed however, by setting invest_at_begining_of_period to True

    >>> values_of_series_of_invest(rates_between_periods, invest_amounts, final_only=False, invest_at_begining_of_period=True)
    [1.05, 2.05]
    >>> invest_amounts = (1, 1)
    >>> rates_between_periods = (0.05, 0.08)
    >>> values_of_series_of_invest(rates_between_periods, invest_amounts, invest_at_begining_of_period=True, final_only=False)
    [1.05, 2.1340000000000003]

    It can easily be used to get total invested value after several regular investments

    >>> n_years = 10
    >>> rate = 0.08
    >>> yearly_investment = 100
    >>> rates_between_periods = [rate] * n_years
    >>> invest_amounts = [yearly_investment] * n_years
    >>> values_of_series_of_invest(rates_between_periods, invest_amounts)
    1448.656246590984

    Another application is to get the historical growth of a stock from one year to the next
    to evaluate the total value of a series of investments

    """

    # if no invest amounts is given, it is assumed 1 unit is invested after the first period and nothing else
    if invest_amounts is None:
        invest_amounts = [1] + [0] * len(rates_between_periods)

    if invest_at_begining_of_period:
        invest_amounts = list(invest_amounts)
        rates_between_periods = list(rates_between_periods)
        total = invest_amounts.pop(0) * (1 + rates_between_periods.pop(0))
        value_over_time = [total]
    else:
        total = 0
        value_over_time = []

    for invest, rate in zip(invest_amounts, rates_between_periods):
        total = total * (1 + rate) + invest
        value_over_time.append(total)

    if final_only:
        return total
    else:
        return value_over_time