Example #1
0
    def test_validate_selection2a(self, mock_on_error):
        """
        test_validate_selection2a expects an error, as it attempts to place a lay bet with a £36 potential
        loss, which is more than the £10 max_selection_exposure
        """
        mock_market = mock.Mock()
        mock_market.blotter = Blotter(market_id="1.234")
        self.mock_flumine.markets.markets = {"1.234": mock_market}

        mock_strategy = mock.Mock()
        mock_strategy.max_order_exposure = 100
        mock_strategy.max_selection_exposure = 10

        mock_trade = mock.Mock()
        mock_trade.strategy = mock_strategy

        mock_order = mock.Mock(market_id="1.234", lookup=(1, 2, 3), side="LAY")
        mock_order.trade = mock_trade
        mock_order.order_type.ORDER_TYPE = OrderTypes.LIMIT
        mock_order.order_type.size = 9.0
        mock_order.order_type.price = 5.0

        self.trading_control._validate(mock_order, OrderPackageType.PLACE)
        mock_on_error.assert_called_with(
            mock_order,
            "Potential selection exposure (36.00) is greater than strategy.max_selection_exposure (10)",
        )
Example #2
0
 def test__process_simulated_orders(self):
     mock_market = mock.Mock(context={})
     mock_market.blotter = Blotter("1.23")
     mock_order = mock.Mock(size_remaining=0, complete=False)
     mock_order.order_type.ORDER_TYPE = OrderTypes.LIMIT
     mock_order.trade.status = TradeStatus.COMPLETE
     mock_order_two = mock.Mock(size_remaining=1, complete=False)
     mock_order_two.order_type.ORDER_TYPE = OrderTypes.LIMIT
     mock_order_two.trade.status = TradeStatus.COMPLETE
     mock_market.blotter._live_orders = [mock_order, mock_order_two]
     self.flumine._process_simulated_orders(mock_market)
     mock_order.execution_complete.assert_called()
     mock_order_two.execution_complete.assert_not_called()
 def test__process_backtest_orders(self, mock_process_current_order):
     mock_market = mock.Mock(context={})
     mock_market.blotter = Blotter("1.23")
     mock_order = mock.Mock()
     mock_order.trade.status = TradeStatus.COMPLETE
     mock_order_two = mock.Mock()
     mock_order_two.trade.status = TradeStatus.COMPLETE
     mock_market.blotter._live_orders = [mock_order, mock_order_two]
     self.flumine._process_backtest_orders(mock_market)
     mock_process_current_order.assert_has_calls([
         mock.call(mock_order),
         mock.call(mock_order_two),
     ])
     self.assertEqual(mock_market.blotter._live_orders, [])
Example #4
0
    def test_validate_selection2b(self, mock_on_error):
        """
        test_validate_selection2b expects no error.
        Unlike test_validate_selection2a, the blotter contains an existing order. The order that it attempts
        to validate hedges the existing order, and reduces the total exposure.
        """
        mock_market = mock.Mock()
        mock_market.blotter = Blotter(market_id="1.234")

        self.mock_flumine.markets.markets = {"1.234": mock_market}

        mock_strategy = mock.Mock()
        mock_strategy.max_order_exposure = 100
        mock_strategy.max_selection_exposure = 10

        mock_trade = mock.Mock()
        mock_trade.strategy = mock_strategy

        existing_matched_order = mock.Mock(market_id="1.234",
                                           lookup=(1, 2, 3),
                                           side="BACK")
        existing_matched_order.trade = mock_trade
        existing_matched_order.order_type.ORDER_TYPE = OrderTypes.LIMIT
        existing_matched_order.size_matched = 9.0
        existing_matched_order.average_price_matched = 6.0
        existing_matched_order.size_remaining = 0.0

        mock_order = mock.Mock(market_id="1.234", lookup=(1, 2, 3), side="LAY")
        mock_order.trade = mock_trade
        mock_order.order_type.ORDER_TYPE = OrderTypes.LIMIT
        mock_order.order_type.size = 9.0
        mock_order.order_type.price = 5.0

        mock_market.blotter["existing_order"] = existing_matched_order

        self.trading_control._validate(mock_order, OrderPackageType.PLACE)
        mock_on_error.assert_not_called()
Example #5
0
 def setUp(self) -> None:
     self.mock_market = mock.Mock()
     self.blotter = Blotter(self.mock_market, "1.23")
Example #6
0
class BlotterTest(unittest.TestCase):
    def setUp(self) -> None:
        self.mock_market = mock.Mock()
        self.blotter = Blotter(self.mock_market, "1.23")

    def test_init(self):
        self.assertEqual(self.blotter.market, self.mock_market)
        self.assertEqual(self.blotter.market_id, "1.23")
        self.assertEqual(self.blotter._orders, {})
        self.assertEqual(self.blotter.pending_place, [])
        self.assertEqual(self.blotter.pending_cancel, [])
        self.assertEqual(self.blotter.pending_update, [])
        self.assertEqual(self.blotter.pending_replace, [])
        self.assertEqual(self.blotter._live_orders, [])

    def test_strategy_orders(self):
        mock_order = mock.Mock()
        mock_order.trade.strategy = 69
        self.blotter._orders = {"12345": mock_order}
        self.assertEqual(self.blotter.strategy_orders(12), [])
        self.assertEqual(self.blotter.strategy_orders(69), [mock_order])

    @mock.patch("flumine.markets.blotter.Blotter._create_packages")
    def test_process_orders(self, mock__create_packages):
        mock_client = mock.Mock()
        self.blotter.pending_place = [1]
        self.assertEqual(self.blotter.process_orders(mock_client),
                         mock__create_packages().__radd__())
        self.blotter.pending_place = []
        self.blotter.pending_cancel = [2]
        self.assertEqual(self.blotter.process_orders(mock_client),
                         mock__create_packages().__radd__())
        self.blotter.pending_cancel = []
        self.blotter.pending_update = [3]
        self.assertEqual(self.blotter.process_orders(mock_client),
                         mock__create_packages().__radd__())
        self.blotter.pending_update = []
        self.blotter.pending_replace = [4]
        self.assertEqual(self.blotter.process_orders(mock_client),
                         mock__create_packages().__radd__())

    @mock.patch("flumine.markets.blotter.BetfairOrderPackage")
    def test___create_packages(self, mock_cls):
        mock_client = mock.Mock()
        mock_order = mock.Mock()
        mock_orders = [mock_order]
        packages = self.blotter._create_packages(mock_client, mock_orders,
                                                 OrderPackageType.PLACE)
        self.assertEqual(
            packages,
            [
                mock_cls(
                    client=None,
                    market_id=self.blotter.market_id,
                    orders=mock_orders,
                    package_type=OrderPackageType.PLACE,
                )
            ],
        )
        self.assertEqual(mock_orders, [])

    def test_live_orders(self):
        self.assertEqual(list(self.blotter.live_orders), [])
        mock_order = mock.Mock(complete=False)
        self.blotter._live_orders = [mock_order]
        self.assertEqual(list(self.blotter.live_orders), [mock_order])

    def test_has_live_orders(self):
        self.assertFalse(self.blotter.has_live_orders)
        self.blotter._live_orders = [mock.Mock()]
        self.assertTrue(self.blotter.has_live_orders)

    def test_process_closed_market(self):
        mock_market_book = mock.Mock()
        mock_runner = mock.Mock(selection_id=123, handicap=0.0)
        mock_market_book.runners = [mock_runner]
        mock_order = mock.Mock(selection_id=123, handicap=0.0)
        self.blotter._orders = {"12345": mock_order}
        self.blotter.process_closed_market(mock_market_book)
        self.assertEqual(mock_order.runner_status, mock_runner.status)

    def test_process_cleared_orders(self):
        mock_cleared_orders = mock.Mock()
        self.assertEqual(
            self.blotter.process_cleared_orders(mock_cleared_orders), [])

    def test_selection_exposure(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="BACK",
            average_price_matched=5.6,
            size_matched=2.0,
        )
        self.blotter._orders = {"12345": mock_order}
        self.assertEqual(
            self.blotter.selection_exposure(mock_strategy, mock_order.lookup),
            -2,
        )

    def test_selection_exposure_no_match(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="BACK",
            average_price_matched=5.6,
            size_matched=0.0,
        )
        self.blotter._orders = {"12345": mock_order}
        self.assertEqual(
            self.blotter.selection_exposure(mock_strategy, mock_order.lookup),
            0,
        )

    def test_complete_order(self):
        self.blotter._live_orders = ["test"]
        self.blotter.complete_order("test")

    def test__contains(self):
        self.blotter._orders = {"123": "test"}
        self.assertIn("123", self.blotter)
        self.assertNotIn("321", self.blotter)

    def test__setitem(self):
        self.blotter["123"] = "test"
        self.assertEqual(self.blotter._orders, {"123": "test"})
        self.assertEqual(self.blotter._live_orders, ["test"])

    def test__getitem(self):
        self.blotter._orders = {"12345": "test", "54321": "test2"}
        self.assertEqual(self.blotter["12345"], "test")
        self.assertEqual(self.blotter["54321"], "test2")

    def test__len(self):
        self.blotter._orders = {"12345": "test", "54321": "test"}
        self.assertEqual(len(self.blotter), 2)
Example #7
0
 def setUp(self) -> None:
     self.blotter = Blotter("1.23")
Example #8
0
class BlotterTest(unittest.TestCase):
    def setUp(self) -> None:
        self.blotter = Blotter("1.23")

    def test_init(self):
        self.assertEqual(self.blotter.market_id, "1.23")
        self.assertEqual(self.blotter._orders, {})
        self.assertEqual(self.blotter._live_orders, [])
        self.assertEqual(self.blotter._strategy_orders, {})
        self.assertEqual(self.blotter._strategy_selection_orders, {})

    def test_strategy_orders(self):
        mock_order = mock.Mock(lookup=(1, 2, 3))
        mock_order.trade.strategy = 69
        self.blotter["12345"] = mock_order
        self.assertEqual(self.blotter.strategy_orders(12), [])
        self.assertEqual(self.blotter.strategy_orders(69), [mock_order])

    def test_strategy_selection_orders(self):
        mock_order = mock.Mock(lookup=(1, 2, 3))
        mock_order.trade.strategy = 69
        self.blotter["12345"] = mock_order
        self.assertEqual(self.blotter.strategy_selection_orders(12, 2, 3), [])
        self.assertEqual(self.blotter.strategy_selection_orders(69, 2, 3), [mock_order])

    def test_live_orders(self):
        self.assertEqual(list(self.blotter.live_orders), [])
        mock_order = mock.Mock(complete=False)
        self.blotter._live_orders = [mock_order]
        self.assertEqual(list(self.blotter.live_orders), [mock_order])

    def test_has_live_orders(self):
        self.assertFalse(self.blotter.has_live_orders)
        self.blotter._live_orders = [mock.Mock()]
        self.assertTrue(self.blotter.has_live_orders)

    def test_process_closed_market(self):
        mock_market_book = mock.Mock()
        mock_runner = mock.Mock(selection_id=123, handicap=0.0)
        mock_market_book.runners = [mock_runner]
        mock_order = mock.Mock(selection_id=123, handicap=0.0)
        self.blotter._orders = {"12345": mock_order}
        self.blotter.process_closed_market(mock_market_book)
        self.assertEqual(mock_order.runner_status, mock_runner.status)

    def test_process_cleared_orders(self):
        mock_cleared_orders = mock.Mock()
        self.assertEqual(self.blotter.process_cleared_orders(mock_cleared_orders), [])

    def test_selection_exposure(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="BACK",
            average_price_matched=5.6,
            size_matched=2.0,
            size_remaining=0.0,
            order_type=LimitOrder(price=5.6, size=2.0),
        )
        self.blotter["12345"] = mock_order
        self.assertEqual(
            self.blotter.selection_exposure(mock_strategy, mock_order.lookup),
            2.0,
        )

    def test_selection_exposure_raises_value_error(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="BACK",
            average_price_matched=5.6,
            size_matched=2.0,
            size_remaining=0.0,
            order_type=mock.Mock(ORDER_TYPE="INVALID"),
        )
        self.blotter["12345"] = mock_order

        with self.assertRaises(ValueError) as e:
            self.blotter.selection_exposure(mock_strategy, mock_order.lookup)

        self.assertEqual("Unexpected order type: INVALID", e.exception.args[0])

    def test_selection_exposure_with_price_none(self):
        """
        Check that selection_exposure works if order.order_type.price is None.
        If order.order_type.price is None, the controls will flag the order as a violation
        and it won't be set to the exchange, so there won't be any exposure and we can ignore it.
        :return:
        """
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        lookup = (self.blotter.market_id, 123, 0)
        mock_order1 = mock.Mock(
            trade=mock_trade,
            lookup=lookup,
            side="BACK",
            average_price_matched=5.6,
            size_matched=2.0,
            size_remaining=0.0,
            order_type=LimitOrder(price=5.6, size=2.0),
        )
        mock_order2 = mock.Mock(
            trade=mock_trade,
            lookup=lookup,
            side="LAY",
            average_price_matched=5.6,
            size_matched=0.0,
            size_remaining=2.0,
            order_type=LimitOrder(price=None, size=2.0),
        )
        self.blotter["12345"] = mock_order1
        self.blotter["23456"] = mock_order2
        self.assertEqual(
            self.blotter.selection_exposure(mock_strategy, lookup),
            2.0,
        )

    def test_selection_exposure_no_match(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="BACK",
            average_price_matched=5.6,
            size_matched=0.0,
            size_remaining=0.0,
            order_type=LimitOrder(price=5.6, size=2.0),
        )
        self.blotter["12345"] = mock_order
        self.assertEqual(
            self.blotter.selection_exposure(mock_strategy, mock_order.lookup),
            0.0,
        )

    def test_selection_exposure_from_unmatched_back(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="BACK",
            average_price_matched=5.6,
            size_matched=2.0,
            size_remaining=2.0,
            order_type=LimitOrder(price=6, size=4.0),
        )
        self.blotter["12345"] = mock_order
        # On the win side, we have 2.0 * (5.6-1.0) = 9.2
        # On the lose side, we have -2.0-2.0=-4.0
        self.assertEqual(
            self.blotter.selection_exposure(mock_strategy, mock_order.lookup),
            4.0,
        )

    def test_selection_exposure_from_unmatched_lay(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="LAY",
            average_price_matched=5.6,
            size_matched=2.0,
            size_remaining=2.0,
            order_type=LimitOrder(price=6, size=4.0),
        )
        self.blotter["12345"] = mock_order
        # On the win side, we have -2.0 * (5.6-1.0) -2.0 * (6.0-1.0) = -19.2
        # On the lose side, we have 2.0 from size_matched
        self.assertEqual(
            self.blotter.selection_exposure(mock_strategy, mock_order.lookup),
            19.2,
        )

    def test_selection_exposure_from_market_on_close_back(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="BACK",
            order_type=MarketOnCloseOrder(liability=10.0),
        )
        self.blotter["12345"] = mock_order
        self.assertEqual(
            self.blotter.selection_exposure(mock_strategy, mock_order.lookup),
            10.0,
        )

    def test_selection_exposure_from_market_on_close_lay(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="LAY",
            order_type=MarketOnCloseOrder(liability=10.0),
        )
        self.blotter["12345"] = mock_order
        self.assertEqual(
            self.blotter.selection_exposure(mock_strategy, mock_order.lookup),
            10.0,
        )

    def test_selection_exposure_from_limit_on_close_lay(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="LAY",
            order_type=LimitOnCloseOrder(price=1.01, liability=10.0),
        )
        self.blotter["12345"] = mock_order
        self.assertEqual(
            self.blotter.selection_exposure(mock_strategy, mock_order.lookup),
            10.0,
        )

    def test_selection_exposure_voided(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="BACK",
            order_type=LimitOrder(price=5, size=10.0),
            status=OrderStatus.VIOLATION,
        )
        self.blotter["12345"] = mock_order
        self.assertEqual(
            self.blotter.selection_exposure(mock_strategy, mock_order.lookup),
            0,
        )

    def test_complete_order(self):
        self.blotter._live_orders = ["test"]
        self.blotter.complete_order("test")

    def test__contains(self):
        self.blotter._orders = {"123": "test"}
        self.assertIn("123", self.blotter)
        self.assertNotIn("321", self.blotter)

    def test__setitem(self):
        mock_order = mock.Mock(lookup=(1, 2, 3))
        self.blotter["123"] = mock_order
        self.assertEqual(self.blotter._orders, {"123": mock_order})
        self.assertEqual(self.blotter._live_orders, [mock_order])
        self.assertEqual(
            self.blotter._strategy_orders, {mock_order.trade.strategy: [mock_order]}
        )
        self.assertEqual(
            self.blotter._strategy_selection_orders,
            {(mock_order.trade.strategy, 2, 3): [mock_order]},
        )

    def test__getitem(self):
        self.blotter._orders = {"12345": "test", "54321": "test2"}
        self.assertEqual(self.blotter["12345"], "test")
        self.assertEqual(self.blotter["54321"], "test2")

    def test__len(self):
        self.blotter._orders = {"12345": "test", "54321": "test"}
        self.assertEqual(len(self.blotter), 2)
Example #9
0
 def setUp(self):
     self.market = mock.Mock()
     self.market.blotter = Blotter("market_id")
     self.mock_flumine = mock.Mock()
     self.mock_flumine.markets.markets = {"market_id": self.market}
     self.trading_control = StrategyExposure(self.mock_flumine)
Example #10
0
class BlotterTest(unittest.TestCase):
    def setUp(self) -> None:
        self.blotter = Blotter("1.23")

    def test_init(self):
        self.assertEqual(self.blotter.market_id, "1.23")
        self.assertEqual(self.blotter._orders, {})
        self.assertEqual(self.blotter._live_orders, [])
        self.assertEqual(self.blotter._trades, {})
        self.assertEqual(self.blotter._strategy_orders, {})
        self.assertEqual(self.blotter._strategy_selection_orders, {})

    def test_strategy_orders(self):
        mock_order = mock.Mock(lookup=(1, 2, 3))
        mock_order.trade.strategy = 69
        self.blotter["12345"] = mock_order
        self.assertEqual(self.blotter.strategy_orders(12), [])
        self.assertEqual(self.blotter.strategy_orders(69), [mock_order])

    def test_strategy_selection_orders(self):
        mock_order = mock.Mock(lookup=(1, 2, 3))
        mock_order.trade.strategy = 69
        self.blotter["12345"] = mock_order
        self.assertEqual(self.blotter.strategy_selection_orders(12, 2, 3), [])
        self.assertEqual(self.blotter.strategy_selection_orders(69, 2, 3),
                         [mock_order])

    def test_live_orders(self):
        self.assertEqual(list(self.blotter.live_orders), [])
        mock_order = mock.Mock(complete=False)
        self.blotter._live_orders = [mock_order]
        self.assertEqual(list(self.blotter.live_orders), [mock_order])

    def test_has_live_orders(self):
        self.assertFalse(self.blotter.has_live_orders)
        self.blotter._live_orders = [mock.Mock()]
        self.assertTrue(self.blotter.has_live_orders)

    def test_process_closed_market(self):
        mock_market_book = mock.Mock(number_of_winners=1)
        mock_runner = mock.Mock(selection_id=123, handicap=0.0)
        mock_market_book.runners = [mock_runner]
        mock_order = mock.Mock(selection_id=123, handicap=0.0)
        self.blotter._orders = {"12345": mock_order}
        self.blotter.process_closed_market(mock_market_book)
        self.assertEqual(mock_order.runner_status, mock_runner.status)

    def test_process_cleared_orders(self):
        mock_cleared_orders = mock.Mock()
        mock_cleared_orders.orders = []
        self.assertEqual(
            self.blotter.process_cleared_orders(mock_cleared_orders), [])

    def test_selection_exposure(self):
        """
        Check that selection_exposure returns the absolute worse loss
        """
        def get_exposures(strategy, lookup):
            if strategy == "strategy" and lookup == (1, 2, 3):
                return {
                    "worst_possible_profit_on_win": -1.0,
                    "worst_possible_profit_on_lose": -2.0,
                }

        self.blotter.get_exposures = mock.Mock(side_effect=get_exposures)

        result = self.blotter.selection_exposure("strategy", (1, 2, 3))

        self.assertEqual(2.0, result)

    def test_selection_exposure2(self):
        """
        Check that selection_exposure returns zero if there is no risk of loss.
        """
        def get_exposures(strategy, lookup):
            if strategy == "strategy" and lookup == (1, 2, 3):
                return {
                    "worst_possible_profit_on_win": 0.0,
                    "worst_possible_profit_on_lose": 1.0,
                }

        self.blotter.get_exposures = mock.Mock(side_effect=get_exposures)

        result = self.blotter.selection_exposure("strategy", (1, 2, 3))

        self.assertEqual(0.0, result)

    def test_get_exposures(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="BACK",
            average_price_matched=5.6,
            size_matched=2.0,
            size_remaining=0.0,
            order_type=LimitOrder(price=5.6, size=2.0),
        )
        self.blotter["12345"] = mock_order
        self.assertEqual(
            self.blotter.get_exposures(mock_strategy, mock_order.lookup),
            {
                "matched_profit_if_lose": -2.0,
                "matched_profit_if_win": 9.2,
                "worst_possible_profit_on_lose": -2.0,
                "worst_possible_profit_on_win": 9.2,
                "worst_potential_unmatched_profit_if_lose": 0.0,
                "worst_potential_unmatched_profit_if_win": 0.0,
            },
        )

    def test_get_exposures_with_exclusion(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="BACK",
            average_price_matched=5.6,
            size_matched=2.0,
            size_remaining=0.0,
            order_type=LimitOrder(price=5.6, size=2.0),
        )
        mock_order_excluded = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="BACK",
            average_price_matched=5.6,
            size_matched=2.0,
            size_remaining=0.0,
            order_type=LimitOrder(price=5.6, size=2.0),
        )
        self.blotter["12345"] = mock_order
        self.blotter["67890"] = mock_order_excluded
        self.assertEqual(
            self.blotter.get_exposures(mock_strategy,
                                       mock_order.lookup,
                                       exclusion=mock_order_excluded),
            {
                "matched_profit_if_lose": -2.0,
                "matched_profit_if_win": 9.2,
                "worst_possible_profit_on_lose": -2.0,
                "worst_possible_profit_on_win": 9.2,
                "worst_potential_unmatched_profit_if_lose": 0.0,
                "worst_potential_unmatched_profit_if_win": 0.0,
            },
        )

    def test_get_exposures_value_error(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="BACK",
            average_price_matched=5.6,
            size_matched=2.0,
            size_remaining=0.0,
            order_type=mock.Mock(ORDER_TYPE="INVALID"),
        )
        self.blotter["12345"] = mock_order

        with self.assertRaises(ValueError) as e:
            self.blotter.get_exposures(mock_strategy, mock_order.lookup)

        self.assertEqual("Unexpected order type: INVALID", e.exception.args[0])

    def test_get_exposures_with_price_none(self):
        """
        Check that get_exposures works if order.order_type.price is None.
        If order.order_type.price is None, the controls will flag the order as a violation
        and it won't be set to the exchange, so there won't be any exposure and we can ignore it.
        """
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        lookup = (self.blotter.market_id, 123, 0)
        mock_order1 = mock.Mock(
            trade=mock_trade,
            lookup=lookup,
            side="BACK",
            average_price_matched=5.6,
            size_matched=2.0,
            size_remaining=0.0,
            order_type=LimitOrder(price=5.6, size=2.0),
        )
        mock_order2 = mock.Mock(
            trade=mock_trade,
            lookup=lookup,
            side="LAY",
            average_price_matched=5.6,
            size_matched=0.0,
            size_remaining=2.0,
            order_type=LimitOrder(price=None, size=2.0),
        )
        self.blotter["12345"] = mock_order1
        self.blotter["23456"] = mock_order2
        self.assertEqual(
            self.blotter.get_exposures(mock_strategy, lookup),
            {
                "matched_profit_if_lose": -2.0,
                "matched_profit_if_win": 9.2,
                "worst_possible_profit_on_lose": -2.0,
                "worst_possible_profit_on_win": 9.2,
                "worst_potential_unmatched_profit_if_lose": 0.0,
                "worst_potential_unmatched_profit_if_win": 0.0,
            },
        )

    def test_get_exposures_no_match(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="BACK",
            average_price_matched=5.6,
            size_matched=0.0,
            size_remaining=0.0,
            order_type=LimitOrder(price=5.6, size=2.0),
        )
        self.blotter["12345"] = mock_order
        self.assertEqual(
            self.blotter.get_exposures(mock_strategy, mock_order.lookup),
            {
                "matched_profit_if_lose": 0.0,
                "matched_profit_if_win": 0.0,
                "worst_possible_profit_on_lose": 0.0,
                "worst_possible_profit_on_win": 0.0,
                "worst_potential_unmatched_profit_if_lose": 0.0,
                "worst_potential_unmatched_profit_if_win": 0.0,
            },
        )

    def test_get_exposures_from_unmatched_back(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="BACK",
            average_price_matched=5.6,
            size_matched=2.0,
            size_remaining=2.0,
            order_type=LimitOrder(price=6, size=4.0),
        )
        self.blotter["12345"] = mock_order
        # On the win side, we have 2.0 * (5.6-1.0) = 9.2
        # On the lose side, we have -2.0-2.0=-4.0
        self.assertEqual(
            self.blotter.get_exposures(mock_strategy, mock_order.lookup),
            {
                "matched_profit_if_lose": -2.0,
                "matched_profit_if_win": 9.2,
                "worst_possible_profit_on_lose": -4.0,
                "worst_possible_profit_on_win": 9.2,
                "worst_potential_unmatched_profit_if_lose": -2.0,
                "worst_potential_unmatched_profit_if_win": 0,
            },
        )

    def test_get_exposures_from_unmatched_lay(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="LAY",
            average_price_matched=5.6,
            size_matched=2.0,
            size_remaining=2.0,
            order_type=LimitOrder(price=6, size=4.0),
        )
        self.blotter["12345"] = mock_order
        # On the win side, we have -2.0 * (5.6-1.0) -2.0 * (6.0-1.0) = -19.2
        # On the lose side, we have 2.0 from size_matched
        self.assertEqual(
            self.blotter.get_exposures(mock_strategy, mock_order.lookup),
            {
                "matched_profit_if_lose": 2.0,
                "matched_profit_if_win": -9.2,
                "worst_possible_profit_on_lose": 2.0,
                "worst_possible_profit_on_win": -19.2,
                "worst_potential_unmatched_profit_if_lose": 0,
                "worst_potential_unmatched_profit_if_win": -10.0,
            },
        )

    def test_get_exposures_from_market_on_close_back(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="BACK",
            order_type=MarketOnCloseOrder(liability=10.0),
        )
        self.blotter["12345"] = mock_order
        self.assertEqual(
            self.blotter.get_exposures(mock_strategy, mock_order.lookup),
            {
                "matched_profit_if_lose": 0.0,
                "matched_profit_if_win": 0.0,
                "worst_possible_profit_on_lose": -10.0,
                "worst_possible_profit_on_win": 0.0,
                "worst_potential_unmatched_profit_if_lose": 0.0,
                "worst_potential_unmatched_profit_if_win": 0.0,
            },
        )

    def test_get_exposures_from_market_on_close_lay(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="LAY",
            order_type=MarketOnCloseOrder(liability=10.0),
        )
        self.blotter["12345"] = mock_order
        self.assertEqual(
            self.blotter.get_exposures(mock_strategy, mock_order.lookup),
            {
                "matched_profit_if_lose": 0.0,
                "matched_profit_if_win": 0.0,
                "worst_possible_profit_on_lose": 0.0,
                "worst_possible_profit_on_win": -10.0,
                "worst_potential_unmatched_profit_if_lose": 0.0,
                "worst_potential_unmatched_profit_if_win": 0.0,
            },
        )

    def test_get_exposures_from_limit_on_close_lay(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="LAY",
            order_type=LimitOnCloseOrder(price=1.01, liability=10.0),
        )
        self.blotter["12345"] = mock_order
        self.assertEqual(
            self.blotter.get_exposures(mock_strategy, mock_order.lookup),
            {
                "matched_profit_if_lose": 0.0,
                "matched_profit_if_win": 0.0,
                "worst_possible_profit_on_lose": 0.0,
                "worst_possible_profit_on_win": -10.0,
                "worst_potential_unmatched_profit_if_lose": 0.0,
                "worst_potential_unmatched_profit_if_win": 0.0,
            },
        )

    def test_get_exposures_voided(self):
        mock_strategy = mock.Mock()
        mock_trade = mock.Mock(strategy=mock_strategy)
        mock_order = mock.Mock(
            trade=mock_trade,
            lookup=(self.blotter.market_id, 123, 0),
            side="BACK",
            order_type=LimitOrder(price=5, size=10.0),
            status=OrderStatus.VIOLATION,
        )
        self.blotter["12345"] = mock_order
        self.assertEqual(
            self.blotter.get_exposures(mock_strategy, mock_order.lookup),
            {
                "matched_profit_if_lose": 0.0,
                "matched_profit_if_win": 0.0,
                "worst_possible_profit_on_lose": 0.0,
                "worst_possible_profit_on_win": 0.0,
                "worst_potential_unmatched_profit_if_lose": 0.0,
                "worst_potential_unmatched_profit_if_win": 0.0,
            },
        )

    def test_complete_order(self):
        self.blotter._live_orders = ["test"]
        self.blotter.complete_order("test")

    def test_has_trade(self):
        self.assertFalse(self.blotter.has_trade("123"))
        self.blotter._trades["123"].append(1)
        self.assertTrue(self.blotter.has_trade("123"))

    def test__contains(self):
        self.blotter._orders = {"123": "test"}
        self.assertIn("123", self.blotter)
        self.assertNotIn("321", self.blotter)

    def test__setitem(self):
        mock_order = mock.Mock(lookup=(1, 2, 3))
        self.blotter["123"] = mock_order
        self.assertEqual(self.blotter._orders, {"123": mock_order})
        self.assertEqual(self.blotter._live_orders, [mock_order])
        self.assertEqual(self.blotter._trades,
                         {mock_order.trade.id: [mock_order]})
        self.assertEqual(self.blotter._strategy_orders,
                         {mock_order.trade.strategy: [mock_order]})
        self.assertEqual(
            self.blotter._strategy_selection_orders,
            {(mock_order.trade.strategy, 2, 3): [mock_order]},
        )

    def test__getitem(self):
        self.blotter._orders = {"12345": "test", "54321": "test2"}
        self.assertEqual(self.blotter["12345"], "test")
        self.assertEqual(self.blotter["54321"], "test2")

    def test__len(self):
        self.blotter._orders = {"12345": "test", "54321": "test"}
        self.assertEqual(len(self.blotter), 2)