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