class SupervisorOrdersTests(unittest.TestCase):
    def setUp(self) -> None:
        self.exchange_mock = Mock()
        self.exchange_mock.get_open_orders_ws.return_value = []
        self.supervisor = Supervisor(interface=self.exchange_mock)

    def tearDown(self) -> None:
        self.supervisor.exit_cycle()

    def test_add_order(self):
        new_order = Order(order_type='Limit', qty=228, price=1000, side='Buy')
        self.supervisor.add_order(new_order)

        self.assertIn(new_order, self.supervisor.orders)

    def test_add_empty_order(self):
        with self.assertRaises(ValueError):
            self.supervisor.add_order(Order())

    def test_remove_order(self):
        new_order = Order(order_type='Limit', qty=228, price=1000, side='Buy')
        self.supervisor.add_order(new_order)

        self.supervisor.remove_order(new_order)
        self.assertNotIn(new_order, self.supervisor.orders)
class SyncPositionTests(unittest.TestCase):
    def setUp(self) -> None:
        self.exchange_mock = Mock()
        self.exchange_mock.get_open_orders_ws.return_value = []
        self.supervisor = Supervisor(interface=self.exchange_mock)

    def tearDown(self) -> None:
        self.supervisor.exit_cycle()

    def test_enter_long_position(self):
        self.exchange_mock.get_position_size_ws.return_value = 0
        self.supervisor.correct_position_size = Mock()

        self.supervisor.position_size = 100
        self.supervisor.sync_position()

        self.supervisor.correct_position_size.assert_called_once_with(qty=100)

    def test_correct_position_size(self):
        self.supervisor.position_size = 20
        self.exchange_mock.get_position_size_ws.return_value = 0
        self.supervisor.correct_position_size(20)

        self.assertEqual(20, self.supervisor.position_size)
        self.exchange_mock.place_market_order.assert_called_once_with(qty=20)
class SupervisorCycleTests(unittest.TestCase):

    def setUp(self) -> None:
        self.exchange_mock = Mock()
        self.exchange_mock.get_open_orders_ws.return_value = []
        self.exchange_mock.get_position_size_ws.return_value = 0
        self.supervisor = Supervisor(interface=self.exchange_mock)

    def tearDown(self) -> None:
        self.supervisor.exit_cycle()

    def test_run_cycle(self):
        self.supervisor.run_cycle()
        self.assertTrue(self.supervisor._run_thread.is_set())
        self.assertFalse(self.supervisor._exit_sync_thread.is_set())
        self.assertFalse(self.supervisor._stopped.is_set())
        self.assertTrue(self.supervisor.sync_thread.is_alive())

    def test_exit_cycle(self):
        self.supervisor.run_cycle()
        self.assertTrue(self.supervisor.sync_thread.is_alive())

        self.supervisor.exit_cycle()
        self.assertFalse(self.supervisor.sync_thread.is_alive())

    def test_stop_cycle(self):
        self.supervisor.run_cycle()
        self.supervisor.stop_cycle()

        self.assertTrue(self.supervisor._stopped.is_set())
        self.assertFalse(self.supervisor._run_thread.is_set())

    def test_continue_cycle(self):
        self.supervisor.run_cycle()
        self.supervisor.stop_cycle()
        self.supervisor.run_cycle()

        # assert that events conditions are the same as in just-created supervisor
        self.assertTrue(self.supervisor._run_thread.is_set())
        self.assertFalse(self.supervisor._exit_sync_thread.is_set())
        self.assertFalse(self.supervisor._stopped.is_set())
        # cycle should also be alive of course :)
        self.assertTrue(self.supervisor.sync_thread.is_alive())

    def test_exit_from_exited_cycle(self):
        self.supervisor.run_cycle()
        self.supervisor.exit_cycle()
        self.assertFalse(self.supervisor.sync_thread.is_alive())

        self.supervisor.exit_cycle()  # must not raise anything
        self.assertFalse(self.supervisor.sync_thread.is_alive())

    def test_reset(self):
        self.supervisor.run_cycle()
        self.supervisor.reset()

        self.assertEqual(0, self.supervisor.position_size)
        self.assertListEqual([], self.supervisor._orders)
class SyncOrdersTests(unittest.TestCase):
    """All methods that associated with placing and cancelling orders in cycle."""
    def setUp(self) -> None:
        self.exchange_mock = Mock()
        self.exchange_mock.get_open_orders_ws.return_value = []
        self.exchange_mock.get_position_size_ws.return_value = 0
        self.supervisor = Supervisor(interface=self.exchange_mock)

    def tearDown(self) -> None:
        self.supervisor.exit_cycle()

    def test_cancel_needless_order(self):
        order1 = Order()
        self.exchange_mock.get_open_orders_ws.return_value = [order1]
        expected_orders = [order1]
        self.supervisor.cancel_needless_orders()

        # assert that Supervisor try to cancel needless order
        self.exchange_mock.bulk_cancel_orders.assert_called_once_with(
            expected_orders)

    def test_move_changed_order(self):
        """Test that Supervisor will amend order, not cancel it."""

        order1 = Order(order_type='Limit', qty=228, price=1000, side='Buy')
        order1_copy = Order(order_type='Limit',
                            qty=228,
                            price=1000,
                            side='Buy')
        self.supervisor.add_order(order1)

        self.exchange_mock.get_open_orders_ws.return_value = [order1_copy]
        order1.move(to=1001)

        self.supervisor.cancel_needless_orders()

        self.exchange_mock.bulk_cancel_orders.assert_not_called()
        self.exchange_mock.move_order.assert_called_once_with(order=order1)

    def test_cancel_several_needless_orders(self):
        order1 = Order()
        order2 = Order()
        order3 = Order()
        self.exchange_mock.get_open_orders_ws.return_value = [
            order1, order2, order3
        ]
        expected_orders = [order1, order2, order3]
        self.supervisor.cancel_needless_orders()

        # assert that Supervisor try to cancel needless order
        self.exchange_mock.bulk_cancel_orders.assert_called_once_with(
            expected_orders)

    def test_cancel_duplicates(self):
        order1 = Order(order_type='Limit', qty=228, price=1000, side='Buy')
        order2 = Order(order_type='Limit', qty=229, price=1001, side='Buy')
        self.exchange_mock.get_open_orders_ws.return_value = [
            order1, order2, order2
        ]
        self.supervisor.add_order(order1)
        self.supervisor.add_order(order2)
        expected_orders = [order2]
        self.supervisor.cancel_needless_orders()

        # assert that Supervisor try to cancel needless order
        self.exchange_mock.bulk_cancel_orders.assert_called_once_with(
            expected_orders)

    def test_cancel_two_same_needed_orders(self):
        order1 = Order(order_type='Limit', qty=228, price=1000, side='Buy')
        order2 = Order(order_type='Limit', qty=228, price=1000, side='Buy')
        order3 = Order(order_type='Limit', qty=229, price=1001, side='Buy')
        self.exchange_mock.get_open_orders_ws.return_value = [order1, order2]
        self.supervisor.add_order(order1)
        self.supervisor.add_order(order2)
        self.supervisor.add_order(order3)
        self.supervisor.cancel_needless_orders()
        self.exchange_mock.bulk_cancel_orders.assert_not_called()

    def test_check_unplaced_order(self):
        order = Order(order_type='Limit', qty=228, price=1000, side='Buy')
        self.supervisor.add_order(order)
        self.supervisor.check_needed_orders()

        self.exchange_mock.place_order.assert_called_once_with(order)

    def test_check_several_unplaced_orders(self):
        order1 = Order(order_type='Limit', qty=228, price=1001, side='Buy')
        order2 = Order(order_type='Limit', qty=229, price=1002, side='Buy')
        order3 = Order(order_type='Limit', qty=2210, price=1003, side='Buy')
        self.supervisor.add_order(order1)
        self.supervisor.add_order(order2)
        self.supervisor.add_order(order3)
        self.supervisor.check_needed_orders()

        self.exchange_mock.bulk_place_orders.assert_called_once_with(
            [order1, order2, order3])

    def test_check_rejected_order(self):
        def order_status_mock(_order):
            if _order == order:
                return 'Rejected'

        on_reject_mock = Mock()

        self.exchange_mock.get_order_status_ws.side_effect = order_status_mock

        order = Order(order_type='Limit', qty=228, price=1000, side='Buy')
        order.order_id = '1234'
        order._on_reject = on_reject_mock
        self.supervisor.add_order(order)
        self.supervisor.check_needed_orders()

        # assert that we didn`t place this order
        self.exchange_mock.place_order.not_called(order)
        # assert that Supervisor forget this order
        self.assertNotIn(order, self.supervisor.orders)
        # assert that Supervisor call matching callback
        on_reject_mock.assert_called_once()

    def test_check_filled_order(self):
        def order_status_mock(_order):
            if _order == order:
                return 'Filled'

        on_filled_mock = Mock()

        self.exchange_mock.get_order_status_ws.side_effect = order_status_mock

        order = Order(order_type='Limit', qty=228, price=1000, side='Buy')
        order.order_id = '1234'
        order._on_fill = on_filled_mock
        self.supervisor.add_order(order)
        self.supervisor.check_needed_orders()

        # assert that we didn`t place this order
        self.exchange_mock.place_order.not_called(order)
        # assert that Supervisor forget this order
        self.assertNotIn(order, self.supervisor.orders)
        # assert that Supervisor call matching callback
        on_filled_mock.assert_called_once()

    def test_check_filled_stop_order(self):
        def order_status_mock(_order):
            if _order == order:
                return 'Triggered'

        on_filled_mock = Mock()

        self.exchange_mock.get_order_status_ws.side_effect = order_status_mock

        order = Order(order_type='Stop', qty=228, stop_px=1000, side='Buy')
        order.order_id = '1234'
        order._on_fill = on_filled_mock
        self.supervisor.add_order(order)
        self.supervisor.check_needed_orders()

        # assert that we didn`t place this order
        self.exchange_mock.place_order.not_called(order)
        # assert that Supervisor forget this order
        self.assertNotIn(order, self.supervisor.orders)
        # assert that Supervisor call matching callback
        on_filled_mock.assert_called_once()

    def test_validation_error_while_placing_order(self):
        validation_error = requests.HTTPError()
        validation_error.response = Mock()
        validation_error.response.text = 'Order price is above the liquidation price of current'
        self.exchange_mock.place_order.side_effect = validation_error

        order = Order(order_type='Limit', qty=228, price=1000, side='Buy')
        self.supervisor.add_order(order)
        self.supervisor.check_needed_orders()

        # assert that method has been called
        self.exchange_mock.place_order.assert_called_once_with(order)
        # assert that we catch the exception and forget the order
        self.assertNotIn(order, self.supervisor.orders)
class SupervisorEntryTests(unittest.TestCase):
    def setUp(self) -> None:
        self.exchange_mock = Mock()
        self.exchange_mock.get_open_orders_ws.return_value = []
        self.exchange_mock.get_position_size_ws.return_value = 0
        self.supervisor = Supervisor(interface=self.exchange_mock)

    def tearDown(self) -> None:
        self.supervisor.exit_cycle()

    def test_market_entry(self):
        self.supervisor.enter_by_market_order(228)

        self.exchange_mock.place_market_order.assert_called_once_with(qty=228)

    def test_fb_entry_last_price(self):
        self.exchange_mock.get_last_price_ws.return_value = 1000
        self.exchange_mock.get_order_status_ws.return_value = 'Filled'
        self.exchange_mock.conn.get_tick_size.return_value = 0.5
        self.supervisor.enter_fb_method(qty=228,
                                        price_type='last',
                                        max_retry=5,
                                        timeout=3)
        order = Order(order_type='Limit',
                      qty=228,
                      price=1000,
                      side='Buy',
                      passive=True)
        self.exchange_mock.place_order.assert_called_once_with(order)

    def test_fb_entry_last_price_timedout(self):
        self.exchange_mock.get_last_price_ws.return_value = 1000
        self.exchange_mock.get_order_status_ws.return_value = 'New'
        self.exchange_mock.conn.get_tick_size.return_value = 0.5
        self.supervisor.enter_fb_method(qty=228,
                                        price_type='last',
                                        max_retry=3,
                                        timeout=1)
        order = Order(order_type='Limit',
                      qty=228,
                      price=1000,
                      side='Buy',
                      passive=True)
        expected_calls = [call(order)] * 3
        self.exchange_mock.place_order.assert_has_calls(expected_calls)

        self.exchange_mock.place_market_order.assert_called_once_with(qty=228)

    def test_fb_entry_first_orderbook_price(self):
        self.exchange_mock.get_first_orderbook_price_ws.return_value = 1000
        self.exchange_mock.get_order_status_ws.return_value = 'Filled'
        self.exchange_mock.conn.get_tick_size.return_value = 0.5
        self.supervisor.enter_fb_method(qty=228,
                                        price_type='first_ob',
                                        max_retry=5,
                                        timeout=1)
        order = Order(order_type='Limit',
                      qty=228,
                      price=1000,
                      side='Buy',
                      passive=True)
        self.exchange_mock.place_order.assert_called_once_with(order)

    def test_fb_entry_third_orderbook_price(self):
        self.exchange_mock.get_third_orderbook_price_ws.return_value = 1000
        self.exchange_mock.get_order_status_ws.return_value = 'Filled'
        self.exchange_mock.conn.get_tick_size.return_value = 0.5
        self.supervisor.enter_fb_method(qty=228,
                                        price_type='third_ob',
                                        max_retry=5,
                                        timeout=1)
        order = Order(order_type='Limit',
                      qty=228,
                      price=1000,
                      side='Buy',
                      passive=True)
        self.exchange_mock.place_order.assert_called_once_with(order)

    def test_fb_entry_with_deviation(self):
        self.exchange_mock.get_last_price_ws.return_value = 1000
        self.exchange_mock.get_order_status_ws.return_value = 'Filled'
        self.exchange_mock.conn.get_tick_size.return_value = 0.5
        self.supervisor.enter_fb_method(qty=228,
                                        price_type='deviant',
                                        max_retry=5,
                                        timeout=1,
                                        deviation=-10)
        order = Order(order_type='Limit',
                      qty=228,
                      price=900,
                      side='Buy',
                      passive=True)
        self.exchange_mock.place_order.assert_called_once_with(order)
Exemplo n.º 6
0
    # you can disable managing position or orders by set to False needed properties
    # supervisor.manage_position = False
    # supervisor.manage_orders = False

    # create Order objects
    stop_loss = Order(order_type='Stop', stop_px=2000, qty=10, side='Sell')
    tp1 = Order(order_type='Limit', price=15000, qty=6, side='Sell', passive=True)
    tp2 = Order(order_type='Limit', price=20000, qty=4, side='Sell', hidden=True)

    trailing_stop = Order(order_type='Stop', stop_px=3000, qty=10, side='Sell')

    # attach some callbacks to stop-loss, note that events starts with "_"
    # DO NOT USE stop_cycle() method in callbacks!!! It causes deadlock
    stop_loss._on_reject = lambda: print('Rejected')
    stop_loss._on_fill = lambda: print('We lost position(')

    input('Enter to run cycle')
    supervisor.run_cycle()
    input('Enter to add orders to needed')
    supervisor.add_order(stop_loss)
    supervisor.add_order(tp1)
    supervisor.add_order(tp2)
    supervisor.add_trailing_order(trailing_stop, offset=10)  # order will trail on 10% distance from current price
    input('Enter to enter position')
    supervisor.stop_cycle()
    supervisor.enter_by_market_order(10)
    supervisor.run_cycle()
    input('Enter to exit cycle')
    supervisor.exit_cycle()
class TrailingStopTests(unittest.TestCase):

    def setUp(self) -> None:
        self.exchange_mock = Mock()
        self.exchange_mock.get_open_orders_ws.return_value = []
        self.exchange_mock.get_position_size_ws.return_value = 0
        self.supervisor = Supervisor(interface=self.exchange_mock)

        self.exchange_mock.conn.base_url = 'https://testnet.bitmex.com/api/v1'
        self.exchange_mock.conn.get_tick_size.return_value = 0.5

    def tearDown(self) -> None:
        self.supervisor.exit_cycle()

    def test_buy_order_will_follow_the_price(self):
        order = Order(order_type='Stop', side='Buy', qty=228, stop_px=10000)
        self.exchange_mock.get_open_orders_ws.return_value = [order]

        self.exchange_mock.get_last_price_ws.return_value = 9000

        self.supervisor.add_trailing_order(order, offset=10)
        self.supervisor.run_cycle()

        self.exchange_mock.get_last_price_ws.return_value = 8000
        order.tracker.min_price = 8000
        self.assertEqual(8800, order.stop_px)

        self.exchange_mock.get_last_price_ws.return_value = 7000
        order.tracker.min_price = 7000
        self.assertEqual(7700, order.stop_px)

    def test_sell_order_will_follow_the_price(self):
        order = Order(order_type='Stop', side='Sell', qty=228, stop_px=1000)
        self.exchange_mock.get_open_orders_ws.return_value = [order]

        self.exchange_mock.get_last_price_ws.return_value = 1000

        self.supervisor.add_trailing_order(order, offset=10)
        self.supervisor.run_cycle()

        self.exchange_mock.get_last_price_ws.return_value = 7000
        order.tracker.max_price = 7000
        self.assertEqual(6300, order.stop_px)

        self.exchange_mock.get_last_price_ws.return_value = 8000
        order.tracker.max_price = 8000
        self.assertEqual(7200, order.stop_px)

    def test_stop_tracking_after_fill_order(self):
        order = Order(order_type='Stop', side='Sell', qty=228, stop_px=1000)
        self.exchange_mock.get_open_orders_ws.return_value = [order]
        self.exchange_mock.get_last_price_ws.return_value = 9000

        self.supervisor.add_trailing_order(order, 10)

        self.supervisor.run_cycle()

        order.order_id = 1234
        self.exchange_mock.get_open_orders_ws.return_value = []
        self.exchange_mock.get_order_status_ws.return_value = 'Filled'

        sleep(0.5)

        self.assertTrue(order.tracker.exited)
class SupervisorEntryTests(unittest.TestCase):
    def setUp(self) -> None:
        self.exchange_mock = Mock()
        self.exchange_mock.get_open_orders_ws.return_value = []
        self.exchange_mock.get_position_size_ws.return_value = 0
        self.supervisor = Supervisor(interface=self.exchange_mock)

    def tearDown(self) -> None:
        self.supervisor.exit_cycle()

    def test_market_position_enter_while_running_cycle(self):
        self.supervisor.run_cycle()

        self.supervisor.stop_cycle()
        self.supervisor.enter_by_market_order(qty=20)
        self.exchange_mock.get_position_size_ws.return_value = 20
        self.supervisor.run_cycle()

        sleep(1)

        # assert that Supervisor change position only once
        self.exchange_mock.place_market_order.assert_called_once_with(qty=20)

    def test_fb_last_position_enter_while_running_cycle(self):
        self.exchange_mock.get_last_price_ws.return_value = 1000
        self.exchange_mock.get_order_status_ws.return_value = 'Filled'
        self.exchange_mock.conn.get_tick_size.return_value = 0.5

        self.supervisor.run_cycle()

        self.supervisor.stop_cycle()
        self.supervisor.enter_fb_method(qty=20,
                                        price_type='last',
                                        timeout=5,
                                        max_retry=3)
        self.exchange_mock.get_position_size_ws.return_value = 20
        self.supervisor.run_cycle()

        sleep(1)

        order = Order(order_type='Limit',
                      qty=20,
                      price=1000,
                      side='Buy',
                      passive=True)
        # assert that Supervisor change position only once with limit order
        self.exchange_mock.place_order.assert_called_once_with(order)

    def test_fb_first_ob_position_enter_while_running_cycle(self):
        self.exchange_mock.get_first_orderbook_price_ws.return_value = 1000
        self.exchange_mock.get_order_status_ws.return_value = 'Filled'
        self.exchange_mock.conn.get_tick_size.return_value = 0.5

        self.supervisor.run_cycle()

        self.supervisor.stop_cycle()
        self.supervisor.enter_fb_method(qty=20,
                                        price_type='first_ob',
                                        timeout=5,
                                        max_retry=3)
        self.exchange_mock.get_position_size_ws.return_value = 20
        self.supervisor.run_cycle()

        sleep(1)

        order = Order(order_type='Limit',
                      qty=20,
                      price=1000,
                      side='Buy',
                      passive=True)
        # assert that Supervisor change position only once with limit order
        self.exchange_mock.place_order.assert_called_once_with(order)

    def test_fb_third_ob_position_enter_while_running_cycle(self):
        self.exchange_mock.get_third_orderbook_price_ws.return_value = 1000
        self.exchange_mock.get_order_status_ws.return_value = 'Filled'
        self.exchange_mock.conn.get_tick_size.return_value = 0.5

        self.supervisor.run_cycle()

        self.supervisor.stop_cycle()
        self.supervisor.enter_fb_method(qty=20,
                                        price_type='third_ob',
                                        timeout=5,
                                        max_retry=3)
        self.exchange_mock.get_position_size_ws.return_value = 20
        self.supervisor.run_cycle()

        sleep(1)

        order = Order(order_type='Limit',
                      qty=20,
                      price=1000,
                      side='Buy',
                      passive=True)
        # assert that Supervisor change position only once with limit order
        self.exchange_mock.place_order.assert_called_once_with(order)

    def test_fb_positive_deviant_position_enter_while_running_cycle(self):
        self.exchange_mock.get_last_price_ws.return_value = 1000
        self.exchange_mock.get_order_status_ws.return_value = 'Filled'
        self.exchange_mock.conn.get_tick_size.return_value = 0.5

        self.supervisor.run_cycle()

        self.supervisor.stop_cycle()
        self.supervisor.enter_fb_method(qty=20,
                                        price_type='deviant',
                                        timeout=5,
                                        max_retry=3,
                                        deviation=15)
        self.exchange_mock.get_position_size_ws.return_value = 20
        self.supervisor.run_cycle()

        sleep(1)

        order = Order(order_type='Limit',
                      qty=20,
                      price=1150,
                      side='Buy',
                      passive=True)
        # assert that Supervisor change position only once with limit order
        self.exchange_mock.place_order.assert_called_once_with(order)

    def test_fb_negative_deviant_position_enter_while_running_cycle(self):
        self.exchange_mock.get_last_price_ws.return_value = 1000
        self.exchange_mock.get_order_status_ws.return_value = 'Filled'
        self.exchange_mock.conn.get_tick_size.return_value = 0.5

        self.supervisor.run_cycle()

        self.supervisor.stop_cycle()
        self.supervisor.enter_fb_method(qty=20,
                                        price_type='deviant',
                                        timeout=5,
                                        max_retry=3,
                                        deviation=-15)
        self.exchange_mock.get_position_size_ws.return_value = 20
        self.supervisor.run_cycle()

        sleep(1)

        order = Order(order_type='Limit',
                      qty=20,
                      price=850,
                      side='Buy',
                      passive=True)
        # assert that Supervisor change position only once with limit order
        self.exchange_mock.place_order.assert_called_once_with(order)
class OrdersCallbacksTests(unittest.TestCase):
    def setUp(self) -> None:
        self.exchange_mock = Mock()
        self.exchange_mock.get_open_orders_ws.return_value = []
        self.exchange_mock.get_position_size_ws.return_value = 0
        self.supervisor = Supervisor(interface=self.exchange_mock)

    def tearDown(self) -> None:
        self.supervisor.exit_cycle()

    def test_filled_callback_will_be_called(self):

        order = Order(order_type='Limit', side='Sell', qty=228, price=1000)
        order.order_id = 123456

        callback = Mock()
        order._on_fill = callback
        self.supervisor.add_order(order)

        self.exchange_mock.get_order_status_ws.return_value = 'Filled'

        self.supervisor.run_cycle()

        sleep(1)

        callback.assert_called_once()
        self.assertListEqual([], self.supervisor._orders)

    def test_rejected_callback_will_be_called(self):
        order = Order(order_type='Limit', side='Sell', qty=228, price=1000)
        order.order_id = 123456

        callback = Mock()
        order._on_reject = callback
        self.supervisor.add_order(order)

        self.exchange_mock.get_order_status_ws.return_value = 'Rejected'

        self.supervisor.run_cycle()

        sleep(1)

        callback.assert_called_once()
        self.assertListEqual([], self.supervisor._orders)

    def test_several_filled_orders_at_the_same_time(self):
        order_1 = Order(order_type='Limit', side='Sell', qty=228, price=1000)
        order_1.order_id = 123456
        order_2 = Order(order_type='Limit', side='Sell', qty=229, price=1001)
        order_2.order_id = 123457
        order_3 = Order(order_type='Limit', side='Sell', qty=2210, price=1002)
        order_3.order_id = 123458
        order_4 = Order(order_type='Limit', side='Sell', qty=2211, price=1003)
        order_4.order_id = 123459

        callback_1 = Mock()
        callback_2 = Mock()
        callback_3 = Mock()
        callback_4 = Mock()
        order_1._on_fill = callback_1
        order_2._on_fill = callback_2
        order_3._on_fill = callback_3
        order_4._on_fill = callback_4
        self.supervisor.add_order(order_1)
        self.supervisor.add_order(order_2)
        self.supervisor.add_order(order_3)
        self.supervisor.add_order(order_4)

        self.exchange_mock.get_order_status_ws.return_value = 'Filled'

        self.supervisor.run_cycle()

        sleep(1)

        callback_1.assert_called_once()
        callback_2.assert_called_once()
        callback_3.assert_called_once()
        callback_4.assert_called_once()
        self.assertListEqual([], self.supervisor._orders)