Ejemplo n.º 1
0
def order(symbol, quantity, orderType, trigger, side, limitPrice = None, stopPrice = None, timeInForce = 'gtc', extendedHours = False):
    """A generic order function. All parameters must be supplied.

    :param symbol: The stock ticker of the stock to sell.
    :type symbol: str
    :param quantity: The number of stocks to sell.
    :type quantity: int
    :param orderType: Either 'market' or 'limit'
    :type orderType: str
    :param trigger: Either 'immediate' or 'stop'
    :type trigger: str
    :param side: Either 'buy' or 'sell'
    :type side: str
    :param limitPrice: The price to trigger the market order.
    :type limitPrice: float
    :param stopPrice: The price to trigger the limit or market order.
    :type stopPrice: float
    :param timeInForce: Changes how long the order will be in effect for. 'gtc' = good until cancelled. \
    'gfd' = good for the day. 'ioc' = immediate or cancel. 'opg' execute at opening.
    :type timeInForce: str
    :param extendedHours: Premium users only. Allows trading during extended hours. Should be true or false.
    :type extendedHours: Optional[str]
    :returns: Dictionary that contains information regarding the purchase or selling of stocks, \
    such as the order id, the state of order (queued,confired,filled, failed, canceled, etc.), \
    the price, and the quantity.

    """
    try:
        symbol = symbol.upper().strip()
    except AttributeError as message:
        print(message)
        return None

    if stopPrice:
        stopPrice = helper.round_price(stopPrice)

    if limitPrice:
        limitPrice = helper.round_price(limitPrice)
    else:
        limitPrice = helper.round_price(stocks.get_latest_price(symbol)[0])
    payload = {
    'account': profiles.load_account_profile(info='url'),
    'instrument': stocks.get_instruments_by_symbols(symbol, info='url')[0],
    'symbol': symbol,
    'price': limitPrice,
    'quantity': quantity,
    'ref_id': str(uuid4()),
    'type': orderType,
    'stop_price': stopPrice,
    'time_in_force': timeInForce,
    'trigger': trigger,
    'side': side,
    'extended_hours': extendedHours
    }

    url = urls.orders()
    data = helper.request_post(url, payload)

    return(data)
Ejemplo n.º 2
0
def order_sell_stop_limit(symbol,
                          quantity,
                          limitPrice,
                          stopPrice,
                          timeInForce='gtc',
                          extendedHours=False):
    """Submits a stop order to be turned into a limit order once a certain stop price is reached.

    :param symbol: The stock ticker of the stock to sell.
    :type symbol: str
    :param quantity: The number of stocks to sell.
    :type quantity: int
    :param limitPrice: The price to trigger the market order.
    :type limitPrice: float
    :param stopPrice: The price to trigger the limit order.
    :type stopPrice: float
    :param timeInForce: Changes how long the order will be in effect for. 'gtc' = good until cancelled. \
    'gfd' = good for the day. 'ioc' = immediate or cancel. 'opg' execute at opening.
    :type timeInForce: Optional[str]
    :param extendedHours: Premium users only. Allows trading during extended hours. Should be true or false.
    :type extendedHours: Optional[str]
    :returns: Dictionary that contains information regarding the selling of stocks, \
    such as the order id, the state of order (queued,confired,filled, failed, canceled, etc.), \
    the price, and the quantity.

    """
    try:
        symbol = symbol.upper().strip()
        latestPrice = helper.round_price(stocks.get_latest_price(symbol)[0])
        stopPrice = helper.round_price(stopPrice)
        limitPrice = helper.round_price(limitPrice)
    except AttributeError as message:
        print(message)
        return None

    if (latestPrice < stopPrice):
        print('Error: stopPrice must be below the current price.')
        return (None)

    payload = {
        'account': profiles.load_account_profile(info='url'),
        'instrument': stocks.get_instruments_by_symbols(symbol, info='url')[0],
        'symbol': symbol,
        'price': limitPrice,
        'quantity': quantity,
        'ref_id': str(uuid4()),
        'type': 'limit',
        'stop_price': stopPrice,
        'time_in_force': timeInForce,
        'trigger': 'stop',
        'side': 'sell',
        'extended_hours': extendedHours
    }

    url = urls.orders()
    data = helper.request_post(url, payload)

    return (data)
Ejemplo n.º 3
0
def build_holdings():
    """Builds a dictionary of important information regarding the stocks and positions owned by the user.

    :returns: Returns a dictionary where the keys are the stock tickers and the value is another dictionary \
    that has the stock price, quantity held, equity, percent change, equity change, type, name, id, pe ratio, \
    percentage of portfolio, and average buy price.

    """
    positions_data = get_current_positions()
    portfolios_data = profiles.load_portfolio_profile()
    accounts_data = profiles.load_account_profile()

    if not positions_data or not portfolios_data or not accounts_data:
        return({})

    if portfolios_data['extended_hours_equity'] is not None:
        total_equity = max(float(portfolios_data['equity']),float(portfolios_data['extended_hours_equity']))
    else:
        total_equity = float(portfolios_data['equity'])

    cash = "{0:.2f}".format(float(accounts_data['cash'])+float(accounts_data['uncleared_deposits']))

    holdings = {}
    for item in positions_data:
        # It is possible for positions_data to be [None]
        if not item:
            continue

        try:
            instrument_data = stocks.get_instrument_by_url(item['instrument'])
            symbol = instrument_data['symbol']
            fundamental_data = stocks.get_fundamentals(symbol)[0]

            price           = stocks.get_latest_price(instrument_data['symbol'])[0]
            quantity        = item['quantity']
            equity          = float(item['quantity'])*float(price)
            equity_change   = (float(quantity)*float(price))-(float(quantity)*float(item['average_buy_price']))
            percentage      = float(item['quantity'])*float(price)*100/(float(total_equity)-float(cash))
            if (float(item['average_buy_price']) == 0.0):
                percent_change = 0.0
            else:
                percent_change  = (float(price)-float(item['average_buy_price']))*100/float(item['average_buy_price'])

            holdings[symbol]=({'price': price })
            holdings[symbol].update({'quantity': quantity})
            holdings[symbol].update({'average_buy_price': item['average_buy_price']})
            holdings[symbol].update({'equity':"{0:.2f}".format(equity)})
            holdings[symbol].update({'percent_change': "{0:.2f}".format(percent_change)})
            holdings[symbol].update({'equity_change':"{0:2f}".format(equity_change)})
            holdings[symbol].update({'type': instrument_data['type']})
            holdings[symbol].update({'name': stocks.get_name_by_symbol(symbol)})
            holdings[symbol].update({'id': instrument_data['id']})
            holdings[symbol].update({'pe_ratio': fundamental_data['pe_ratio'] })
            holdings[symbol].update({'percentage': "{0:.2f}".format(percentage)})
        except:
            pass

    return(holdings)
Ejemplo n.º 4
0
def order_buy_stop_limit(symbol,quantity,limitPrice,stopPrice,timeInForce='gtc'):
    """Submits a stop order to be turned into a limit order once a certain stop price is reached.

    :param symbol: The stock ticker of the stock to purchase.
    :type symbol: str
    :param quantity: The number of stocks to buy.
    :type quantity: int
    :param limitPrice: The price to trigger the market order.
    :type limitPrice: float
    :param stopPrice: The price to trigger the limit order.
    :type stopPrice: float
    :param timeInForce: Changes how long the order will be in effect for. 'gtc' = good until cancelled. \
    'gfd' = good for the day. 'ioc' = immediate or cancel. 'opg' execute at opening.
    :type timeInForce: Optional[str]
    :returns: Dictionary that contains information regarding the purchase of stocks, \
    such as the order id, the state of order (queued,confired,filled, failed, canceled, etc.), \
    the price, and the quantity.

    """
    try:
        symbol = symbol.upper().strip()
        latestPrice = float(stocks.get_latest_price(symbol)[0])
        stopPrice = float(stopPrice)
        limitPrice = float(limitPrice)
    except AttributeError as message:
        print(message)
        return None

    if (latestPrice > stopPrice):
        print('Error: stopPrice must be above the current price.')
        return(None)

    payload = {
    'account': profiles.load_account_profile(info='url'),
    'instrument': stocks.get_instruments_by_symbols(symbol,info='url')[0],
    'symbol': symbol,
    'price': limitPrice,
    'quantity': quantity,
    'ref_id': helper.get_device_token(),
    'type': 'limit',
    'stop_price': stopPrice,
    'time_in_force': timeInForce,
    'trigger': 'stop',
    'side': 'buy'
    }

    url = urls.orders()
    data = helper.request_post(url,payload)

    return(data)
Ejemplo n.º 5
0
def order_buy_market(symbol,
                     quantity,
                     timeInForce='gtc',
                     extendedHours='false'):
    """Submits a market order to be executed immediately.

    :param symbol: The stock ticker of the stock to purchase.
    :type symbol: str
    :param quantity: The number of stocks to buy.
    :type quantity: int
    :param timeInForce: Changes how long the order will be in effect for. 'gtc' = good until cancelled. \
    'gfd' = good for the day. 'ioc' = immediate or cancel. 'opg' execute at opening.
    :type timeInForce: Optional[str]
    :param extendedHours: Premium users only. Allows trading during extended hours. Should be true or false.
    :type extendedHours: str
    :returns: Dictionary that contains information regarding the purchase of stocks, \
    such as the order id, the state of order (queued,confired,filled, failed, canceled, etc.), \
    the price, and the quantity.

    """
    try:
        symbol = symbol.upper().strip()
    except AttributeError as message:
        print(message)
        return None

    payload = {
        'account': profiles.load_account_profile(info='url'),
        'instrument': stocks.get_instruments_by_symbols(symbol, info='url')[0],
        'symbol': symbol,
        'price': float(stocks.get_latest_price(symbol)[0]),
        'quantity': quantity,
        'ref_id': str(uuid4()),
        'type': 'market',
        'stop_price': None,
        'time_in_force': timeInForce,
        'trigger': 'immediate',
        'side': 'buy',
        "extended_hours": extendedHours
    }

    url = urls.orders()
    data = helper.request_post(url, payload)

    return (data)
Ejemplo n.º 6
0
def build_holdings(access_token, with_dividends=False):
    """Builds a dictionary of important information regarding the stocks and positions owned by the user.

    :param with_dividends: True if you want to include divident information.
    :type with_dividends: bool
    :returns: Returns a dictionary where the keys are the stock tickers and the value is another dictionary \
    that has the stock price, quantity held, equity, percent change, equity change, type, name, id, pe ratio, \
    percentage of portfolio, and average buy price.

    """
    positions_data = get_open_stock_positions(access_token)
    portfolios_data = profiles.load_portfolio_profile(access_token)
    accounts_data = profiles.load_account_profile(access_token)

    # user wants dividend information in their holdings
    if with_dividends is True:
        dividend_data = get_dividends()

    if not positions_data or not portfolios_data or not accounts_data:
        return ({})

    if portfolios_data['extended_hours_equity'] is not None:
        total_equity = max(float(portfolios_data['equity']),
                           float(portfolios_data['extended_hours_equity']))
    else:
        total_equity = float(portfolios_data['equity'])

    cash = "{0:.2f}".format(
        float(accounts_data['cash']) +
        float(accounts_data['uncleared_deposits']))

    holdings = {}
    for item in positions_data:
        # It is possible for positions_data to be [None]
        if not item:
            continue

        try:
            instrument_data = stocks.get_instrument_by_url(item['instrument'],
                                                           access_token,
                                                           info=None)
            symbol = instrument_data['symbol']
            # fundamental_data = stocks.get_fundamentals(symbol, access_token, info=None)[0]

            price = stocks.get_latest_price(instrument_data['symbol'],
                                            access_token=access_token)[0]
            quantity = item['quantity']
            equity = float(item['quantity']) * float(price)
            equity_change = (float(quantity) * float(price)) - \
                (float(quantity) * float(item['average_buy_price']))
            percentage = float(item['quantity']) * float(price) * \
                100 / (float(total_equity) - float(cash))
            if (float(item['average_buy_price']) == 0.0):
                percent_change = 0.0
            else:
                percent_change = (float(price) - float(
                    item['average_buy_price'])) * 100 / float(
                        item['average_buy_price'])

            holdings[symbol] = ({'price': price})
            holdings[symbol].update({'quantity': quantity})
            holdings[symbol].update(
                {'average_buy_price': item['average_buy_price']})
            holdings[symbol].update({'equity': "{0:.2f}".format(equity)})
            holdings[symbol].update(
                {'percent_change': "{0:.2f}".format(percent_change)})
            holdings[symbol].update(
                {'equity_change': "{0:2f}".format(equity_change)})
            holdings[symbol].update(
                {'percentage': "{0:2f}".format(percentage)})
            holdings[symbol].update({'type': instrument_data['type']})
            holdings[symbol].update(
                {'name': stocks.get_name_by_symbol(symbol)})
            holdings[symbol].update({'id': instrument_data['id']})
            # holdings[symbol].update(
            #     {'percentage': "{0:2f}".format(percentage)})
            # holdings[symbol].update({'pe_ratio': fundamental_data['pe_ratio']})

            if with_dividends is True:
                # dividend_data was retrieved earlier
                holdings[symbol].update(
                    get_dividends_by_instrument(item['instrument'],
                                                dividend_data))

        except:
            pass

    return (holdings)
Ejemplo n.º 7
0
def find_options_by_expiration_and_strike_count(inputSymbols,
                                                expirationDate,
                                                strikeCount,
                                                optionType=None,
                                                info=None):
    """Returns a list of all the option orders that match the search parameters

    :param inputSymbols: The ticker of either a single stock or a list of stocks.
    :type inputSymbols: str
    :param expirationDate: Represents the expiration date in the format YYYY-MM-DD.
    :type expirationDate: str
    :param optionType: Can be either 'call' or 'put' or leave blank to get both.
    :type optionType: Optional[str]
    :param strikeCount: Number of strikes to return above and below ATM price
    :type strikeCount: intd
    :param info: Will filter the results to get a specific value.
    :type info: Optional[str]
    :returns: Returns a list of dictionaries of key/value pairs for all options
        of the stock that match the search parameters.
        If info parameter is provided, a list of strings is
        returned where the strings are the value of the key that matches info.
    """

    try:
        symbols = helper.inputs_to_set(inputSymbols)
        if optionType:
            optionType = optionType.lower().strip()
    except AttributeError as message:
        print(message)
        return [None]

    data = []
    for symbol in symbols:
        underlying = float(stocks.get_latest_price(symbol)[0])
        allOptions = find_tradable_options(symbol, expirationDate, None,
                                           optionType, None)
        strikes = []
        for each in allOptions:
            strikePrice = each['strike_price']
            strikes.append(
                strikePrice) if strikePrice not in strikes else strikes
        sortedStrikes = list(map(float, strikes))
        sortedStrikes.sort()
        filteredStrikes = find_strikes(sortedStrikes, strikeCount, underlying)
        for x in range(0, len(filteredStrikes)):
            filteredStrikes[x] = '%.4f' % filteredStrikes[
                x]  # DO NOT CHANGE ROUNDING

        x = 0
        while x < len(allOptions):
            if allOptions[x]['strike_price'] not in filteredStrikes:
                allOptions.remove(allOptions[x])
            else:
                x = x + 1

        for item in allOptions:
            marketData = get_option_market_data_by_id(item['id'])
            item.update(marketData)
            # write_spinner()

        data.extend(allOptions)

    return (helper.filter(data, info))