@@ -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
151172class 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
395468class 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
600736class 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