예제 #1
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()
예제 #2
0
    def received_order_book(self, order_book, market_id):

        time_elapsed = int(round(((time.time() - self._start_time) /
                                  60)))  #rounds seconds to minutes

        # updates current unit holdings according to item name and in order with payoff data
        for items in self._payoffs:
            self._current_unit_holdings[items] = self.holdings["markets"][
                self._market_ids[items]]["available_units"]

        #print("[CURRENT HOLDING] ", self._current_unit_holdings)

        #changes bot type from mm to reactive once time left <= 5min
        if (self._session_time - time_elapsed) <= 5:
            self._role = BotType.MARKET_MAKER
        else:
            self._role = BotType.REACTIVE

        Orders = [
            Order(500, 1, OrderType.LIMIT, OrderSide.SELL, 713, ref="b1"),
            Order(100, 1, OrderType.LIMIT, OrderSide.BUY, 714, ref="b1")
        ]

        self.get_potential_performance(Orders)

        pass
예제 #3
0
파일: DSBot.py 프로젝트: tinat1/agent
    def _print_trade_opportunity(self, other_order):
        order_type = "Sell" if other_order.side == OrderSide.BUY else "Buy"
        self.inform("Opportunity: {} one unit at price of ${:<5.2f}".format(order_type, other_order.price/100))

        if self._role == Role.BUYER:
            #do we really need to define this again?
            # cash_avail =self.holdings["cash"]["available_cash"]
            can_buy = cash_avail >= other_order.price
            #why are there massive gaps here
            self.inform("           : Profit is ${:.2f} per unit".format(int(DS_REWARD_CHARGE - other_order.price) / 100))
            self.inform("           : With ${:.2f} of available cash I can buy at least {} units".format(cash_avail / 100, cash_avail // other_order.price))
            self.inform("           : There are {} units for sale at this price".format(other_order.units))
            #I feel some of the code here overlaps what we've previously done
            #is there a way to call the other method instead of repeating this code?
            #although this is only a suggestion
            if can_buy and self._bot_type == BotType.REACTIVE and not (self._have_an_order or self._waiting_for_server):
                self.inform("           : I will buy one unit of widget at the price of {}".format(other_order.price))
                order = Order(other_order.price, 1, OrderType.LIMIT, OrderSide.BUY, self._market_id, ref="o{}".format(self._orders_ref))
                self._orders_ref += 1
                self.send_order(order)
                self._waiting_for_server = True
                self.inform("The buy order reference is: o{}".format(self._orders_ref))
            else:
                reason = "I do not have enough cash"
                if self._bot_type != BotType.REACTIVE:
                    reason = "I am not a reactive trader"
                elif self._have_an_order:
                    reason = "I already have an order placed in the order book"
                elif self._waiting_for_server:
                    reason = "I am still waiting for the server"
                self.inform("           : I cannot buy any units because {}".format(reason))

        else:
            #you don't need this line because you've already defined it above, right?
            # widgets_avail = self.holdings["markets"][self._market_id]["available_units"]
            can_sell = widgets_avail > 0
            self.inform("           : Profit is {} per unit".format(other_order.price - DS_REWARD_CHARGE))
            self.inform("           : I have a total of {0} widgets, so I can sell up to {0} units".format(widgets_avail))
            self.inform("           : The buyer wishes to buy {} units at this price".format(other_order.units))
            if can_sell and self._bot_type == BotType.REACTIVE and not (self._have_an_order or self._waiting_for_server):
                self.inform("           : I will sell one unit of widget at the price of {}".format(other_order.price))
                order = Order(other_order.price, 1, OrderType.LIMIT, OrderSide.SELL, self._market_id, ref="o{}".format(self._orders_ref))
                self._orders_ref += 1
                self.send_order(order)
                self._waiting_for_server = True
                self.inform("The sell order reference is: o{}".format(self._orders_ref))
            else:
                #again, is there a way to pull this out into a new method so we can just call that method each time instead?
                reason = "I do not have enough widgets"
                if self._bot_type != BotType.REACTIVE:
                    reason = "I am not a reactive trader"
                elif self._have_an_order:
                    reason = "I already have an order in the order book"
                elif self._waiting_for_server:
                    reason = "I am still waiting for the server"
                self.inform("           : I cannot sell any units because {}".format(reason))
예제 #4
0
파일: IEL_b1.py 프로젝트: MeganTj/IEL
    def _get_order(self, order_side):
        """
        Takes a request for a either a buy or sell order, the type of which is
        specified by order_side. Returns an order.

        :param order_side: either OrderSide.BUY or OrderSide.SELL
        """
        action = self.BUY
        if order_side == OrderSide.SELL:
            action = self.SELL
        self.Vexperimentation(action)
        self.updateW(action)
        self.replicate(action)
        self.strat_selection(action)
        if order_side == OrderSide.SELL and (
                self.curr_strat[self.SELL] < self.sl
                or self.curr_strat[self.SELL] > self.su):
            raise Exception(
                'Price should not be less than the minimum or greater than the maximum when selling.'
            )
        if order_side == OrderSide.BUY and (
                self.curr_strat[self.BUY] < self.sl
                or self.curr_strat[self.BUY] > self.su):
            raise Exception(
                'Price should not be less than the minimum or greater than the maximum when selling.'
            )
        price = max(self.sl, self.curr_strat[action])
        order = Order.create_new(self.markets[self._market_id])
        order.price = price
        order.units = self._units
        order.order_type = OrderType.LIMIT
        order.order_side = order_side
        return order
예제 #5
0
    def _get_best_bid_ask():
        """
        Determine and return best active bid and asks in the order book
        :return: best_bid: best buy price
                 best_ask: best sell price
                 best_ask_order: best bid order object
                 best_bid_order:  best ask order object

        """
        # initial bid and asks unrealistic / out of bound
        best_bid = 0
        best_ask = 999999
        best_ask_order = None
        best_bid_order = None

        # run through the order book, determine best bid and asks
        for fm_id, order in Order.current().items():
            if not order.is_consumed and not order.is_private:
                if order.order_side == OrderSide.BUY and order.price > best_bid:
                    best_bid = order.price
                    best_bid_order = order
                elif order.order_side == OrderSide.SELL and order.price < best_ask:
                    best_ask = order.price
                    best_ask_order = order

        return best_bid, best_ask, best_bid_order, best_ask_order
예제 #6
0
    def _make_market(self, priv_order: Order):
        """
        Implements market-maker functionality

        Public order price determination -
            private order price - Profit margin for buying
            private order price + Profit margin for selling
        """
        self._pending_order = False

        # ensure we don't have an already active/pending order
        for _, order in Order.current().items():
            if order.mine and not order.is_consumed and not order.is_private:
                self._pending_order = True

        # PUBLIC MARKET SIDE ======================================================

        market = self._public_market_id

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

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

        # submit order
        if not self._pending_order and not self._waiting_for_server:
            self._create_new_order(market, price, units, order_side,
                                   order_type, ref)
예제 #7
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
예제 #8
0
    def _create_new_order(self,
                          price: int,
                          units: int,
                          order_side: OrderSide,
                          order_type: OrderType,
                          ref: str,
                          is_private: bool):
        """
        :param price: determined price
        :param units: # of units to be submitted, fixed to 1
        :param order_side: buy or sell
        :param order_type: limit or market, fixed to limit
        :param ref: customer string of format "Order: {self._sent_order_count} - SM"
        :return:
        """
        new_order = Order.create_new()

        if is_private:
            market = self._private_market_id
            new_order.owner_or_target = "M000"
        else:
            market = self._public_market_id

        new_order.market = Market(market)
        new_order.price = price
        new_order.units = units
        new_order.order_side = order_side
        new_order.order_type = order_type
        new_order.ref = ref

        self.send_order(new_order)
        self._waiting_for_server = True
예제 #9
0
    def _send_valid_mm_orders(self):
        """
        Executes list of valid market maker orders
        :return: List[Order] of valid orders
        """
        for key in self._mm_orders:

            order = Order.create_new()
            order.market = Market(self._market_ids[key[0]])
            price_tick = order.market.price_tick

            price = self._mm_orders[key] - \
                          (self._mm_orders[key] % price_tick)

            if price <= order.market.min_price:
                price = order.market.min_price
            elif price >= order.market.max_price:
                price = order.market.max_price

            order.price = price

            order.order_side = key[-1]
            order.order_type = OrderType.LIMIT
            order.units = 1

            if order.market.min_price <= order.price <= order.market.max_price:
                self._order_id += 1
                self._num_orders_sent += 1
                self._num_active_mm_orders += 1
                self.send_order(order)
        return
예제 #10
0
    def _send_orders(self, orders):
        """
        Creates *corresponding* orders to the list of orders received
        :param orders: list of favourable orders
        """

        if not self.is_session_active():
            return

        # REACTIVE ORDERS
        for order in orders:

            price_tick = order.market.price_tick

            new_order = Order.create_new()
            new_order.price = order.price - (order.price % price_tick)
            new_order.market = order.market
            new_order.units = 1

            if order.order_side == OrderSide.BUY:
                new_order.order_side = OrderSide.SELL
            else:
                new_order.order_side = OrderSide.BUY

                # don't send invalid orders, kill switch for edge cases
                if new_order.price > self._cash_available:
                    return

            new_order.order_type = OrderType.LIMIT
            new_order.ref = f"Order {self._order_id} - SM"
            self._order_id += 1
            self.send_order(new_order)
예제 #11
0
    def _make_order(self,
                    order_price,
                    order_side,
                    order_unit=ORDER_UNIT,
                    order_type=OrderType.LIMIT):
        """
        MAKES order and stores in active order
        :param order_price: price made after decision
        :param order_side: buyer or seller
        :param order_unit: (Optional, not available) Traded units
        :param order_type: (Optional, not available) Type of order
        :return: sends order
        """
        self._line_break_inform(inspect.stack()[0][3])

        # Use reference maker to make reference for current order
        ref = self._make_order_ref(self._market_id, order_price, order_side)

        # Updates the active order to store latest order to be made
        self.active_order = Order(order_price,
                                  order_unit,
                                  order_type,
                                  order_side,
                                  self._market_id,
                                  ref=ref)

        # Change order status to MADE
        self.order_status = OrderStatus["MADE"]
예제 #12
0
    def received_orders(self, orders: List[Order]):
        orders_avail = orders
        for o in orders_avail:
            # inform method just logs the messages
            self.inform(o)
            if o.mine:
                self.inform(o.owner, o.owner_or_target)

            # cancelling an order, make sure to check all orders sent are accepted
            # if o.mine:
            #     cancel_order = copy.copy(o)
            #     cancel_order.order_type = OrderType.CANCEL
            #     self.send_order(cancel_order)

        # order has attribute mine (bool) to know if our order or not

        # order.all() fetches all previous orders, and we don't need to physically track all changes,
        # we can query this order.all() data to find the status of the order
        # all_orders = Order.all()

        if not self._order_sent:
            order = Order.create_new()
            order.market = Market(1573)
            order.order_side = OrderSide.BUY
            order.order_type = OrderType.LIMIT
            order.price = 100
            order.ref = "rip"
            order.units = 1

            # we will know this owner/target from the private orders we receive
            # Manager is always M000

            order.owner_or_target = "T002"  # sending private orders, the market code should be changed to 1573
            self.send_order(order)
            self._order_sent = True
예제 #13
0
    def _marketmaker(self, other_order):

        #initial parameters and displays cash balance
        place_sell_order = False
        place_buy_order = False
        print("Current cash balance ", self.holdings['cash']['available_cash'])
        print("Current asset balance ",
              self.holdings['cash']['available_units'])

        #if we already have a sell/buy order, then we do not place another
        for order in other_order:
            if (order.mine and order.side == OrderSide.SELL):
                place_sell_order = True
            if (order.mine and order.side == OrderSide.BUY):
                place_buy_order = True

        #if we have positive asset, and can place a order, we place sell order for 5c more than our DS_REWARD_CHARGE
        if (not self._wait_sell_server_mm and not place_sell_order and
                self.holdings['markets'][self._market_id]['available_units'] >
                0):  #sell
            place_sell_order = Order(DS_REWARD_CHARGE + 5,
                                     1,
                                     OrderType.LIMIT,
                                     OrderSide.SELL,
                                     self._market_id,
                                     ref="b1")

            #Send order
            self.send_order(place_sell_order)
            self._wait_buy_server_mm = True
            print("[ORDER PLACED] ", place_sell_order)

        # if we have positive asset, and can place a order, we place buy order for 5c less than our DS_REWARD_CHARGE
        if (not self._wait_buy_server_mm and not place_buy_order
                and self.holdings['cash']['available_cash'] >=
            (DS_REWARD_CHARGE - 5)):  # buy
            place_buy_order = Order(DS_REWARD_CHARGE - 5,
                                    1,
                                    OrderType.LIMIT,
                                    OrderSide.BUY,
                                    self._market_id,
                                    ref="s1")
            self._wait_sell_server_mm = True
            self.send_order(place_buy_order)
            print("[ORDER PLACED] ", place_buy_order)
예제 #14
0
 def make_order(self, agent=None):
     if agent:
         agent.inform("Making Order with ref" + self.ref)
     return Order(self.price,
                  self.units,
                  self.order_type,
                  self.order_side,
                  self.market_id,
                  ref=self.ref)
예제 #15
0
    def enforce_liquidity(self, market_id, units=1, confidence=None):
        """
        If a sell @ bid in the current market leads to net improved performance, creates and sends the sell @ bid order.
        Creates confidence bounds for bids/asks based on market volatility, to ensure arbitrage execution.
        """
        confidence = confidence if confidence else self._ARBITRAGE_CONDFIDENCE
        # if volatility info is not available, end function
        ask_vol = self._timewvar.get(market_id,{}).get(OrderSide.SELL)
        if ask_vol==None: return

        # initialise buy order and cash needed for the order
        ask = self.t_confint_bound(self._asks[market_id], ask_vol**0.5, confidence, int(self.time_elapsed()), upper=True)
        if not (self.markets[market_id]['minimum'] <= ask <= self.markets[market_id]['maximum']): return
        current_buy = Order(ask, units, OrderType.LIMIT, OrderSide.BUY, market_id, ref="current_buy")
        cn = max(ask*units - self._holdings['cash']['available_cash'], 0)
        # if more than enough cash is available, end function
        if not cn: return
        # else, if another market can sell @ bid and improve net performance buying in current market @ ask, sell @ bid in that market
        highest_pchange = 0
        highest_sell = None
        for other_m_id, raw_bid in {k:v for k,v in self._bids.items() if (k!=market_id) & (v>self.markets[k]['minimum'])}.items():
            # if volatility info is not available, continue to next market
            bid_vol = self._timewvar.get(market_id,{}).get(OrderSide.BUY)
            if bid_vol==None: continue
            # if bid price would create an invalid order, continue to next market
            bid = self.t_confint_bound(raw_bid, bid_vol**0.5, confidence, int(self.time_elapsed()))
            if not (self.markets[other_m_id]['minimum'] <= bid <= self.markets[other_m_id]['maximum']): continue
            # initialise the sell @ bid order
            other_sell = Order(bid, int(cn/bid)+(cn%bid>0), OrderType.LIMIT, OrderSide.SELL, other_m_id, ref="other_sell")
            # records the (valid) order pair with the highest performance change
            if self.valid_order(other_sell, bypass_tracking=True):
                pchange = self.get_performance_change([current_buy, other_sell])
                if pchange > highest_pchange:
                    highest_sell = other_sell
                    highest_pchange = pchange
        
        # sell @ bid in the market that results in the highest performance increase
        if highest_sell:
            if self.valid_order(highest_sell, bypass_tracking=True):
                self.send_order(highest_sell)
                self._holdings['markets'][highest_sell.market_id]['available_units'] -= highest_sell.units
                self.inform(f"[LIQUIDITY MANAGEMENT] offloading {self.markets[highest_sell.market_id]['item']} @ {highest_sell.price}.")
예제 #16
0
    def received_orders(self, orders: List[Order]):
        """
        Subscribed to Order book updates
        :param orders: list of order objects
        """
        for order in orders:
            self.inform(order)

            # pending order in private market
            # even if order is partially filled out, it returns 3 entries
            # the buy for x units going through (consumed, not pending)
            # the sell (how many units were sold) (consumed not pending)
            # an order update, with outstanding quantity and price (pending)
            if order.is_private and order.is_pending:
                # if order.is_private and not order.mine: FOR ACTUAL SIMULATION TIMES
                # assign correct role to bot

                if order.order_side == OrderSide.BUY:
                    self._role = Role.BUYER

                elif order.order_side == OrderSide.SELL:
                    self._role = Role.SELLER

                # call strategy based on bot type
                if self._bot_type == BotType.MARKET_MAKER:
                    self._make_market(order)
                elif self._bot_type == BotType.REACTIVE:
                    self._react_to_market(order)

            # during actual simulation add a not order.mine to this
            # if the private order gets cancelled, delete our order from public market
            if order.is_private and order.order_type == OrderType.CANCEL:
                # for some reason, all the order attributes need to be present, so it's not
                # possible to keep track of your old order by reference
                # old order reference only contain the specific attributes we define, everything
                # else is None type
                orders = Order.current()
                for _, o in orders.items():

                    # future proofing, if multiple types of orders in priv and one type expires
                    # only delete the corresponding orders in public
                    if o.mine and not o.is_private and order.order_side == o.order_side\
                            and not self._waiting_for_server:
                        cancel_order = copy.copy(o)
                        cancel_order.ref = f"Cancel {o.ref}"
                        cancel_order.order_type = OrderType.CANCEL
                        self.send_order(cancel_order)
                        self._waiting_for_server = True
                        break

            # if our order gets consumed
            if order.mine and not order.is_private and order.is_consumed:
                self._pending_order = False
예제 #17
0
    def received_order_book(self, order_book, market_id):
        print("hehrhrhe")
        print(self._market_id)
        orders_count = 0
        for order in order_book:
            if order.mine:
                orders_count += 1
        if orders_count < 2:
            my_buy_order = Order(100, 1, OrderType.LIMIT, OrderSide.BUY, 539, ref="b1")
            print("my buy order is ",my_buy_order)

            self.send_order(my_buy_order)
        pass
예제 #18
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
예제 #19
0
    def _cancel_my_orders(self):
        """
        Cancels all of my orders in the market
        """
        for _, order in Order.current().items():

            # if I have an active order, cancel it UNLESS
            if order.mine and not self._waiting:
                self._waiting = True
                cancel_order = copy.copy(order)
                cancel_order.order_type = OrderType.CANCEL
                cancel_order.ref = f"Cancel - {order.ref} - SM"
                self.send_order(cancel_order)
                self._waiting = False
예제 #20
0
    def _make_market(self):
        # if there is a private order, and no public order, CREATE NEW ORDER(S)
        self._active_public_orders_count = len(self._active_public_orders)
        self.inform(
            f"Private: {self._active_private_orders_count}, Public: {self._active_public_orders_count}"
        )
        self.inform(
            f"{self._active_private_orders}, {self._active_public_orders}")
        if self._active_private_orders_count > 0 and self._active_public_orders_count < 1\
                and not self._waiting_for_server:
            self.inform("Order required ====================================")
            # for each active order in private market (for task 1, just 1)
            for fm_id in self._active_private_orders:

                # PUBLIC ORDER CREATION ==================================================
                is_private = False
                priv_order = self._active_private_orders[fm_id]

                # if manager order is a bid
                if priv_order.order_side == OrderSide.BUY:
                    self._role = Role.BUYER
                    price = priv_order.price - PROFIT_MARGIN
                    order_side = OrderSide.BUY

                # if manager order is an ask
                else:
                    self._role = Role.SELLER
                    price = priv_order.price + PROFIT_MARGIN
                    order_side = OrderSide.SELL

                units = 1
                order_type = OrderType.LIMIT
                ref = f"Order: {self._order_tracking_number} - SM"
                # PRIVATE ORDER CREATION

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

        # if there is a public order, but not private order (STALE PUBLIC ORDER)
        # walk through current orders, delete my orders
        if self._active_public_orders_count > 0 and self._active_private_orders_count < 1\
                and not self._waiting_for_server:
            current_orders = Order.current()
            for _, o in current_orders.items():
                if o.mine:
                    cancel_order = copy.copy(o)
                    cancel_order.order_type = OrderType.CANCEL
                    cancel_order.ref = f"Cancel {o.ref}"
                    self.send_order(cancel_order)
                    self._waiting_for_server = True
예제 #21
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
예제 #22
0
 def _make_order(self, market_id, oside, price, otype = OrderType.LIMIT, \
     units = 1):
     """
     Makes and returns Order object with the defined parameters
     """
     new_order = Order.create_new()
     new_order.mine = True
     new_order.market = Market(market_id)
     new_order.order_side = oside
     new_order.order_type = otype
     new_order.price = price
     new_order.units = units
     new_order.ref = f'{otype} Order in {new_order.market.fm_id} \
          for {new_order.units}@{new_order.price}'
     return new_order
예제 #23
0
 def received_holdings(self, holdings):
     try:
         self._current_assets = sum(
             [m['units'] for m in holdings['markets'].values()])
         # if total assets do not match required assets
         if self._current_assets != self._ASSETS_REQ and self._private_units > 0:
             # trade from private market until required asset count is reached again
             private_order = Order(
                 self._private_price,
                 1,
                 OrderType.LIMIT,
                 (OrderSide.BUY if self._current_assets < self._ASSETS_REQ
                  else OrderSide.SELL),
                 self._private_market_id,
                 ref='priv_order')
             private_order.owner_or_target = self._DEALER_ID
             # decrement private units and disable role if private units have reached zero (no arbitrage opportunities left)
             self._private_units -= 1
             if self._private_units == 0:
                 self._role = None
             self.send_if_valid_order(private_order)
     # display tracebacks for main recurring loops to aid debugging
     except:
         traceback.print_exc()
예제 #24
0
    def  Go_create_new_order(self,
                          price: int,
                          units: int,
                          order_side: OrderSide,
                          order_type: OrderType,
                          ref: str,
                          is_private: bool):
        """
        Creates a new order given the parameters
        :param price: determined price
        :param units: # of units to be submitted, fixed to 1
        :param order_side: buy or sell
        :param order_type: limit or market, fixed to limit
        :param ref: customer string of format "Order: {self._sent_order_count} - SM"
        :return:
        """

        new_order = Order.create_new()

        # derive order attributes
        if is_private:
            market = self._private_market_id
            new_order.owner_or_target = MANAGER_ID
        else:
            market = self._public_market_id

            # make sure price is rounded in the public market
            price -= price % self._price_tick

            # in case price goes less than the tick, or more than ten
            # set prices to the bounds
            if price < self._price_tick:
                price = self._price_tick
            elif price > MAX_PRICE:
                price = MAX_PRICE

        new_order.market = Market(market)
        new_order.price = price
        new_order.units = units
        new_order.order_side = order_side
        new_order.order_type = order_type
        new_order.ref = ref

        # send order through
        self._waiting_for_server = True
        self.send_order(new_order)

        self._tradeID += 1
예제 #25
0
    def _market_making_strategy(self):
        """
        MARKET MAKER STRATEGY
        =====================
        Simulate acquiring/disposing off one unit of each security to calculate
        the change in performance because of this balancing.

        This change in performance is determined to be the price the security
        should by bought/sold for (accounts for changing variance and
        changing expected return)

        That price is then adjusted by a PROFIT MARGIN, and submitted to the
        market
        """
        # do nothing if sending through orders
        if self._waiting or (len(self._asset_units.keys()) == 0):
            return

        self._mm_orders = {}

        # acquire list of all securities
        securities = list(self._payoffs.keys())

        # for each security, determine the prices of valid buys and sells that
        # can be created in the market
        order = Order.create_new()
        order.price = 0

        for security in securities:

            order.market = Market(self._market_ids[security])

            # create quasi buy order
            order.order_side = OrderSide.BUY
            self.is_portfolio_optimal([order])

            # create quasi sell order
            order.order_side = OrderSide.SELL
            self.is_portfolio_optimal([order])

        # filter out orders from potential orders that can't be executed
        # due to not enough cash / units
        self._remove_invalid_mm_orders()

        # # send valid market maker orders in the market
        if not self._waiting:
            self._waiting = True
            self._send_valid_mm_orders()
예제 #26
0
    def make_order(self, market_id, oside, price, otype = OrderType.LIMIT, \
        units = 1):
        """
        Makes and returns Order object with the defined parameters
        """
        new_order = Order.create_new()
        new_order.market = Market(market_id)
        new_order.order_side = oside
        new_order.order_type = otype
        new_order.price = price
        new_order.units = units
        new_order.ref = f'{otype} Order in {new_order.market} \
             for {new_order.units}@{new_order.price}'

        if market_id == self._private_market_id:
            new_order.owner_or_target = "M000"
        return new_order
예제 #27
0
    def _reactive_condition(self):
        """
        Returns True when the reactive strategy is to be executed
        """
        self._order_count = len([o for o in Order.current().values() if o.mine])
        time = self._find_time_elapsed()

        # Do not run on the first instance as variables are yet to be initiated
        if time < 2/30:
            return False
        
        # Run reactive strategy in the latter 1 - MM_PROPORTION of the session time.
        if time > self._MM_PROPORTION * self._session_time and self._order_count == 0:
            return True
        elif self._order_count != 0:
            return False
        else:
            return False
예제 #28
0
    def _get_best_bid_ask():
        """
        Walks the order book and determines what the best bid and asks are
        for each market
        :return     : dictionaries of best bid and ask orders for each
                        market
        """
        VERY_HIGH_ASK = 999999
        VERY_LOW_BID = -1

        # track best bid_ask prices and orders
        # key - market, value - [best price, best price order]
        best_bids = {
            'a': [VERY_LOW_BID, None],
            'b': [VERY_LOW_BID, None],
            'c': [VERY_LOW_BID, None],
            'note': [VERY_LOW_BID, None]
        }
        best_asks = {
            'a': [VERY_HIGH_ASK, None],
            'b': [VERY_HIGH_ASK, None],
            'c': [VERY_HIGH_ASK, None],
            'note': [VERY_HIGH_ASK, None]
        }

        # track current best bids and asks
        for order_id, order in Order.current().items():

            dict_key = order.market.item.lower()

            if order.order_side == OrderSide.BUY:
                if order.price > best_bids[dict_key][0]:
                    best_bids[dict_key][0] = order.price
                    best_bids[dict_key][1] = order
            else:
                if order.price < best_asks[dict_key][0]:
                    best_asks[dict_key][0] = order.price
                    best_asks[dict_key][1] = order

        return best_bids, best_asks
예제 #29
0
    def _sell_notes(self):
        """
        Determines if current cash level is below arbitrary threshold,
        if it yes, sells notes at a small loss
        :return:
        """
        # stop if initialising OR if have enough cash
        if len(self._asset_units.keys()) == 0 or \
                self._cash_available > MIN_CASH_THRESHOLD:
            return

        # find the note key
        note_key = ""
        for asset in self._asset_units:
            if asset.lower() == "note":
                note_key = asset

        # check if have notes available to short
        if self._asset_units[note_key] > self._short_units_allowed[note_key]:
            self.inform(f"Cash avail: {self._cash_available}")
            self.inform(f"Selling notes+++++++++++++++++++++++++++")

            # create note sell orders for some price to obtain quick cash
            market = Market(self._market_ids[note_key])
            price_tick = market.price_tick
            new_order = Order.create_new()
            new_order.price = NOTE_SELLING_PRICE - \
                              (NOTE_SELLING_PRICE % price_tick)
            new_order.market = market
            new_order.units = 1
            new_order.order_side = OrderSide.SELL
            new_order.order_type = OrderType.LIMIT

            new_order.ref = "Order need_cash - SM"

            self._waiting = True
            self._order_id += 1
            self._num_orders_sent += 1
            self.send_order(new_order)
예제 #30
0
    def _create_new_order(self, market: int, price: int, units: int,
                          order_side: OrderSide, order_type: OrderType,
                          ref: str):
        """
        :param market: market ID for the order
        :param price: determined price
        :param units: # of units to be submitted, fixed to 1
        :param order_side: buy or sell
        :param order_type: limit or market, fixed to limit
        :param ref: customer string of format "Order: {self._sent_order_count} - SM"
        :return:
        """
        new_order = Order.create_new()
        new_order.market = Market(market)
        new_order.price = price
        new_order.units = units
        new_order.order_side = order_side
        new_order.order_type = order_type
        new_order.ref = ref

        self.send_order(new_order)
        self._waiting_for_server = True
        self._sent_order_count += 1