Skip to content

Commit 49a134a

Browse files
committed
docs: update docstrings in MC
1 parent 207778e commit 49a134a

File tree

1 file changed

+196
-3
lines changed

1 file changed

+196
-3
lines changed

okama/portfolios/cashflow_strategies.py

Lines changed: 196 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,22 @@ def __init__(
3030
time_series_dic: dict = {},
3131
time_series_discounted_values: bool = False
3232
):
33+
"""
34+
Initialize the CashFlow strategy.
35+
36+
Parameters
37+
----------
38+
parent : Portfolio
39+
The parent Portfolio instance.
40+
frequency : str, optional
41+
Frequency of cash flows. Default is "none".
42+
initial_investment : float, optional
43+
Initial investment amount. Default is 1000.0.
44+
time_series_dic : dict, optional
45+
Dictionary with dates and cash flow values. Default is empty dict.
46+
time_series_discounted_values : bool, optional
47+
If True, values in time_series_dic are considered as discounted (PV). Default is False.
48+
"""
3349
self.parent = parent
3450
self._frequency = frequency
3551
self._initial_investment = initial_investment
@@ -70,7 +86,12 @@ def frequency(self, frequency):
7086
@property
7187
def periods_per_year(self) -> int:
7288
"""
73-
Show the number of periods per year. Period is defined by the frequency.
89+
Get the number of periods per year based on the frequency.
90+
91+
Returns
92+
-------
93+
int
94+
Number of periods per year.
7495
"""
7596
return settings.frequency_periods_per_year[self.frequency]
7697

@@ -150,7 +171,7 @@ def _clear_cf_cache(self):
150171

151172
class IndexationStrategy(CashFlow):
152173
"""
153-
Cash flow strategy with regualr indexed withdrawals or contributions.
174+
Cash flow strategy with regular indexed withdrawals or contributions.
154175
155176
Parameters
156177
----------
@@ -187,6 +208,26 @@ def __init__(
187208
amount: float = 0,
188209
indexation: Optional[Union[str, float]] = None,
189210
):
211+
"""
212+
Initialize the IndexationStrategy.
213+
214+
Parameters
215+
----------
216+
parent : Portfolio
217+
The parent Portfolio instance.
218+
frequency : str, optional
219+
Frequency of cash flows. Default is "none".
220+
initial_investment : float, optional
221+
Initial investment amount. Default is 1000.0.
222+
time_series_dic : dict, optional
223+
Dictionary with dates and cash flow values. Default is empty dict.
224+
time_series_discounted_values : bool, optional
225+
If True, values in time_series_dic are considered as discounted (PV). Default is False.
226+
amount : float, optional
227+
Amount of regular cash flow. Negative for withdrawals, positive for contributions. Default is 0.
228+
indexation : str or float, optional
229+
Indexation rate (CAGR). Can be 'inflation' (if portfolio has inflation data) or a float value. Default is None.
230+
"""
190231
super().__init__(
191232
parent,
192233
frequency=frequency,
@@ -293,6 +334,24 @@ def __init__(
293334
time_series_discounted_values: bool = False,
294335
percentage: float = 0.0,
295336
):
337+
"""
338+
Initialize the PercentageStrategy.
339+
340+
Parameters
341+
----------
342+
parent : Portfolio
343+
The parent Portfolio instance.
344+
frequency : str, optional
345+
Frequency of cash flows. Default is "none".
346+
initial_investment : float, optional
347+
Initial investment amount. Default is 1000.0.
348+
time_series_dic : dict, optional
349+
Dictionary with dates and cash flow values. Default is empty dict.
350+
time_series_discounted_values : bool, optional
351+
If True, values in time_series_dic are considered as discounted (PV). Default is False.
352+
percentage : float, optional
353+
Percentage of portfolio balance to be withdrawn or contributed. Negative for withdrawals. Default is 0.0.
354+
"""
296355
super().__init__(
297356
parent,
298357
frequency=frequency,
@@ -373,6 +432,20 @@ def __init__(
373432
time_series_dic: dict = {},
374433
time_series_discounted_values: bool = False
375434
):
435+
"""
436+
Initialize the TimeSeriesStrategy.
437+
438+
Parameters
439+
----------
440+
parent : Portfolio
441+
The parent Portfolio instance.
442+
initial_investment : float, optional
443+
Initial investment amount. Default is 0.
444+
time_series_dic : dict, optional
445+
Dictionary with dates and cash flow values. Default is empty dict.
446+
time_series_discounted_values : bool, optional
447+
If True, values in time_series_dic are considered as discounted (PV). Default is False.
448+
"""
376449
super().__init__(
377450
parent,
378451
frequency="none",
@@ -393,6 +466,13 @@ def __repr__(self):
393466

394467

395468
class VanguardDynamicSpending(PercentageStrategy):
469+
"""
470+
Vanguard Dynamic Spending strategy.
471+
472+
The withdrawal amount is calculated as a percentage of the portfolio balance,
473+
but it is limited by a ceiling and a floor.
474+
The ceiling and floor are calculated based on the previous year's withdrawal amount.
475+
"""
396476
NAME = "VDS"
397477
def __init__(
398478
self,
@@ -407,6 +487,33 @@ def __init__(
407487
adjust_floor_ceiling: bool = False,
408488
indexation: Optional[Union[str, float]] = None,
409489
):
490+
"""
491+
Initialize the VanguardDynamicSpending strategy.
492+
493+
Parameters
494+
----------
495+
parent : Portfolio
496+
The parent Portfolio instance.
497+
initial_investment : float, optional
498+
Initial investment amount. Default is 1000.0.
499+
time_series_dic : dict, optional
500+
Dictionary with dates and cash flow values. Default is empty dict.
501+
time_series_discounted_values : bool, optional
502+
If True, values in time_series_dic are considered as discounted (PV). Default is False.
503+
percentage : float, optional
504+
Percentage of portfolio balance to be withdrawn. Negative value. Default is 0.0.
505+
min_max_annual_withdrawal : tuple[float, float], optional
506+
Minimum and maximum annual withdrawal limits (positive values). Default is None.
507+
adjust_min_max : bool, optional
508+
If True, min and max limits are adjusted by indexation. Default is True.
509+
floor_ceiling : tuple[float, float], optional
510+
Floor and ceiling percentages relative to the previous year's withdrawal.
511+
Example: (-0.025, 0.05) means floor is -2.5% and ceiling is +5%. Default is None.
512+
adjust_floor_ceiling : bool, optional
513+
If True, floor and ceiling are adjusted by indexation. Default is False.
514+
indexation : str or float, optional
515+
Indexation rate. Default is None.
516+
"""
410517
super().__init__(
411518
parent=parent,
412519
frequency="year",
@@ -442,6 +549,9 @@ def __repr__(self):
442549

443550
@property
444551
def frequency(self):
552+
"""
553+
Frequency of cash flows. Always 'year' for VDS.
554+
"""
445555
return "year"
446556

447557
@frequency.setter
@@ -453,6 +563,9 @@ def frequency(self, value):
453563

454564
@property
455565
def min_max_annual_withdrawals(self):
566+
"""
567+
Minimum and maximum annual withdrawal limits.
568+
"""
456569
return self._min_max_annual_withdrawals
457570

458571
@min_max_annual_withdrawals.setter
@@ -475,6 +588,9 @@ def min_max_annual_withdrawals(self, value: Optional[tuple[float, float]]):
475588

476589
@property
477590
def adjust_min_max(self):
591+
"""
592+
Whether to adjust min and max limits by indexation.
593+
"""
478594
return self._adjust_min_max
479595

480596
@adjust_min_max.setter
@@ -486,6 +602,9 @@ def adjust_min_max(self, value):
486602

487603
@property
488604
def floor_ceiling(self):
605+
"""
606+
Floor and ceiling percentages relative to the previous year's withdrawal.
607+
"""
489608
return self._floor_ceiling
490609

491610
@floor_ceiling.setter
@@ -505,6 +624,9 @@ def floor_ceiling(self, value: Optional[tuple[float, float]]):
505624

506625
@property
507626
def adjust_floor_ceiling(self):
627+
"""
628+
Whether to adjust floor and ceiling by indexation.
629+
"""
508630
return self._adjust_floor_ceiling
509631

510632
@adjust_floor_ceiling.setter
@@ -517,7 +639,7 @@ def adjust_floor_ceiling(self, value):
517639
@property
518640
def indexation(self) -> float:
519641
"""
520-
Indexation rate for Minimum annual withdrawal and Minimum annual withdrawal.
642+
Indexation rate for Minimum/Maximum annual withdrawal and Floor/Ceiling.
521643
522644
Returns
523645
-------
@@ -542,6 +664,20 @@ def indexation(self, indexation: Optional[float]):
542664
def calculate_withdrawal_size(self, last_withdrawal: float, balance: float, number_of_periods: int) -> float:
543665
"""
544666
Calculate regular withdrawal size (Extra Withdrawals are not taken into account).
667+
668+
Parameters
669+
----------
670+
last_withdrawal : float
671+
Withdrawal amount from the previous period.
672+
balance : float
673+
Current portfolio balance.
674+
number_of_periods : int
675+
Number of periods elapsed.
676+
677+
Returns
678+
-------
679+
float
680+
Calculated withdrawal size.
545681
"""
546682
# All values are positive
547683
withdrawal_size_by_percentage = balance * abs(self.percentage)
@@ -598,6 +734,11 @@ def calculate_withdrawal_size(self, last_withdrawal: float, balance: float, numb
598734
return withdrawal
599735

600736
class CutWithdrawalsIfDrawdown(IndexationStrategy):
737+
"""
738+
Withdrawal strategy that reduces the withdrawal amount if the portfolio drawdown exceeds a certain threshold.
739+
740+
The reduction coefficients are defined in `crash_threshold_reduction` list of tuples.
741+
"""
601742
NAME = "CWID"
602743
def __init__(
603744
self,
@@ -610,6 +751,30 @@ def __init__(
610751
indexation: Optional[Union[str, float]] = None,
611752
crash_threshold_reduction: list[tuple[float, float]] = [(.20, .40), (.50, 1)],
612753
):
754+
"""
755+
Initialize the CutWithdrawalsIfDrawdown strategy.
756+
757+
Parameters
758+
----------
759+
parent : Portfolio
760+
The parent Portfolio instance.
761+
frequency : str, optional
762+
Frequency of cash flows. Default is "year".
763+
initial_investment : float, optional
764+
Initial investment amount. Default is 1000.0.
765+
time_series_dic : dict, optional
766+
Dictionary with dates and cash flow values. Default is empty dict.
767+
time_series_discounted_values : bool, optional
768+
If True, values in time_series_dic are considered as discounted (PV). Default is False.
769+
amount : float, optional
770+
Regular withdrawal amount (negative value) before reduction. Default is 0.0.
771+
indexation : str or float, optional
772+
Indexation rate for the withdrawal amount. Default is None.
773+
crash_threshold_reduction : list[tuple[float, float]], optional
774+
List of tuples (threshold, reduction_coefficient).
775+
Example: [(0.20, 0.40)] means if drawdown > 20%, reduce withdrawal by 40%.
776+
Default is [(.20, .40), (.50, 1)].
777+
"""
613778
super().__init__(
614779
parent=parent,
615780
frequency=frequency,
@@ -639,6 +804,9 @@ def __repr__(self):
639804

640805
@property
641806
def crash_threshold_reduction(self):
807+
"""
808+
List of tuples (threshold, reduction_coefficient).
809+
"""
642810
return self._crash_threshold_reduction
643811

644812
@crash_threshold_reduction.setter
@@ -658,6 +826,18 @@ def crash_threshold_reduction(self, value):
658826
def calculate_withdrawal_size(self, drawdown: float, withdrawal_without_drawdowns: float) -> float:
659827
"""
660828
Calculate regular withdrawal size (Extra Withdrawals are not taken into account).
829+
830+
Parameters
831+
----------
832+
drawdown : float
833+
Current portfolio drawdown (negative value).
834+
withdrawal_without_drawdowns : float
835+
Withdrawal amount calculated without considering drawdowns.
836+
837+
Returns
838+
-------
839+
float
840+
Calculated withdrawal size.
661841
"""
662842
withdrawal = abs(withdrawal_without_drawdowns)
663843
for threshold, reduction in self._crash_threshold_reduction_series.items():
@@ -667,6 +847,19 @@ def calculate_withdrawal_size(self, drawdown: float, withdrawal_without_drawdown
667847
return - withdrawal
668848

669849
def make_series_from_list(self, l: list[tuple[float, float]]) -> pd.Series:
850+
"""
851+
Convert list of tuples to pandas Series.
852+
853+
Parameters
854+
----------
855+
l : list[tuple[float, float]]
856+
List of tuples.
857+
858+
Returns
859+
-------
860+
pd.Series
861+
Series with threshold as index and reduction as value.
862+
"""
670863
indices = [abs(index) for index, _ in l]
671864
values = [abs(value) for _, value in l]
672865
crash_series = pd.Series(values, index=indices)

0 commit comments

Comments
 (0)