summaryrefslogtreecommitdiff
path: root/finance/flow.py
diff options
context:
space:
mode:
authorxengineering <me@xengineering.eu>2024-09-08 17:02:33 +0200
committerxengineering <me@xengineering.eu>2024-09-08 17:21:32 +0200
commit458a24d09f95eefb161728d9676ecdfca30e3f5e (patch)
treed3260b2531f42a6e8335661312661302b9653730 /finance/flow.py
parent6973093a2b80b4fb9e216d1b3e329dd4c2badc7c (diff)
downloadfinance-py-458a24d09f95eefb161728d9676ecdfca30e3f5e.tar
finance-py-458a24d09f95eefb161728d9676ecdfca30e3f5e.tar.zst
finance-py-458a24d09f95eefb161728d9676ecdfca30e3f5e.zip
Split flow.py to simulate.py and model.py
model.py should be a file containing only dataclasses to model finance. simulate.py should take care of the simulation of that finance data to create a financial forecast.
Diffstat (limited to 'finance/flow.py')
-rw-r--r--finance/flow.py66
1 files changed, 0 insertions, 66 deletions
diff --git a/finance/flow.py b/finance/flow.py
deleted file mode 100644
index c6b28c0..0000000
--- a/finance/flow.py
+++ /dev/null
@@ -1,66 +0,0 @@
-import dataclasses
-from datetime import datetime
-from decimal import Decimal
-from typing import Generator
-
-
-@dataclasses.dataclass(kw_only=True, frozen=True)
-class Flow:
- """Time-discrete flow of money paid on the first day of a month"""
-
- amount: Decimal
- since: None | datetime
- until: None | datetime
-
- def integrate(self, start: datetime, end: datetime) -> Decimal:
- """Integrate the flow between two dates to an amount of money"""
-
- payments: int = 0
-
- if self.since is not None:
- if start < self.since:
- start = self.since
-
- if self.until is not None:
- if end > self.until:
- end = self.until
-
- for candidate in monthly_candidates(start):
- if start <= candidate <= end:
- payments += 1
- if candidate > end:
- break
-
- return self.amount * Decimal(payments)
-
-
-def monthly_candidates(start: datetime) -> Generator[datetime, None, None]:
- current = datetime(start.year, start.month, 1)
- while True:
- yield current
- if current.month == 12:
- current = datetime(current.year + 1, 1, 1)
- else:
- current = datetime(current.year, current.month + 1, 1)
-
-
-def simulate(
- start: datetime, end: datetime, flows: tuple[Flow, ...]
-) -> list[tuple[datetime, Decimal]]:
- dates: list[datetime] = []
- values: list[Decimal] = []
-
- for candidate in monthly_candidates(start):
- if start <= candidate <= end:
- dates.append(candidate)
-
- if candidate > end:
- break
-
- for date in dates:
- value = Decimal(0.0)
- for flow in flows:
- value += flow.integrate(start, date)
- values.append(value)
-
- return [(date, values[index]) for index, date in enumerate(dates)]