Compare commits

..

No commits in common. "978566e0a885380cc6fdbe95aff897442b5311f2" and "65f2e8434ccdbe16b538006b8407890845e99f25" have entirely different histories.

4 changed files with 25 additions and 64 deletions

View File

@ -19,7 +19,7 @@ Fincal aims to simplify things by allowing you to:
## To-do
### Core features
- [x] Add __setitem__
- [ ] Add __setitem__
- [ ] Create emtpy TimeSeries object
- [x] Read from CSV
- [ ] Write to CSV

View File

@ -6,7 +6,7 @@ import warnings
from collections import UserList
from dataclasses import dataclass
from numbers import Number
from typing import Any, Callable, Iterable, List, Literal, Mapping, Sequence, Type
from typing import Callable, Iterable, List, Literal, Mapping, Sequence, Type
from dateutil.relativedelta import relativedelta
@ -393,7 +393,7 @@ class TimeSeriesCore:
def _get_item_from_date(self, date: str | datetime.datetime):
"""Helper function to retrieve item using a date"""
return self.get(date, raise_error=True)
return date, self.data[date]
def _get_item_from_key(self, key: str | datetime.datetime):
"""Helper function to implement special keys"""
@ -447,9 +447,9 @@ class TimeSeriesCore:
raise TypeError("Only numerical values can be stored in TimeSeries")
if key in self.data:
self.data[key] = float(value)
self.data[key] = value
else:
self.data.update({key: float(value)})
self.data.update({key: value})
self.data = dict(sorted(self.data.items()))
@date_parser(1)
@ -765,71 +765,32 @@ class TimeSeriesCore:
raise NotImplementedError("This operation is not supported.")
@date_parser(1)
def get(
self,
date: str | datetime.datetime,
default: Any = None,
closest: Literal["previous", "next"] = None,
limit: int = 1000,
raise_error: bool = False,
) -> tuple | Any:
"""Get a value for a particular key. Return a default value on KeyError
Parameters
----------
date:
Date for which the value needs to be fetched.
default: Optional, Default None
Default value to be returned in case the date is not found. Default None.
closest:
Look for previous or next value when date is not found.
If not specified, the value set in FincalOptions is used
limit:
Maximum number of days to look for the closest available date.
If exceeded without finding a date, default value will be returned.
raise_error : bool, optional
Whether to raise an error and ignore the default value.
Meant for use with __getitem__.
Returns
-------
tuple | Any
_description_
Raises
------
ValueError
If the argument for closest is not valid.
KeyError
if raise_error is true and date is not found
"""
def get(self, date: str | datetime.datetime, default=None, closest=None):
if closest is None:
closest = FincalOptions.get_closest
time_delta_dict = {"exact": 0, "previous": -1, "next": 1}
if closest not in time_delta_dict:
raise ValueError(f"Invalid argument from closest {closest!r}")
delta = relativedelta(days=time_delta_dict[closest])
for _ in range(limit):
if closest == "exact":
try:
return date, self.data[date]
item = self._get_item_from_date(date)
return item
except KeyError:
if not delta:
break
date += delta
if raise_error:
raise KeyError(date)
return default
if closest == "previous":
delta = datetime.timedelta(-1)
elif closest == "next":
delta = datetime.timedelta(1)
else:
raise ValueError(f"Invalid argument from closest {closest!r}")
while True:
try:
item = self._get_item_from_date(date)
return item
except KeyError:
date += delta
@property
def iloc(self) -> Mapping:
"""Returns an item or a set of items based on index

View File

@ -8,7 +8,7 @@ from .exceptions import DateNotFoundError, DateOutOfRangeError
@dataclass
class FincalOptions:
date_format: str = "%Y-%m-%d"
closest: str = "previous" # next
closest: str = "before" # after
traded_days: int = 365
get_closest: str = "exact"

View File

@ -386,7 +386,7 @@ class TestTimeSeriesArithmatic:
def test_truediv(self):
ts = TimeSeriesCore(self.data, "M")
ser = Series([22, 23, 24, 25], "number")
ser = Series([21, 21, 23, 24], "number")
num_div_ts = ts / 10
assert num_div_ts["2021-01-01"][1] == 22