def __init__(self, data_provider: GeneralPriceProvider, settings: Settings,
                 pdf_exporter: PDFExporter, excel_exporter: ExcelExporter):
        self._logger = qf_logger.getChild(self.__class__.__name__)

        self._backtest_name = "Backtest Results"
        self._initial_cash = 10000000
        self._initial_risk = None
        self._benchmark_tms = None
        self._monitor_settings = None

        self._contract_ticker_mapper = SimulatedBloombergContractTickerMapper()

        self._commission_model_type = FixedCommissionModel
        self._commission_model_kwargs = {"commission": 0.0}

        self._slippage_model_type = PriceBasedSlippage
        self._slippage_model_kwargs = {
            "slippage_rate": 0.0,
            "max_volume_share_limit": None
        }

        self._position_sizer_type = SimplePositionSizer
        self._position_sizer_kwargs = dict()

        self._orders_filter_types_params = [
        ]  # type: List[Tuple[Type[OrdersFilter], Dict]]

        self._signals_register = None
        self._data_provider = data_provider
        self._settings = settings
        self._pdf_exporter = pdf_exporter
        self._excel_exporter = excel_exporter

        self._frequency = None
        self._scheduling_time_delay = RelativeDelta(minutes=1)

        BeforeMarketOpenEvent.set_trigger_time({
            "hour": 8,
            "minute": 0,
            "second": 0,
            "microsecond": 0
        })
        MarketOpenEvent.set_trigger_time({
            "hour": 13,
            "minute": 30,
            "second": 0,
            "microsecond": 0
        })
        MarketCloseEvent.set_trigger_time({
            "hour": 20,
            "minute": 0,
            "second": 0,
            "microsecond": 0
        })
        AfterMarketCloseEvent.set_trigger_time({
            "hour": 23,
            "minute": 00,
            "second": 0,
            "microsecond": 0
        })
예제 #2
0
 def setUp(self):
     BeforeMarketOpenEvent.set_trigger_time({
         "hour": 8,
         "minute": 0,
         "second": 0,
         "microsecond": 0
     })
     MarketOpenEvent.set_trigger_time({
         "hour": 13,
         "minute": 30,
         "second": 0,
         "microsecond": 0
     })
     MarketCloseEvent.set_trigger_time({
         "hour": 20,
         "minute": 0,
         "second": 0,
         "microsecond": 0
     })
     AfterMarketCloseEvent.set_trigger_time({
         "hour": 21,
         "minute": 0,
         "second": 0,
         "microsecond": 0
     })
예제 #3
0
    def setUpClass(cls):
        cls.YESTERDAY_OPEN = str_to_date("2018-01-29 13:30:00.000000", DateFormat.FULL_ISO)
        cls.YESTERDAY_CLOSE = str_to_date("2018-01-29 20: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 13:30:00.000000", DateFormat.FULL_ISO)
        cls.TODAY_MIDDLE_DAY = str_to_date("2018-01-30 15:00:00.000000", DateFormat.FULL_ISO)
        cls.TODAY_CLOSE = str_to_date("2018-01-30 20:00:00.000000", DateFormat.FULL_ISO)
        cls.TODAY_AFTER_CLOSE = str_to_date("2018-01-30 20:00:00.000000", DateFormat.FULL_ISO)

        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.timer, self.tickers, self.data_handler = _get_test_case_set_up()
     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.timer, self.tickers, self.data_handler = _get_test_case_set_up()
     self.tickers_index = pd.Index(self.tickers, name='tickers')
     self.fields_index = pd.Index(PriceField.ohlcv(), name='fields')
     MarketOpenEvent.set_trigger_time({
         "hour": 13,
         "minute": 30,
         "second": 0,
         "microsecond": 0
     })
     MarketCloseEvent.set_trigger_time({
         "hour": 20,
         "minute": 0,
         "second": 0,
         "microsecond": 0
     })
예제 #6
0
    def __init__(self,
                 tickers: Union[Ticker, Sequence[Ticker]],
                 start_date: datetime,
                 end_date: datetime,
                 data_handler: DataHandler,
                 alpha_models: Union[AlphaModel, Sequence[AlphaModel]],
                 settings: Settings,
                 pdf_exporter: PDFExporter,
                 only_entry_signals: bool = True,
                 title: str = "Signals Plotter"):

        super().__init__(settings, pdf_exporter, title)

        # Set the market open and close events in order to use the data handler (necessary to e.g. compute the market
        # close time of the previous day)
        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.tickers, _ = convert_to_list(tickers, Ticker)
        self.alpha_models, _ = convert_to_list(alpha_models, AlphaModel)

        self.start_date = start_date
        self.end_date = end_date

        self.data_handler = data_handler

        assert isinstance(self.data_handler.timer, SettableTimer)
        self.timer: SettableTimer = self.data_handler.timer

        self.only_entry_signals = only_entry_signals

        for ticker in tickers:
            if isinstance(ticker, FutureTicker):
                ticker.initialize_data_provider(
                    self.timer, self.data_handler.data_provider)
    def test_get_price_aggregation_single_ticker(self):
        MarketOpenEvent.set_trigger_time({"hour": 17, "minute": 13, "second": 0, "microsecond": 0})

        dp = PortaraDataProvider(self.futures_path, self.ticker, PriceField.Close, self.start_date, self.end_date,
                                 Frequency.MIN_1)
        prices = dp.get_price(self.ticker, PriceField.Close, self.start_date, self.end_date, Frequency.MIN_1)
        prices5 = dp.get_price(self.ticker, PriceField.Close, self.start_date, self.end_date, Frequency.MIN_5)
        prices15 = dp.get_price(self.ticker, PriceField.Close, self.start_date, self.end_date, Frequency.MIN_15)

        self.assertTrue(len(prices5))
        self.assertEqual(type(prices5), PricesSeries)
        self.assertEqual(Frequency.infer_freq(prices5.index), Frequency.MIN_5)

        assert_series_equal(prices5, prices.resample('5T', origin=datetime(2021, 6, 17, 17, 13)).last().dropna(),
                            check_names=False)

        self.assertTrue(len(prices15))
        self.assertEqual(type(prices15), PricesSeries)
        self.assertEqual(Frequency.infer_freq(prices15.index), Frequency.MIN_15)
        assert_series_equal(prices15, prices.resample('15T', origin=datetime(2021, 6, 17, 17, 13)).last().dropna(),
                            check_names=False)
예제 #8
0
    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_ticker = BloombergTicker(self.MSFT_TICKER_STR)

        self.timer = SettableTimer(initial_time=before_close)

        self.data_handler = Mock(spec=DataHandler)
        self.data_handler.data_provider = Mock(spec=DataProvider)

        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)
        self.exec_handler = SimulatedExecutionHandler(self.data_handler, self.timer, scheduler, self.monitor,
                                                      commission_model, 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_ticker, quantity=-1, execution_style=StopOrder(95.0),
                                       time_in_force=TimeInForce.GTC)
        self.stop_loss_order_2 = Order(self.msft_ticker, quantity=-1, execution_style=StopOrder(90.0),
                                       time_in_force=TimeInForce.GTC)

        self.stop_loss_order_3 = Order(self.msft_ticker, 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])
예제 #9
0
    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
        })
예제 #10
0
    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
        })
예제 #11
0
class TradingSessionForTests(TradingSession):
    """
    Encapsulates the settings and components for carrying out a backtest session. Pulls for data every day.
    """

    # initialise market time
    BeforeMarketOpenEvent.set_trigger_time({"hour": 7, "minute": 30, "second": 0, "microsecond": 0})
    MarketOpenEvent.set_trigger_time({"hour": 13, "minute": 30, "second": 0, "microsecond": 0})
    MarketCloseEvent.set_trigger_time({"hour": 20, "minute": 0, "second": 0, "microsecond": 0})
    AfterMarketCloseEvent.set_trigger_time({"hour": 21, "minute": 0, "second": 0, "microsecond": 0})

    def __init__(self, data_provider: DataProvider, start_date, end_date, initial_cash,
                 frequency: Frequency = Frequency.MIN_1):
        """
        Set up the backtest variables according to what has been passed in.
        """
        super().__init__()
        self.logger = qf_logger.getChild(self.__class__.__name__)

        self.logger.info(
            "\n".join([
                "Testing the Backtester:",
                "Start date: {:s}".format(date_to_str(start_date)),
                "End date: {:s}".format(date_to_str(end_date)),
                "Initial cash: {:.2f}".format(initial_cash),
                "Frequency of the simulated execution handler: {}".format(frequency)
            ])
        )

        timer = SettableTimer(start_date)
        notifiers = Notifiers(timer)
        if frequency <= Frequency.DAILY:
            data_handler = DailyDataHandler(data_provider, timer)
        else:
            data_handler = IntradayDataHandler(data_provider, timer)

        contract_ticker_mapper = SimulatedBloombergContractTickerMapper()
        portfolio = Portfolio(data_handler, initial_cash, timer, contract_ticker_mapper)
        signals_register = BacktestSignalsRegister()
        backtest_result = BacktestResult(portfolio=portfolio, backtest_name="Testing the Backtester",
                                         start_date=start_date, end_date=end_date, signals_register=signals_register)

        monitor = Mock(spec=BacktestMonitor)
        commission_model = FixedCommissionModel(0.0)
        slippage_model = PriceBasedSlippage(0.0, data_provider, contract_ticker_mapper)

        execution_handler = SimulatedExecutionHandler(
            data_handler, timer, notifiers.scheduler, monitor, commission_model,
            contract_ticker_mapper, portfolio, slippage_model)

        broker = BacktestBroker(portfolio, execution_handler)
        order_factory = OrderFactory(broker, data_handler, contract_ticker_mapper)

        event_manager = self._create_event_manager(timer, notifiers)
        time_flow_controller = BacktestTimeFlowController(
            notifiers.scheduler, event_manager, timer, notifiers.empty_queue_event_notifier, end_date
        )
        position_sizer = SimplePositionSizer(broker, data_handler, order_factory, contract_ticker_mapper,
                                             signals_register)

        self.logger.info(
            "\n".join([
                "Configuration of components:",
                "Position sizer: {:s}".format(position_sizer.__class__.__name__),
                "Timer: {:s}".format(timer.__class__.__name__),
                "Data Provider: {:s}".format(data_provider.__class__.__name__),
                "Backtest Result: {:s}".format(backtest_result.__class__.__name__),
                "Monitor: {:s}".format(monitor.__class__.__name__),
                "Execution Handler: {:s}".format(execution_handler.__class__.__name__),
                "Commission Model: {:s}".format(commission_model.__class__.__name__),
                "Broker: {:s}".format(broker.__class__.__name__),
                "Contract-Ticker Mapper: {:s}".format(contract_ticker_mapper.__class__.__name__)
            ])
        )

        self.broker = broker
        self.notifiers = notifiers
        self.initial_cash = initial_cash
        self.start_date = start_date
        self.end_date = end_date
        self.event_manager = event_manager
        self.contract_ticker_mapper = contract_ticker_mapper
        self.data_handler = data_handler
        self.portfolio = portfolio
        self.execution_handler = execution_handler
        self.position_sizer = position_sizer
        self.orders_filters = []
        self.monitor = monitor
        self.timer = timer
        self.order_factory = order_factory
        self.time_flow_controller = time_flow_controller
예제 #12
0
class TestFastAlphaModelsTester(TestCase):
    apple_ticker = QuandlTicker("AAPL", "WIKI")
    ibm_ticker = QuandlTicker("IBM", "WIKI")
    tickers = [apple_ticker, ibm_ticker]

    test_start_date = str_to_date("2015-01-01")
    test_end_date = str_to_date("2015-01-31")

    data_start_date = str_to_date("2014-12-25")
    data_end_date = test_end_date

    frequency = Frequency.DAILY

    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):
        all_fields = PriceField.ohlcv()

        self._mocked_prices_arr = self._make_mock_data_array(
            self.tickers, all_fields)
        self._price_provider_mock = PresetDataProvider(self._mocked_prices_arr,
                                                       self.data_start_date,
                                                       self.data_end_date,
                                                       self.frequency)
        self.timer = SettableTimer()
        self.contract_ticker_mapper = DummyQuandlContractTickerMapper()

        self.alpha_model_type = DummyAlphaModel

    @classmethod
    def _make_mock_data_array(cls, tickers, fields):
        all_dates_index = pd.bdate_range(start=cls.data_start_date,
                                         end=cls.test_end_date)

        num_of_dates = len(all_dates_index)
        num_of_tickers = len(tickers)
        num_of_fields = len(fields)

        start_value = 100.0
        values = np.arange(
            start_value,
            num_of_dates * num_of_tickers * num_of_fields + start_value)
        reshaped_values = np.reshape(
            values, (num_of_dates, num_of_tickers, num_of_fields))

        mocked_result = QFDataArray.create(all_dates_index,
                                           tickers,
                                           fields,
                                           data=reshaped_values)
        mocked_result.loc[:, :, PriceField.Low] -= 50.0
        mocked_result.loc[:, :, PriceField.High] += 50.0

        return mocked_result

    def test_alpha_models_tester(self):
        first_param_set = (10, Exposure.LONG)
        second_param_set = (5, Exposure.SHORT)
        data_handler = FastDataHandler(self._price_provider_mock, self.timer)

        params = [
            FastAlphaModelTesterConfig(
                self.alpha_model_type, {
                    "period_length": 10,
                    "first_suggested_exposure": Exposure.LONG,
                    "risk_estimation_factor": None
                }, ("period_length", "first_suggested_exposure")),
            FastAlphaModelTesterConfig(
                self.alpha_model_type, {
                    "period_length": 5,
                    "first_suggested_exposure": Exposure.SHORT,
                    "risk_estimation_factor": None
                }, ("period_length", "first_suggested_exposure"))
        ]

        tester = FastAlphaModelTester(params, self.tickers,
                                      self.contract_ticker_mapper,
                                      self.test_start_date, self.test_end_date,
                                      data_handler, self.timer)

        backtest_summary = tester.test_alpha_models()
        self.assertEqual(self.tickers, backtest_summary.tickers)
        self.assertEqual(DummyAlphaModel, backtest_summary.alpha_model_type)

        backtest_summary_elements = backtest_summary.elements_list
        self.assertEqual(2 * (len(self.tickers) + 1),
                         len(backtest_summary_elements))

        # check first backtest summary element - trades
        first_elem = backtest_summary_elements[2]
        self.assertEqual(first_param_set, first_elem.model_parameters)

        expected_trades_data = [[
            self.apple_ticker,
            str_to_date("2015-01-02"),
            str_to_date("2015-01-16"), (260.0 / 160.0 - 1), 1.0
        ],
                                [
                                    self.ibm_ticker,
                                    str_to_date("2015-01-02"),
                                    str_to_date("2015-01-16"),
                                    (265.0 / 165.0 - 1), 1.0
                                ]]

        generated_trades_data = [[
            self.contract_ticker_mapper.contract_to_ticker(t.contract),
            t.start_time, t.end_time, t.pnl, t.direction
        ] for t in first_elem.trades]

        self.assertCountEqual(generated_trades_data, expected_trades_data)

        # check first backtest summary element - returns
        all_dates_index = pd.bdate_range(start=self.test_start_date + BDay(2),
                                         end=self.test_end_date)
        expected_returns = SimpleReturnsSeries(
            index=all_dates_index,
            data=[
                0.0615530, 0.0579832, 0.0548048, 0.0519568, 0.0493902,
                0.0470653, 0.0449495, 0.0430157, 0.0412415, 0.0396078,
                0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,
                0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000
            ])
        assert_series_equal(expected_returns, first_elem.returns_tms)

        # check second backtest summary element
        second_elem = backtest_summary_elements[5]
        self.assertEqual(second_param_set, second_elem.model_parameters)

        expected_trades_data = [[
            self.apple_ticker,
            str_to_date("2015-01-02"),
            str_to_date("2015-01-09"), (1 - 210.0 / 160.0), -1.0
        ],
                                [
                                    self.apple_ticker,
                                    str_to_date("2015-01-16"),
                                    str_to_date("2015-01-23"),
                                    (310.0 / 260.0 - 1), 1.0
                                ],
                                [
                                    self.apple_ticker,
                                    str_to_date("2015-01-23"),
                                    str_to_date("2015-01-30"),
                                    (1 - 360.0 / 310.0), -1.0
                                ],
                                [
                                    self.ibm_ticker,
                                    str_to_date("2015-01-02"),
                                    str_to_date("2015-01-09"),
                                    (1 - 215.0 / 165.0), -1.0
                                ],
                                [
                                    self.ibm_ticker,
                                    str_to_date("2015-01-16"),
                                    str_to_date("2015-01-23"),
                                    (315.0 / 265.0 - 1), 1.0
                                ],
                                [
                                    self.ibm_ticker,
                                    str_to_date("2015-01-23"),
                                    str_to_date("2015-01-30"),
                                    (1 - 365.0 / 315.0), -1.0
                                ]]
        generated_trades_data = [[
            self.contract_ticker_mapper.contract_to_ticker(t.contract),
            t.start_time, t.end_time, t.pnl, t.direction
        ] for t in second_elem.trades]
        self.assertCountEqual(expected_trades_data, generated_trades_data)

        # check second backtest summary element - returns
        all_dates_index = pd.bdate_range(start=self.test_start_date + BDay(2),
                                         end=self.test_end_date)
        expected_returns = SimpleReturnsSeries(
            index=all_dates_index,
            data=[
                -0.0615530, -0.0579832, -0.0548048, -0.0519568, -0.0493902,
                0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,
                0.0380987, 0.0367003, 0.0354010, 0.0341905, 0.0330601,
                -0.0320020, -0.0310096, -0.0300769, -0.0291986, -0.0283702
            ])
        assert_series_equal(expected_returns, second_elem.returns_tms)
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]))
예제 #14
0
 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})