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 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)
示例#3
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 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)