Compare commits
No commits in common. "335a6fc2e9e2b5b2b7b6a15cadb1042ccba6f44a" and "1f2b75282b313564bc6043c784a48f3370267691" have entirely different histories.
335a6fc2e9
...
1f2b75282b
@ -1,6 +1,6 @@
|
|||||||
import datetime
|
import datetime
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Dict, Iterable, List, Literal, Tuple, Union
|
from typing import List
|
||||||
|
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
|
|
||||||
@ -11,12 +11,15 @@ class Options:
|
|||||||
closest: str = 'before' # after
|
closest: str = 'before' # after
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
|
||||||
class Frequency:
|
class Frequency:
|
||||||
name: str
|
def __init__(self, name, interval_type, interval_value, interval_days_value):
|
||||||
freq_type: str
|
self.name = name
|
||||||
value: int
|
self.type = interval_type
|
||||||
days: int
|
self.value = interval_value
|
||||||
|
self.days = interval_days_value
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"Frequency({self.name}, {self.type}, {self.value}, {self.days})"
|
||||||
|
|
||||||
|
|
||||||
class AllFrequencies:
|
class AllFrequencies:
|
||||||
@ -40,65 +43,16 @@ def create_date_series(
|
|||||||
dates = []
|
dates = []
|
||||||
|
|
||||||
for i in range(0, int(datediff)):
|
for i in range(0, int(datediff)):
|
||||||
diff = {frequency.freq_type: frequency.value*i}
|
diff = {frequency.type: frequency.value*i}
|
||||||
dates.append(start_date + relativedelta(**diff))
|
dates.append(start_date + relativedelta(**diff))
|
||||||
|
|
||||||
return dates
|
return dates
|
||||||
|
|
||||||
|
|
||||||
def _preprocess_timeseries(
|
|
||||||
data: Union[
|
|
||||||
List[Iterable[Union[str, datetime.datetime, float]]],
|
|
||||||
List[Dict[str, Union[float, datetime.datetime]]],
|
|
||||||
List[Dict[Union[str, datetime.datetime], float]],
|
|
||||||
Dict[Union[str, datetime.datetime], float]
|
|
||||||
],
|
|
||||||
date_format: str
|
|
||||||
) -> List[Tuple[datetime.datetime, float]]:
|
|
||||||
"""Converts any type of list to the correct type"""
|
|
||||||
|
|
||||||
if isinstance(data, list):
|
|
||||||
if isinstance(data[0], dict):
|
|
||||||
if len(data[0].keys()) == 2:
|
|
||||||
current_data = [tuple(i.values()) for i in data]
|
|
||||||
elif len(data[0].keys()) == 1:
|
|
||||||
current_data = [tuple(*i.items()) for i in data]
|
|
||||||
else:
|
|
||||||
raise TypeError("Could not parse the data")
|
|
||||||
current_data = _preprocess_timeseries(current_data, date_format)
|
|
||||||
|
|
||||||
elif isinstance(data[0], Iterable):
|
|
||||||
if isinstance(data[0][0], str):
|
|
||||||
current_data = []
|
|
||||||
for i in data:
|
|
||||||
row = datetime.datetime.strptime(i[0], date_format), i[1]
|
|
||||||
current_data.append(row)
|
|
||||||
elif isinstance(data[0][0], datetime.datetime):
|
|
||||||
current_data = [(i, j) for i, j in data]
|
|
||||||
else:
|
|
||||||
raise TypeError("Could not parse the data")
|
|
||||||
else:
|
|
||||||
raise TypeError("Could not parse the data")
|
|
||||||
|
|
||||||
elif isinstance(data, dict):
|
|
||||||
current_data = [(k, v) for k, v in data.items()]
|
|
||||||
current_data = _preprocess_timeseries(current_data, date_format)
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise TypeError("Could not parse the data")
|
|
||||||
current_data.sort()
|
|
||||||
return current_data
|
|
||||||
|
|
||||||
|
|
||||||
class TimeSeries:
|
class TimeSeries:
|
||||||
"""Container for TimeSeries objects"""
|
"""Container for TimeSeries objects"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(self, data: List[tuple], date_format: str = "%Y-%m-%d", frequency="D"):
|
||||||
self,
|
|
||||||
data: List[Iterable],
|
|
||||||
date_format: str = "%Y-%m-%d",
|
|
||||||
frequency=Literal['D', 'W', 'M', 'Q', 'H', 'Y']
|
|
||||||
):
|
|
||||||
"""Instantiate a TimeSeries object
|
"""Instantiate a TimeSeries object
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
@ -118,11 +72,11 @@ class TimeSeries:
|
|||||||
Valid values are {D, W, M, Q, H, Y}
|
Valid values are {D, W, M, Q, H, Y}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
data = _preprocess_timeseries(data, date_format=date_format)
|
time_series = [(datetime.datetime.strptime(i[0], date_format), i[1]) for i in data]
|
||||||
|
time_series.sort()
|
||||||
self.time_series = dict(data)
|
self.time_series = dict(time_series)
|
||||||
self.dates = set(list(self.time_series))
|
self.dates = set(list(self.time_series))
|
||||||
if len(self.dates) != len(data):
|
if len(self.dates) != len(time_series):
|
||||||
print("Warning: The input data contains duplicate dates which have been ignored.")
|
print("Warning: The input data contains duplicate dates which have been ignored.")
|
||||||
self.start_date = list(self.time_series)[0]
|
self.start_date = list(self.time_series)[0]
|
||||||
self.end_date = list(self.time_series)[-1]
|
self.end_date = list(self.time_series)[-1]
|
||||||
@ -172,7 +126,7 @@ class TimeSeries:
|
|||||||
cur_val = self.time_series[cur_date]
|
cur_val = self.time_series[cur_date]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
new_ts.update({cur_date: cur_val})
|
new_ts.update({cur_date: cur_val}) # type: ignore
|
||||||
|
|
||||||
if inplace:
|
if inplace:
|
||||||
self.time_series = new_ts
|
self.time_series = new_ts
|
||||||
@ -190,7 +144,7 @@ class TimeSeries:
|
|||||||
cur_val = self.time_series[cur_date]
|
cur_val = self.time_series[cur_date]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
new_ts.update({cur_date: cur_val})
|
new_ts.update({cur_date: cur_val}) # type: ignore
|
||||||
|
|
||||||
if inplace:
|
if inplace:
|
||||||
self.time_series = new_ts
|
self.time_series = new_ts
|
||||||
@ -200,7 +154,7 @@ class TimeSeries:
|
|||||||
|
|
||||||
def calculate_returns(
|
def calculate_returns(
|
||||||
self, as_on: datetime.datetime, closest: str = "previous", compounding: bool = True, years: int = 1
|
self, as_on: datetime.datetime, closest: str = "previous", compounding: bool = True, years: int = 1
|
||||||
) -> float:
|
) -> int:
|
||||||
"""Method to calculate returns for a certain time-period as on a particular date
|
"""Method to calculate returns for a certain time-period as on a particular date
|
||||||
>>> calculate_returns(datetime.date(2020, 1, 1), years=1)
|
>>> calculate_returns(datetime.date(2020, 1, 1), years=1)
|
||||||
"""
|
"""
|
||||||
@ -216,7 +170,7 @@ class TimeSeries:
|
|||||||
elif closest == "next":
|
elif closest == "next":
|
||||||
delta = 1
|
delta = 1
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Invalid value for closest parameter: {closest}")
|
raise ValueError(f"Invalid value for closes parameter: {closest}")
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
Loading…
Reference in New Issue
Block a user