def __init__(self, start=start_default, end=end_default): # Midnight in UTC for each trading day. # In pandas 0.18.1, pandas calls into its own code here in a way that # fires a warning. The calling code in pandas tries to suppress the # warning, but does so incorrectly, causing it to bubble out here. # Actually catch and suppress the warning here: with warnings.catch_warnings(): warnings.simplefilter('ignore') _all_days = date_range(start, end, freq=self.day, tz='UTC') # `DatetimeIndex`s of standard opens/closes for each day. self._opens = days_at_time(_all_days, self.open_time, self.tz, self.open_offset) self._closes = days_at_time( _all_days, self.close_time, self.tz, self.close_offset ) # `DatetimeIndex`s of nonstandard opens/closes _special_opens = self._calculate_special_opens(start, end) _special_closes = self._calculate_special_closes(start, end) # Overwrite the special opens and closes on top of the standard ones. _overwrite_special_dates(_all_days, self._opens, _special_opens) _overwrite_special_dates(_all_days, self._closes, _special_closes) # In pandas 0.16.1 _opens and _closes will lose their timezone # information. This looks like it has been resolved in 0.17.1. # http://pandas.pydata.org/pandas-docs/stable/whatsnew.html#datetime-with-tz # noqa self.schedule = DataFrame( index=_all_days, columns=['market_open', 'market_close'], data={ 'market_open': self._opens, 'market_close': self._closes, }, dtype='datetime64[ns]', ) # Simple cache to avoid recalculating the same minute -> session in # "next" mode. Analysis of current zipline code paths show that # `minute_to_session_label` is often called consecutively with the same # inputs. self._minute_to_session_label_cache = LRU(1) self.market_opens_nanos = self.schedule.market_open.values.\ astype(np.int64) self.market_closes_nanos = self.schedule.market_close.values.\ astype(np.int64) self._trading_minutes_nanos = self.all_minutes.values.\ astype(np.int64) self.first_trading_session = _all_days[0] self.last_trading_session = _all_days[-1] self._early_closes = pd.DatetimeIndex( _special_closes.map(self.minute_to_session_label) )
def __init__(self, start=start_default, end=end_default): # Midnight in UTC for each trading day. # In pandas 0.18.1, pandas calls into its own code here in a way that # fires a warning. The calling code in pandas tries to suppress the # warning, but does so incorrectly, causing it to bubble out here. # Actually catch and suppress the warning here: with warnings.catch_warnings(): warnings.simplefilter('ignore') _all_days = date_range(start, end, freq=self.day, tz='UTC') # `DatetimeIndex`s of standard opens/closes for each day. self._opens = days_at_time(_all_days, self.open_time, self.tz, self.open_offset) self._closes = days_at_time( _all_days, self.close_time, self.tz, self.close_offset ) # `DatetimeIndex`s of nonstandard opens/closes _special_opens = self._calculate_special_opens(start, end) _special_closes = self._calculate_special_closes(start, end) # Overwrite the special opens and closes on top of the standard ones. _overwrite_special_dates(_all_days, self._opens, _special_opens) _overwrite_special_dates(_all_days, self._closes, _special_closes) # In pandas 0.16.1 _opens and _closes will lose their timezone # information. This looks like it has been resolved in 0.17.1. # http://pandas.pydata.org/pandas-docs/stable/whatsnew.html#datetime-with-tz # noqa self.schedule = DataFrame( index=_all_days, columns=['market_open', 'market_close'], data={ 'market_open': self._opens, 'market_close': self._closes, }, dtype='datetime64[ns]', ) # Simple cache to avoid recalculating the same minute -> session in # "next" mode. Analysis of current zipline code paths show that # `minute_to_session_label` is often called consecutively with the same # inputs. self._minute_to_session_label_cache = LRU(1) self.market_opens_nanos = self.schedule.market_open.values.\ astype(np.int64) self.market_closes_nanos = self.schedule.market_close.values.\ astype(np.int64) self._trading_minutes_nanos = self.all_minutes.values.\ astype(np.int64) self.first_trading_session = _all_days[0] self.last_trading_session = _all_days[-1] self._early_closes = pd.DatetimeIndex( _special_closes.map(self.minute_to_session_label) )
def all_minutes(self): """ 返回表示此日历中所有分钟的`DatetimeIndex`。 """ opens_in_ns = self._opens.values.astype( 'datetime64[ns]', ).view('int64') closes_in_ns = self._closes.values.astype( 'datetime64[ns]', ).view('int64') # compute_all_minutes假设每天仅包含连续分钟块 dts = DatetimeIndex( compute_all_minutes(opens_in_ns, closes_in_ns), tz='utc', ) # 如果有午休,则排除午休时段 if self.use_lunch_break: # 需要使用utc时间 utc_start = days_at_time( [dts[0].date()], self.lunch_break_start_time, self.tz).time[0] utc_end = days_at_time( [dts[0].date()], self.lunch_break_end_time, self.tz).time[0] locs = dts.indexer_between_time( utc_start, utc_end, include_start=True, include_end=True) return dts.delete(locs) else: return dts
def __init__(self, start=start_default, end=end_default): # 每个交易日UTC的午夜 # self.use_lunch_break = lunch_break # 标记对象是否使用午休时间 # In pandas 0.18.1, pandas calls into its own code here in a way that # fires a warning. The calling code in pandas tries to suppress the # warning, but does so incorrectly, causing it to bubble out here. # Actually catch and suppress the warning here: with warnings.catch_warnings(): warnings.simplefilter('ignore') _all_days = date_range(start, end, freq=self.day, tz='UTC') # 每天标准的开盘和收盘`DatetimeIndex` self._opens = days_at_time(_all_days, self.open_time, self.tz, self.open_offset) self._closes = days_at_time( _all_days, self.close_time, self.tz, self.close_offset ) # 每天非标准的开盘和收盘`DatetimeIndex` _special_opens = self._calculate_special_opens(start, end) _special_closes = self._calculate_special_closes(start, end) # 在标准集的基础上,重写特殊开盘与收盘 _overwrite_special_dates(_all_days, self._opens, _special_opens) _overwrite_special_dates(_all_days, self._closes, _special_closes) # In pandas 0.16.1 _opens and _closes will lose their timezone # information. This looks like it has been resolved in 0.17.1. # http://pandas.pydata.org/pandas-docs/stable/whatsnew.html#datetime-with-tz # noqa self.schedule = DataFrame( index=_all_days, columns=['market_open', 'market_close'], data={ 'market_open': self._opens, 'market_close': self._closes, }, dtype='datetime64[ns]', ) # 简单缓存以避免在“下一个”模式下重新计算相同的分钟 - >会话。 # 对当前zipline代码路径的分析显示,连续调用函数`minute_to_session_label`通常使用相 # 同的输入。 self._minute_to_session_label_cache = LRU(1) # 转化为纳秒整数 self.market_opens_nanos = self.schedule.market_open.values.\ astype(np.int64) self.market_closes_nanos = self.schedule.market_close.values.\ astype(np.int64) # 所有交易分钟(纳秒整数) self._trading_minutes_nanos = self.all_minutes.values.\ astype(np.int64) self.first_trading_session = _all_days[0] self.last_trading_session = _all_days[-1] self._early_closes = pd.DatetimeIndex( _special_closes.map(self.minute_to_session_label) )
def data_query_cutoff_for_sessions(self, sessions): return days_at_time( sessions, self._data_query_time, self._data_query_time.tzinfo, self._data_query_date_offset, )
def data_query_cutoff_for_sessions(self, sessions): return days_at_time( sessions, self._data_query_time, self._data_query_time.tzinfo, self._data_query_date_offset, )
def _test_equity_calendar_domain( self, domain, expected_cutoff_time, expected_cutoff_date_offset=0 ): sessions = pd.DatetimeIndex(domain.calendar.all_sessions[:50]) expected = days_at_time( sessions, expected_cutoff_time, domain.calendar.tz, expected_cutoff_date_offset, ) actual = domain.data_query_cutoff_for_sessions(sessions) assert_equal(actual, expected, check_names=False)
def _test_equity_calendar_domain(self, domain, expected_cutoff_time, expected_cutoff_date_offset=0): sessions = pd.DatetimeIndex(domain.calendar.all_sessions[:50]) expected = days_at_time( sessions, expected_cutoff_time, domain.calendar.tz, expected_cutoff_date_offset, ) actual = domain.data_query_cutoff_for_sessions(sessions) assert_equal(actual, expected, check_names=False)
def _special_dates(self, calendars, ad_hoc_dates, start_date, end_date): """ Union an iterable of pairs of the form (time, calendar) and an iterable of pairs of the form (time, [dates]) (This is shared logic for computing special opens and special closes.) """ _dates = DatetimeIndex([], tz='UTC').union_many([ holidays_at_time(calendar, start_date, end_date, time_, self.tz) for time_, calendar in calendars ] + [ days_at_time(datetimes, time_, self.tz) for time_, datetimes in ad_hoc_dates ]) return _dates[(_dates >= start_date) & (_dates <= end_date)]
def _special_dates(self, calendars, ad_hoc_dates, start_date, end_date): """ 联合一对以(时间,日历)格式的迭代和一对以(时间,[日期])格式的迭代 (这是计算特殊开盘和特殊收盘的共享逻辑。) """ _dates = DatetimeIndex([], tz='UTC').union_many( [ holidays_at_time(calendar, start_date, end_date, time_, self.tz) for time_, calendar in calendars ] + [ days_at_time(datetimes, time_, self.tz) for time_, datetimes in ad_hoc_dates ] ) return _dates[(_dates >= start_date) & (_dates <= end_date)]
def _special_dates(self, calendars, ad_hoc_dates, start_date, end_date): """ Union an iterable of pairs of the form (time, calendar) and an iterable of pairs of the form (time, [dates]) (This is shared logic for computing special opens and special closes.) """ _dates = DatetimeIndex([], tz='UTC').union_many( [ holidays_at_time(calendar, start_date, end_date, time_, self.tz) for time_, calendar in calendars ] + [ days_at_time(datetimes, time_, self.tz) for time_, datetimes in ad_hoc_dates ] ) return _dates[(_dates >= start_date) & (_dates <= end_date)]
def holidays_at_time(calendar, start, end, time, tz): return days_at_time( calendar.holidays(start, end), time, tz=tz, )
def holidays_at_time(calendar, start, end, time, tz): return days_at_time( calendar.holidays(start, end), time, tz=tz, )