Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add / Rename ExchangeCalendar methods #105

Merged
merged 3 commits into from
Oct 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions exchange_calendars/calendar_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def previous_divider_idx(dividers: np.ndarray, minute_val: int) -> int:
return divider_idx - 1


def compute_all_minutes(
def compute_minutes(
opens_in_ns: np.ndarray,
break_starts_in_ns: np.ndarray,
break_ends_in_ns: np.ndarray,
Expand Down Expand Up @@ -112,7 +112,7 @@ def one_minute_later(arr: np.ndarray) -> np.ndarray:

def parse_timestamp(
timestamp: Date | Minute,
param_name: str,
param_name: str = "minute",
calendar: ExchangeCalendar | None = None,
raise_oob: bool = True,
side: str | None = None,
Expand Down Expand Up @@ -214,7 +214,7 @@ def parse_timestamp(


def parse_trading_minute(
calendar: ExchangeCalendar, minute: TradingMinute, param_name: str
calendar: ExchangeCalendar, minute: TradingMinute, param_name: str = "minute"
) -> pd.Timestamp:
"""Parse input intended to represent a trading minute.

Expand Down Expand Up @@ -249,7 +249,7 @@ def parse_trading_minute(

def parse_date(
date: Date,
param_name: str,
param_name: str = "date",
calendar: ExchangeCalendar | None = None,
raise_oob: bool = True,
) -> pd.Timestamp:
Expand Down Expand Up @@ -322,7 +322,7 @@ def parse_date(


def parse_session(
calendar: ExchangeCalendar, session: Session, param_name: str
calendar: ExchangeCalendar, session: Session, param_name: str = "session"
) -> pd.Timestamp:
"""Parse input intended to represent a session label.

Expand All @@ -337,7 +337,7 @@ def parse_session(
`calendar`.

param_name
Name of a parameter that was to receive a session label.
Name of a parameter that was to receive a session.

Returns
-------
Expand Down Expand Up @@ -388,17 +388,17 @@ def __init__(
self.curtail_overlaps = curtail_overlaps

# get session bound values over requested range
slice_start = calendar.all_sessions.searchsorted(start)
slice_end = calendar.all_sessions.searchsorted(end, side="right")
slice_start = calendar.sessions.searchsorted(start)
slice_end = calendar.sessions.searchsorted(end, side="right")
slce = slice(slice_start, slice_end)

self.interval_nanos = period.value
self.dtype = np.int64 if self.interval_nanos < 3000000000 else np.int32

self.opens = calendar.market_opens_nanos[slce]
self.closes = calendar.market_closes_nanos[slce]
self.break_starts = calendar.market_break_starts_nanos[slce]
self.break_ends = calendar.market_break_ends_nanos[slce]
self.opens = calendar.opens_nanos[slce]
self.closes = calendar.closes_nanos[slce]
self.break_starts = calendar.break_starts_nanos[slce]
self.break_ends = calendar.break_ends_nanos[slce]

self.mask = self.break_starts != pd.NaT.value # break mask
self.has_break = self.mask.any()
Expand Down
84 changes: 70 additions & 14 deletions exchange_calendars/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def __init__(self, calendar: ExchangeCalendar, ts: pd.Timestamp, param_name: str

def __str__(self) -> str:
msg = (
f"Parameter `{self.param_name}` takes a session label"
f"Parameter `{self.param_name}` takes a session"
f" although received input that parsed to '{self.ts}' which"
)

Expand Down Expand Up @@ -219,7 +219,7 @@ def __str__(self) -> str:
f"Parameter `{self.param_name}` takes a trading minute although"
f" received input that parsed to '{self.minute}' which"
)
if self.minute < self.calendar.first_trading_minute:
if self.minute < self.calendar.first_minute:
msg += (
" is earlier than the first trading minute of calendar"
f" '{self.calendar.name}' ('{self.calendar.first_session}')."
Expand Down Expand Up @@ -260,24 +260,80 @@ def __init__(

def __str__(self) -> str:
msg = f"Parameter `{self.param_name}` receieved as '{self.minute}' although"
if self.minute < self.calendar.first_trading_minute:
if self.minute < self.calendar.first_minute:
msg += (
" cannot be earlier than the first trading minute of calendar"
f" '{self.calendar.name}' ('{self.calendar.first_trading_minute}')."
f" '{self.calendar.name}' ('{self.calendar.first_minute}')."
)
elif self.minute > self.calendar.last_trading_minute:
elif self.minute > self.calendar.last_minute:
msg += (
" cannot be later than the last trading minute of calendar"
f" '{self.calendar.name}' ('{self.calendar.last_trading_minute}')."
f" '{self.calendar.name}' ('{self.calendar.last_minute}')."
)
else:
assert (
self.minute < self.calendar.first_trading_minute
or self.minute > self.calendar.last_trading_minute
self.minute < self.calendar.first_minute
or self.minute > self.calendar.last_minute
)
return msg


class RequestedSessionOutOfBounds(ValueError):
"""The requested session would fall beyond calendar bounds.

Parameters
----------
calendar
Calendar for which session would be out-of-bounds.

too_early
True if requested session would be earlier than the first calendar
session.
False if requested session would be later than the last calendar
session.
"""

def __init__(self, calendar: ExchangeCalendar, too_early: bool):
self.calendar = calendar
self.adverb = "before" if too_early else "after"
self.position = "first" if too_early else "last"
self.bound = calendar.first_session if too_early else calendar.last_session

def __str__(self) -> str:
return (
f"Requested session would fall {self.adverb} the calendar's {self.position}"
f" session ('{self.bound}')."
)


class RequestedMinuteOutOfBounds(ValueError):
"""The requested trading minute would fall beyond calendar bounds.

Parameters
----------
calendar
Calendar for which minute would be out-of-bounds.

too_early
True if requested minute would be earlier than the first calendar
minute.
False if requested minute would be later than the last calendar
minute.
"""

def __init__(self, calendar: ExchangeCalendar, too_early: bool):
self.calendar = calendar
self.adverb = "before" if too_early else "after"
self.position = "first" if too_early else "last"
self.bound = calendar.first_minute if too_early else calendar.last_minute

def __str__(self) -> str:
return (
f"Requested minute would fall {self.adverb} the calendar's {self.position}"
f" trading minute ('{self.bound}')."
)


class IndexOverlapError(ValueError):
"""Periods implied by indices overlap."""

Expand All @@ -290,9 +346,9 @@ def __str__(self): # noqa: D105
return (
"Unable to create trading index as intervals would overlap."
" This can occur when the frequency is longer than a break or"
" the period between one session's close and the next"
" session's open. To shorten intervals that would otherwise"
" overlap either pass `curtail_overlaps` as True or pass"
" the gap between one session's close and the next session's"
" open. To shorten intervals that would otherwise overlap"
" either pass `curtail_overlaps` as True or pass"
" `force_close` and/or `force_break_close` as True."
)

Expand All @@ -306,8 +362,8 @@ def __str__(self): # noqa: D105
"Unable to create trading index as an indice would fall to the"
" right of (later than) the subsequent indice. This can occur"
" when the frequency is longer than a break or the frequency"
" is longer than the period between one session's close and"
" the next session's open. Consider passing `closed` as"
" 'left' or passing `force_close` and/or `force_break_close`"
" is longer than the gap between one session's close and the"
" next session's open. Consider passing `closed` as `left`"
" or passing `force_close` and/or `force_break_close`"
" as True."
)
Loading