def get_orders(self): response = self.rh.session.get(endpoints.orders()).json() res = self.get_full_results(response) def filter_order(order): return len(order['executions']) > 0 def get_order(order): execution = order['executions'][0] return { 'uid': order['id'], 'instruction': order['side'], 'date': execution['timestamp'], 'stock': get_stock_from_instrument_id( get_instrument_id_from_url(order['instrument'])), 'quantity': Decimal(order['quantity']), 'value': Decimal(execution['price']) } return [get_order(order) for order in res if filter_order(order)]
def order_history(self, orderId=None): """Wrapper for portfolios Optional Args: add an order ID to retrieve information about a single order. Returns: (:obj:`dict`): JSON dict from getting orders """ return self.get(endpoints.orders(orderId))
def cancel_order(self, order_id): # noqa: C901 """Cancels specified order and returns the response. If order cannot be cancelled, `None` is returned. (results from `orders` command). Args: order_id (str or dict): Order ID string that is to be cancelled or open order dict returned from order get. Returns: (:obj:`requests.request`): result from `orders` put command """ if isinstance(order_id, str): try: order = self.get(endpoints.orders() + order_id) except (requests.exceptions.HTTPError) as err_msg: raise ValueError( "Failed to get Order for ID: " + order_id + "\n Error message: " + repr(err_msg) ) if order.get("cancel") is not None: try: res = self.post(order["cancel"]) return res except requests.exceptions.HTTPError: try: # sometimes Robinhood asks for another log in when placing an # order res = self.post(order["cancel"]) return res except (requests.exceptions.HTTPError) as err_msg: raise ValueError( "Failed to cancel order ID: " + order_id + "\n Error message: " + repr(err_msg) ) return None elif isinstance(order_id, dict): order_id = order_id["id"] try: order = self.get(endpoints.orders() + order_id) except (requests.exceptions.HTTPError) as err_msg: raise ValueError( "Failed to get Order for ID: " + order_id + "\n Error message: " + repr(err_msg) ) if order.get("cancel") is not None: try: res = self.post(order["cancel"]) return res except requests.exceptions.HTTPError: try: # sometimes Robinhood asks for another log in when placing an # order res = self.post(order["cancel"]) return res except (requests.exceptions.HTTPError) as err_msg: raise ValueError( "Failed to cancel order ID: " + order_id + "\n Error message: " + repr(err_msg) ) return None elif not isinstance(order_id, str) or not isinstance(order_id, dict): raise ValueError( "Cancelling orders requires a valid order_id string or open order" "dictionary" ) # Order type cannot be cancelled without a valid cancel link else: raise ValueError("Unable to cancel order ID: " + order_id)
def place_order( self, instrument, quantity=1, price=0.0, transaction=None, trigger="immediate", order="market", time_in_force="gfd", ): """Place an order with Robinhood Args: instrument (dict): the RH URL and symbol in dict for the instrument to be traded quantity (int): quantity of stocks in order bid_price (float): price for order transaction (:obj:`Transaction`): BUY or SELL enum trigger (:obj:`Trigger`): IMMEDIATE or STOP enum order (:obj:`Order`): MARKET or LIMIT time_in_force (:obj:`TIME_IN_FORCE`): GFD or GTC (day or until cancelled) Returns: (:obj:`requests.request`): result from `orders` put command """ if isinstance(transaction, str): transaction = Transaction(transaction) if not price: price = self.quote_data(instrument["symbol"])["bid_price"] if (price == 0) or (price is None): price = self.quote_data(instrument["symbol"])["last_trade_price"] payload = { "account": self.get_account()["url"], "instrument": unquote(instrument["url"]), "symbol": instrument["symbol"], "type": order.lower(), "time_in_force": time_in_force.lower(), "trigger": trigger, "quantity": quantity, "side": transaction.name.lower(), } if order.lower() == "stop": payload["stop_price"] = float(price) else: payload["price"] = float(price) try: res = self.post(endpoints.orders(), data=payload) return res except Exception as ex: # sometimes Robinhood asks for another log in when placing an order # TODO: fix bare except try: self.auth_method except: # noqa: E722 print(ex)
def submit_buy_order( # noqa: C901 self, instrument_URL=None, symbol=None, order_type=None, time_in_force=None, trigger=None, price=None, stop_price=None, quantity=None, side=None, ): """Submits buy order to Robinhood Notes: This is normally not called directly. Most programs should use one of the following instead: place_market_buy_order() place_limit_buy_order() place_stop_loss_buy_order() place_stop_limit_buy_order() place_market_sell_order() place_limit_sell_order() place_stop_loss_sell_order() place_stop_limit_sell_order() Args: instrument_URL (str): the RH URL for the instrument symbol (str): the ticker symbol for the instrument order_type (str): 'market' or 'limit' time_in_force (:obj:`TIME_IN_FORCE`): 'gfd' or 'gtc' (day or until cancelled) trigger (str): 'immediate' or 'stop' enum price (float): The share price you'll accept stop_price (float): The price at which the order becomes a market or limit order quantity (int): The number of shares to buy/sell side (str): BUY or sell Returns: (:obj:`requests.request`): result from `orders` put command """ # Used for default price input # Price is required, so we use the current ask price if it is not specified current_quote = self.get_quote(symbol) if (current_quote["ask_price"] == 0) or (current_quote["ask_price"] is None): current_ask_price = current_quote["last_trade_price"] else: current_ask_price = current_quote["ask_price"] # Start with some parameter checks. I'm paranoid about $. if instrument_URL is None: if symbol is None: raise ( ValueError( "Neither instrument_URL nor symbol were passed to " "submit_buy_order" ) ) raise (ValueError("Instrument_URL not passed to submit_buy_order")) if symbol is None: raise (ValueError("Symbol not passed to submit_buy_order")) if side is None: raise ( ValueError("Order is neither buy nor sell in call to submit_buy_order") ) if order_type is None: if price is None: if stop_price is None: order_type = "market" else: order_type = "limit" symbol = str(symbol).upper() order_type = str(order_type).lower() time_in_force = str(time_in_force).lower() trigger = str(trigger).lower() side = str(side).lower() if (order_type != "market") and (order_type != "limit"): raise (ValueError("Invalid order_type in call to submit_buy_order")) if order_type == "limit": if price is None: raise ( ValueError("Limit order has no price in call to submit_buy_order") ) if price <= 0: raise ( ValueError( "Price must be positive number in call to submit_buy_order" ) ) if trigger == "stop": if stop_price is None: raise ( ValueError( "Stop order has no stop_price in call to submit_buy_order" ) ) if price <= 0: raise ( ValueError( "Stop_price must be positive number in call to submit_buy_order" ) ) if stop_price is not None: if trigger != "stop": raise ( ValueError( "Stop price set for non-stop order in call to submit_buy_order" ) ) if price is None: if order_type == "limit": raise ( ValueError("Limit order has no price in call to submit_buy_order") ) if price is not None: if order_type.lower() == "market": raise ( ValueError( "Market order has price limit in call to submit_buy_order" ) ) price = float(price) else: price = current_ask_price # default to current ask price if quantity is None: raise (ValueError("No quantity specified in call to submit_buy_order")) quantity = int(quantity) if quantity <= 0: raise ( ValueError( "Quantity must be positive number in call to submit_buy_order" ) ) payload = {} for field, value in [ ("account", self.get_account()["url"]), ("instrument", instrument_URL), ("symbol", symbol), ("type", order_type), ("time_in_force", time_in_force), ("trigger", trigger), ("price", price), ("stop_price", stop_price), ("quantity", quantity), ("side", side), ]: if value is not None: payload[field] = value try: res = self.post(endpoints.orders(), data=payload) return res except Exception as ex: # sometimes Robinhood asks for another log in when placing an order # TODO: fix bare except try: self.auth_method except: # noqa: E722 print(ex)