Ejemplo n.º 1
0
    def order_accepted(self, order: Order):

        self.inform(
            f"{order.order_side} for {order.units}@{order.price} was accepted")
        self._waiting_for_order = False

        all_orders = list(Order.all().values())
        my_current_orders = [o for o in all_orders if o.is_pending and o.mine]

        #allow market maker orders to remain pending for 2 seconds
        if self._bot_type == BotType.MARKET_MAKER and not order.is_private:
            time.sleep(2)

        #if there is still a pending order, cancel it.
        if order in my_current_orders:
            cancel_order = self.make_cancel_order(order)
            self.send_order(cancel_order)
            self._waiting_for_order = True
        else:
            #otherwise, act in the private market to arbitrage
            if not order.is_private and order.order_type != OrderType.CANCEL:
                if self._role == Role.BUYER:
                    oside = OrderSide.SELL
                else:
                    oside = OrderSide.BUY

                match_order = self.make_order(self._private_market_id, oside, \
                self._standing_priv_order.price)
                self.send_order(match_order)
                self._waiting_for_order = True
Ejemplo n.º 2
0
    def received_orders(self, orders: List[Order]):
        # Track best bids/asks for reactive strategy, this is tracked
        # throughout the session in case is_portfolio optimal is called
        current_orders = [o for o in Order.all().values() if o.is_pending]

        for market_id, market_info in sorted(self.markets.items()):
            orders_in_market = []
            security = market_info.item
            for order in current_orders:
                if order.market.fm_id == market_id:
                    orders_in_market.append(order)

            self._best_bid_dict[security] = self._get_best_bid(orders_in_market)
            self._best_ask_dict[security] = self._get_best_ask(orders_in_market)     

        my_orders = [o for o in Order.current().values() if o.mine and o.is_pending]

        # Clear stale orders (based on order depth) when running reative strategy
        if self._reactive_condition and len(my_orders) != 0:
            for o in my_orders:
                if self._find_order_depth(o, current_orders) > 2 and \
                    not self._waiting_for_order:
                        cancel_order = self._make_cancel_order(o)
                        self.send_order(cancel_order)
                        self._waiting_for_order = True

        # Clear order book if there are unmet orders only when the MM strategy is running
        if self._mm_condition() and len(my_orders) != 0:
                self._clear_orders()
Ejemplo n.º 3
0
    def _categorize_orders(self, item):
        """

        Categorizes orders in 4 groups: {Mine, Others} and {Buy, Sell}.

        :param orders: List of orders

        :return: a dictionary with top level key for the owner, and second level key for the order side.

        The values are sorted list of orders.

        """

        # Uses a dictionary mapping from  a string to a list within a dicitonary
        # mapping  a string to a string to retrieve orders in one of the four
        # categories.
        orders_dict = {
            "mine": {
                "buy": [],
                "sell": []
            },
            "others": {
                "buy": [],
                "sell": []
            }
        }
        for order in Order.all().values():
            # Make sure to exclude cancel orders
            order_item = order.market.item
            if order.order_type == OrderType.LIMIT and order.is_pending and \
                order_item == item:
                if order.mine and order.order_side == OrderSide.BUY:
                    orders_dict["mine"]["buy"].append(order)
                elif order.mine and order.order_side == OrderSide.SELL:
                    orders_dict["mine"]["sell"].append(order)
                elif not order.mine and order.order_side == OrderSide.SELL:
                    orders_dict["others"]["sell"].append(order)
                elif not order.mine and order.order_side == OrderSide.BUY:
                    orders_dict["others"]["buy"].append(order)

        # IMPORTANT! Sort the orders to make it easier to reason on what to do.
        for owner_key in orders_dict.keys():
            for type_key in orders_dict[owner_key]:
                # multiplier ensures the sorting is correct for the buy ands sell side
                if type_key == "buy":
                    multiplier = -1
                else:
                    multiplier = 1
                orders_dict[owner_key][type_key].sort(
                    key=lambda o: multiplier * o.price)
        return orders_dict
Ejemplo n.º 4
0
    def _clear_orders(self):
        """
        Clears all pending orders in the order book that are mine
        """
        all_orders = Order.all().values()
        my_orders = [o for o in all_orders if o.mine and o.is_pending]
        
        self._order_count = len(my_orders)

        if self._order_count != 0:
            for order in my_orders:
                if not self._waiting_for_order:
                    cancel_order = self._make_cancel_order(order)
                    self.send_order(cancel_order)
                    self._waiting_for_order = True
Ejemplo n.º 5
0
    def received_orders(self, orders: List[Order]):

        all_orders = list(Order.all().values())
        current_orders = [order for order in all_orders if order.is_pending]

        #update best bid/ask if a cancel order is detected
        for order in orders:
            if order.order_type == OrderType.CANCEL:
                #self.inform('Cancel order')

                best_bid = self._get_best_bid(all_orders)
                best_ask = self._get_best_ask(all_orders)
                return

        #update standing private order and role
        priv_orders = [order for order in all_orders if order.is_private and \
            order.is_pending]
        if priv_orders:
            self._standing_priv_order = priv_orders[0]
            #self.inform("private order updated")
            self.role(self._standing_priv_order)
        else:
            self._standing_priv_order = None
            #self.inform("no private order, do not trade")
            return

        #Obtaining best bid/ask
        best_bid = self._get_best_bid(current_orders)
        best_ask = self._get_best_ask(current_orders)

        if best_bid == None and best_ask == None:
            self.inform("No best ask and best bid, do nothing")
            return
        elif self._role == Role.SELLER and best_bid == None:
            self.inform("Is seller, no best bid, do nothing")
            return
        elif self._role == Role.BUYER and best_ask == None:
            self.inform("Is buyer, no best ask, do nothing")
            return

        best_bid_price = best_bid.price if best_bid else None
        best_ask_price = best_ask.price if best_ask else None

        priv_price = self._standing_priv_order.price

        #Printing possible trade opportunities, not necessarily acting on them
        if (self._role == Role.SELLER and best_bid_price > priv_price + \
            PROFIT_MARGIN) or (self._role == Role.BUYER and best_ask_price  < \
            priv_price - PROFIT_MARGIN):
            self._print_trade_opportunity(best_ask)

        #Pending order check
        if not self._check_existing_order(current_orders):
            my_order = [order for order in current_orders if order.mine]
            if len(my_order) > 0:
                self.inform(f"Cannot trade, {len(my_order)} pending order(s)")
                return
            else:
                return

        #Market Maker strategy
        if self._bot_type == BotType.MARKET_MAKER:

            #if seller and no pending orders
            if self._role == Role.SELLER and not self._waiting_for_order and \
                 self._check_existing_order(current_orders):

                #send sell order at standing private price + profit margin
                new_order = self.make_order(self._public_market_id, \
                    OrderSide.SELL, priv_price + PROFIT_MARGIN)

                if self._check_holdings(new_order, self.holdings):
                    self.send_order(new_order)
                    self._waiting_for_order = True

            #if buyer and no pending order
            elif self._role == Role.BUYER and not self._waiting_for_order and \
                 self._check_existing_order(current_orders):
                new_order = self.make_order(self._public_market_id, \
                    OrderSide.BUY, priv_price - PROFIT_MARGIN)

                #send by order at standing private price - profit margin
                if self._check_holdings(new_order, self.holdings):
                    self.send_order(new_order)
                    self._waiting_for_order = True

        if best_ask_price == None or best_bid_price == None:
            return

        #Reactive strategy
        if self._bot_type == BotType.REACTIVE:
            if self._role == Role.SELLER and best_bid_price > priv_price + \
                PROFIT_MARGIN:
                #send sell order at best bid in public market
                #if best bid is a profitable opportunity

                if not self._waiting_for_order and \
                    self._check_existing_order(current_orders):
                    new_order = self.make_order(self._public_market_id, \
                        OrderSide.SELL, best_bid_price)

                    if self._check_holdings(new_order, self.holdings):
                        self.send_order(new_order)
                        self._waiting_for_order = True

            elif self._role == Role.BUYER and best_ask_price < priv_price - \
                 PROFIT_MARGIN:
                #send buy order at best ask in public market
                #if best ask is a profitable opportunity

                if not self._waiting_for_order and self._check_existing_order(
                        current_orders):
                    new_order = self.make_order(self._public_market_id, \
                    OrderSide.BUY, best_ask_price)

                    if self._check_holdings(new_order, self.holdings):
                        self.send_order(new_order)
                        self._waiting_for_order = True
            else:
                self.inform("No profitable trading opportunities")
Ejemplo n.º 6
0
    def _make_market(self):
        """
        Market Making Strategy
        Parts:
            1. Iterate over all orders, track number of active public orders by me
            2. Track active private orders
            3. Cancel stale orders
            4. If private order by manager exists, and no public orders by me, create one
        """
        num_pending_orders = 0
        num_manager_order = 0
        manager_order = None

        for _, order in Order.all().items():

            # 1. if i have a current order in the public market
            if order.mine and not order.is_private and not order.is_consumed:
                num_pending_orders += 1

                # 3. cancel stale orders in public market
                if not self._priv_order_exists and not self._waiting_for_server:
                    cancel_order = copy.copy(order)
                    cancel_order.ref = f"Cancel {order.ref}"
                    cancel_order.order_type = OrderType.CANCEL
                    self.send_order(cancel_order)
                    self._waiting_for_server = True
                    self._sent_order_count -= 1

            # 2. track active private orders
            # SIMULATION
            # if order.is_private and not order.mine:
            if order.is_private and not order.is_consumed and not order.mine:

                # set role of bot
                if order.order_side == OrderSide.BUY:
                    self._role = Role.BUYER
                else:
                    self._role = Role.SELLER

                num_manager_order += 1
                manager_order = order

        # 4. if 0 mine orders in public, and not waiting for server, and there is a
        # private order to be serviced
        if num_pending_orders == 0 and not self._waiting_for_server \
                and num_manager_order > 0:

            is_private = False

            # PUBLIC ORDER SIDE - Determine attributes of order to be created==========
            market = self._public_market_id

            if self._role == Role.BUYER:
                price = manager_order.price - PROFIT_MARGIN
                order_side = OrderSide.BUY
            else:
                price = manager_order.price + PROFIT_MARGIN
                order_side = OrderSide.SELL

            units = 1
            order_type = OrderType.LIMIT
            ref = f"Order: {self._sent_order_count} - SM"

            self._create_new_order(market, price, units, order_side,
                                   order_type, ref, is_private)

            # PRIVATE ORDER SIDE - Determine attributes of order to be created========
            # flip attributes
            is_private = True
            market = self._private_market_id
            price = manager_order.price

            if self._role == Role.BUYER:
                order_side = OrderSide.SELL
            else:
                order_side = OrderSide.BUY

            units = 1
            order_type = OrderType.LIMIT
            ref = f"Order: {self._sent_order_count} - SM"
            self._create_new_order(market, price, units, order_side,
                                   order_type, ref, is_private)