コード例 #1
0
def main():
    this_dir_path = os.path.dirname(os.path.abspath(__file__))
    trades, nr_of_assets_traded, start_date, end_date = cached_value(
        get_data, os.path.join(this_dir_path, 'trade_analysis.cache'))

    settings = container.resolve(Settings)  # type: Settings
    pdf_exporter = container.resolve(PDFExporter)  # type: PDFExporter
    contract_ticker_mapper = SimulatedBloombergContractTickerMapper()

    initial_risk = 0.05

    nr_of_assets_traded = len(
        set(
            contract_ticker_mapper.contract_to_ticker(t.contract, False)
            for t in trades))

    trade_analysis_sheet = TradeAnalysisSheet(settings,
                                              pdf_exporter,
                                              nr_of_assets_traded,
                                              trades,
                                              start_date,
                                              end_date,
                                              initial_risk,
                                              title="Sample trade analysis")
    trade_analysis_sheet.build_document()
    trade_analysis_sheet.save()

    print("Finished")
コード例 #2
0
    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
        })
コード例 #3
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)
コード例 #4
0
 def setUpClass(cls) -> None:
     """ Setup a preset data provider and a scenario, in which the sized orders will exceed the volume limits. """
     MarketCloseEvent.set_trigger_time({
         "hour": 20,
         "minute": 0,
         "second": 0,
         "microsecond": 0
     })
     cls.ticker = BloombergTicker("Example Index")
     cls.contract_ticker_mapper = SimulatedBloombergContractTickerMapper()
コード例 #5
0
    def setUpClass(cls) -> None:
        cls.end_date = str_to_date('2015-10-08')
        cls.start_date = cls.end_date - RelativeDelta(years=2)

        cls.timer = SettableTimer(cls.end_date)

        cls.frequency = Frequency.DAILY
        cls.TICKER_1 = BloombergFutureTicker("Cotton", "CT{} Comdty", 1, 3)
        cls.TICKER_2 = BloombergFutureTicker("Corn", 'C {} Comdty', 1, 5)

        cls.contract_ticker_mapper = SimulatedBloombergContractTickerMapper()
コード例 #6
0
    def setUp(self):
        msft_ticker = BloombergTicker("MSFT US Equity")
        aapl_ticker = BloombergTicker("AAPL US Equity")
        googl_ticker = BloombergTicker("GOOGL US Equity")

        self.tickers = [msft_ticker, aapl_ticker, googl_ticker]
        self.data_provider = self._create_data_provider_mock()

        self.contract_ticker_mapper = SimulatedBloombergContractTickerMapper()

        self.orders = [
            Order(
                contract=self.contract_ticker_mapper.ticker_to_contract(msft_ticker),
                quantity=1250,
                execution_style=MarketOrder(),
                time_in_force=TimeInForce.GTC
            ),
            Order(
                contract=self.contract_ticker_mapper.ticker_to_contract(aapl_ticker),
                quantity=-200,
                execution_style=MarketOrder(),
                time_in_force=TimeInForce.GTC
            ),
            Order(
                contract=self.contract_ticker_mapper.ticker_to_contract(googl_ticker),
                quantity=1,
                execution_style=MarketOrder(),
                time_in_force=TimeInForce.GTC
            )
        ]

        self.market_on_close_order = [Order(
                contract=self.contract_ticker_mapper.ticker_to_contract(msft_ticker),
                quantity=1250,
                execution_style=MarketOnCloseOrder(),
                time_in_force=TimeInForce.GTC
            )]
コード例 #7
0
 def setUpClass(cls) -> None:
     cls.contract_ticker_mapper = SimulatedBloombergContractTickerMapper()
     cls.example_ticker = BloombergTicker("Example Index")
     cls.example_ticker_2 = BloombergTicker("Example2 Index")
     cls.orders = [
         Order(contract=cls.contract_ticker_mapper.ticker_to_contract(
             cls.example_ticker),
               quantity=1000,
               execution_style=MarketOrder(),
               time_in_force=TimeInForce.GTC),
         Order(contract=cls.contract_ticker_mapper.ticker_to_contract(
             cls.example_ticker_2),
               quantity=1000,
               execution_style=MarketOrder(),
               time_in_force=TimeInForce.GTC),
     ]
     cls.backtest_date = str_to_date("2020-01-01")
コード例 #8
0
ファイル: test_order_factory.py プロジェクト: espiney/qf-lib
    def setUpClass(cls):
        cls.contract = Contract('AAPL US Equity', 'STK', 'NASDAQ')
        cls.ticker = BloombergTicker('AAPL US Equity')
        cls.current_portfolio_value = 1000.0
        cls.share_price = 10.0

        position = Mock(spec=Position)
        position.quantity.return_value = 10
        position.contract.return_value = cls.contract

        broker = Mock(spec=Broker)
        broker.get_portfolio_value.return_value = cls.current_portfolio_value
        broker.get_positions.return_value = [position]

        data_handler = Mock(spec=DataHandler)
        data_handler.get_last_available_price.return_value = QFSeries([cls.share_price], index=[cls.ticker])

        cls.order_factory = OrderFactory(broker, data_handler, SimulatedBloombergContractTickerMapper())
コード例 #9
0
    def setUp(self) -> None:
        self.ticker = BloombergTicker("Example Ticker")
        self.future_ticker = MagicMock(spec=BloombergFutureTicker)
        self.future_ticker.configure_mock(name="Example", family_id="Example{} Comdty", days_before_exp_date=1,
                                          point_value=1)

        self.alpha_model = MagicMock()

        # Mock trading session
        self.ts = MagicMock()
        self.ts.contract_ticker_mapper = SimulatedBloombergContractTickerMapper()
        self.ts.timer = SettableTimer(str_to_date("2000-01-04 08:00:00.0", DateFormat.FULL_ISO))

        self.positions_in_portfolio = []  # type: List[Contract]
        """Contracts for which a position in the portfolio currently exists. This list is used to return backtest
        positions list by the broker."""

        self.ts.broker.get_positions.side_effect = lambda: self.positions_in_portfolio
コード例 #10
0
    def setUp(self) -> None:
        position = BrokerPosition(self.contract, self.initial_position, 25)

        self.timer = Mock(spec=Timer)
        self.timer.now.return_value = str_to_date("2017-01-01")

        self.broker = Mock(spec=Broker)
        self.broker.get_open_orders.return_value = []
        self.broker.get_positions.return_value = [position]

        data_handler = Mock(spec=DataHandler, timer=self.timer)
        data_handler.get_last_available_price.side_effect = lambda _: self.last_price

        order_factory = self._mock_order_factory(self.initial_position,
                                                 self.initial_allocation)
        contract_ticker_mapper = SimulatedBloombergContractTickerMapper()

        self.simple_position_sizer = SimplePositionSizer(
            self.broker, data_handler, order_factory, contract_ticker_mapper,
            BacktestSignalsRegister())
        self.initial_risk_position_sizer = InitialRiskPositionSizer(
            self.broker, data_handler, order_factory, contract_ticker_mapper,
            BacktestSignalsRegister(), self.initial_risk,
            self.max_target_percentage)
コード例 #11
0
    def setUp(self) -> None:
        self.contract_ticker_mapper = SimulatedBloombergContractTickerMapper()
        self.current_date = str_to_date("2017-01-01")

        self.timer = SettableTimer(self.current_date)
コード例 #12
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
コード例 #13
0
class TestSlippage(TestCase):
    def setUp(self):
        msft_ticker = BloombergTicker("MSFT US Equity")
        aapl_ticker = BloombergTicker("AAPL US Equity")
        googl_ticker = BloombergTicker("GOOGL US Equity")

        self.tickers = [msft_ticker, aapl_ticker, googl_ticker]
        self.data_provider = self._create_data_provider_mock()

        self.contract_ticker_mapper = SimulatedBloombergContractTickerMapper()

        self.orders = [
            Order(
                contract=self.contract_ticker_mapper.ticker_to_contract(msft_ticker),
                quantity=1250,
                execution_style=MarketOrder(),
                time_in_force=TimeInForce.GTC
            ),
            Order(
                contract=self.contract_ticker_mapper.ticker_to_contract(aapl_ticker),
                quantity=-200,
                execution_style=MarketOrder(),
                time_in_force=TimeInForce.GTC
            ),
            Order(
                contract=self.contract_ticker_mapper.ticker_to_contract(googl_ticker),
                quantity=1,
                execution_style=MarketOrder(),
                time_in_force=TimeInForce.GTC
            )
        ]

        self.market_on_close_order = [Order(
                contract=self.contract_ticker_mapper.ticker_to_contract(msft_ticker),
                quantity=1250,
                execution_style=MarketOnCloseOrder(),
                time_in_force=TimeInForce.GTC
            )]

    def _create_data_provider_mock(self):
        def get_price(tickers, fields, start_date, end_date, _):
            prices_bar = [5.0, 10.0, 1.0, 4.0, 50]  # Open, High, Low, Close, Volume

            dates_index = pd.date_range(start_date, end_date, freq='B')
            tickers, got_single_ticker = convert_to_list(tickers, Ticker)
            fields, got_single_field = convert_to_list(fields, PriceField)
            got_single_date = len(dates_index) == 1

            prices_df = pd.DataFrame(
                index=pd.Index(dates_index, name=TICKERS),
                columns=pd.Index(PriceField.ohlcv(), name=FIELDS),
                data=[prices_bar] * len(dates_index)
            )
            data_array = tickers_dict_to_data_array({
                ticker: prices_df for ticker in self.tickers
            }, self.tickers, PriceField.ohlcv())

            return normalize_data_array(data_array.loc[start_date:end_date, tickers, fields], tickers, fields,
                                        got_single_date, got_single_ticker, got_single_field)

        data_provider = MagicMock()
        data_provider.get_price.side_effect = get_price

        return data_provider

    def test_price_based_slippage__no_volume_limits(self):
        """Volume should remain the same. Prices should be increased by the slippage rate."""
        slippage_rate = 0.1
        slippage_model = PriceBasedSlippage(slippage_rate, self.data_provider, self.contract_ticker_mapper)

        prices_without_slippage = [20.0, 30.0, 40.0]
        # Each price should be changed by +0.1 / -0.1 depending on whether it is a BUY or SELL
        expected_fill_prices = [22.0, 27.0, 44.0]

        # Volumes should remain equal to the initial quantities
        expected_fill_volumes = [order.quantity for order in self.orders]  # [1250, -200, 1]

        actual_fill_prices, actual_fill_volumes = slippage_model.process_orders(str_to_date("2020-01-01"),
                                                                                self.orders,
                                                                                prices_without_slippage)

        assert_lists_equal(expected_fill_prices, actual_fill_prices)
        assert_lists_equal(expected_fill_volumes, actual_fill_volumes)

    def test_price_based_slippage__with_volume(self):
        """Volume should be changed in case of exceeding limits. Slippage rate is set to 0.0, so the prices should
        remain unchanged."""
        slippage_rate = 0.0
        max_volume_share_limit = 0.1
        slippage_model = PriceBasedSlippage(slippage_rate, self.data_provider, self.contract_ticker_mapper,
                                            max_volume_share_limit)

        prices_without_slippage = [20.0, 30.0, 40.0]
        expected_fill_prices = prices_without_slippage

        # Mean historical volume is set to 50.0 for each of the tickers. As the max_volume_share_limit = 0.1, the limit
        # is set to +/-5.0
        expected_fill_volumes = [5.0, -5.0, 1]

        actual_fill_prices, actual_fill_volumes = slippage_model.process_orders(str_to_date("2020-01-01"),
                                                                                self.orders,
                                                                                prices_without_slippage)

        assert_lists_equal(expected_fill_prices, actual_fill_prices)
        assert_lists_equal(expected_fill_volumes, actual_fill_volumes)

    def test_price_based_slippage__nan_prices(self):
        slippage_rate = 0.1
        slippage_model = PriceBasedSlippage(slippage_rate, self.data_provider, self.contract_ticker_mapper)

        prices_without_slippage = [float('nan'), np.nan, float('nan')]
        expected_fill_prices = [float('nan'), float('nan'), float('nan')]

        actual_fill_prices, actual_fill_volumes = slippage_model.process_orders(str_to_date("2020-01-01"),
                                                                                self.orders,
                                                                                prices_without_slippage)
        assert_lists_equal(expected_fill_prices, actual_fill_prices)

    def test_fixed_slippage__no_volume(self):
        """Volume should remain unchanged. Prices should be increased by the slippage rate."""
        slippage_per_share = 0.05
        slippage_model = FixedSlippage(slippage_per_share=slippage_per_share, data_provider=self.data_provider,
                                       contract_ticker_mapper=self.contract_ticker_mapper)

        prices_without_slippage = [20.0, 30.0, 40.0]
        # [BUY, SELL, BUY] => [+, -, +]
        expected_fill_prices = [20.0 + slippage_per_share, 30.0 - slippage_per_share, 40.0 + slippage_per_share]

        # Volumes should remain equal to the initial quantities
        expected_fill_volumes = [order.quantity for order in self.orders]  # [1250, -200, 1]

        actual_fill_prices, actual_fill_volumes = slippage_model.process_orders(str_to_date("2020-01-01"),
                                                                                self.orders,
                                                                                prices_without_slippage)

        assert_lists_equal(expected_fill_prices, actual_fill_prices)
        assert_lists_equal(expected_fill_volumes, actual_fill_volumes)

    def test_fixed_slippage__with_volume(self):
        """Prices should remain unchanged."""
        slippage_per_share = 0.0
        max_volume_share_limit = 0.1
        slippage_model = FixedSlippage(slippage_per_share=slippage_per_share, data_provider=self.data_provider,
                                       contract_ticker_mapper=self.contract_ticker_mapper,
                                       max_volume_share_limit=max_volume_share_limit)

        prices_without_slippage = [20.0, 30.0, 40.0]
        expected_fill_prices = prices_without_slippage

        # Mean historical volume is set to 50.0 for each of the tickers.
        expected_fill_volumes = [5.0, -5.0, 1]

        actual_fill_prices, actual_fill_volumes = slippage_model.process_orders(str_to_date("2020-01-01"),
                                                                                self.orders,
                                                                                prices_without_slippage)

        assert_lists_equal(expected_fill_prices, actual_fill_prices)
        assert_lists_equal(expected_fill_volumes, actual_fill_volumes)

    def test_fixed_slippage__nan_prices(self):
        slippage_per_share = 0.1
        slippage_model = FixedSlippage(slippage_per_share, self.data_provider, self.contract_ticker_mapper)

        prices_without_slippage = [float('nan'), np.nan, float('nan')]
        expected_fill_prices = [float('nan'), float('nan'), float('nan')]

        actual_fill_prices, actual_fill_volumes = slippage_model.process_orders(str_to_date("2020-01-01"),
                                                                                self.orders,
                                                                                prices_without_slippage)
        assert_lists_equal(expected_fill_prices, actual_fill_prices)

    def test_square_root_market_slippage__no_volume(self):
        """The volatility used by the slippage model is mocked to be equal to 0.1. The volume is equal to 50.0"""
        price_impact = 0.1
        close_prices_volatility = 0.1
        prices_without_slippage = [20.0, 30.0, 40.0]

        slippage_model = SquareRootMarketImpactSlippage(price_impact=price_impact,
                                                        data_provider=self.data_provider,
                                                        contract_ticker_mapper=self.contract_ticker_mapper)

        slippage_model._compute_volatility = Mock()
        slippage_model._compute_volatility.return_value = close_prices_volatility

        actual_fill_prices, actual_fill_volumes = slippage_model.process_orders(str_to_date('2020-01-01'),
                                                                                self.orders,
                                                                                prices_without_slippage)

        expected_fill_prices = [20.0 + 20.0 * price_impact * close_prices_volatility * math.sqrt(1250 / 50.0),
                                30.0 - 30.0 * price_impact * close_prices_volatility * math.sqrt(200 / 50.0),
                                40.0 + 40.0 * price_impact * close_prices_volatility * math.sqrt(1 / 50.0)]

        # Volumes should remain equal to the initial quantities
        expected_fill_volumes = [order.quantity for order in self.orders]  # [1250, -200, 1]

        assert_lists_equal(expected_fill_prices, actual_fill_prices)
        assert_lists_equal(expected_fill_volumes, actual_fill_volumes)

    def test_square_root_market_slippage__no_volume_no_volatility(self):
        """As all the mocked close prices are equal, the volatility should be equal to 0.0. Thus, the prices do not
        change after applying slippage."""
        price_impact = 0.1
        prices_without_slippage = [20.0, 30.0, 40.0]

        slippage_model = SquareRootMarketImpactSlippage(price_impact=price_impact,
                                                        data_provider=self.data_provider,
                                                        contract_ticker_mapper=self.contract_ticker_mapper)

        actual_fill_prices, actual_fill_volumes = slippage_model.process_orders(str_to_date('2020-01-01'),
                                                                                self.orders,
                                                                                prices_without_slippage)

        expected_fill_prices = prices_without_slippage

        # Volumes should remain equal to the initial quantities
        expected_fill_volumes = [order.quantity for order in self.orders]  # [1250, -200, 1]

        assert_lists_equal(expected_fill_prices, actual_fill_prices)
        assert_lists_equal(expected_fill_volumes, actual_fill_volumes)

    def test_square_root_market_slippage__with_volume(self):
        """The volatility used by the slippage model is mocked to be equal to 0.1. The volume is equal to 50.0"""
        price_impact = 0.1
        max_volume_share_limit = 0.1
        close_prices_volatility = 0.1
        prices_without_slippage = [20.0, 30.0, 40.0]

        slippage_model = SquareRootMarketImpactSlippage(price_impact=price_impact,
                                                        data_provider=self.data_provider,
                                                        contract_ticker_mapper=self.contract_ticker_mapper,
                                                        max_volume_share_limit=max_volume_share_limit)
        slippage_model._compute_volatility = Mock()
        slippage_model._compute_volatility.return_value = close_prices_volatility

        actual_fill_prices, actual_fill_volumes = slippage_model.process_orders(str_to_date('2020-01-01'),
                                                                                self.orders,
                                                                                prices_without_slippage)

        expected_fill_prices = [20.0 + 20.0 * price_impact * close_prices_volatility * math.sqrt(5.0 / 50.0),
                                30.0 - 30.0 * price_impact * close_prices_volatility * math.sqrt(5.0 / 50.0),
                                40.0 + 40.0 * price_impact * close_prices_volatility * math.sqrt(1 / 50.0)]

        expected_fill_volumes = [5.0, -5.0, 1.0]

        assert_lists_equal(expected_fill_prices, actual_fill_prices)
        assert_lists_equal(expected_fill_volumes, actual_fill_volumes)

    def test_square_root_market_slippage__nan_volatility(self):
        price_impact = 0.1
        close_prices_volatility = float('nan')

        prices_without_slippage = [float('nan'), np.nan, 40]
        expected_fill_prices = [float('nan'), float('nan'), float('nan')]

        slippage_model = SquareRootMarketImpactSlippage(price_impact=price_impact,
                                                        data_provider=self.data_provider,
                                                        contract_ticker_mapper=self.contract_ticker_mapper)

        slippage_model._compute_volatility = Mock()
        slippage_model._compute_volatility.return_value = close_prices_volatility

        actual_fill_prices, actual_fill_volumes = slippage_model.process_orders(str_to_date("2020-01-01"),
                                                                                self.orders,
                                                                                prices_without_slippage)
        assert_lists_equal(expected_fill_prices, actual_fill_prices)

    def test_square_root_market_slippage__nan_prices_without_slippage(self):
        price_impact = 0.1
        slippage_model = SquareRootMarketImpactSlippage(price_impact=price_impact,
                                                        data_provider=self.data_provider,
                                                        contract_ticker_mapper=self.contract_ticker_mapper)

        prices_without_slippage = [float('nan'), np.nan, float('nan')]
        expected_fill_prices = [float('nan'), float('nan'), float('nan')]

        actual_fill_prices, actual_fill_volumes = slippage_model.process_orders(str_to_date("2020-01-01"),
                                                                                self.orders,
                                                                                prices_without_slippage)
        assert_lists_equal(expected_fill_prices, actual_fill_prices)

    def test_square_root_market_slippage__nan_average_daily_volume(self):
        price_impact = 0.1
        avg_daily_volume = float('nan')

        prices_without_slippage = [20, 30, 40]
        expected_fill_prices = [float('nan'), float('nan'), float('nan')]

        slippage_model = SquareRootMarketImpactSlippage(price_impact=price_impact,
                                                        data_provider=self.data_provider,
                                                        contract_ticker_mapper=self.contract_ticker_mapper)
        slippage_model._compute_average_volume = Mock()
        slippage_model._compute_average_volume.return_value = avg_daily_volume
        actual_fill_prices, actual_fill_volumes = slippage_model.process_orders(str_to_date("2020-01-01"),
                                                                                self.orders,
                                                                                prices_without_slippage)
        assert_lists_equal(expected_fill_prices, actual_fill_prices)
コード例 #14
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_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
        ])