Пример #1
0
    def cancel_order(self, order_id):
        """
        Cancels specified order and returns the response (results from `orders` command).
        If order cannot be cancelled, `None` is returned.
        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.session.get(endpoints.orders() + order_id,
                                         timeout=15).json()
            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.session.post(order['cancel'], timeout=15)
                    res.raise_for_status()
                    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

        if isinstance(order_id, dict):
            order_id = order_id['id']
            try:
                order = self.session.get(endpoints.orders() + order_id,
                                         timeout=15).json()
            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.session.post(order['cancel'], timeout=15)
                    res.raise_for_status()
                    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)
Пример #2
0
    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.session.get(endpoints.orders(orderId), timeout=15).json()
Пример #3
0
    def order_history(self):
        """Wrapper for portfolios

            Returns:
                (:obj:`dict`): JSON dict from getting orders
        """

        return self.session.get(endpoints.orders(), timeout=15).json()
Пример #4
0
    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

            Notes:
                OMFG TEST THIS PLEASE!

                Just realized this won't work since if type is LIMIT you need to use "price" and if
                a STOP you need to use "stop_price".  Oops.
                Reference: https://github.com/sanko/Robinhood/blob/master/Order.md#place-an-order

            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 (:enum:`Transaction`): BUY or SELL enum
                trigger (:enum:`Trigger`): IMMEDIATE or STOP enum
                order (:enum:`Order`): MARKET or LIMIT
                time_in_force (:enum:`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']

        payload = {
            'account': self.get_account()['url'],
            'instrument': unquote(instrument['url']),
            'quantity': quantity,
            'side': transaction.name.lower(),
            'symbol': instrument['symbol'],
            'time_in_force': time_in_force.lower(),
            'trigger': trigger,
            'type': order.lower()
        }

        if order.lower() == "stop":
            payload['stop_price'] = float(price)
        else:
            payload['price'] = float(price)

        res = self.session.post(endpoints.orders(), data=payload, timeout=15)
        res.raise_for_status()

        return res
Пример #5
0
    def submit_order(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 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 (:enum:`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 bid price if it is not specified
        current_quote = self.get_quote(symbol)
        current_bid_price = current_quote['bid_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_order'
                ))
            for result in self.instruments(symbol):
                if result['symbol'].upper() == symbol.upper():
                    instrument_URL = result['url']
                    break
            if (instrument_URL is None):
                raise (ValueError(
                    'instrument_URL could not be defined. Symbol %s not found'
                    % symbol))

        if (symbol is None):
            symbol = self.session.get(instrument_URL,
                                      timeout=15).json()['symbol']

        if (side is None):
            raise (ValueError(
                'Order is neither buy nor sell in call to submit_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_order'))

        if (order_type == 'limit'):
            if (price is None):
                raise (ValueError(
                    'Limit order has no price in call to submit_order'))
            if (price <= 0):
                raise (ValueError(
                    'Price must be positive number in call to submit_order'))

        if (trigger == 'stop'):
            if (stop_price is None):
                raise (ValueError(
                    'Stop order has no stop_price in call to submit_order'))
            if (stop_price <= 0):
                raise (ValueError(
                    'Stop_price must be positive number in call to submit_order'
                ))

        if (stop_price is not None):
            if (trigger != 'stop'):
                raise (ValueError(
                    'Stop price set for non-stop order in call to submit_order'
                ))

        if (price is None):
            if (order_type == 'limit'):
                raise (ValueError(
                    'Limit order has no price in call to submit_order'))

        if (price is not None):
            if (order_type.lower() == 'market'):
                raise (ValueError(
                    'Market order has price limit in call to submit_order'))
            price = float(price)
        else:
            price = current_bid_price  # default to current bid price

        if (quantity is None):
            raise (ValueError('No quantity specified in call to submit_order'))

        quantity = int(quantity)

        if (quantity <= 0):
            raise (ValueError(
                'Quantity must be positive number in call to submit_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

        print(payload)

        res = self.session.post(endpoints.orders(), data=payload, timeout=15)
        res.raise_for_status()

        return res