def test_semi_active_day(self): # on self.days[0], only asset1 has data bar_data = BarData(self.data_portal, lambda: self.days[0], "daily") self.check_internal_consistency(bar_data) self.assertTrue(bar_data.can_trade(self.ASSET1)) self.assertFalse(bar_data.can_trade(self.ASSET2)) # because there is real data self.assertFalse(bar_data.is_stale(self.ASSET1)) # because there has never been a trade bar yet self.assertFalse(bar_data.is_stale(self.ASSET2)) self.assertEqual(3, bar_data.current(self.ASSET1, "open")) self.assertEqual(4, bar_data.current(self.ASSET1, "high")) self.assertEqual(1, bar_data.current(self.ASSET1, "low")) self.assertEqual(2, bar_data.current(self.ASSET1, "close")) self.assertEqual(200, bar_data.current(self.ASSET1, "volume")) self.assertEqual(2, bar_data.current(self.ASSET1, "price")) self.assertEqual(self.days[0], bar_data.current(self.ASSET1, "last_traded")) for field in OHLCP: self.assertTrue(np.isnan(bar_data.current(self.ASSET2, field)), field) self.assertEqual(0, bar_data.current(self.ASSET2, "volume")) self.assertTrue( bar_data.current(self.ASSET2, "last_traded") is pd.NaT )
def test_semi_active_day(self): # on self.days[0], only asset1 has data bar_data = BarData(self.data_portal, lambda: self.days[0], "daily") self.check_internal_consistency(bar_data) self.assertTrue(bar_data.can_trade(self.ASSET1)) self.assertFalse(bar_data.can_trade(self.ASSET2)) # because there is real data self.assertFalse(bar_data.is_stale(self.ASSET1)) # because there has never been a trade bar yet self.assertFalse(bar_data.is_stale(self.ASSET2)) self.assertEqual(3, bar_data.current(self.ASSET1, "open")) self.assertEqual(4, bar_data.current(self.ASSET1, "high")) self.assertEqual(1, bar_data.current(self.ASSET1, "low")) self.assertEqual(2, bar_data.current(self.ASSET1, "close")) self.assertEqual(200, bar_data.current(self.ASSET1, "volume")) self.assertEqual(2, bar_data.current(self.ASSET1, "price")) self.assertEqual(self.days[0], bar_data.current(self.ASSET1, "last_traded")) for field in OHLCP: self.assertTrue(np.isnan(bar_data.current(self.ASSET2, field)), field) self.assertEqual(0, bar_data.current(self.ASSET2, "volume")) self.assertTrue(bar_data.current(self.ASSET2, "last_traded") is pd.NaT)
def test_minute_before_assets_trading(self): # grab minutes that include the day before the asset start minutes = self.env.market_minutes_for_day( self.env.previous_trading_day(self.days[0]) ) # this entire day is before either asset has started trading for idx, minute in enumerate(minutes): bar_data = BarData(self.data_portal, lambda: minute, "minute") self.check_internal_consistency(bar_data) self.assertFalse(bar_data.can_trade(self.ASSET1)) self.assertFalse(bar_data.can_trade(self.ASSET2)) self.assertFalse(bar_data.is_stale(self.ASSET1)) self.assertFalse(bar_data.is_stale(self.ASSET2)) for field in ALL_FIELDS: for asset in self.ASSETS: asset_value = bar_data.current(asset, field) if field in OHLCP: self.assertTrue(np.isnan(asset_value)) elif field == "volume": self.assertEqual(0, asset_value) elif field == "last_traded": self.assertTrue(asset_value is pd.NaT)
def test_minute_after_assets_stopped(self): minutes = self.env.market_minutes_for_day( self.env.next_trading_day(self.days[-1])) last_trading_minute = \ self.env.market_minutes_for_day(self.days[-1])[-1] # this entire day is after both assets have stopped trading for idx, minute in enumerate(minutes): bar_data = BarData(self.data_portal, lambda: minute, "minute") self.assertFalse(bar_data.can_trade(self.ASSET1)) self.assertFalse(bar_data.can_trade(self.ASSET2)) self.assertFalse(bar_data.is_stale(self.ASSET1)) self.assertFalse(bar_data.is_stale(self.ASSET2)) self.check_internal_consistency(bar_data) for field in ALL_FIELDS: for asset in self.ASSETS: asset_value = bar_data.current(asset, field) if field in OHLCP: self.assertTrue(np.isnan(asset_value)) elif field == "volume": self.assertEqual(0, asset_value) elif field == "last_traded": self.assertEqual(last_trading_minute, asset_value)
def test_minute_after_assets_stopped(self): minutes = self.env.market_minutes_for_day( self.env.next_trading_day(self.days[-1]) ) last_trading_minute = \ self.env.market_minutes_for_day(self.days[-1])[-1] # this entire day is after both assets have stopped trading for idx, minute in enumerate(minutes): bar_data = BarData(self.data_portal, lambda: minute, "minute") self.assertFalse(bar_data.can_trade(self.ASSET1)) self.assertFalse(bar_data.can_trade(self.ASSET2)) self.assertFalse(bar_data.is_stale(self.ASSET1)) self.assertFalse(bar_data.is_stale(self.ASSET2)) self.check_internal_consistency(bar_data) for field in ALL_FIELDS: for asset in self.ASSETS: asset_value = bar_data.current(asset, field) if field in OHLCP: self.assertTrue(np.isnan(asset_value)) elif field == "volume": self.assertEqual(0, asset_value) elif field == "last_traded": self.assertEqual(last_trading_minute, asset_value)
def test_after_assets_dead(self): # both assets end on self.day[-1], so let's try the next day next_day = self.trading_schedule.next_execution_day( self.equity_daily_bar_days[-1] ) bar_data = BarData(self.data_portal, lambda: next_day, "daily") self.check_internal_consistency(bar_data) for asset in self.ASSETS: self.assertFalse(bar_data.can_trade(asset)) self.assertFalse(bar_data.is_stale(asset)) for field in OHLCP: self.assertTrue(np.isnan(bar_data.current(asset, field))) self.assertEqual(0, bar_data.current(asset, "volume")) last_traded_dt = bar_data.current(asset, "last_traded") if asset == self.ASSET1: self.assertEqual(self.equity_daily_bar_days[-2], last_traded_dt) else: self.assertEqual(self.equity_daily_bar_days[1], last_traded_dt)
def test_day_before_assets_trading(self): # use the day before self.equity_daily_bar_days[0] day = self.trading_schedule.previous_execution_day( self.equity_daily_bar_days[0] ) bar_data = BarData(self.data_portal, lambda: day, "daily") self.check_internal_consistency(bar_data) self.assertFalse(bar_data.can_trade(self.ASSET1)) self.assertFalse(bar_data.can_trade(self.ASSET2)) self.assertFalse(bar_data.is_stale(self.ASSET1)) self.assertFalse(bar_data.is_stale(self.ASSET2)) for field in ALL_FIELDS: for asset in self.ASSETS: asset_value = bar_data.current(asset, field) if field in OHLCP: self.assertTrue(np.isnan(asset_value)) elif field == "volume": self.assertEqual(0, asset_value) elif field == "last_traded": self.assertTrue(asset_value is pd.NaT)
def test_last_active_day(self): bar_data = BarData( self.data_portal, lambda: self.get_last_minute_of_session( self.equity_daily_bar_days[-1] ), "daily", self.trading_calendar ) self.check_internal_consistency(bar_data) for asset in self.ASSETS: if asset in (1, 2): self.assertFalse(bar_data.can_trade(asset)) else: self.assertTrue(bar_data.can_trade(asset)) self.assertFalse(bar_data.is_stale(asset)) if asset in (1, 2): assert_almost_equal(nan, bar_data.current(asset, "open")) assert_almost_equal(nan, bar_data.current(asset, "high")) assert_almost_equal(nan, bar_data.current(asset, "low")) assert_almost_equal(nan, bar_data.current(asset, "close")) assert_almost_equal(0, bar_data.current(asset, "volume")) assert_almost_equal(nan, bar_data.current(asset, "price")) else: self.assertEqual(6, bar_data.current(asset, "open")) self.assertEqual(7, bar_data.current(asset, "high")) self.assertEqual(4, bar_data.current(asset, "low")) self.assertEqual(5, bar_data.current(asset, "close")) self.assertEqual(500, bar_data.current(asset, "volume")) self.assertEqual(5, bar_data.current(asset, "price"))
def test_fully_active_day(self): bar_data = BarData( self.data_portal, lambda: self.get_last_minute_of_session( self.equity_daily_bar_days[1] ), "daily", self.trading_calendar ) self.check_internal_consistency(bar_data) # on self.equity_daily_bar_days[1], both assets have data for asset in self.ASSETS: self.assertTrue(bar_data.can_trade(asset)) self.assertFalse(bar_data.is_stale(asset)) self.assertEqual(4, bar_data.current(asset, "open")) self.assertEqual(5, bar_data.current(asset, "high")) self.assertEqual(2, bar_data.current(asset, "low")) self.assertEqual(3, bar_data.current(asset, "close")) self.assertEqual(300, bar_data.current(asset, "volume")) self.assertEqual(3, bar_data.current(asset, "price")) self.assertEqual( self.equity_daily_bar_days[1], bar_data.current(asset, "last_traded") )
def test_day_before_assets_trading(self): # use the day before self.bcolz_daily_bar_days[0] minute = self.get_last_minute_of_session( self.trading_calendar.previous_session_label( self.equity_daily_bar_days[0] ) ) bar_data = BarData(self.data_portal, lambda: minute, "daily", self.trading_calendar) self.check_internal_consistency(bar_data) self.assertFalse(bar_data.can_trade(self.ASSET1)) self.assertFalse(bar_data.can_trade(self.ASSET2)) self.assertFalse(bar_data.is_stale(self.ASSET1)) self.assertFalse(bar_data.is_stale(self.ASSET2)) for field in ALL_FIELDS: for asset in self.ASSETS: asset_value = bar_data.current(asset, field) if field in OHLCP: self.assertTrue(np.isnan(asset_value)) elif field == "volume": self.assertEqual(0, asset_value) elif field == "last_traded": self.assertTrue(asset_value is pd.NaT)
def test_after_assets_dead(self): # both assets end on self.day[-1], so let's try the next day minute = self.get_last_minute_of_session( self.trading_calendar.next_session_label( self.equity_daily_bar_days[-1])) bar_data = BarData(self.data_portal, lambda: minute, "daily") self.check_internal_consistency(bar_data) for asset in self.ASSETS: self.assertFalse(bar_data.can_trade(asset)) self.assertFalse(bar_data.is_stale(asset)) for field in OHLCP: self.assertTrue(np.isnan(bar_data.current(asset, field))) self.assertEqual(0, bar_data.current(asset, "volume")) last_traded_dt = bar_data.current(asset, "last_traded") if asset == self.ASSET1: self.assertEqual(self.equity_daily_bar_days[-2], last_traded_dt) else: self.assertEqual(self.equity_daily_bar_days[1], last_traded_dt)
def test_minute_before_assets_trading(self): # grab minutes that include the day before the asset start minutes = self.env.market_minutes_for_day( self.env.previous_trading_day(self.days[0])) # this entire day is before either asset has started trading for idx, minute in enumerate(minutes): bar_data = BarData(self.data_portal, lambda: minute, "minute") self.check_internal_consistency(bar_data) self.assertFalse(bar_data.can_trade(self.ASSET1)) self.assertFalse(bar_data.can_trade(self.ASSET2)) self.assertFalse(bar_data.is_stale(self.ASSET1)) self.assertFalse(bar_data.is_stale(self.ASSET2)) for field in ALL_FIELDS: for asset in self.ASSETS: asset_value = bar_data.current(asset, field) if field in OHLCP: self.assertTrue(np.isnan(asset_value)) elif field == "volume": self.assertEqual(0, asset_value) elif field == "last_traded": self.assertTrue(asset_value is pd.NaT)
def test_is_stale_at_midnight(self): bar_data = BarData( self.data_portal, lambda: self.bcolz_minute_bar_days[1], "minute", ) with handle_non_market_minutes(bar_data): self.assertTrue(bar_data.is_stale(self.HILARIOUSLY_ILLIQUID_ASSET))
def test_is_stale_at_midnight(self): bar_data = BarData( self.data_portal, lambda: self.bcolz_minute_bar_days[1], "minute", ) with handle_non_market_minutes(bar_data): self.assertTrue(bar_data.is_stale(self.HILARIOUSLY_ILLIQUID_ASSET))
def test_is_stale_during_non_market_hours(self): bar_data = BarData( self.data_portal, lambda: self.equity_minute_bar_days[1], "minute", ) with handle_non_market_minutes(bar_data): self.assertTrue(bar_data.is_stale(self.HILARIOUSLY_ILLIQUID_ASSET))
def test_is_stale_during_non_market_hours(self): bar_data = BarData( self.data_portal, lambda: self.equity_minute_bar_days[1], "minute", ) with handle_non_market_minutes(bar_data): self.assertTrue(bar_data.is_stale(self.HILARIOUSLY_ILLIQUID_ASSET))
def test_last_active_day(self): bar_data = BarData(self.data_portal, lambda: self.days[-1], "daily") self.check_internal_consistency(bar_data) for asset in self.ASSETS: self.assertTrue(bar_data.can_trade(asset)) self.assertFalse(bar_data.is_stale(asset)) self.assertEqual(6, bar_data.current(asset, "open")) self.assertEqual(7, bar_data.current(asset, "high")) self.assertEqual(4, bar_data.current(asset, "low")) self.assertEqual(5, bar_data.current(asset, "close")) self.assertEqual(500, bar_data.current(asset, "volume")) self.assertEqual(5, bar_data.current(asset, "price"))
def test_last_active_day(self): bar_data = BarData(self.data_portal, lambda: self.days[-1], "daily") self.check_internal_consistency(bar_data) for asset in self.ASSETS: self.assertTrue(bar_data.can_trade(asset)) self.assertFalse(bar_data.is_stale(asset)) self.assertEqual(6, bar_data.current(asset, "open")) self.assertEqual(7, bar_data.current(asset, "high")) self.assertEqual(4, bar_data.current(asset, "low")) self.assertEqual(5, bar_data.current(asset, "close")) self.assertEqual(500, bar_data.current(asset, "volume")) self.assertEqual(5, bar_data.current(asset, "price"))
def test_after_assets_dead(self): session = self.END_DATE bar_data = BarData(self.data_portal, lambda: session, "daily", self.trading_calendar) self.check_internal_consistency(bar_data) for asset in self.ASSETS: self.assertFalse(bar_data.can_trade(asset)) self.assertFalse(bar_data.is_stale(asset)) for field in OHLCP: self.assertTrue(np.isnan(bar_data.current(asset, field))) self.assertEqual(0, bar_data.current(asset, "volume")) last_traded_dt = bar_data.current(asset, "last_traded") if asset in (self.ASSET1, self.ASSET2): self.assertEqual(self.equity_daily_bar_days[3], last_traded_dt)
def test_after_assets_dead(self): # both assets end on self.day[-1], so let's try the next day next_day = self.env.next_trading_day(self.days[-1]) bar_data = BarData(self.data_portal, lambda: next_day, "daily") self.check_internal_consistency(bar_data) for asset in self.ASSETS: self.assertFalse(bar_data.can_trade(asset)) self.assertFalse(bar_data.is_stale(asset)) for field in OHLCP: self.assertTrue(np.isnan(bar_data.current(asset, field))) self.assertEqual(0, bar_data.current(asset, "volume")) last_traded_dt = bar_data.current(asset, "last_traded") if asset == self.ASSET1: self.assertEqual(self.days[-2], last_traded_dt) else: self.assertEqual(self.days[1], last_traded_dt)
def test_day_before_assets_trading(self): # use the day before self.days[0] day = self.env.previous_trading_day(self.days[0]) bar_data = BarData(self.data_portal, lambda: day, "daily") self.check_internal_consistency(bar_data) self.assertFalse(bar_data.can_trade(self.ASSET1)) self.assertFalse(bar_data.can_trade(self.ASSET2)) self.assertFalse(bar_data.is_stale(self.ASSET1)) self.assertFalse(bar_data.is_stale(self.ASSET2)) for field in ALL_FIELDS: for asset in self.ASSETS: asset_value = bar_data.current(asset, field) if field in OHLCP: self.assertTrue(np.isnan(asset_value)) elif field == "volume": self.assertEqual(0, asset_value) elif field == "last_traded": self.assertTrue(asset_value is pd.NaT)
def test_regular_minute(self): minutes = self.env.market_minutes_for_day(self.days[0]) for idx, minute in enumerate(minutes): # day2 has prices # (every minute for asset1, every 10 minutes for asset2) # asset1: # opens: 2-391 # high: 3-392 # low: 0-389 # close: 1-390 # volume: 100-3900 (by 100) # asset2 is the same thing, but with only every 10th minute # populated. # this test covers the "IPO morning" case, because asset2 only # has data starting on the 10th minute. bar_data = BarData(self.data_portal, lambda: minute, "minute") self.check_internal_consistency(bar_data) asset2_has_data = (((idx + 1) % 10) == 0) self.assertTrue(bar_data.can_trade(self.ASSET1)) self.assertFalse(bar_data.is_stale(self.ASSET1)) if idx < 9: self.assertFalse(bar_data.can_trade(self.ASSET2)) self.assertFalse(bar_data.is_stale(self.ASSET2)) else: self.assertTrue(bar_data.can_trade(self.ASSET2)) if asset2_has_data: self.assertFalse(bar_data.is_stale(self.ASSET2)) else: self.assertTrue(bar_data.is_stale(self.ASSET2)) for field in ALL_FIELDS: asset1_value = bar_data.current(self.ASSET1, field) asset2_value = bar_data.current(self.ASSET2, field) # now check the actual values if idx == 0 and field == "low": # first low value is 0, which is interpreted as NaN self.assertTrue(np.isnan(asset1_value)) else: if field in OHLC: self.assertEqual(idx + 1 + field_info[field], asset1_value) if asset2_has_data: self.assertEqual(idx + 1 + field_info[field], asset2_value) else: self.assertTrue(np.isnan(asset2_value)) elif field == "volume": self.assertEqual((idx + 1) * 100, asset1_value) if asset2_has_data: self.assertEqual((idx + 1) * 100, asset2_value) else: self.assertEqual(0, asset2_value) elif field == "price": self.assertEqual(idx + 1, asset1_value) if asset2_has_data: self.assertEqual(idx + 1, asset2_value) elif idx < 9: # no price to forward fill from self.assertTrue(np.isnan(asset2_value)) else: # forward-filled price self.assertEqual((idx // 10) * 10, asset2_value) elif field == "last_traded": self.assertEqual(minute, asset1_value) if idx < 9: self.assertTrue(asset2_value is pd.NaT) elif asset2_has_data: self.assertEqual(minute, asset2_value) else: last_traded_minute = minutes[(idx // 10) * 10] self.assertEqual(last_traded_minute - 1, asset2_value)
def test_regular_minute(self): minutes = self.env.market_minutes_for_day(self.days[0]) for idx, minute in enumerate(minutes): # day2 has prices # (every minute for asset1, every 10 minutes for asset2) # asset1: # opens: 2-391 # high: 3-392 # low: 0-389 # close: 1-390 # volume: 100-3900 (by 100) # asset2 is the same thing, but with only every 10th minute # populated. # this test covers the "IPO morning" case, because asset2 only # has data starting on the 10th minute. bar_data = BarData(self.data_portal, lambda: minute, "minute") self.check_internal_consistency(bar_data) asset2_has_data = (((idx + 1) % 10) == 0) self.assertTrue(bar_data.can_trade(self.ASSET1)) self.assertFalse(bar_data.is_stale(self.ASSET1)) if idx < 9: self.assertFalse(bar_data.can_trade(self.ASSET2)) self.assertFalse(bar_data.is_stale(self.ASSET2)) else: self.assertTrue(bar_data.can_trade(self.ASSET2)) if asset2_has_data: self.assertFalse(bar_data.is_stale(self.ASSET2)) else: self.assertTrue(bar_data.is_stale(self.ASSET2)) for field in ALL_FIELDS: asset1_value = bar_data.current(self.ASSET1, field) asset2_value = bar_data.current(self.ASSET2, field) # now check the actual values if idx == 0 and field == "low": # first low value is 0, which is interpreted as NaN self.assertTrue(np.isnan(asset1_value)) else: if field in OHLC: self.assertEqual( idx + 1 + field_info[field], asset1_value ) if asset2_has_data: self.assertEqual( idx + 1 + field_info[field], asset2_value ) else: self.assertTrue(np.isnan(asset2_value)) elif field == "volume": self.assertEqual((idx + 1) * 100, asset1_value) if asset2_has_data: self.assertEqual((idx + 1) * 100, asset2_value) else: self.assertEqual(0, asset2_value) elif field == "price": self.assertEqual(idx + 1, asset1_value) if asset2_has_data: self.assertEqual(idx + 1, asset2_value) elif idx < 9: # no price to forward fill from self.assertTrue(np.isnan(asset2_value)) else: # forward-filled price self.assertEqual((idx // 10) * 10, asset2_value) elif field == "last_traded": self.assertEqual(minute, asset1_value) if idx < 9: self.assertTrue(asset2_value is pd.NaT) elif asset2_has_data: self.assertEqual(minute, asset2_value) else: last_traded_minute = minutes[(idx // 10) * 10] self.assertEqual(last_traded_minute - 1, asset2_value)