Представьте, что ребенок вашего соседа косит газоны и использует свои карманные деньги, чтобы накопить деньги на покупку игровой консоли через шесть месяцев, а его дядя согласился сопоставлять часть своего дохода каждый месяц в зависимости от того, сколько он накопил в этом месяце.
(Ранее я задавал более простую версию этого вопроса, но не включил концепцию начисления процентов, что делает концепцию расчета конечного баланса каждый месяц необходимой, чтобы перенести эту сумму на следующий месяц и получить проценты от общей суммы. Предыдущий вопрос с простым сложением прибыли и убытка, который может использовать подсчет cumulative_eval() по этой ссылке.)
Давайте начнем со следующего:
- Ребенок начинает с 500 долларов.
- Он зарабатывает дополнительные деньги за стрижку газонов, но также имеет некоторые накладные расходы (например, топливо, техническое обслуживание), поэтому сумма дохода каждый месяц может сильно различаться.
- Его дядя будет платить ему некоторый интерес (в зависимости от настроения) за то, сколько он сэкономил в течение месяца.
- Он задается вопросом, накопит ли он достаточно денег в конце определенного периода времени.
Поэтому единственный известный мне в настоящее время способ решить эту проблему (когда ежемесячный конечный баланс становится начальным балансом на следующий месяц) — использовать внешний цикл; к сожалению, это сильно противоречит оптимизации, доступной через Polars.
Вот код рабочего примера того, чего я пытаюсь достичь:
Код: Выделить всё
import polars as pl
import datetime as dt
from dateutil.relativedelta import relativedelta
from random import normalvariate
starting_balance = 500.00 # how much money they start with (i.e., this month's closing balance)
milestone = 6 # how many months to save
income_average = 700.00 # how much they earn from mowing yards on an average month
income_std = 300.00 # a standard deviation of their mowing income
interest_average = 0.10 # how much his uncle will contribute each month on average, e.g. 10%
interest_std = 0.10 # the uncle is flaky and his contribution varies so much that he might ask for some money back (loss)
start_date = dt.date.today().replace(day=1) # first day of this month
calendar_date = pl.date_range(start_date, start_date + relativedelta(months=milestone), '1mo')
zeroes = [0.0 for _ in range(milestone + 1)]
df = pl.DataFrame(
{
'date': pl.date_range(start=start_date, end=(start_date + relativedelta(months=milestone)), interval="1mo", eager=True),
'opening_balance': zeroes,
'interest': zeroes, # or [normalvariate(interest_average, interest_std) for _ in zeroes]
'income': zeroes, # or [normalvariate(income_average, income_std) for _ in zeroes]
'closing_balance': zeroes,
}
)
print(df, f"\n initialized dataframe")
Код: Выделить всё
┌────────────┬─────────────────┬──────────┬────────┬─────────────────┐
│ date ┆ opening_balance ┆ interest ┆ income ┆ closing_balance │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ date ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
╞════════════╪═════════════════╪══════════╪════════╪═════════════════╡
│ 2023-03-01 ┆ 0.0 ┆ 0.0 ┆ 0.0 ┆ 0.0 │
│ 2023-04-01 ┆ 0.0 ┆ 0.0 ┆ 0.0 ┆ 0.0 │
│ 2023-05-01 ┆ 0.0 ┆ 0.0 ┆ 0.0 ┆ 0.0 │
│ 2023-06-01 ┆ 0.0 ┆ 0.0 ┆ 0.0 ┆ 0.0 │
│ 2023-07-01 ┆ 0.0 ┆ 0.0 ┆ 0.0 ┆ 0.0 │
│ 2023-08-01 ┆ 0.0 ┆ 0.0 ┆ 0.0 ┆ 0.0 │
│ 2023-09-01 ┆ 0.0 ┆ 0.0 ┆ 0.0 ┆ 0.0 │
└────────────┴─────────────────┴──────────┴────────┴─────────────────┘
initialized dataframe
Код: Выделить всё
current_tally = starting_balance
for m in range(len(calendar_date)):
if m == 0:
df[m, 'opening_balance'] = 0.0
df[m, 'interest'] = 0.0
df[m, 'income'] = 0.0
else:
df[m, 'opening_balance'] = current_tally
interest = normalvariate(interest_average, interest_std)
income = round(normalvariate(income_average, income_std), 2)
current_tally *= (1 + interest)
current_tally = round(current_tally + income, 2)
df[m, 'interest'] = interest
df[m, 'income'] = income
df[m, 'closing_balance'] = round(current_tally, 2)
print(df, f"\n slow population of dataframe with a running tally")
Код: Выделить всё
┌────────────┬─────────────────┬──────────┬─────────┬─────────────────┐
│ date ┆ opening_balance ┆ interest ┆ income ┆ closing_balance │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ date ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
╞════════════╪═════════════════╪══════════╪═════════╪═════════════════╡
│ 2023-03-01 ┆ 0.0 ┆ 0.0 ┆ 0.0 ┆ 500.0 │
│ 2023-04-01 ┆ 500.0 ┆ 0.311301 ┆ 767.38 ┆ 1423.03 │
│ 2023-05-01 ┆ 1423.03 ┆ 0.213937 ┆ 468.1 ┆ 2195.57 │
│ 2023-06-01 ┆ 2195.57 ┆ 0.073306 ┆ 1269.07 ┆ 3625.59 │
│ 2023-07-01 ┆ 3625.59 ┆ 0.118544 ┆ 1001.4 ┆ 5056.78 │
│ 2023-08-01 ┆ 5056.78 ┆ 0.175585 ┆ 344.57 ┆ 6289.25 │
│ 2023-09-01 ┆ 6289.25 ┆ 0.28428 ┆ 1139.38 ┆ 9216.54 │
└────────────┴─────────────────┴──────────┴─────────┴─────────────────┘
slow population of dataframe with a running tally
Подробнее здесь: https://stackoverflow.com/questions/757 ... s-interest