improved documentation
This commit is contained in:
		
							parent
							
								
									cad4e1f45c
								
							
						
					
					
						commit
						ad68dcd930
					
				@ -2,7 +2,7 @@ import datetime
 | 
				
			|||||||
from collections import UserDict, UserList
 | 
					from collections import UserDict, UserList
 | 
				
			||||||
from dataclasses import dataclass
 | 
					from dataclasses import dataclass
 | 
				
			||||||
from numbers import Number
 | 
					from numbers import Number
 | 
				
			||||||
from typing import Iterable, List, Literal, Sequence
 | 
					from typing import Iterable, List, Literal, Sequence, Tuple
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .utils import _parse_date, _preprocess_timeseries
 | 
					from .utils import _parse_date, _preprocess_timeseries
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -189,29 +189,40 @@ class TimeSeriesCore(UserDict):
 | 
				
			|||||||
        self._end_date = None
 | 
					        self._end_date = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def dates(self):
 | 
					    def dates(self) -> Series:
 | 
				
			||||||
 | 
					        """Get a list of all the dates in the TimeSeries object"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self._dates is None or len(self._dates) != len(self.data):
 | 
					        if self._dates is None or len(self._dates) != len(self.data):
 | 
				
			||||||
            self._dates = list(self.data.keys())
 | 
					            self._dates = list(self.data.keys())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return Series(self._dates, "date")
 | 
					        return Series(self._dates, "date")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def values(self):
 | 
					    def values(self) -> Series:
 | 
				
			||||||
 | 
					        """Get a list of all the Values in the TimeSeries object"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self._values is None or len(self._values) != len(self.data):
 | 
					        if self._values is None or len(self._values) != len(self.data):
 | 
				
			||||||
            self._values = list(self.data.values())
 | 
					            self._values = list(self.data.values())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return Series(self._values, "number")
 | 
					        return Series(self._values, "number")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def start_date(self):
 | 
					    def start_date(self) -> datetime.datetime:
 | 
				
			||||||
 | 
					        """The first date in the TimeSeries object"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return self.dates[0]
 | 
					        return self.dates[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def end_date(self):
 | 
					    def end_date(self) -> datetime.datetime:
 | 
				
			||||||
 | 
					        """The last date in the TimeSeries object"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return self.dates[-1]
 | 
					        return self.dates[-1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _get_printable_slice(self, n: int):
 | 
					    def _get_printable_slice(self, n: int):
 | 
				
			||||||
        """Returns a slice of the dataframe from beginning and end"""
 | 
					        """Helper function for __repr__ and __str__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Returns a slice of the dataframe from beginning and end.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        printable = {}
 | 
					        printable = {}
 | 
				
			||||||
        iter_f = iter(self.data)
 | 
					        iter_f = iter(self.data)
 | 
				
			||||||
@ -322,7 +333,21 @@ class TimeSeriesCore(UserDict):
 | 
				
			|||||||
        return self.data.items()
 | 
					        return self.data.items()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def iloc(self):
 | 
					    def iloc(self) -> List[Tuple[datetime.datetime, float]]:
 | 
				
			||||||
        """Returns an item or a set of items based on index"""
 | 
					        """Returns an item or a set of items based on index
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            supports slicing using numerical index.
 | 
				
			||||||
 | 
					            Accepts integers or Python slice objects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Usage
 | 
				
			||||||
 | 
					        -----
 | 
				
			||||||
 | 
					        >>> ts = TimeSeries(data, frequency='D')
 | 
				
			||||||
 | 
					        >>> ts.iloc[0]  # get the first value
 | 
				
			||||||
 | 
					        >>> ts.iloc[-1]  # get the last value
 | 
				
			||||||
 | 
					        >>> ts.iloc[:3]  # get the first 3 values
 | 
				
			||||||
 | 
					        >>> ts.illoc[-3:]  # get the last 3 values
 | 
				
			||||||
 | 
					        >>> ts.iloc[5:10]  # get five values starting from the fifth value
 | 
				
			||||||
 | 
					        >>> ts.iloc[::2]  # get every alternate date
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return _IndexSlicer(self)
 | 
					        return _IndexSlicer(self)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										158
									
								
								fincal/fincal.py
									
									
									
									
									
								
							
							
						
						
									
										158
									
								
								fincal/fincal.py
									
									
									
									
									
								
							@ -1,7 +1,7 @@
 | 
				
			|||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import datetime
 | 
					import datetime
 | 
				
			||||||
from typing import List, Literal, Union
 | 
					from typing import Iterable, List, Literal, Mapping, Union
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from dateutil.relativedelta import relativedelta
 | 
					from dateutil.relativedelta import relativedelta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -15,9 +15,41 @@ from .utils import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def create_date_series(
 | 
					def create_date_series(
 | 
				
			||||||
    start_date: datetime.datetime, end_date: datetime.datetime, frequency: str, eomonth: bool = False
 | 
					    start_date: Union[str, datetime.datetime],
 | 
				
			||||||
 | 
					    end_date: Union[str, datetime.datetime],
 | 
				
			||||||
 | 
					    frequency: Literal["D", "W", "M", "Q", "H", "Y"],
 | 
				
			||||||
 | 
					    eomonth: bool = False,
 | 
				
			||||||
) -> List[datetime.datetime]:
 | 
					) -> List[datetime.datetime]:
 | 
				
			||||||
    """Creates a date series using a frequency"""
 | 
					    """Create a date series with a specified frequency
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Parameters
 | 
				
			||||||
 | 
					    ----------
 | 
				
			||||||
 | 
					    start_date : str | datetime.datetime
 | 
				
			||||||
 | 
					        Date series will always start at this date
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    end_date : str | datetime.datetime
 | 
				
			||||||
 | 
					        The date till which the series should extend
 | 
				
			||||||
 | 
					        Depending on the other parameters, this date may or may not be present
 | 
				
			||||||
 | 
					        in the final date series
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    frequency : D | W | M | Q | H | Y
 | 
				
			||||||
 | 
					        Frequency of the date series.
 | 
				
			||||||
 | 
					        The gap between each successive date will be equivalent to this frequency
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    eomonth : bool, optional
 | 
				
			||||||
 | 
					        Speacifies if the dates in the series should be end of month dates.
 | 
				
			||||||
 | 
					        Can only be used if the frequency is Monthly or lower.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Returns
 | 
				
			||||||
 | 
					    -------
 | 
				
			||||||
 | 
					    List[datetime.datetime]
 | 
				
			||||||
 | 
					        Returns the series as a list of datetime objects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Raises
 | 
				
			||||||
 | 
					    ------
 | 
				
			||||||
 | 
					    ValueError
 | 
				
			||||||
 | 
					        If eomonth is True and frequency is higher than monthly
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    frequency = getattr(AllFrequencies, frequency)
 | 
					    frequency = getattr(AllFrequencies, frequency)
 | 
				
			||||||
    if eomonth and frequency.days < AllFrequencies.M.days:
 | 
					    if eomonth and frequency.days < AllFrequencies.M.days:
 | 
				
			||||||
@ -43,7 +75,40 @@ def create_date_series(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TimeSeries(TimeSeriesCore):
 | 
					class TimeSeries(TimeSeriesCore):
 | 
				
			||||||
    """Container for TimeSeries objects"""
 | 
					    """1-Dimensional Time Series object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Parameters
 | 
				
			||||||
 | 
					    ----------
 | 
				
			||||||
 | 
					    data : List[Iterable] | Mapping
 | 
				
			||||||
 | 
					        Time Series data in the form of list of tuples.
 | 
				
			||||||
 | 
					        The first element of each tuple should be a date and second element should be a value.
 | 
				
			||||||
 | 
					        The following types of objects can be passed to create a TimeSeries object:
 | 
				
			||||||
 | 
					        * List of tuples containing date & value
 | 
				
			||||||
 | 
					        * List of lists containing date & value
 | 
				
			||||||
 | 
					        * List of dictionaries containing key: value pair of date and value
 | 
				
			||||||
 | 
					        * List of dictionaries with 2 keys, first representing date & second representing value
 | 
				
			||||||
 | 
					        * Dictionary of key: value pairs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    date_format : str, optional, default "%Y-%m-%d"
 | 
				
			||||||
 | 
					        Specify the format of the date
 | 
				
			||||||
 | 
					        Required only if the first argument of tuples is a string. Otherwise ignored.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    frequency : str, optional, default "infer"
 | 
				
			||||||
 | 
					        The frequency of the time series. Default is infer.
 | 
				
			||||||
 | 
					        The class will try to infer the frequency automatically and adjust to the closest member.
 | 
				
			||||||
 | 
					        Note that inferring frequencies can fail if the data is too irregular.
 | 
				
			||||||
 | 
					        Valid values are {D, W, M, Q, H, Y}
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        data: Union[List[Iterable], Mapping],
 | 
				
			||||||
 | 
					        frequency: Literal["D", "W", "M", "Q", "H", "Y"],
 | 
				
			||||||
 | 
					        date_format: str = "%Y-%m-%d",
 | 
				
			||||||
 | 
					    ):
 | 
				
			||||||
 | 
					        """Instantiate a TimeSeriesCore object"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        super().__init__(data, frequency, date_format)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def info(self):
 | 
					    def info(self):
 | 
				
			||||||
        """Summary info about the TimeSeries object"""
 | 
					        """Summary info about the TimeSeries object"""
 | 
				
			||||||
@ -154,6 +219,12 @@ class TimeSeries(TimeSeriesCore):
 | 
				
			|||||||
            The mode of matching the closest date.
 | 
					            The mode of matching the closest date.
 | 
				
			||||||
            Valid values are 'exact', 'previous', 'next' and next.
 | 
					            Valid values are 'exact', 'previous', 'next' and next.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        closest_max_days: int, default -1
 | 
				
			||||||
 | 
					            The maximum acceptable gap between the provided date arguments and actual date.
 | 
				
			||||||
 | 
					            Pass -1 for no limit.
 | 
				
			||||||
 | 
					            Note: There's a hard max limit of 1000 days due to Python's limits on recursion.
 | 
				
			||||||
 | 
					                  This can be overridden by importing the sys module.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if_not_found : 'fail' | 'nan'
 | 
					        if_not_found : 'fail' | 'nan'
 | 
				
			||||||
            What to do when required date is not found:
 | 
					            What to do when required date is not found:
 | 
				
			||||||
            * fail: Raise a ValueError
 | 
					            * fail: Raise a ValueError
 | 
				
			||||||
@ -173,12 +244,6 @@ class TimeSeries(TimeSeriesCore):
 | 
				
			|||||||
            Should be passed as a datetime library compatible string.
 | 
					            Should be passed as a datetime library compatible string.
 | 
				
			||||||
            Sets the date format only for this operation. To set it globally, use FincalOptions.date_format
 | 
					            Sets the date format only for this operation. To set it globally, use FincalOptions.date_format
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        closest_max_days: int, default -1
 | 
					 | 
				
			||||||
            The maximum acceptable gap between the provided date arguments and actual date.
 | 
					 | 
				
			||||||
            Pass -1 for no limit.
 | 
					 | 
				
			||||||
            Note: There's a hard max limit of 1000 days due to Python's limits on recursion.
 | 
					 | 
				
			||||||
                  This can be overridden by importing the sys module.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Returns
 | 
					        Returns
 | 
				
			||||||
        -------
 | 
					        -------
 | 
				
			||||||
        A tuple containing the date and float value of the returns.
 | 
					        A tuple containing the date and float value of the returns.
 | 
				
			||||||
@ -192,6 +257,7 @@ class TimeSeries(TimeSeriesCore):
 | 
				
			|||||||
        Example
 | 
					        Example
 | 
				
			||||||
        --------
 | 
					        --------
 | 
				
			||||||
        >>> calculate_returns(datetime.date(2020, 1, 1), years=1)
 | 
					        >>> calculate_returns(datetime.date(2020, 1, 1), years=1)
 | 
				
			||||||
 | 
					        (datetime.datetime(2020, 1, 1, 0, 0), .0567)
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        as_on = _parse_date(as_on, date_format)
 | 
					        as_on = _parse_date(as_on, date_format)
 | 
				
			||||||
@ -214,17 +280,81 @@ class TimeSeries(TimeSeriesCore):
 | 
				
			|||||||
        self,
 | 
					        self,
 | 
				
			||||||
        from_date: Union[datetime.date, str],
 | 
					        from_date: Union[datetime.date, str],
 | 
				
			||||||
        to_date: Union[datetime.date, str],
 | 
					        to_date: Union[datetime.date, str],
 | 
				
			||||||
        frequency: str = None,
 | 
					        frequency: Literal["D", "W", "M", "Q", "H", "Y"] = None,
 | 
				
			||||||
        as_on_match: str = "closest",
 | 
					        as_on_match: str = "closest",
 | 
				
			||||||
        prior_match: str = "closest",
 | 
					        prior_match: str = "closest",
 | 
				
			||||||
        closest: str = "previous",
 | 
					        closest: Literal["previous", "next", "exact"] = "previous",
 | 
				
			||||||
        if_not_found: Literal["fail", "nan"] = "fail",
 | 
					        if_not_found: Literal["fail", "nan"] = "fail",
 | 
				
			||||||
        compounding: bool = True,
 | 
					        compounding: bool = True,
 | 
				
			||||||
        interval_type: Literal["years", "months", "days"] = "years",
 | 
					        interval_type: Literal["years", "months", "days"] = "years",
 | 
				
			||||||
        interval_value: int = 1,
 | 
					        interval_value: int = 1,
 | 
				
			||||||
        date_format: str = None,
 | 
					        date_format: str = None,
 | 
				
			||||||
    ) -> List[tuple]:
 | 
					    ) -> TimeSeries:
 | 
				
			||||||
        """Calculates the rolling return"""
 | 
					        """Calculate the returns on a rolling basis.
 | 
				
			||||||
 | 
					            This is a wrapper function around the calculate_returns function.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Parameters
 | 
				
			||||||
 | 
					        ----------
 | 
				
			||||||
 | 
					        from_date : datetime.date | str
 | 
				
			||||||
 | 
					            Start date for the return calculation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        to_date : datetime.date | str
 | 
				
			||||||
 | 
					            End date for the returns calculation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        frequency : str, optional
 | 
				
			||||||
 | 
					            Frequency at which the returns should be calcualated.
 | 
				
			||||||
 | 
					            Valid values are {D, W, M, Q, H, Y}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        as_on_match : str, optional
 | 
				
			||||||
 | 
					            The match mode to be used for the as on date.
 | 
				
			||||||
 | 
					            If not specified, the value for the closes parameter will be used.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        prior_match : str, optional
 | 
				
			||||||
 | 
					            The match mode to be used for the prior date, i.e., the date against which the return will be calculated.
 | 
				
			||||||
 | 
					            If not specified, the value for the closes parameter will be used.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        closest : previous | next | exact
 | 
				
			||||||
 | 
					            The default match mode for dates.
 | 
				
			||||||
 | 
					            * Previous: look for the immediate previous available date
 | 
				
			||||||
 | 
					            * Next: look for the immediate next available date
 | 
				
			||||||
 | 
					            * Exact: Only look for the exact date passed in the input
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if_not_found : fail | nan
 | 
				
			||||||
 | 
					            Specifies what should be done if the date is not found.
 | 
				
			||||||
 | 
					            * fail: raise a DateNotFoundError.
 | 
				
			||||||
 | 
					            * nan: return nan as the value.
 | 
				
			||||||
 | 
					                Note, this will return float('NaN') and not 'nan' as string.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Note, this function will always raise an error if it is not possible to find a matching date.`
 | 
				
			||||||
 | 
					            For instance, if the input date is before the starting of the first date of the time series,
 | 
				
			||||||
 | 
					            but match mode is set to previous. A DateOutOfRangeError will be raised in such cases.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        compounding : bool, optional
 | 
				
			||||||
 | 
					            Should the returns be compounded annually.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        interval_type : years | month | days
 | 
				
			||||||
 | 
					            The interval for the return calculation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        interval_value : int, optional
 | 
				
			||||||
 | 
					            The value of the interval for return calculation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        date_format : str, optional
 | 
				
			||||||
 | 
					            A datetime library compatible format string.
 | 
				
			||||||
 | 
					            If not specified, will use the setting in FincalOptions.date_format.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns
 | 
				
			||||||
 | 
					        -------
 | 
				
			||||||
 | 
					            Returs the rolling returns as a TimeSeries object.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Raises
 | 
				
			||||||
 | 
					        ------
 | 
				
			||||||
 | 
					            ValueError
 | 
				
			||||||
 | 
					            - If an invalid argument is passed for frequency parameter.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        See also
 | 
				
			||||||
 | 
					        --------
 | 
				
			||||||
 | 
					            TimeSeries.calculate_returns
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        from_date = _parse_date(from_date, date_format)
 | 
					        from_date = _parse_date(from_date, date_format)
 | 
				
			||||||
        to_date = _parse_date(to_date, date_format)
 | 
					        to_date = _parse_date(to_date, date_format)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user