def test_merge_schedules(): cal1 = FakeCalendar() cal2 = NYSEExchangeCalendar() # cal1 is open on 2016-07-04 and cal2 is not sch1 = cal1.schedule('2016-07-01', '2016-07-06') sch2 = cal2.schedule('2016-07-01', '2016-07-06') # outer join will include July 4th and have expected = pd.DataFrame( { 'market_open': [ pd.Timestamp(x, tz='UTC') for x in [ '2016-07-01 02:13', '2016-07-04 02:13', '2016-07-05 02:13', '2016-07-06 02:13' ] ], 'market_close': [ pd.Timestamp(x, tz='UTC') for x in [ '2016-07-01 20:00', '2016-07-04 02:49', '2016-07-05 20:00', '2016-07-06 20:00' ] ] }, columns=['market_open', 'market_close'], index=pd.DatetimeIndex( ['2016-07-01', '2016-07-04', '2016-07-05', '2016-07-06'])) actual = mcal.merge_schedules([sch1, sch2], how='outer') assert_frame_equal(actual, expected) # inner join will exclude July 4th because not open for both expected = pd.DataFrame( { 'market_open': [ pd.Timestamp(x, tz='UTC') for x in ['2016-07-01 13:30', '2016-07-05 13:30', '2016-07-06 13:30'] ], 'market_close': [ pd.Timestamp(x, tz='UTC') for x in ['2016-07-01 02:49', '2016-07-05 02:49', '2016-07-06 02:49'] ] }, columns=['market_open', 'market_close'], index=pd.DatetimeIndex(['2016-07-01', '2016-07-05', '2016-07-06'])) actual = mcal.merge_schedules([sch1, sch2], how='inner') assert_frame_equal(actual, expected) # joining more than two calendars works correctly actual = mcal.merge_schedules([sch1, sch1, sch1], how='inner') assert_frame_equal(actual, sch1) with pytest.raises(ValueError): mcal.merge_schedules([sch1, sch2], how='left')
def test_merge_schedules_w_break(): # this currently does not work as all breaks are lost cal = FakeCalendar() cal_breaks = FakeBreakCalendar() schedule = cal.schedule('2016-12-20', '2016-12-30') schedule_breaks = cal_breaks.schedule('2016-12-20', '2016-12-30') with pytest.warns(Warning) as w: result = mcal.merge_schedules([schedule, schedule_breaks]) assert w[0].message.args[ 0] == 'Merge schedules will drop the break_start and break_end from result.' assert 'break_start' not in result.columns assert 'break_end' not in result.columns
def get_mtm_dates(start_date, end_date, exchanges, how='all', holidays=None): """ Dates which are tradeable based on the calendars for the exchanges that the set of instruments in the portfolio trade on. Parameters ---------- start_date: pandas.Timestamp Date to generate mtm dates starting from end_date: pandas.Timestamp Date to generate mtm dates until exchanges: list list of strings representing exchanges, see pandas_market_calendars how: {'all', 'any'}, default 'all' * all: all instruments must be tradeable for date to be included * any: any instrument must be tradeable for date to be included holidays: list list of adhoc pd.Timestamps representing additional holidays to exclude. Returns ------- DatetimeIndex of tradeable dates Examples -------- >>> import strategy.calendar as cal >>> import pandas as pd >>> sd = pd.Timestamp("2018-01-01") >>> ed = pd.Timestamp("2018-02-01") >>> exchanges = ["CME"] >>> holidays = [pd.Timestamp("2018-01-03")] >>> cal.get_mtm_dates(sd, ed, exchanges, holidays=holidays) """ if holidays is None: holidays = [] schedules = [] for exch in exchanges: cal = mcal.get_calendar(exch) schedules.append(cal.schedule(start_date, end_date)) how = {"all": "inner", "any": "outer"}[how] schedule = mcal.merge_schedules(schedules, how=how) mtm_dates = schedule.index mtm_dates = mtm_dates.difference(holidays) return mtm_dates