Source code for lilio.calendar_shorthands

"""Shorthands for calendars, to make generating commonly used calendars a one-liner."""

import re
import pandas as pd
from .calendar import Calendar


[docs] def daily_calendar( anchor: str, length: str = "1d", n_targets: int = 1, n_precursors: int = 0, allow_overlap: bool = False, ) -> Calendar: """Instantiate a basic daily calendar with minimal configuration. Set up a quick calendar revolving around intervals with day-based lengths. The intervals will extend back in time with as many intervals as fit within the cycle time of one year. Args: anchor: String in the form "12-31" for December 31st. The first target interval will contain the anchor, while the precursor intervals are built back in time starting at this date. length: The length of every target and precursor period. n_targets: integer specifying the number of target intervals in a period. n_precursors: Sets the maximum number of precursors of the Calendar. If `0`, the amount will be determined by how many fit in each anchor year. If a value is provided, the intervals can either only cover part of the year, or extend over multiple years. In case of a large max_lag number where the intervals extend over multiple years, anchor years will be skipped to avoid overlapping intervals. To allow overlapping intervals, use the `allow_overlap` kwarg. allow_overlap: Allows intervals to overlap between anchor years, if the max_lag is set to a high enough number that intervals extend over multiple years. `False` by default, to avoid train/test information leakage. Returns: An instantiated Calendar built according to the input kwarg specifications Example: Instantiate a calendar counting towards Christmas in 3-days steps. >>> import lilio >>> calendar = lilio.daily_calendar(anchor='12-25', length="3d", n_precursors=3) >>> calendar # doctest: +NORMALIZE_WHITESPACE Calendar( anchor='12-25', allow_overlap=False, mapping=None, intervals=[ Interval(role='target', length='3d', gap='0d'), Interval(role='precursor', length='3d', gap='0d'), Interval(role='precursor', length='3d', gap='0d'), Interval(role='precursor', length='3d', gap='0d') ] ) """ if not re.fullmatch(r"\d*d", length): raise ValueError("Please input a frequency in the form of '2d'") periods_per_year = pd.Timedelta("365days") / pd.to_timedelta(length) n_intervals = ( (n_precursors + n_targets) if n_precursors > 0 else int(periods_per_year) ) n_precursors = n_intervals - n_targets cal = Calendar(anchor=anchor, allow_overlap=allow_overlap) cal.add_intervals(role="target", length=length, n=n_targets) if n_precursors > 0: cal.add_intervals(role="precursor", length=length, n=n_precursors) return cal
[docs] def weekly_calendar( anchor: str, length: str = "1W", n_targets: int = 1, n_precursors: int = 0, allow_overlap: bool = False, ) -> Calendar: """Instantiate a basic monthly calendar with minimal configuration. Set up a quick calendar revolving around intervals with week-based lengths. The precursor intervals will extend back in time with as many intervals as fit within the cycle time of one year (i.e. 52 - n_targets). Note that the difference between this calendar and the daily_calendar revolves around the use of calendar weeks (Monday - Sunday), instead of 7-day periods. Args: anchor: Str in the form of "40W", denoting the week number. The first target interval will contain the anchor, while the precursor intervals are built back in time starting from this week. length: The length of every precursor and target interval, e.g. '2W'. n_targets: integer specifying the number of target intervals in a period. n_precursors: Sets the maximum number of precursors of the Calendar. If `0`, the amount will be determined by how many fit in each anchor year. If a value is provided, the intervals can either only cover part of the year, or extend over multiple years. In case of a large max_lag number where the intervals extend over multiple years, anchor years will be skipped to avoid overlapping intervals. To allow overlapping intervals, use the `allow_overlap` kwarg. allow_overlap: Allows intervals to overlap between anchor years, if the max_lag is set to a high enough number that intervals extend over multiple years. `False` by default, to avoid train/test information leakage. Returns: An instantiated Calendar built according to the input kwarg specifications Example: Instantiate a calendar counting down the quarters (3 month periods) from december. >>> import lilio >>> calendar = lilio.weekly_calendar(anchor="W40", length="1W", n_precursors=2) >>> calendar # doctest: +NORMALIZE_WHITESPACE Calendar( anchor='W40-1', allow_overlap=False, mapping=None, intervals=[ Interval(role='target', length='1W', gap='0d'), Interval(role='precursor', length='1W', gap='0d'), Interval(role='precursor', length='1W', gap='0d') ] ) """ if not re.fullmatch(r"\d*W", length): raise ValueError("Please input a frequency in the form of '4W'") periods_per_year = pd.Timedelta("365days") / pd.to_timedelta(length) n_intervals = ( (n_precursors + n_targets) if n_precursors > 0 else int(periods_per_year) ) n_precursors = n_intervals - n_targets cal = Calendar(anchor=anchor, allow_overlap=allow_overlap) cal.add_intervals(role="target", length=length, n=n_targets) if n_precursors > 0: cal.add_intervals(role="precursor", length=length, n=n_precursors) return cal
[docs] def monthly_calendar( anchor: str, length: str = "1M", n_targets: int = 1, n_precursors: int = 0, allow_overlap: bool = False, ) -> Calendar: """Instantiate a basic monthly calendar with minimal configuration. Set up a quick calendar revolving around intervals with month-based lengths. The intervals will extend back in time with as many intervals as fit within the cycle time of one year. Args: anchor: Str in the form 'January' or 'Jan'. he first target interval will contain the anchor, while the precursor intervals are built back in time starting at this Month. length: The length of every target and precursor period, in the form '1M', '2M', etc. n_targets: integer specifying the number of target intervals in a period. n_precursors: Sets the maximum number of precursors of the Calendar. If `0`, the amount will be determined by how many fit in each anchor year. If a value is provided, the intervals can either only cover part of the year, or extend over multiple years. In case of a large max_lag number where the intervals extend over multiple years, anchor years will be skipped to avoid overlapping intervals. To allow overlapping intervals, use the `allow_overlap` kwarg. allow_overlap: Allows intervals to overlap between anchor years, if the max_lag is set to a high enough number that intervals extend over multiple years. `False` by default, to avoid train/test information leakage. Returns: An instantiated Calendar built according to the input kwarg specifications Example: Instantiate a calendar counting down the quarters (3 month periods) from december. >>> import lilio >>> calendar = lilio.monthly_calendar(anchor='Dec', length="3M") >>> calendar # doctest: +NORMALIZE_WHITESPACE Calendar( anchor='12', allow_overlap=False, mapping=None, intervals=[ Interval(role='target', length='3M', gap='0d'), Interval(role='precursor', length='3M', gap='0d'), Interval(role='precursor', length='3M', gap='0d'), Interval(role='precursor', length='3M', gap='0d') ] ) """ if not re.fullmatch(r"\d*M", length): raise ValueError("Please input a frequency in the form of '2M'") periods_per_year = 12 / int(length.replace("M", "")) n_intervals = ( (n_precursors + n_targets) if n_precursors > 0 else int(periods_per_year) ) n_precursors = n_intervals - n_targets cal = Calendar(anchor=anchor, allow_overlap=allow_overlap) cal.add_intervals(role="target", length=length, n=n_targets) if n_precursors > 0: cal.add_intervals(role="precursor", length=length, n=n_precursors) return cal