def placeLimitOrder(self, symbol, quantity, is_buy_order, limit_price, order_id=None, ignore_risk=True, tag=None): order = LimitOrder(self.id, self.currentTime, symbol, quantity, is_buy_order, limit_price, order_id, tag) if quantity > 0: # Test if this order can be permitted given our at-risk limits. new_holdings = self.holdings.copy() q = order.quantity if order.is_buy_order else -order.quantity if order.symbol in new_holdings: new_holdings[order.symbol] += q else: new_holdings[order.symbol] = q # If at_risk is lower, always allow. Otherwise, new_at_risk must be below starting cash. if not ignore_risk: # Compute before and after at-risk capital. at_risk = self.markToMarket( self.holdings) - self.holdings['CASH'] new_at_risk = self.markToMarket( new_holdings) - new_holdings['CASH'] if (new_at_risk > at_risk) and (new_at_risk > self.starting_cash): log_print( "TradingAgent ignored limit order due to at-risk constraints: {}\n{}", order, self.fmtHoldings(self.holdings)) return # Copy the intended order for logging, so any changes made to it elsewhere # don't retroactively alter our "as placed" log of the order. Eventually # it might be nice to make the whole history of the order into transaction # objects inside the order (we're halfway there) so there CAN be just a single # object per order, that never alters its original state, and eliminate all these copies. self.orders[order.order_id] = deepcopy(order) self.sendMessage( self.exchangeID, Message({ "msg": "LIMIT_ORDER", "sender": self.id, "order": order })) # Log this activity. if self.log_orders: self.logEvent('ORDER_SUBMITTED', order.to_dict()) else: log_print("TradingAgent ignored limit order of quantity zero: {}", order)
def placeOrder(self, currentTime, order): if len(order) == 1: type = order.type.item() id = order.order_id.item() direction = order.direction.item() price = order.price.item() vol = order.vol.item() existing_order = self.orders.get(id) if type == 'NEW': self.placeLimitOrder(self.symbol, vol, direction == 'BUY', float(price), dollar=False, order_id=id) elif type in ['CANCELLATION', 'PARTIAL_CANCELLATION']: if existing_order: if type == 'CANCELLATION': self.cancelOrder(existing_order) elif type == 'PARTIAL_CANCELLATION': new_order = LimitOrder(self.id, currentTime, self.symbol, vol, direction == 'BUY', float(price), dollar=False, order_id=id) self.modifyOrder(existing_order, new_order) elif type in ['EXECUTE_VISIBLE', 'EXECUTE_HIDDEN']: if existing_order: if existing_order.quantity == vol: self.cancelOrder(existing_order) else: new_vol = existing_order.quantity - vol if new_vol == 0: self.cancelOrder(existing_order) else: executed_order = LimitOrder(self.id, currentTime, self.symbol, new_vol, direction == 'BUY', float(price), dollar=False, order_id=id) self.modifyOrder(existing_order, executed_order) self.orders.get(id).quantity = new_vol else: orders = self.oracle.trades_df.loc[self.oracle.trades_df.timestamp == currentTime] for index, order in orders.iterrows(): self.placeOrder(currentTime, order=pd.DataFrame(order).T)
def placeLimitOrder (self, symbol, quantity, is_buy_order, limit_price): order = LimitOrder(self.id, self.currentTime, symbol, quantity, is_buy_order, limit_price) if quantity > 0: # Test if this order can be permitted given our at-risk limits. new_holdings = self.holdings.copy() q = order.quantity if order.is_buy_order else -order.quantity if order.symbol in new_holdings: new_holdings[order.symbol] += q else: new_holdings[order.symbol] = q # Compute before and after at-risk capital. at_risk = self.markToMarket(self.holdings) - self.holdings['CASH'] new_at_risk = self.markToMarket(new_holdings) - new_holdings['CASH'] # If at_risk is lower, always allow. Otherwise, new_at_risk must be below starting cash. if (new_at_risk > at_risk) and (new_at_risk > self.startingCash): print ("TradingAgent ignored limit order due to at-risk constraints: {}\n{}".format(order, self.fmtHoldings(self.holdings))) return self.orders[order.order_id] = deepcopy(order) self.sendMessage(self.exchangeID, Message({ "msg" : "LIMIT_ORDER", "sender": self.id, "order" : order })) # Log this activity. self.logEvent('ORDER_SUBMITTED', order) else: print ("TradingAgent ignored limit order of quantity zero: {}".format(order))
def handleMarketOrder(self, order): if order.symbol != self.symbol: log_print("{} order discarded. Does not match OrderBook symbol: {}", order.symbol, self.symbol) return if (order.quantity <= 0) or (int(order.quantity) != order.quantity): log_print("{} order discarded. Quantity ({}) must be a positive integer.", order.symbol, order.quantity) return orderbook_side = self.getInsideAsks() if order.is_buy_order else self.getInsideBids() limit_orders = {} # limit orders to be placed (key=price, value=quantity) order_quantity = order.quantity for price_level in orderbook_side: price, size = price_level[0], price_level[1] if order_quantity <= size: limit_orders[price] = order_quantity #i.e. the top of the book has enough volume for the full order break else: limit_orders[price] = size # i.e. not enough liquidity at the top of the book for the full order # therefore walk through the book until all the quantities are matched order_quantity -= size continue log_print("{} placing market order as multiple limit orders", order.symbol, order.quantity) for lo in limit_orders.items(): p, q = lo[0], lo[1] limit_order = LimitOrder(order.agent_id, order.time_placed, order.symbol, q, order.is_buy_order, p) self.handleLimitOrder(limit_order)
def placeOrder(self, currentTime, order): if len(order) == 1: order = order[0] order_id = order['ORDER_ID'] existing_order = self.orders.get(order_id) if not existing_order and order['SIZE'] > 0: self.placeLimitOrder(self.symbol, order['SIZE'], order['BUY_SELL_FLAG'] == 'BUY', order['PRICE'], order_id=order_id) elif existing_order and order['SIZE'] == 0: self.cancelOrder(existing_order) elif existing_order: self.modifyOrder( existing_order, LimitOrder(self.id, currentTime, self.symbol, order['SIZE'], order['BUY_SELL_FLAG'] == 'BUY', order['PRICE'], order_id=order_id)) else: for ind_order in order: self.placeOrder(currentTime, order=[ind_order])
def placeOrder(self, currentTime, order): if len(order) == 1: order = order[0] order_id = order['Order_ID'] existing_order = self.orders.get(order_id) if not existing_order and order['Size'] > 0 and order[ 'Type'] == 'R': self.placeLimitOrder(self.symbol, order['Size'], order['Direction'] == 'BUY', order['Price'], order_id=order_id) elif existing_order and order['Size'] == 0: self.cancelOrder(existing_order) elif existing_order and order['Size'] > 0: # self.modifyOrder(existing_order, LimitOrder(self.id, currentTime, self.symbol, order['SIZE'], # order['BUY_SELL_FLAG'] == 'BUY', order['PRICE'], # order_id=order_id)) self.modifyOrder( existing_order, LimitOrder(self.id, currentTime, self.symbol, order['Size'], order['Direction'] == 'BUY', order['Price'], order_id=order_id)) else: None # TODO: check if something is comming here. We should process A and Z types as well else: for ind_order in order: self.placeOrder(currentTime, order=[ind_order])
def placeOrder(self, currentTime, order): if len(order) == 1: order = order[0] order_id = order['Order_ID'] existing_order = self.orders.get(order_id) if not existing_order and order['Size'] > 0 and order['Type'] in [1,5]: self.placeLimitOrder(self.symbol, order['Size'], order['Direction'] == 'BUY', order['Price'], order_id=order_id) elif existing_order and order['Type'] == 3: self.cancelOrder(existing_order) elif existing_order and order['Type'] == 2: # self.modifyOrder(existing_order, LimitOrder(self.id, currentTime, self.symbol, order['SIZE'], # order['BUY_SELL_FLAG'] == 'BUY', order['PRICE'], # order_id=order_id)) self.modifyOrder(existing_order, LimitOrder(self.id, currentTime, self.symbol, existing_order.quantity - order['Size'], #there was order['Size'] order['Direction'] == 'BUY', order['Price'], order_id=order_id)) else: None # TODO: type 4 should be ok, but type 7 ? else: for ind_order in order: self.placeOrder(currentTime, order=[ind_order])