Exemple #1
0
    def get_portfolio_and_data_handler(self):
        data_handler = Mock(spec=DataHandler)
        data_handler.get_last_available_price.side_effect = lambda tickers: self.data_handler_prices[tickers] \
            if tickers else None

        timer = SettableTimer()
        timer.set_current_time(self.start_time)

        portfolio = Portfolio(data_handler, self.initial_cash, timer)
        return portfolio, data_handler, timer
Exemple #2
0
    def get_portfolio_and_data_handler(self):
        data_handler = Mock(spec=DataHandler)
        data_handler.get_last_available_price.side_effect = lambda tickers: self.data_handler_prices[tickers] \
            if tickers else None

        contract_mapper = Mock(spec=ContractTickerMapper)
        contract_mapper.contract_to_ticker.side_effect = lambda contract: DummyTicker(contract.symbol)

        timer = SettableTimer()
        timer.set_current_time(self.start_time)

        portfolio = Portfolio(data_handler, self.initial_cash, timer, contract_mapper)
        return portfolio, data_handler, timer
Exemple #3
0
    def test_designated_contracts(self):
        future_ticker = PortaraFutureTicker("",
                                            "AB{}",
                                            1,
                                            1,
                                            designated_contracts="MZ")

        timer = SettableTimer()
        future_ticker.initialize_data_provider(timer, self.data_provider)

        timer.set_current_time(str_to_date("2021-06-15"))
        specific_ticker = future_ticker.get_current_specific_ticker()
        self.assertEqual(specific_ticker,
                         PortaraTicker("AB2021Z", SecurityType.FUTURE, 1))
Exemple #4
0
class TestRules(TestCase):
    def setUp(self):
        self.timer = SettableTimer()

    def test_market_open_rule(self):
        self.timer.set_current_time(
            str_to_date("2018-01-01 00:00:00.000000", DateFormat.FULL_ISO))
        now = self.timer.now()
        next_trigger_time = MarketOpenEvent.next_trigger_time(now)
        self.assertEqual(
            str_to_date("2018-01-01 09:30:00.000000", DateFormat.FULL_ISO),
            next_trigger_time)

        self.timer.set_current_time(
            str_to_date("2018-01-01 09:29:59.999999", DateFormat.FULL_ISO))
        now = self.timer.now()
        next_trigger_time = MarketOpenEvent.next_trigger_time(now)
        self.assertEqual(
            str_to_date("2018-01-01 09:30:00.000000", DateFormat.FULL_ISO),
            next_trigger_time)

        self.timer.set_current_time(
            str_to_date("2018-01-01 09:30:00.000000", DateFormat.FULL_ISO))
        now = self.timer.now()
        next_trigger_time = MarketOpenEvent.next_trigger_time(now)
        self.assertEqual(
            str_to_date("2018-01-02 09:30:00.000000", DateFormat.FULL_ISO),
            next_trigger_time)
class TestDataHandlerTimeHelper(TestCase):
    @classmethod
    def setUpClass(cls):
        cls.YESTERDAY_OPEN = str_to_date("2018-01-29 09:30:00.000000",
                                         DateFormat.FULL_ISO)
        cls.YESTERDAY_CLOSE = str_to_date("2018-01-29 16:00:00.000000",
                                          DateFormat.FULL_ISO)
        cls.TODAY_BEFORE_OPEN = str_to_date("2018-01-30 06:00:00.000000",
                                            DateFormat.FULL_ISO)
        cls.TODAY_OPEN = str_to_date("2018-01-30 09:30:00.000000",
                                     DateFormat.FULL_ISO)
        cls.TODAY_MIDDLE_DAY = str_to_date("2018-01-30 12:00:00.000000",
                                           DateFormat.FULL_ISO)
        cls.TODAY_CLOSE = str_to_date("2018-01-30 16:00:00.000000",
                                      DateFormat.FULL_ISO)
        cls.TODAY_AFTER_CLOSE = str_to_date("2018-01-30 20:00:00.000000",
                                            DateFormat.FULL_ISO)

    def setUp(self):
        self.timer = SettableTimer()
        self.time_helper = _DataHandlerTimeHelper(self.timer)

    def test_datetime_of_latest_market_event_before_market_open(self):
        self.timer.set_current_time(self.TODAY_BEFORE_OPEN)

        market_open_datetime = self.time_helper.datetime_of_latest_market_event(
            MarketOpenEvent)
        market_close_datetime = self.time_helper.datetime_of_latest_market_event(
            MarketCloseEvent)

        self.assertEqual(market_open_datetime, self.YESTERDAY_OPEN)
        self.assertEqual(market_close_datetime, self.YESTERDAY_CLOSE)

    def test_datetime_of_latest_market_event_during_trading_session(self):
        self.timer.set_current_time(self.TODAY_MIDDLE_DAY)

        market_open_datetime = self.time_helper.datetime_of_latest_market_event(
            MarketOpenEvent)
        market_close_datetime = self.time_helper.datetime_of_latest_market_event(
            MarketCloseEvent)

        self.assertEqual(market_open_datetime, self.TODAY_OPEN)
        self.assertEqual(market_close_datetime, self.YESTERDAY_CLOSE)

    def test_datetime_of_latest_market_event_after_market_close(self):
        self.timer.set_current_time(self.TODAY_AFTER_CLOSE)

        market_open_datetime = self.time_helper.datetime_of_latest_market_event(
            MarketOpenEvent)
        market_close_datetime = self.time_helper.datetime_of_latest_market_event(
            MarketCloseEvent)

        self.assertEqual(market_open_datetime, self.TODAY_OPEN)
        self.assertEqual(market_close_datetime, self.TODAY_CLOSE)
Exemple #6
0
    def test_get_current_specific_ticker(self):
        timer = SettableTimer()
        self.future_ticker_1.initialize_data_provider(timer,
                                                      self.data_provider)

        timer.set_current_time(str_to_date("2021-03-18"))
        specific_ticker = self.future_ticker_1.get_current_specific_ticker()
        self.assertEqual(specific_ticker,
                         PortaraTicker("AB2021M", SecurityType.FUTURE, 1))

        timer.set_current_time(str_to_date("2021-06-14"))
        specific_ticker = self.future_ticker_1.get_current_specific_ticker()
        self.assertEqual(specific_ticker,
                         PortaraTicker("AB2021M", SecurityType.FUTURE, 1))

        timer.set_current_time(str_to_date("2021-06-15"))
        specific_ticker = self.future_ticker_1.get_current_specific_ticker()
        self.assertEqual(specific_ticker,
                         PortaraTicker("AB2021U", SecurityType.FUTURE, 1))

        timer.set_current_time(datetime(2021, 12, 14, 23, 59))
        specific_ticker = self.future_ticker_1.get_current_specific_ticker()
        self.assertEqual(specific_ticker,
                         PortaraTicker("AB2021Z", SecurityType.FUTURE, 1))
Exemple #7
0
 def _shift_timer_to_next_day(timer: SettableTimer):
     new_time = timer.time + RelativeDelta(days=1)
     timer.set_current_time(new_time)
Exemple #8
0
class TestDataHandler(TestCase):
    @classmethod
    def setUpClass(cls):
        cls.spx_index_ticker = BloombergTicker("SPX Index")
        cls.google_ticker = BloombergTicker("GOOGL US Equity")
        cls.microsoft_ticker = BloombergTicker("MSFT US Equity")

        cls.start_date = str_to_date("2018-01-02")
        cls.end_date = str_to_date("2018-01-31")
        cls.end_date_trimmed = str_to_date("2018-01-30")
        cls.get_history_field = "PX_TO_BOOK_RATIO"

    def setUp(self):
        try:
            self.price_data_provider = get_data_provider()
        except Exception as e:
            raise self.skipTest(e)

        self.timer = SettableTimer()
        self.data_handler = DailyDataHandler(self.price_data_provider,
                                             self.timer)

        MarketOpenEvent.set_trigger_time({
            "hour": 13,
            "minute": 30,
            "second": 0,
            "microsecond": 0
        })
        MarketCloseEvent.set_trigger_time({
            "hour": 20,
            "minute": 0,
            "second": 0,
            "microsecond": 0
        })

    def test_get_price_when_end_date_is_in_the_past(self):
        self.timer.set_current_time(
            str_to_date("2018-02-12 00:00:00.000000", DateFormat.FULL_ISO))
        prices_tms = self.data_handler.get_price(self.spx_index_ticker,
                                                 PriceField.Close,
                                                 self.start_date,
                                                 self.end_date)

        self.assertEqual(self.start_date, prices_tms.index[0].to_pydatetime())
        self.assertEqual(self.end_date, prices_tms.index[-1].to_pydatetime())

    def test_get_price_when_end_date_is_today_after_market_close(self):
        self.timer.set_current_time(
            str_to_date("2018-01-31") + MarketCloseEvent.trigger_time() +
            RelativeDelta(hours=1))
        prices_tms = self.data_handler.get_price(self.spx_index_ticker,
                                                 PriceField.Close,
                                                 self.start_date,
                                                 self.end_date)

        self.assertEqual(self.start_date, prices_tms.index[0].to_pydatetime())
        self.assertEqual(self.end_date, prices_tms.index[-1].to_pydatetime())

    def test_get_price_when_end_date_is_today_before_market_close(self):
        self.timer.set_current_time(
            str_to_date("2018-01-31") + MarketOpenEvent.trigger_time() +
            RelativeDelta(hours=1))
        close_prices_tms = self.data_handler.get_price(self.spx_index_ticker,
                                                       PriceField.Close,
                                                       self.start_date,
                                                       self.end_date)

        self.assertEqual(self.start_date,
                         close_prices_tms.index[0].to_pydatetime())
        self.assertEqual(self.end_date_trimmed,
                         close_prices_tms.index[-1].to_pydatetime())

    def test_get_open_price_when_end_date_is_today_before_market_close__single_ticker(
            self):
        self.timer.set_current_time(
            str_to_date("2018-01-31") + MarketOpenEvent.trigger_time() +
            RelativeDelta(hours=1))
        current_date = datetime(self.timer.now().year,
                                self.timer.now().month,
                                self.timer.now().day)
        open_prices_tms = self.data_handler.get_price(self.spx_index_ticker,
                                                      PriceField.Open,
                                                      self.start_date,
                                                      self.timer.now())

        self.assertEqual(self.start_date,
                         open_prices_tms.index[0].to_pydatetime())
        self.assertEqual(current_date,
                         open_prices_tms.index[-1].to_pydatetime())

        prices_df = self.data_handler.get_price(
            self.spx_index_ticker, [PriceField.Open, PriceField.Close],
            self.start_date, self.timer.now())
        self.assertEqual(self.start_date, prices_df.index[0].to_pydatetime())
        self.assertEqual(current_date, prices_df.index[-1].to_pydatetime())

        last_bar = prices_df.iloc[-1]
        self.assertTrue(isnan(last_bar.loc[PriceField.Close]))
        self.assertIsNotNone(last_bar.loc[PriceField.Open])

    def test_get_open_price_when_end_date_is_today_before_market_close__multiple_tickers(
            self):
        self.timer.set_current_time(
            str_to_date("2018-01-31") + MarketOpenEvent.trigger_time() +
            RelativeDelta(hours=1))
        current_date = datetime(self.timer.now().year,
                                self.timer.now().month,
                                self.timer.now().day)

        tickers = [self.spx_index_ticker, self.microsoft_ticker]
        open_prices_tms = self.data_handler.get_price(tickers, PriceField.Open,
                                                      self.start_date,
                                                      self.timer.now())

        self.assertEqual(self.start_date,
                         open_prices_tms.index[0].to_pydatetime())
        self.assertEqual(current_date,
                         open_prices_tms.index[-1].to_pydatetime())

        prices_data_array = self.data_handler.get_price(
            tickers, [PriceField.Open, PriceField.Close], self.start_date,
            self.timer.now())
        last_bar_df = prices_data_array.loc[current_date, :, :].to_pandas()

        self.assertTrue(last_bar_df[PriceField.Close].isna().all())
        self.assertTrue(last_bar_df[PriceField.Open].notna().all())

    def test_get_price_when_end_date_is_tomorrow(self):
        self.timer.set_current_time(
            str_to_date("2018-01-30") + MarketCloseEvent.trigger_time() +
            RelativeDelta(hours=1))
        prices_tms = self.data_handler.get_price(self.spx_index_ticker,
                                                 PriceField.Close,
                                                 self.start_date,
                                                 self.end_date_trimmed)

        self.assertEqual(self.start_date, prices_tms.index[0].to_pydatetime())
        self.assertEqual(self.end_date_trimmed,
                         prices_tms.index[-1].to_pydatetime())

    def test_get_last_price_single_ticker(self):
        # just test if getting single ticker value works, when a single ticker (not wrapped in a list) is passed
        self.timer.set_current_time(
            str_to_date("2018-01-31") + MarketOpenEvent.trigger_time() +
            RelativeDelta(hours=1))
        single_price = self.data_handler.get_last_available_price(
            self.spx_index_ticker)
        self.assertTrue(isinstance(single_price, float))

        # at market open
        self.timer.set_current_time(
            str_to_date("2018-01-31") + MarketOpenEvent.trigger_time())
        at_market_open = self.data_handler.get_last_available_price(
            [self.spx_index_ticker])

        self.assertEqual(self.spx_index_ticker, at_market_open.index[0])
        self.assertEqual(single_price, at_market_open[0])

        # during the trading session
        self.timer.set_current_time(
            str_to_date("2018-01-31") + MarketOpenEvent.trigger_time() +
            RelativeDelta(hours=1))
        during_the_day_last_prices = self.data_handler.get_last_available_price(
            [self.spx_index_ticker])

        self.assertEqual(self.spx_index_ticker,
                         during_the_day_last_prices.index[0])
        self.assertEqual(single_price, during_the_day_last_prices[0])

        # after the trading session
        self.timer.set_current_time(
            str_to_date("2018-01-31") + MarketCloseEvent.trigger_time() +
            RelativeDelta(hours=1))
        after_close_last_prices = self.data_handler.get_last_available_price(
            [self.spx_index_ticker])

        self.assertEqual(self.spx_index_ticker,
                         after_close_last_prices.index[0])
        self.assertNotEqual(during_the_day_last_prices[0],
                            after_close_last_prices[0])

        # before the trading session
        self.timer.set_current_time(
            str_to_date("2018-01-31") + MarketOpenEvent.trigger_time() -
            RelativeDelta(hours=1))
        before_trading_session_prices = self.data_handler.get_last_available_price(
            [self.spx_index_ticker])

        self.assertEqual(self.spx_index_ticker,
                         before_trading_session_prices.index[0])
        self.assertNotEqual(during_the_day_last_prices[0],
                            before_trading_session_prices[0])
        self.assertNotEqual(after_close_last_prices[0],
                            before_trading_session_prices[0])

    def test_get_last_price_with_multiple_tickers_when_current_data_is_unavailable(
            self):
        self.timer.set_current_time(
            str_to_date("2018-01-01") + MarketOpenEvent.trigger_time() +
            RelativeDelta(hours=1))
        last_prices = self.data_handler.get_last_available_price(
            [self.spx_index_ticker, self.google_ticker])

        self.assertEqual(self.spx_index_ticker, last_prices.index[0])
        self.assertEqual(self.google_ticker, last_prices.index[1])

    def test_get_last_price_with_empty_tickers_list(self):
        self.timer.set_current_time(
            str_to_date("2018-01-31") + MarketOpenEvent.trigger_time() +
            RelativeDelta(hours=1))
        last_prices = self.data_handler.get_last_available_price([])
        assert_series_equal(QFSeries(), last_prices)

    def test_get_history_when_end_date_is_in_the_past(self):
        self.timer.set_current_time(
            str_to_date("2018-02-12 00:00:00.000000", DateFormat.FULL_ISO))
        prices_tms = self.data_handler.get_history(self.spx_index_ticker,
                                                   self.get_history_field,
                                                   self.start_date,
                                                   self.end_date)

        self.assertEqual(self.start_date, prices_tms.index[0].to_pydatetime())
        self.assertEqual(self.end_date, prices_tms.index[-1].to_pydatetime())

    def test_get_history_when_end_date_is_today_after_market_close(self):
        self.timer.set_current_time(
            str_to_date("2018-01-31") + MarketCloseEvent.trigger_time() +
            RelativeDelta(hours=1))
        prices_tms = self.data_handler.get_history(self.spx_index_ticker,
                                                   self.get_history_field,
                                                   self.start_date,
                                                   self.end_date)

        self.assertEqual(self.start_date, prices_tms.index[0].to_pydatetime())
        self.assertEqual(self.end_date, prices_tms.index[-1].to_pydatetime())

    def test_get_history_when_end_date_is_today_before_market_close(self):
        self.timer.set_current_time(
            str_to_date("2018-01-31") + MarketOpenEvent.trigger_time() +
            RelativeDelta(hours=1))
        prices_tms = self.data_handler.get_history(self.spx_index_ticker,
                                                   self.get_history_field,
                                                   self.start_date,
                                                   self.end_date)

        self.assertEqual(self.start_date, prices_tms.index[0].to_pydatetime())
        self.assertEqual(self.end_date_trimmed,
                         prices_tms.index[-1].to_pydatetime())

    def test_get_history_when_end_date_is_tomorrow(self):
        self.timer.set_current_time(
            str_to_date("2018-01-30") + MarketCloseEvent.trigger_time() +
            RelativeDelta(hours=1))
        prices_tms = self.data_handler.get_history(self.spx_index_ticker,
                                                   self.get_history_field,
                                                   self.start_date,
                                                   self.end_date_trimmed)

        self.assertEqual(self.start_date, prices_tms.index[0].to_pydatetime())
        self.assertEqual(self.end_date_trimmed,
                         prices_tms.index[-1].to_pydatetime())

    def test_get_history_with_multiple_tickers(self):
        self.timer.set_current_time(
            str_to_date("2018-01-31") + MarketOpenEvent.trigger_time() +
            RelativeDelta(hours=1))
        resilt_df = self.data_handler.get_history(
            [self.microsoft_ticker, self.google_ticker],
            self.get_history_field, self.start_date, self.end_date_trimmed)

        self.assertEqual(self.microsoft_ticker, resilt_df.columns[0])
        self.assertEqual(self.google_ticker, resilt_df.columns[1])
        self.assertEqual(self.start_date, resilt_df.index[0].to_pydatetime())
        self.assertEqual(self.end_date_trimmed,
                         resilt_df.index[-1].to_pydatetime())
        self.assertEqual(resilt_df.shape, (20, 2))

    def test_historical_price_many_tickers_many_fields(self):
        self.timer.set_current_time(
            str_to_date("2018-01-31") + MarketOpenEvent.trigger_time() +
            RelativeDelta(hours=1))
        result_array = self.data_handler.historical_price(
            [self.microsoft_ticker], [PriceField.Open, PriceField.Close],
            nr_of_bars=5)

        self.assertEqual(QFDataArray, type(result_array))
        self.assertEqual((5, 1, 2), result_array.shape)

        expected_dates_str = [
            "2018-01-24", "2018-01-25", "2018-01-26", "2018-01-29",
            "2018-01-30"
        ]
        expected_dates = [
            str_to_date(date_str) for date_str in expected_dates_str
        ]
        assert_same_index(pd.DatetimeIndex(expected_dates, name=DATES),
                          result_array.dates.to_index(),
                          check_index_type=True,
                          check_names=True)

    def test_historical_price_many_tickers_one_field(self):
        self.timer.set_current_time(
            str_to_date("2018-01-04") + MarketOpenEvent.trigger_time() +
            RelativeDelta(hours=1))
        result_df = self.data_handler.historical_price([self.microsoft_ticker],
                                                       PriceField.Open,
                                                       nr_of_bars=5)

        self.assertEqual(PricesDataFrame, type(result_df))

        expected_dates_idx = pd.DatetimeIndex([
            '2017-12-27', '2017-12-28', '2017-12-29', '2018-01-02',
            '2018-01-03'
        ],
                                              name=DATES)
        assert_same_index(expected_dates_idx,
                          result_df.index,
                          check_index_type=True,
                          check_names=True)

        expected_tickers_idx = pd.Index([self.microsoft_ticker], name=TICKERS)
        assert_same_index(expected_tickers_idx,
                          result_df.columns,
                          check_index_type=True,
                          check_names=True)
Exemple #9
0
class TestScheduler(TestCase):
    class _CustomTimeEvent(TimeEvent):
        def next_trigger_time(self, now: datetime) -> datetime:
            return now + RelativeDelta(days=2)

        def notify(self, listener) -> None:
            listener.on_custom_time_event(self)

    class _AnotherCustomTimeEvent(TimeEvent):
        def next_trigger_time(self, now: datetime) -> datetime:
            return now + RelativeDelta(day=4)

        def notify(self, listener) -> None:
            listener.on_another_custom_time_event(self)

    class PeriodicEvent15Minutes(PeriodicEvent):
        frequency = Frequency.MIN_15
        start_time = {"hour": 9, "minute": 45, "second": 0}
        end_time = {"hour": 11, "minute": 15, "second": 0}

        def notify(self, _) -> None:
            pass

    class PeriodicEvent30Minutes(PeriodicEvent):
        frequency = Frequency.MIN_30
        start_time = {"hour": 9, "minute": 30, "second": 0}
        end_time = {"hour": 10, "minute": 30, "second": 0}

        def notify(self, _) -> None:
            pass

    def setUp(self):
        self.timer = SettableTimer()
        self.scheduler = Scheduler(self.timer)

    def test_get_next_time_event(self):
        listener = Mock()
        self.scheduler.subscribe(self._CustomTimeEvent, listener)
        self.timer.set_current_time(str_to_date("2018-01-01"))

        time_events_list, time = self.scheduler.get_next_time_events()
        self.assertEqual(str_to_date("2018-01-03"), time)

    def test_get_multiple_next_time_events(self):
        listener = Mock()

        self.timer.set_current_time(str_to_date("2018-01-01"))
        self.scheduler.subscribe(self._AnotherCustomTimeEvent, listener)

        self.timer.set_current_time(str_to_date("2018-01-02"))
        self.scheduler.subscribe(self._CustomTimeEvent, listener)

        time_events_list, time = self.scheduler.get_next_time_events()
        expected_time_events = [
            self._CustomTimeEvent(),
            self._AnotherCustomTimeEvent()
        ]

        self.assertCountEqual(time_events_list, expected_time_events)

    def test_get_next_time_event_is_not_changing_state_of_scheduler(self):
        listener = Mock()

        self.scheduler.subscribe(self._CustomTimeEvent, listener)
        self.timer.set_current_time(str_to_date("2018-01-01"))

        self.scheduler.get_next_time_events()
        self.scheduler.get_next_time_events()
        time_events_list, time = self.scheduler.get_next_time_events()
        self.assertEqual(str_to_date("2018-01-03"), time)

    def test_correct_time_event_is_returned(self):
        self.timer.set_current_time(str_to_date("2018-01-01"))

        listener = Mock()
        another_listener = Mock()

        self.scheduler.subscribe(self._CustomTimeEvent, listener)
        self.scheduler.subscribe(self._AnotherCustomTimeEvent,
                                 another_listener)

        actual_time_events_list, time = self.scheduler.get_next_time_events()
        expected_time_event = self._CustomTimeEvent()
        self.assertIn(expected_time_event, actual_time_events_list)

        self.timer.set_current_time(str_to_date("2018-01-03"))
        another_actual_time_events_list, time = self.scheduler.get_next_time_events(
        )
        another_expected_time_event = self._AnotherCustomTimeEvent()
        self.assertIn(another_expected_time_event,
                      another_actual_time_events_list)

    def test_callback_method_called(self):
        self.timer.set_current_time(str_to_date("2018-01-01"))

        # create custom time events of two kinds
        custom_event = self._CustomTimeEvent()
        another_custom_event = self._AnotherCustomTimeEvent()

        listener = Mock()
        another_listener = Mock()

        # subscribe listeners to corresponding time events
        self.scheduler.subscribe(self._CustomTimeEvent, listener)
        self.scheduler.subscribe(self._AnotherCustomTimeEvent,
                                 another_listener)

        # test behaviour
        self.scheduler.notify_all(custom_event)

        listener.on_custom_time_event.assert_called_once()

        self.scheduler.notify_all(another_custom_event)
        another_listener.on_another_custom_time_event.assert_called_once()

    def test_get_next_time_event_single_time_events(self):
        self.timer.set_current_time(
            str_to_date("2018-01-02 10:00:00.000000", DateFormat.FULL_ISO))

        listener = Mock()
        self.scheduler.subscribe(SingleTimeEvent, listener)

        trigger_time = str_to_date("2018-01-02 13:00:00.000000",
                                   DateFormat.FULL_ISO)
        SingleTimeEvent.schedule_new_event(trigger_time, {})

        time_events_list, time = self.scheduler.get_next_time_events()
        self.assertEqual(trigger_time, time)

    def test_get_next_time_event_periodic_events(self):
        self.timer.set_current_time(
            str_to_date("2018-01-01 10:00:00.000000", DateFormat.FULL_ISO))

        listener = Mock()

        self.scheduler.subscribe(self.PeriodicEvent15Minutes, listener)
        self.scheduler.subscribe(self.PeriodicEvent30Minutes, listener)

        # There will be exactly one event scheduled for 10:15:00
        time_events_list, time = self.scheduler.get_next_time_events()
        self.assertEqual(
            str_to_date("2018-01-01 10:15:00.000000", DateFormat.FULL_ISO),
            time)
        self.assertEqual(1, len(time_events_list))

        self.timer.set_current_time(
            str_to_date("2018-01-01 10:15:00.000000", DateFormat.FULL_ISO))

        # There will be two events scheduled for 10:30:00
        time_events_list, time = self.scheduler.get_next_time_events()
        self.assertEqual(
            str_to_date("2018-01-01 10:30:00.000000", DateFormat.FULL_ISO),
            time)
        self.assertEqual(2, len(time_events_list))

    def test_get_next_time_event_periodic_and_single_time_events(self):
        self.timer.set_current_time(
            str_to_date("2018-01-01 10:00:00.000000", DateFormat.FULL_ISO))

        listener_periodic = Mock()
        listener_single = Mock()

        self.scheduler.subscribe(self.PeriodicEvent15Minutes,
                                 listener_periodic)
        self.scheduler.subscribe(SingleTimeEvent, listener_single)

        trigger_time = str_to_date("2018-01-01 10:15:00.000000",
                                   DateFormat.FULL_ISO)
        SingleTimeEvent.schedule_new_event(trigger_time, {})

        # There will be two events scheduled for 10:15:00
        time_events_list, time = self.scheduler.get_next_time_events()
        self.assertEqual(
            str_to_date("2018-01-01 10:15:00.000000", DateFormat.FULL_ISO),
            time)
        self.assertEqual(2, len(time_events_list))

        time_events_list_types = [type(event) for event in time_events_list]
        self.assertCountEqual(time_events_list_types,
                              [self.PeriodicEvent15Minutes, SingleTimeEvent])
Exemple #10
0
class TestRules(TestCase):

    def setUp(self):
        self.timer = SettableTimer()
        MarketOpenEvent.set_trigger_time({"hour": 13, "minute": 30, "second": 0, "microsecond": 0})
        MarketCloseEvent.set_trigger_time({"hour": 20, "minute": 0, "second": 0, "microsecond": 0})

    def test_market_open_rule(self):

        market_open_event = MarketOpenEvent()
        self.timer.set_current_time(str_to_date("2018-01-01 00:00:00.000000", DateFormat.FULL_ISO))
        now = self.timer.now()
        next_trigger_time = market_open_event.next_trigger_time(now)
        self.assertEqual(str_to_date("2018-01-01 13:30:00.000000", DateFormat.FULL_ISO), next_trigger_time)

        self.timer.set_current_time(str_to_date("2018-01-01 09:29:59.999999", DateFormat.FULL_ISO))
        now = self.timer.now()
        next_trigger_time = market_open_event.next_trigger_time(now)
        self.assertEqual(str_to_date("2018-01-01 13:30:00.000000", DateFormat.FULL_ISO), next_trigger_time)

        self.timer.set_current_time(str_to_date("2018-01-01 13:30:00.000000", DateFormat.FULL_ISO))
        now = self.timer.now()
        next_trigger_time = market_open_event.next_trigger_time(now)
        self.assertEqual(str_to_date("2018-01-02 13:30:00.000000", DateFormat.FULL_ISO), next_trigger_time)

    def test_periodic_events(self):
        self.timer.set_current_time(str_to_date("2018-01-01 13:23:00.000000", DateFormat.FULL_ISO))
        now = self.timer.now()

        class MinuteBarEvent(PeriodicEvent):
            frequency = Frequency.MIN_1
            start_time = {"hour": 8, "minute": 0, "second": 0}
            end_time = {"hour": 16, "minute": 0, "second": 0}

            def notify(self, listener):
                pass

        class Minutes15BarEvent(PeriodicEvent):
            frequency = Frequency.MIN_15
            start_time = {"hour": 8, "minute": 0, "second": 0}
            end_time = {"hour": 16, "minute": 0, "second": 0}

            def notify(self, listener):
                pass

        self.assertEqual(now + RelativeDelta(minutes=1), MinuteBarEvent().next_trigger_time(now))
        self.assertEqual(now + RelativeDelta(minute=30), Minutes15BarEvent().next_trigger_time(now))

        self.timer.set_current_time(str_to_date("2018-01-01 23:23:00.000000", DateFormat.FULL_ISO))
        now = self.timer.now()

        start_time = str_to_date("2018-01-02 08:00:00.000000", DateFormat.FULL_ISO)
        self.assertEqual(start_time, MinuteBarEvent().next_trigger_time(now))
        self.assertEqual(start_time, Minutes15BarEvent().next_trigger_time(now))

    def test_periodic_events_short_time_range(self):
        self.timer.set_current_time(str_to_date("2018-01-01 9:30:00.000000", DateFormat.FULL_ISO))
        now = self.timer.now()

        class Periodic15MinutesEvent(PeriodicEvent):
            frequency = Frequency.MIN_15
            start_time = {"hour": 9, "minute": 45, "second": 0}
            end_time = {"hour": 10, "minute": 10, "second": 0}

            def notify(self, listener):
                pass

        periodic_15_minutes_event = Periodic15MinutesEvent()

        now = periodic_15_minutes_event.next_trigger_time(now)
        self.assertEqual(str_to_date("2018-01-01 9:45:00.000000", DateFormat.FULL_ISO), now)

        now = periodic_15_minutes_event.next_trigger_time(now)
        self.assertEqual(str_to_date("2018-01-01 10:00:00.000000", DateFormat.FULL_ISO), now)

        now = periodic_15_minutes_event.next_trigger_time(now)
        self.assertEqual(str_to_date("2018-01-02 9:45:00.000000", DateFormat.FULL_ISO), now)

    def test_single_time_events(self):
        self.timer.set_current_time(str_to_date("2018-01-01 13:00:00.000000", DateFormat.FULL_ISO))
        now = self.timer.now()

        # Schedule a few new events
        date_times = (
            str_to_date("2018-01-01 13:15:00.000000", DateFormat.FULL_ISO),
            str_to_date("2018-01-01 13:30:00.000000", DateFormat.FULL_ISO),
            str_to_date("2018-01-01 13:45:00.000000", DateFormat.FULL_ISO),
            str_to_date("2018-01-01 12:45:00.000000", DateFormat.FULL_ISO)
        )

        for date_time in date_times:
            SingleTimeEvent.schedule_new_event(date_time, None)

        self.assertEqual(str_to_date("2018-01-01 13:15:00.000000", DateFormat.FULL_ISO),
                         SingleTimeEvent().next_trigger_time(now))

        self.timer.set_current_time(SingleTimeEvent().next_trigger_time(now))
        now = self.timer.now()

        self.assertEqual(str_to_date("2018-01-01 13:30:00.000000", DateFormat.FULL_ISO),
                         SingleTimeEvent().next_trigger_time(now))

        self.timer.set_current_time(str_to_date("2018-01-01 13:44:50.000000", DateFormat.FULL_ISO))
        now = self.timer.now()

        self.assertEqual(str_to_date("2018-01-01 13:45:00.000000", DateFormat.FULL_ISO),
                         SingleTimeEvent().next_trigger_time(now))

        self.timer.set_current_time(SingleTimeEvent().next_trigger_time(now))
        now = self.timer.now()

        self.assertEqual(None, SingleTimeEvent().next_trigger_time(now))

    def test_simultaneous_time_event(self):

        def schedule_events():
            SingleTimeEvent.schedule_new_event(str_to_date("2017-04-10 14:00:00.000000", DateFormat.FULL_ISO), 1)
            SingleTimeEvent.schedule_new_event(str_to_date("2017-04-10 14:00:00.000000", DateFormat.FULL_ISO), 2)

        self.assertRaises(ValueError, schedule_events)
Exemple #11
0
class TestScheduler(TestCase):
    class _CustomTimeEvent(TimeEvent):
        @classmethod
        def next_trigger_time(cls, now: datetime) -> datetime:
            return now + RelativeDelta(days=2)

        def notify(self, listener) -> None:
            listener.on_custom_time_event(self)

    class _AnotherCustomTimeEvent(TimeEvent):
        @classmethod
        def next_trigger_time(cls, now: datetime) -> datetime:
            return now + RelativeDelta(day=4)

        def notify(self, listener) -> None:
            listener.on_another_custom_time_event(self)

    def setUp(self):
        self.timer = SettableTimer()
        self.scheduler = Scheduler(self.timer)

    def test_get_next_time_event(self):
        listener = self._get_listeners_mock()

        self.scheduler.subscribe(self._CustomTimeEvent, listener)
        self.timer.set_current_time(str_to_date("2018-01-01"))

        time_event = self.scheduler.get_next_time_event()
        self.assertEqual(str_to_date("2018-01-03"), time_event.time)

    def test_get_next_time_event_is_not_changing_state_of_scheduler(self):
        listener = self._get_listeners_mock()

        self.scheduler.subscribe(self._CustomTimeEvent, listener)
        self.timer.set_current_time(str_to_date("2018-01-01"))

        self.scheduler.get_next_time_event()
        self.scheduler.get_next_time_event()
        time_event = self.scheduler.get_next_time_event()
        self.assertEqual(str_to_date("2018-01-03"), time_event.time)

    def test_correct_time_event_is_returned(self):
        self.timer.set_current_time(str_to_date("2018-01-01"))

        listener = self._get_listeners_mock()
        another_listener = self._get_listeners_mock()

        self.scheduler.subscribe(self._CustomTimeEvent, listener)
        self.scheduler.subscribe(self._AnotherCustomTimeEvent,
                                 another_listener)

        actual_time_event = self.scheduler.get_next_time_event()
        expected_time_event = self._CustomTimeEvent(str_to_date("2018-01-03"))
        self.assertEqual(expected_time_event, actual_time_event)

        self.timer.set_current_time(str_to_date("2018-01-03"))
        another_actual_time_event = self.scheduler.get_next_time_event()
        another_expected_time_event = self._AnotherCustomTimeEvent(
            str_to_date("2018-01-04"))
        self.assertEqual(another_expected_time_event,
                         another_actual_time_event)

    def test_callback_method_called(self):
        self.timer.set_current_time(str_to_date("2018-01-01"))

        # create custom time events of two kinds
        custom_event_1 = self._CustomTimeEvent(str_to_date("2018-01-03"))
        custom_event_2 = self._CustomTimeEvent(str_to_date("2018-01-05"))
        another_custom_event_1 = self._AnotherCustomTimeEvent(
            str_to_date("2018-01-04"))
        another_custom_event_2 = self._AnotherCustomTimeEvent(
            str_to_date("2018-01-05"))
        another_custom_event_3 = self._AnotherCustomTimeEvent(
            str_to_date("2018-01-06"))

        # create listener's mock
        listener = mock(strict=True)
        when(listener).on_custom_time_event(custom_event_1)
        when(listener).on_custom_time_event(custom_event_2)

        # create another listener's mock
        another_listener = mock(strict=True)
        when(another_listener).on_another_custom_time_event(
            another_custom_event_1)
        when(another_listener).on_another_custom_time_event(
            another_custom_event_2)
        when(another_listener).on_another_custom_time_event(
            another_custom_event_3)

        # subscribe listeners to corresponding time events
        self.scheduler.subscribe(self._CustomTimeEvent, listener)
        self.scheduler.subscribe(self._AnotherCustomTimeEvent,
                                 another_listener)

        # test behaviour
        self.scheduler.notify_all(custom_event_1)
        verify(listener).on_custom_time_event(custom_event_1)

        self.scheduler.notify_all(another_custom_event_1)
        verify(another_listener).on_another_custom_time_event(
            another_custom_event_1)

        self.scheduler.notify_all(custom_event_2)
        verify(listener).on_custom_time_event(custom_event_2)

        self.scheduler.notify_all(another_custom_event_2)
        verify(another_listener).on_another_custom_time_event(
            another_custom_event_2)

        self.scheduler.notify_all(another_custom_event_3)
        verify(another_listener).on_another_custom_time_event(
            another_custom_event_3)

    @staticmethod
    def _get_listeners_mock():
        listener = mock(strict=True)
        when(listener).on_custom_time_event(ANY(TimeEvent))

        return listener
def future_ticker_example(path_to_data_files: str):
    """
    In order to run the example you need to provide the path to the top directory, containing your data files. The
    example below will:

    1. initialize the Silver FutureTicker
    2. return the list of tickers belonging to the futures chain
    3. return the current specific ticker
    4. check for some tickers, if they belong to the Silver futures family
    5. return Open, High, Low, Close and Volume pricing data for the current specific ticker

    Parameters
    -----------
    path_to_data_files: str
        path to the top directory, which contains all your Portara data files
    """

    start_date = str_to_date('2020-12-02')
    end_date = str_to_date('2021-02-01')
    fields = PriceField.ohlcv()
    # Use the front contract (N = 1)
    # Roll the tickers 1 day before the expiration (days_before_exp_date = 1)
    # Set the point value to 50 (value for each of the contracts can be checked in Portara)
    future_ticker = PortaraFutureTicker('Silver',
                                        'SIA{}',
                                        1,
                                        1,
                                        50,
                                        designated_contracts="HKNUZ")
    daily_freq = Frequency.DAILY

    if path_to_data_files is None:
        raise ValueError(
            "Please provide a correct path to the Portara data and assign it to the "
            "path_to_data_files variable.")

    dp = PortaraDataProvider(path_to_data_files, future_ticker, fields,
                             start_date, end_date, daily_freq)

    # Initialize the future ticker with the data provider and timer. Timer is used to identify the current front ticker.
    timer = SettableTimer()
    future_ticker.initialize_data_provider(timer, dp)

    print(
        '\nCurrent individual contract (front contract) as of 10th December 2020:'
    )
    timer.set_current_time(str_to_date('2020-12-10'))
    current_ticker = future_ticker.get_current_specific_ticker()
    print(f'> {current_ticker}')

    print(
        '\nCurrent individual contract (front contract) as of 10th January 2021:'
    )
    timer.set_current_time(str_to_date('2021-01-10'))
    current_ticker = future_ticker.get_current_specific_ticker()
    print(f'> {current_ticker}')

    print(
        '\nCheck if the following tickers belong to the Silver futures chain:')
    ticker = PortaraTicker('SIA2017H', SecurityType.FUTURE, 50)
    print(f'- {ticker}: {future_ticker.belongs_to_family(ticker)}')
    ticker = PortaraTicker('OH2017H', SecurityType.FUTURE, 50)
    print(f'- {ticker}: {future_ticker.belongs_to_family(ticker)}')
    ticker = PortaraTicker('SIA2017', SecurityType.FUTURE, 50)
    print(f'- {ticker}: {future_ticker.belongs_to_family(ticker)}')
    ticker = PortaraTicker('SIA1999Z', SecurityType.FUTURE, 50)
    print(f'- {ticker}: {future_ticker.belongs_to_family(ticker)}')

    print(
        '\nOpen, High, Low, Close and Volume pricing data for the current specific ticker (as of 10th January 2021)'
    )
    prices = dp.get_price(current_ticker, PriceField.ohlcv(), start_date,
                          end_date, daily_freq)
    print(prices)
Exemple #13
0
class TestStopLossExecutionStyle(TestCase):
    MSFT_TICKER_STR = "MSFT US Equity"

    def setUp(self):
        MarketOpenEvent.set_trigger_time({
            "hour": 13,
            "minute": 30,
            "second": 0,
            "microsecond": 0
        })
        MarketCloseEvent.set_trigger_time({
            "hour": 20,
            "minute": 0,
            "second": 0,
            "microsecond": 0
        })

        self.start_date = str_to_date("2018-02-04")
        self.number_of_minutes = 5

        before_close = self.start_date + MarketCloseEvent.trigger_time(
        ) - RelativeDelta(minutes=self.number_of_minutes)

        self.msft_contract = Contract(self.MSFT_TICKER_STR,
                                      security_type='STK',
                                      exchange='TEST')
        self.msft_ticker = BloombergTicker(self.MSFT_TICKER_STR)

        contracts_to_tickers_mapper = SimulatedBloombergContractTickerMapper()
        self.timer = SettableTimer(initial_time=before_close)

        self.data_handler = Mock(spec=DataHandler)

        scheduler = Mock(spec=Scheduler)
        ScheduleOrderExecutionEvent.clear()

        # Set the periodic bar events to intraday trading
        IntradayBarEvent.frequency = Frequency.MIN_1

        commission_model = FixedCommissionModel(commission=0.0)
        self.monitor = Mock(spec=AbstractMonitor)
        self.portfolio = Mock(spec=Portfolio)

        slippage_model = PriceBasedSlippage(0.0, self.data_handler,
                                            contracts_to_tickers_mapper)
        self.exec_handler = SimulatedExecutionHandler(
            self.data_handler, self.timer, scheduler, self.monitor,
            commission_model, contracts_to_tickers_mapper, self.portfolio,
            slippage_model, RelativeDelta(minutes=self.number_of_minutes))

        self._set_last_available_price(100.0)
        self.stop_loss_order_1 = Order(self.msft_contract,
                                       quantity=-1,
                                       execution_style=StopOrder(95.0),
                                       time_in_force=TimeInForce.GTC)
        self.stop_loss_order_2 = Order(self.msft_contract,
                                       quantity=-1,
                                       execution_style=StopOrder(90.0),
                                       time_in_force=TimeInForce.GTC)

        self.stop_loss_order_3 = Order(self.msft_contract,
                                       quantity=-1,
                                       execution_style=StopOrder(50.0),
                                       time_in_force=TimeInForce.DAY)

        self.exec_handler.assign_order_ids([
            self.stop_loss_order_1, self.stop_loss_order_2,
            self.stop_loss_order_3
        ])

    def _trigger_single_time_event(self):
        self.timer.set_current_time(self.timer.now() + RelativeDelta(
            minutes=self.number_of_minutes))
        event = ScheduleOrderExecutionEvent()
        self.exec_handler.on_orders_accept(event)

    def test_day_order_disappears_after_a_day(self):
        self._set_bar_for_today(open_price=105.0,
                                high_price=110.0,
                                low_price=100.0,
                                close_price=105.0,
                                volume=100000000)
        self._trigger_single_time_event()

        expected_orders = [
            self.stop_loss_order_1, self.stop_loss_order_2,
            self.stop_loss_order_3
        ]
        actual_orders = self.exec_handler.get_open_orders()
        assert_lists_equal(expected_orders, actual_orders)

        self.exec_handler.on_market_close(...)

        self.portfolio.transact_transaction.assert_not_called()
        self.monitor.record_transaction.assert_not_called()

        actual_orders = self.exec_handler.get_open_orders()
        expected_orders = [self.stop_loss_order_1, self.stop_loss_order_2]
        assert_lists_equal(expected_orders, actual_orders)

    def test_no_orders_executed_on_market_open(self):
        # Move before the market open event
        self._set_bar_for_today(open_price=105.0,
                                high_price=110.0,
                                low_price=100.0,
                                close_price=105.0,
                                volume=100000000.0)
        self.timer.set_current_time(self.timer.now() +
                                    MarketOpenEvent.trigger_time() -
                                    RelativeDelta(
                                        minutes=self.number_of_minutes))
        self.exec_handler.assign_order_ids([
            self.stop_loss_order_1, self.stop_loss_order_2,
            self.stop_loss_order_3
        ])
        # Trigger the order execution event (the function also forwards time into the future)
        self._trigger_single_time_event()
        self.exec_handler.on_market_open(...)

        self.portfolio.transact_transaction.assert_not_called()
        self.monitor.record_transaction.assert_not_called()

        actual_orders = self.exec_handler.get_open_orders()
        expected_orders = [
            self.stop_loss_order_1, self.stop_loss_order_2,
            self.stop_loss_order_3
        ]
        assert_lists_equal(expected_orders, actual_orders)

    def test_order_not_executed_when_stop_price_not_hit(self):
        self._set_bar_for_today(open_price=105.0,
                                high_price=110.0,
                                low_price=100.0,
                                close_price=105.0,
                                volume=100000000.0)
        self._trigger_single_time_event()
        self.exec_handler.on_market_close(...)

        self.portfolio.transact_transaction.assert_not_called()
        self.monitor.record_transaction.assert_not_called()

        actual_orders = self.exec_handler.get_open_orders()
        expected_orders = [self.stop_loss_order_1, self.stop_loss_order_2]
        assert_lists_equal(expected_orders, actual_orders)

    def test_order_not_executed_when_bar_for_today_is_incomplete(self):
        self._set_bar_for_today(open_price=None,
                                high_price=110.0,
                                low_price=100.0,
                                close_price=105.0,
                                volume=100000000.0)
        self._trigger_single_time_event()
        self.exec_handler.on_market_close(...)

        self.portfolio.transact_transaction.assert_not_called()
        self.monitor.record_transaction.assert_not_called()

        actual_orders = self.exec_handler.get_open_orders()
        expected_orders = [self.stop_loss_order_1, self.stop_loss_order_2]
        assert_lists_equal(expected_orders, actual_orders)

    def test_one_order_executed_when_one_stop_price_hit(self):
        self._set_bar_for_today(open_price=100.0,
                                high_price=110.0,
                                low_price=94.0,
                                close_price=105.0,
                                volume=100000000.0)
        self._trigger_single_time_event()
        self.exec_handler.on_market_close(...)

        assert_lists_equal([self.stop_loss_order_2],
                           self.exec_handler.get_open_orders())

        expected_transaction = Transaction(
            self.timer.now(), self.msft_contract, -1,
            self.stop_loss_order_1.execution_style.stop_price, 0.0)
        self.monitor.record_transaction.assert_called_once_with(
            expected_transaction)
        self.portfolio.transact_transaction.assert_called_once_with(
            expected_transaction)

    def test_both_orders_executed_when_both_stop_prices_hit(self):
        self._set_bar_for_today(open_price=100.0,
                                high_price=110.0,
                                low_price=90.0,
                                close_price=105.0,
                                volume=100000000.0)
        self._trigger_single_time_event()
        self.exec_handler.on_market_close(...)

        assert_lists_equal([], self.exec_handler.get_open_orders())

        expected_transactions = [
            Transaction(self.timer.now(), self.msft_contract, -1,
                        self.stop_loss_order_1.execution_style.stop_price, 0),
            Transaction(self.timer.now(), self.msft_contract, -1,
                        self.stop_loss_order_2.execution_style.stop_price, 0),
        ]
        self.monitor.record_transaction.assert_has_calls(
            call(t) for t in expected_transactions)
        self.portfolio.transact_transaction.assert_has_calls(
            call(t) for t in expected_transactions)

        self.assertEqual(self.monitor.record_transaction.call_count, 2)
        self.assertEqual(self.portfolio.transact_transaction.call_count, 2)

    def test_market_opens_at_much_lower_price_than_it_closed_at_yesterday(
            self):
        self._set_bar_for_today(open_price=70.0,
                                high_price=100.0,
                                low_price=68.0,
                                close_price=90.0,
                                volume=100000000.0)
        self._trigger_single_time_event()
        self.exec_handler.on_market_close(...)

        assert_lists_equal([], self.exec_handler.get_open_orders())
        expected_transactions = [
            Transaction(self.timer.now(), self.msft_contract, -1, 70.0, 0),
            Transaction(self.timer.now(), self.msft_contract, -1, 70.0, 0),
        ]
        self.monitor.record_transaction.assert_has_calls(
            call(t) for t in expected_transactions)
        self.portfolio.transact_transaction.assert_has_calls(
            call(t) for t in expected_transactions)

        self.assertEqual(self.monitor.record_transaction.call_count, 2)
        self.assertEqual(self.portfolio.transact_transaction.call_count, 2)

    def test_market_opens_at_much_higher_price_than_it_closed_at_yesterday(
            self):
        self.buy_stop_loss_order = Order(self.msft_contract,
                                         quantity=1,
                                         execution_style=StopOrder(120.0),
                                         time_in_force=TimeInForce.GTC)

        self.exec_handler.assign_order_ids([self.buy_stop_loss_order])
        self._set_bar_for_today(open_price=120.0,
                                high_price=130.0,
                                low_price=68.0,
                                close_price=90.0,
                                volume=100000000.0)

        self._trigger_single_time_event()
        self.exec_handler.on_market_close(...)

        assert_lists_equal([], self.exec_handler.get_open_orders())

        expected_transactions = [
            Transaction(self.timer.now(), self.msft_contract, -1,
                        self.stop_loss_order_1.execution_style.stop_price, 0),
            Transaction(self.timer.now(), self.msft_contract, -1,
                        self.stop_loss_order_2.execution_style.stop_price, 0),
            Transaction(self.timer.now(), self.msft_contract, 1, 120, 0),
        ]
        self.monitor.record_transaction.assert_has_calls(
            call(t) for t in expected_transactions)
        self.portfolio.transact_transaction.assert_has_calls(
            call(t) for t in expected_transactions)

        self.assertEqual(self.monitor.record_transaction.call_count, 3)
        self.assertEqual(self.portfolio.transact_transaction.call_count, 3)

    def _set_last_available_price(self, price):
        self.data_handler.get_last_available_price.side_effect = lambda tickers: QFSeries(
            data=[price], index=pd.Index(tickers), name=self.start_date)

    def _set_bar_for_today(self, open_price, high_price, low_price,
                           close_price, volume):
        self.data_handler.get_current_bar.side_effect = lambda tickers: pd.DataFrame(
            index=pd.Index(tickers),
            columns=PriceField.ohlcv(),
            data=[[open_price, high_price, low_price, close_price, volume]])
Exemple #14
0
class TestSeries(unittest.TestCase):
    def setUp(self):
        self.timer = SettableTimer(initial_time=str_to_date('2017-01-01'))
        settings = get_test_settings()
        self.bbg_provider = BloombergDataProvider(settings)

    def test_valid_ticker_1(self):
        future_ticker = CustomFutureTicker("Custom", "CT{} Custom", 1, 5, 500)
        future_ticker.initialize_data_provider(self.timer, self.bbg_provider)

        # '2017-12-15' is the official expiration date of CustomTicker:B, setting the days_before_exp_date equal to
        # 5 forces the expiration to occur on the 11th ('2017-12-15' - 5 days = '2017-12-10' is the last day of old
        # contract).
        self.timer.set_current_time(str_to_date('2017-12-05'))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("B"))

        self.timer.set_current_time(str_to_date('2017-12-10'))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("B"))

        self.timer.set_current_time(str_to_date('2017-12-11'))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("C"))

    def test_valid_ticker_2(self):
        # Test the 2nd contract instead of front one

        future_ticker = CustomFutureTicker("Custom", "CT{} Custom", 2, 5, 500)
        future_ticker.initialize_data_provider(self.timer, self.bbg_provider)

        self.timer.set_current_time(str_to_date('2017-12-05'))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("C"))

        self.timer.set_current_time(str_to_date('2017-12-10'))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("C"))

        self.timer.set_current_time(str_to_date('2017-12-11'))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("D"))

    def test_valid_ticker_3(self):
        future_ticker = CustomFutureTicker("Custom", "CT{} Custom", 1, 45, 500)
        future_ticker.initialize_data_provider(self.timer, self.bbg_provider)

        self.timer.set_current_time(str_to_date('2017-11-28'))
        # '2017-11-28' + 45 days = '2018-01-12' - the front contract will be equal to CustomTicker:D
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("C"))

        self.timer.set_current_time(str_to_date('2017-11-29'))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("D"))

        self.timer.set_current_time(str_to_date('2017-12-05'))
        # '2017-12-05' + 45 days = '2018-01-19' - the front contract will be equal to CustomTicker:D
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("D"))

    def test_valid_ticker_4(self):
        future_ticker = CustomFutureTicker("Custom", "CT{} Custom", 2, 45, 500)
        future_ticker.initialize_data_provider(self.timer, self.bbg_provider)

        self.timer.set_current_time(str_to_date('2017-11-28'))
        # '2017-11-28' + 45 days = '2018-01-12' - the front contract will be equal to CustomTicker:D
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("D"))

        self.timer.set_current_time(str_to_date('2017-11-29'))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("E"))

        self.timer.set_current_time(str_to_date('2017-12-05'))
        # '2017-12-05' + 45 days = '2018-01-19' - the front contract will be equal to CustomTicker:D
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("E"))
Exemple #15
0
class TestDataHandler(TestCase):
    @classmethod
    def setUpClass(cls):
        cls.spx_index_ticker = BloombergTicker("SPX Index")
        cls.google_ticker = BloombergTicker("GOOGL US Equity")
        cls.microsoft_ticker = BloombergTicker("MSFT US Equity")

        cls.start_date = str_to_date("2018-01-02")
        cls.end_date = str_to_date("2018-01-31")
        cls.end_date_trimmed = str_to_date("2018-01-30")

    def setUp(self):
        self.price_data_provider = bbg_provider

        self.timer = SettableTimer()
        self.data_handler = DataHandler(self.price_data_provider, self.timer)

    def test_get_price_when_end_date_is_in_the_past(self):
        self.timer.set_current_time(str_to_date("2018-02-12 00:00:00.000000", DateFormat.FULL_ISO))
        prices_tms = self.data_handler.get_price(self.spx_index_ticker, PriceField.Close,
                                                 self.start_date, self.end_date)

        self.assertEqual(self.start_date, prices_tms.index[0].to_pydatetime())
        self.assertEqual(self.end_date, prices_tms.index[-1].to_pydatetime())

    def test_get_price_when_end_date_is_today_after_market_close(self):
        self.timer.set_current_time(str_to_date("2018-01-31 21:00:00.000000", DateFormat.FULL_ISO))
        prices_tms = self.data_handler.get_price(self.spx_index_ticker, PriceField.Close,
                                                 self.start_date, self.end_date)

        self.assertEqual(self.start_date, prices_tms.index[0].to_pydatetime())
        self.assertEqual(self.end_date, prices_tms.index[-1].to_pydatetime())

    def test_get_price_when_end_date_is_today_before_market_close(self):
        self.timer.set_current_time(str_to_date("2018-01-31 12:00:00.000000", DateFormat.FULL_ISO))
        prices_tms = self.data_handler.get_price(self.spx_index_ticker, PriceField.Close,
                                                 self.start_date, self.end_date)

        self.assertEqual(self.start_date, prices_tms.index[0].to_pydatetime())
        self.assertEqual(self.end_date_trimmed, prices_tms.index[-1].to_pydatetime())

    def test_get_price_when_end_date_is_tomorrow(self):
        self.timer.set_current_time(str_to_date("2018-01-30 18:00:00.000000", DateFormat.FULL_ISO))
        prices_tms = self.data_handler.get_price(self.spx_index_ticker, PriceField.Close, self.start_date,
                                                 self.end_date_trimmed)

        self.assertEqual(self.start_date, prices_tms.index[0].to_pydatetime())
        self.assertEqual(self.end_date_trimmed, prices_tms.index[-1].to_pydatetime())

    def test_get_last_price_single_ticker(self):
        # just test if getting single ticker value works, when a single ticker (not wrapped in a list) is passed
        self.timer.set_current_time(str_to_date("2018-01-31 12:00:00.000000", DateFormat.FULL_ISO))
        single_price = self.data_handler.get_last_available_price(self.spx_index_ticker)
        self.assertTrue(isinstance(single_price, float))

        # during the trading session
        self.timer.set_current_time(str_to_date("2018-01-31 12:00:00.000000", DateFormat.FULL_ISO))
        during_the_day_last_prices = self.data_handler.get_last_available_price([self.spx_index_ticker])

        self.assertEqual(self.spx_index_ticker, during_the_day_last_prices.index[0])
        self.assertEqual(single_price, during_the_day_last_prices[0])

        # after the trading session
        self.timer.set_current_time(str_to_date("2018-01-31 20:00:00.000000", DateFormat.FULL_ISO))
        after_close_last_prices = self.data_handler.get_last_available_price([self.spx_index_ticker])

        self.assertEqual(self.spx_index_ticker, after_close_last_prices.index[0])
        self.assertNotEqual(during_the_day_last_prices[0], after_close_last_prices[0])

        # before the trading session
        self.timer.set_current_time(str_to_date("2018-01-31 07:00:00.000000", DateFormat.FULL_ISO))
        before_close_last_prices = self.data_handler.get_last_available_price([self.spx_index_ticker])

        self.assertEqual(self.spx_index_ticker, before_close_last_prices.index[0])
        self.assertNotEqual(during_the_day_last_prices[0], before_close_last_prices[0])
        self.assertNotEqual(after_close_last_prices[0], before_close_last_prices[0])

    def test_get_last_price_with_multiple_tickers_when_current_data_is_unavailable(self):
        self.timer.set_current_time(str_to_date("2018-01-01 12:00:00.000000", DateFormat.FULL_ISO))
        last_prices = self.data_handler.get_last_available_price([self.spx_index_ticker, self.google_ticker])

        self.assertEqual(self.spx_index_ticker, last_prices.index[0])
        self.assertEqual(self.google_ticker, last_prices.index[1])

    def test_get_last_price_with_empty_tickers_list(self):
        self.timer.set_current_time(str_to_date("2018-01-31 12:00:00.000000", DateFormat.FULL_ISO))
        last_prices = self.data_handler.get_last_available_price([])
        assert_series_equal(pd.Series(), last_prices)

    def test_get_history_when_end_date_is_in_the_past(self):
        self.timer.set_current_time(str_to_date("2018-02-12 00:00:00.000000", DateFormat.FULL_ISO))
        prices_tms = self.data_handler.get_history(self.spx_index_ticker, 'PX_TO_BOOK_RATIO',
                                                   self.start_date, self.end_date)

        self.assertEqual(self.start_date, prices_tms.index[0].to_pydatetime())
        self.assertEqual(self.end_date, prices_tms.index[-1].to_pydatetime())

    def test_get_history_when_end_date_is_today_after_market_close(self):
        self.timer.set_current_time(str_to_date("2018-01-31 21:00:00.000000", DateFormat.FULL_ISO))
        prices_tms = self.data_handler.get_history(self.spx_index_ticker, 'PX_TO_BOOK_RATIO',
                                                   self.start_date, self.end_date)

        self.assertEqual(self.start_date, prices_tms.index[0].to_pydatetime())
        self.assertEqual(self.end_date, prices_tms.index[-1].to_pydatetime())

    def test_get_history_when_end_date_is_today_before_market_close(self):
        self.timer.set_current_time(str_to_date("2018-01-31 12:00:00.000000", DateFormat.FULL_ISO))
        prices_tms = self.data_handler.get_history(self.spx_index_ticker, 'PX_TO_BOOK_RATIO',
                                                   self.start_date, self.end_date)

        self.assertEqual(self.start_date, prices_tms.index[0].to_pydatetime())
        self.assertEqual(self.end_date_trimmed, prices_tms.index[-1].to_pydatetime())

    def test_get_history_when_end_date_is_tomorrow(self):
        self.timer.set_current_time(str_to_date("2018-01-30 18:00:00.000000", DateFormat.FULL_ISO))
        prices_tms = self.data_handler.get_history(self.spx_index_ticker, 'PX_TO_BOOK_RATIO',
                                                   self.start_date, self.end_date_trimmed)

        self.assertEqual(self.start_date, prices_tms.index[0].to_pydatetime())
        self.assertEqual(self.end_date_trimmed, prices_tms.index[-1].to_pydatetime())

    def test_get_history_with_multiple_tickers(self):
        self.timer.set_current_time(str_to_date("2018-01-31 12:00:00.000000", DateFormat.FULL_ISO))
        resilt_df = self.data_handler.get_history([self.microsoft_ticker, self.google_ticker], 'PX_TO_BOOK_RATIO',
                                                  self.start_date, self.end_date_trimmed)

        self.assertEqual(self.microsoft_ticker, resilt_df.columns[0])
        self.assertEqual(self.google_ticker, resilt_df.columns[1])
        self.assertEqual(self.start_date, resilt_df.index[0].to_pydatetime())
        self.assertEqual(self.end_date_trimmed, resilt_df.index[-1].to_pydatetime())
        self.assertEqual(resilt_df.shape, (20, 2))

    def test_historical_price_many_tickers_many_fields(self):
        self.timer.set_current_time(str_to_date("2018-01-31 12:00:00.000000", DateFormat.FULL_ISO))
        result_array = self.data_handler.historical_price([self.microsoft_ticker], [PriceField.Open, PriceField.Close],
                                                          nr_of_bars=5)

        self.assertEquals(QFDataArray, type(result_array))
        self.assertEquals((5, 1, 2), result_array.shape)

        expected_dates_str = ["2018-01-24", "2018-01-25", "2018-01-26", "2018-01-29", "2018-01-30"]
        expected_dates = [str_to_date(date_str) for date_str in expected_dates_str]
        assert_same_index(pd.DatetimeIndex(expected_dates, name=DATES), result_array.dates.to_index(),
                          check_index_type=True, check_names=True)

    def test_historical_price_many_tickers_one_field(self):
        self.timer.set_current_time(str_to_date("2018-01-04 12:00:00.000000", DateFormat.FULL_ISO))
        result_df = self.data_handler.historical_price([self.microsoft_ticker], PriceField.Open, nr_of_bars=5)

        self.assertEquals(PricesDataFrame, type(result_df))

        expected_dates_idx = pd.DatetimeIndex(
            ['2017-12-27', '2017-12-28', '2017-12-29', '2018-01-02', '2018-01-03'], name=DATES
        )
        assert_same_index(expected_dates_idx, result_df.index, check_index_type=True, check_names=True)

        expected_tickers_idx = pd.Index([self.microsoft_ticker], name=TICKERS)
        assert_same_index(expected_tickers_idx, result_df.columns, check_index_type=True, check_names=True)
class TestMarketOnOpenExecutionStyle(TestCase):
    MarketOpenEvent.set_trigger_time({
        "hour": 13,
        "minute": 30,
        "second": 0,
        "microsecond": 0
    })
    MarketCloseEvent.set_trigger_time({
        "hour": 20,
        "minute": 0,
        "second": 0,
        "microsecond": 0
    })

    def setUp(self):
        self.scheduling_time_delay = 1
        start_date = str_to_date("2018-02-04")

        before_close = start_date + MarketCloseEvent.trigger_time(
        ) - RelativeDelta(minutes=self.scheduling_time_delay)
        self.timer = SettableTimer(initial_time=before_close)

        contracts_to_tickers_mapper = SimulatedBloombergContractTickerMapper()
        msft_contract = Contract("MSFT US Equity",
                                 security_type='STK',
                                 exchange='TEST')
        self.msft_ticker = contracts_to_tickers_mapper.contract_to_ticker(
            msft_contract)

        self.data_handler = Mock(spec=DataHandler)
        self.scheduler = Mock(spec=Scheduler)

        self.commission_model = FixedCommissionModel(commission=0.0)
        self.monitor = Mock(spec=AbstractMonitor)
        self.portfolio = Mock(spec=Portfolio)

        slippage_model = PriceBasedSlippage(0.0, self.data_handler,
                                            contracts_to_tickers_mapper)
        self.exec_handler = SimulatedExecutionHandler(
            self.data_handler, self.timer, self.scheduler, self.monitor,
            self.commission_model, contracts_to_tickers_mapper, self.portfolio,
            slippage_model, RelativeDelta(minutes=self.scheduling_time_delay))

        self.order_1 = Order(msft_contract,
                             quantity=10,
                             execution_style=MarketOrder(),
                             time_in_force=TimeInForce.OPG)
        self.order_2 = Order(msft_contract,
                             quantity=-5,
                             execution_style=MarketOrder(),
                             time_in_force=TimeInForce.OPG)
        self.order_3 = Order(msft_contract,
                             quantity=-7,
                             execution_style=MarketOrder(),
                             time_in_force=TimeInForce.OPG)

        self.order_4 = Order(msft_contract,
                             quantity=4,
                             execution_style=MarketOnCloseOrder(),
                             time_in_force=TimeInForce.DAY)

    def _trigger_single_time_event(self):
        self.timer.set_current_time(self.timer.now() + RelativeDelta(
            minutes=self.scheduling_time_delay))
        event = ScheduleOrderExecutionEvent()
        self.exec_handler.on_orders_accept(event)

    def test_1_order_fill(self):
        self.exec_handler.assign_order_ids([self.order_1])
        self._set_current_price(101)
        self._trigger_single_time_event()
        self.exec_handler.on_market_open(...)

        self.monitor.record_transaction.assert_called_once()
        self.portfolio.transact_transaction.assert_called_once()

        actual_orders = self.exec_handler.get_open_orders()
        expected_orders = []
        assert_lists_equal(expected_orders, actual_orders)

    def test_3_orders_fill(self):
        self.exec_handler.assign_order_ids(
            [self.order_1, self.order_2, self.order_3])
        self._set_current_price(101)
        self._trigger_single_time_event()
        self.exec_handler.on_market_open(...)

        self.assertEqual(self.monitor.record_transaction.call_count, 3)
        self.assertEqual(self.portfolio.transact_transaction.call_count, 3)

        actual_orders = self.exec_handler.get_open_orders()
        expected_orders = []
        assert_lists_equal(expected_orders, actual_orders)

    def test_3_orders_fill_only_at_open(self):
        self.exec_handler.assign_order_ids(
            [self.order_1, self.order_2, self.order_3])
        self._set_current_price(101)
        self._trigger_single_time_event()
        self.exec_handler.on_market_close(...)

        self.portfolio.transact_transaction.assert_not_called()
        self.monitor.record_transaction.assert_not_called()

        actual_orders = self.exec_handler.get_open_orders()
        expected_orders = [self.order_1, self.order_2, self.order_3]
        self.assertCountEqual(expected_orders, actual_orders)

    def test_fill_open_and_close(self):
        self.exec_handler.assign_order_ids([self.order_1, self.order_2])
        self.exec_handler.assign_order_ids([self.order_2, self.order_3])
        self.exec_handler.assign_order_ids([self.order_3, self.order_4])
        self.exec_handler.assign_order_ids([self.order_4, self.order_4])

        self._set_current_price(101)
        self._trigger_single_time_event()
        self.exec_handler.on_market_open(...)

        self.assertEqual(self.monitor.record_transaction.call_count, 3)
        self.assertEqual(self.portfolio.transact_transaction.call_count, 3)

        actual_orders = self.exec_handler.get_open_orders()
        expected_orders = [self.order_4]
        assert_lists_equal(expected_orders, actual_orders)

        self.exec_handler.on_market_close(...)

        self.assertEqual(self.monitor.record_transaction.call_count, 4)
        self.assertEqual(self.portfolio.transact_transaction.call_count, 4)

        actual_orders = self.exec_handler.get_open_orders()
        expected_orders = []
        assert_lists_equal(expected_orders, actual_orders)

    def test_fill_close_and_open(self):
        self.exec_handler.assign_order_ids([self.order_1, self.order_2])
        self.exec_handler.assign_order_ids([self.order_2, self.order_3])
        self.exec_handler.assign_order_ids([self.order_3, self.order_4])
        self.exec_handler.assign_order_ids([self.order_4, self.order_4])

        self._set_current_price(101)

        self._trigger_single_time_event()
        self.exec_handler.on_market_close(...)

        # Transaction related to order 4 will be executed only once, as only one Order object was passed
        self.monitor.record_transaction.assert_called_once()
        self.portfolio.transact_transaction.assert_called_once()

        actual_orders = self.exec_handler.get_open_orders()
        expected_orders = [self.order_1, self.order_2, self.order_3]
        self.assertCountEqual(expected_orders, actual_orders)

        self.exec_handler.on_market_open(...)

        self.assertEqual(self.monitor.record_transaction.call_count, 4)
        self.assertEqual(self.portfolio.transact_transaction.call_count, 4)

        actual_orders = self.exec_handler.get_open_orders()
        expected_orders = []
        self.assertCountEqual(expected_orders, actual_orders)

    def test_market_open_transaction(self):
        order = self.order_1
        price = 102
        self.exec_handler.assign_order_ids([order])
        self._set_current_price(price)
        self._trigger_single_time_event()
        self.exec_handler.on_market_open(...)

        timestamp = self.timer.now()
        contract = order.contract
        quantity = order.quantity
        commission = self.commission_model.calculate_commission(order, price)
        expected_transaction = Transaction(timestamp, contract, quantity,
                                           price, commission)

        self.monitor.record_transaction.assert_called_once_with(
            expected_transaction)

    def test_market_close_transaction(self):
        order = self.order_4
        price = 102
        self.exec_handler.assign_order_ids([self.order_1, order])
        self._set_current_price(price)
        self._trigger_single_time_event()
        self.exec_handler.on_market_close(...)

        timestamp = self.timer.now()
        contract = order.contract
        quantity = order.quantity
        commission = self.commission_model.calculate_commission(order, price)
        expected_transaction = Transaction(timestamp, contract, quantity,
                                           price, commission)

        self.monitor.record_transaction.assert_called_once_with(
            expected_transaction)

    def test_market_close_does_not_trade(self):
        price = None
        self.exec_handler.assign_order_ids([self.order_1, self.order_4])
        self._set_current_price(price)
        self._trigger_single_time_event()
        self.exec_handler.on_market_close(...)

        self.portfolio.transact_transaction.assert_not_called()
        self.monitor.record_transaction.assert_not_called()

    def test_market_open_does_not_trade(self):
        price = None
        self.exec_handler.assign_order_ids([self.order_1, self.order_4])
        self._set_current_price(price)
        self._trigger_single_time_event()
        self.exec_handler.on_market_open(...)

        self.portfolio.transact_transaction.assert_not_called()
        self.monitor.record_transaction.assert_not_called()

    def _set_last_available_price(self, price):
        self.data_handler.get_last_available_price.side_effect = lambda t: QFSeries(
            data=[price], index=pd.Index([self.msft_ticker]))

    def _set_current_price(self, price):
        self.data_handler.get_current_price.side_effect = lambda t: QFSeries(
            data=[price], index=pd.Index([self.msft_ticker]))
class TestDailyDataHandler(TestCase):
    def setUp(self):
        self.timer = SettableTimer()
        self.tickers = [
            QuandlTicker("MSFT", "WIKI"),
            QuandlTicker("AAPL", "WIKI")
        ]
        price_data_provider_mock = self._create_price_provider_mock(
            self.tickers)
        self.data_handler = DailyDataHandler(price_data_provider_mock,
                                             self.timer)

        MarketOpenEvent.set_trigger_time({
            "hour": 13,
            "minute": 30,
            "second": 0,
            "microsecond": 0
        })
        MarketCloseEvent.set_trigger_time({
            "hour": 20,
            "minute": 0,
            "second": 0,
            "microsecond": 0
        })

    def test_before_data_starts(self):
        self._assert_last_prices_are_correct("2009-12-28 06:00:00.000000",
                                             [nan, nan])

    def test_at_market_open_when_data_available_for_every_ticker(self):
        self._assert_last_prices_are_correct("2009-12-28 13:30:00.000000",
                                             [25.0, 27.0])

    def test_at_market_open_when_data_available_for_the_first_ticker(self):
        self._assert_last_prices_are_correct("2009-12-30 13:30:00.000000",
                                             [31.0, 30.0])

    def test_during_trading_hours_when_data_available_for_every_ticker(self):
        self._assert_last_prices_are_correct("2009-12-28 14:30:00.000000",
                                             [25.0, 27.0])

    def test_during_trading_hours_when_data_available_for_the_first_ticker(
            self):
        self._assert_last_prices_are_correct("2009-12-30 14:30:00.000000",
                                             [31.0, 30.0])

    def test_at_market_close_when_data_available_for_the_first_ticker(self):
        self._assert_last_prices_are_correct("2009-12-30 20:00:00.000000",
                                             [32.0, 30.0])

    def test_after_market_close_when_data_is_not_available_for_anything_anymore(
            self):
        self._assert_last_prices_are_correct("2009-12-30 20:00:00.000000",
                                             [32.0, 30.0])

    def test_before_market_close_when_old_data_is_available(self):
        self._assert_last_prices_are_correct("2009-12-31 06:00:00.000000",
                                             [32.0, 30.0])

    def _assert_last_prices_are_correct(self, curr_time_str, expected_values):
        current_time = str_to_date(curr_time_str, DateFormat.FULL_ISO)
        self.timer.set_current_time(current_time)
        expected_series = QFSeries(data=expected_values, index=self.tickers)
        actual_series = self.data_handler.get_last_available_price(
            self.tickers)
        assert_series_equal(expected_series, actual_series, check_names=False)

    def _create_price_provider_mock(self, tickers):
        mock_data_array = QFDataArray.create(
            dates=date_range(start='2009-12-28', end='2009-12-30', freq='D'),
            tickers=tickers,
            fields=PriceField.ohlcv(),
            data=[
                # 2009-12-28
                [
                    # Open High  Low   Close Volume
                    [25.0, 25.1, 25.2, 26.0, 25.3],  # MSFT
                    [27.0, 27.1, 27.2, 28.0, 27.3]  # AAPL
                ],
                # 2009-12-29
                [
                    # Open High  Low   Close Volume
                    [None, None, None, None, None],  # MSFT
                    [29.0, 29.1, 29.2, 30.0, 29.3]  # AAPL
                ],
                # 2009-12-30
                [
                    # Open High  Low   Close Volume
                    [31.0, 31.1, 31.2, 32.0, 31.3],  # MSFT
                    [None, None, None, None, None]  # AAPL
                ]
            ])

        price_data_provider_mock = Mock(spec=DataProvider,
                                        frequency=Frequency.DAILY)
        price_data_provider_mock.get_price.side_effect = lambda t, fields, start_time, end_time, frequency: \
            mock_data_array.loc[start_time:end_time, t, fields].to_pandas()

        return price_data_provider_mock
Exemple #18
0
class TestSeries(unittest.TestCase):
    def setUp(self):
        self.timer = SettableTimer(initial_time=str_to_date('2017-01-01'))
        settings = get_test_settings()
        self.bbg_provider = BloombergDataProvider(settings)

    def test_valid_ticker_1(self):
        future_ticker = CustomFutureTicker("Custom", "CT{} Custom", 1, 5, 500)
        future_ticker.initialize_data_provider(self.timer, self.bbg_provider)

        # '2017-12-15' is the official expiration date of CustomTicker:B, setting the days_before_exp_date equal to
        # 5 forces the expiration to occur on the 11th ('2017-12-15' - 5 days = '2017-12-10' is the last day of old
        # contract).
        self.timer.set_current_time(str_to_date('2017-12-05'))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("B"))

        self.timer.set_current_time(str_to_date('2017-12-10'))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("B"))

        self.timer.set_current_time(str_to_date('2017-12-11'))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("C"))

    def test_valid_ticker_2(self):
        # Test the 2nd contract instead of front one

        future_ticker = CustomFutureTicker("Custom", "CT{} Custom", 2, 5, 500)
        future_ticker.initialize_data_provider(self.timer, self.bbg_provider)

        self.timer.set_current_time(str_to_date('2017-12-05'))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("C"))

        self.timer.set_current_time(str_to_date('2017-12-10'))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("C"))

        self.timer.set_current_time(str_to_date('2017-12-11'))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("D"))

    def test_valid_ticker_3(self):
        future_ticker = CustomFutureTicker("Custom", "CT{} Custom", 1, 45, 500)
        future_ticker.initialize_data_provider(self.timer, self.bbg_provider)

        self.timer.set_current_time(str_to_date('2017-11-28'))
        # '2017-11-28' + 45 days = '2018-01-12' - the front contract will be equal to CustomTicker:D
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("C"))

        self.timer.set_current_time(str_to_date('2017-11-29'))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("D"))

        self.timer.set_current_time(str_to_date('2017-12-05'))
        # '2017-12-05' + 45 days = '2018-01-19' - the front contract will be equal to CustomTicker:D
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("D"))

    def test_valid_ticker_4(self):
        future_ticker = CustomFutureTicker("Custom", "CT{} Custom", 2, 45, 500)
        future_ticker.initialize_data_provider(self.timer, self.bbg_provider)

        self.timer.set_current_time(str_to_date('2017-11-28'))
        # '2017-11-28' + 45 days = '2018-01-12' - the front contract will be equal to CustomTicker:D
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("D"))

        self.timer.set_current_time(str_to_date('2017-11-29'))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("E"))

        self.timer.set_current_time(str_to_date('2017-12-05'))
        # '2017-12-05' + 45 days = '2018-01-19' - the front contract will be equal to CustomTicker:D
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("E"))

    def test_set_expiration_hour__first_caching_before_exp_hour(self):
        """ Test set expiration hour when the first caching occurs on the expiration day, before expiration hour. """
        future_ticker = CustomFutureTicker("Custom", "CT{} Custom", 1, 5, 500)
        future_ticker.initialize_data_provider(self.timer, self.bbg_provider)
        future_ticker.set_expiration_hour(hour=8, minute=10)

        self.timer.set_current_time(
            str_to_date('2017-12-11 00:00:00.0', DateFormat.FULL_ISO))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("B"))

        self.timer.set_current_time(
            str_to_date('2017-12-11 07:59:00.0', DateFormat.FULL_ISO))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("B"))

        self.timer.set_current_time(
            str_to_date('2017-12-11 08:10:00.0', DateFormat.FULL_ISO))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("C"))

        self.timer.set_current_time(
            str_to_date('2017-12-11 07:10:00.0', DateFormat.FULL_ISO))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("B"))

        self.timer.set_current_time(
            str_to_date('2017-12-11 09:10:00.0', DateFormat.FULL_ISO))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("C"))

    def test_set_expiration_hour__first_caching_after_exp_hour(self):
        """ Test set expiration hour when the first caching occurs a day before the expiration day, after
        expiration hour. """
        future_ticker = CustomFutureTicker("Custom", "CT{} Custom", 1, 5, 500)
        future_ticker.initialize_data_provider(self.timer, self.bbg_provider)
        future_ticker.set_expiration_hour(hour=10, minute=10)

        self.timer.set_current_time(
            str_to_date('2017-12-10 19:00:00.0', DateFormat.FULL_ISO))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("B"))

        self.timer.set_current_time(
            str_to_date('2017-12-11 10:10:00.0', DateFormat.FULL_ISO))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("C"))

        self.timer.set_current_time(
            str_to_date('2017-12-11 11:10:00.0', DateFormat.FULL_ISO))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("C"))

    def test_set_expiration_hour__first_caching_at_exp_hour(self):
        """ Test set expiration hour when the first caching occurs a day before the expiration day, at
        expiration hour. """
        future_ticker = CustomFutureTicker("Custom", "CT{} Custom", 1, 5, 500)
        future_ticker.initialize_data_provider(self.timer, self.bbg_provider)
        future_ticker.set_expiration_hour(hour=8, minute=10)

        self.timer.set_current_time(
            str_to_date('2017-12-11 08:10:00.0', DateFormat.FULL_ISO))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("C"))

        self.timer.set_current_time(
            str_to_date('2017-12-11 09:10:00.0', DateFormat.FULL_ISO))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("C"))

        self.timer.set_current_time(
            str_to_date('2017-12-10 19:00:00.0', DateFormat.FULL_ISO))
        self.assertEqual(future_ticker.get_current_specific_ticker(),
                         CustomTicker("B"))