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()
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
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))
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
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
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)
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
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
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
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)
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"]
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
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)
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)
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}.")
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
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
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
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
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
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
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
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()
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
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()
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
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
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
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)
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