# 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 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)
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)