Как создать модель сбережений с помощью Python и Polars, которая будет приносить проценты и иметь итоговый баланс каждыйPython

Программы на Python
Anonymous
 Как создать модель сбережений с помощью Python и Polars, которая будет приносить проценты и иметь итоговый баланс каждый

Сообщение Anonymous »

Я пытаюсь создать симуляцию плана сбережений (например, банковских сбережений или выхода на пенсию), который позволяет на начальном балансе каждый месяц получать некоторые переменные проценты и может иметь депозиты (или снятие средств), и подсчитываю это для конечного баланса каждый месяц и переношу эту конечную сумму в начальный баланс в следующем месяце.
Представьте, что ребенок вашего соседа косит газоны и использует свои карманные деньги, чтобы накопить деньги на покупку игровой консоли через шесть месяцев, а его дядя согласился сопоставлять часть своего дохода каждый месяц в зависимости от того, сколько он накопил в этом месяце.

(Ранее я задавал более простую версию этого вопроса, но не включил концепцию начисления процентов, что делает концепцию расчета конечного баланса каждый месяц необходимой, чтобы перенести эту сумму на следующий месяц и получить проценты от общей суммы. Предыдущий вопрос с простым сложением прибыли и убытка, который может использовать подсчет cumulative_eval() по этой ссылке.)
Давайте начнем со следующего:
  • Ребенок начинает с 500 долларов.
  • Он зарабатывает дополнительные деньги за стрижку газонов, но также имеет некоторые накладные расходы (например, топливо, техническое обслуживание), поэтому сумма дохода каждый месяц может сильно различаться.
  • Его дядя будет платить ему некоторый интерес (в зависимости от настроения) за то, сколько он сэкономил в течение месяца.
  • Он задается вопросом, накопит ли он достаточно денег в конце определенного периода времени.
Я пытался использовать различные выражения .with_columns(), но не смог перенести 'closing_balance' вперед из месяца в месяц. Кто-то показал мне пример с .cumulative_eval(), который хорошо работал для простого случая добавления (или вычитания) сумм, но не обрабатывает случай, когда проценты начисляются на основе начального баланса.

Поэтому единственный известный мне в настоящее время способ решить эту проблему (когда ежемесячный конечный баланс становится начальным балансом на следующий месяц) — использовать внешний цикл; к сожалению, это сильно противоречит оптимизации, доступной через 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), interval='1mo', eager=True)
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
Я потратил много часов, пытаясь узнать, каким может быть оптимизированный способ сделать это (с помощью документации Polars и любых примеров, которые я смог найти в Интернете), но до сих пор не смог найти лучший способ сделать это. Любая помощь и указания очень ценятся.


Подробнее здесь: https://stackoverflow.com/questions/757 ... s-interest

Вернуться в «Python»