예제 #1
0
def get_quote(ticker, jsonify=None):
    """ Gets quote information for a single stock.

    :param ticker: The ticker of the stock.
    :type ticker: str
    :param jsonify: If set to false, will return the raw response object. \
        If set to True, will return a dictionary parsed using the JSON format.
    :type jsonify: Optional[str]
    :returns: Returns a tuple where the first entry in the tuple is a requests reponse object  \
        or a dictionary parsed using the JSON format and the second entry is an error string or \
        None if there was not an error.

    """
    url = URLS.quote(ticker)
    data, error = request_get(url, None, jsonify)
    return data, error
예제 #2
0
def get_instrument(cusip, jsonify=None):
    """ Gets instrument data for a specific stock.

    :param cusip: The CUSIP for a stock.
    :type cusip: str
    :param jsonify: If set to false, will return the raw response object. \
        If set to True, will return a dictionary parsed using the JSON format.
    :type jsonify: Optional[str]
    :returns: Returns a tuple where the first entry in the tuple is a requests reponse object  \
        or a dictionary parsed using the JSON format and the second entry is an error string or \
        None if there was not an error.

    """
    url = URLS.instrument(cusip)
    data, error = request_get(url, None, jsonify)
    return data, error
예제 #3
0
def get_quotes(tickers, jsonify=None):
    """ Gets quote information for multiple stocks. The stock string should be comma separated with no spaces.

    :param ticker: The string list of stock tickers.
    :type ticker: str
    :param jsonify: If set to false, will return the raw response object. \
        If set to True, will return a dictionary parsed using the JSON format.
    :type jsonify: Optional[str]
    :returns: Returns a tuple where the first entry in the tuple is a requests reponse object  \
        or a dictionary parsed using the JSON format and the second entry is an error string or \
        None if there was not an error.

    """
    url = URLS.quotes()
    payload = {"symbol": tickers}
    data, error = request_get(url, payload, jsonify)
    return data, error
예제 #4
0
def get_transaction(account_id, transaction_id, jsonify=None):
    """ Get account information for a specific account.

    :param account_id: The account id.
    :type account_id: str
    :param transaction_id: The transaction id.
    :type transaction_id: str
    :param jsonify: If set to false, will return the raw response object. \
        If set to True, will return a dictionary parsed using the JSON format.
    :type jsonify: Optional[str]
    :returns: Returns a tuple where the first entry in the tuple is a requests reponse object  \
        or a dictionary parsed using the JSON format and the second entry is an error string or \
        None if there was not an error.
    """
    url = URLS.transaction(account_id, transaction_id)
    data, error = request_get(url, None, jsonify)
    return data, error
예제 #5
0
def place_order(account_id, order_payload, jsonify=None):
    """ Place an order for a given account.

    :param account_id: The account id.
    :type account_id: str
    :param order_payload: A dictionary of key value pairs for the infromation you want to send to order.
    :type order_payload: str
    :param jsonify: If set to false, will return the raw response object. \
        If set to True, will return a dictionary parsed using the JSON format.
    :type jsonify: Optional[str]
    :returns: Returns a tuple where the first entry in the tuple is a requests reponse object  \
        or a dictionary parsed using the JSON format and the second entry is an error string or \
        None if there was not an error.

    """
    url = URLS.orders(account_id)
    data, error = request_headers(url, order_payload, jsonify)
    return data, error
예제 #6
0
def cancel_order(account_id, order_id, jsonify=None):
    """ Cancel an order for a given account.

    :param account_id: The account id.
    :type account_id: str
    :param order_id: The order id.
    :type order_id: str
    :param jsonify: If set to false, will return the raw response object. \
        If set to True, will return a dictionary parsed using the JSON format.
    :type jsonify: Optional[str]
    :returns: Returns a tuple where the first entry in the tuple is a requests reponse object  \
        or a dictionary parsed using the JSON format and the second entry is an error string or \
        None if there was not an error.

    """
    url = URLS.order(account_id, order_id)
    data, error = request_delete(url, jsonify)
    return data, error
예제 #7
0
def get_orders_for_account(account_id,
                           max_results=None,
                           from_time=None,
                           to_time=None,
                           status=None,
                           jsonify=None):
    """ Gets all the orders for a given account.

    :param account_id: The account id.
    :type account_id: Optional[str]
    :param max_results: The max number of orders to retrieve.
    :type max_results: Optional[str]
    :param from_time: Specifies that no orders entered before this time should be returned. Valid ISO-8601 formats are : \
yyyy-MM-dd. Date must be within 60 days from today's date. 'toEnteredTime' must also be set.
    :type from_time: Optional[str]
    :param to_time: Specifies that no orders entered after this time should be returned.Valid ISO-8601 formats are : \
yyyy-MM-dd. 'fromEnteredTime' must also be set.
    :type to_time: Optional[str]
    :param status: Specifies that only orders of this status should be returned. Possible values are \
        AWAITING_PARENT_ORDER, AWAITING_CONDITION, AWAITING_MANUAL_REVIEW, ACCEPTED, AWAITING_UR_OUT, PENDING_ACTIVATION, QUEUED \
        WORKING, REJECTED, PENDING_CANCEL, CANCELED, PENDING_REPLACE, REPLACED, FILLED, EXPIRED
    :type status: Optional[str]
    :param jsonify: If set to false, will return the raw response object. \
        If set to True, will return a dictionary parsed using the JSON format.
    :type jsonify: Optional[str]
    :returns: Returns a tuple where the first entry in the tuple is a requests reponse object  \
        or a dictionary parsed using the JSON format and the second entry is an error string or \
        None if there was not an error.

    """
    url = URLS.orders(account_id)
    payload = {}
    if max_results:
        payload["maxResults"] = max_results
    if from_time:
        payload["fromEnteredTime"] = from_time
    if to_time:
        payload["toEnteredTime"] = to_time
    if status:
        payload["status"] = status
    data, error = request_get(url, payload, jsonify)
    return data, error
예제 #8
0
def get_accounts(options=None, jsonify=None):
    """ Gets all accounts associated with your API keys.

    :param options: Balances displayed by default, additional fields can be added here by adding positions or orders\
        As a comma separated list. Example:"positions,orders"
    :type options: str
    :param jsonify: If set to false, will return the raw response object. \
        If set to True, will return a dictionary parsed using the JSON format.
    :type jsonify: Optional[str]
    :returns: Returns a tuple where the first entry in the tuple is a requests reponse object  \
        or a dictionary parsed using the JSON format and the second entry is an error string or \
        None if there was not an error.
    """
    url = URLS.accounts()
    if options:
        payload = {"fields": options}
    else:
        payload = None
    data, error = request_get(url, payload, jsonify)
    return data, error
예제 #9
0
def get_hours_for_markets(markets, date, jsonify=None):
    """ Gets market hours for various markets.

    :param markets: The markets for which you're requesting market hours, comma-separated. \
        Valid markets are EQUITY, OPTION, FUTURE, BOND, or FOREX.
    :type markets: str
    :param date: The date for which market hours information is requested. Valid ISO-8601 formats are : \
        yyyy-MM-dd and yyyy-MM-dd'T'HH:mm:ssz.
    :type date: str
    :param jsonify: If set to false, will return the raw response object. \
        If set to True, will return a dictionary parsed using the JSON format.
    :type jsonify: Optional[str]
    :returns: Returns a tuple where the first entry in the tuple is a requests reponse object  \
        or a dictionary parsed using the JSON format and the second entry is an error string or \
        None if there was not an error.

    """
    url = URLS.markets()
    payload = {"markets": markets, "date": date}
    data, error = request_get(url, payload, jsonify)
    return data, error
예제 #10
0
def get_transactions(id,
                     type_value=None,
                     symbol=None,
                     start_date=None,
                     end_date=None,
                     jsonify=None):
    """ Get account information for a specific account.

    :param id: The account id.
    :type id: str
    :param type_value: Only transactions with the specified type will be returned. ALL, TRADE, \
        BUY_ONLY, SELL_ONLY, CASH_IN_OR_CASH_OUT, CHECKING, DIVIDEND, INTEREST, OTHER, ADVISOR_FEES
    :type type_value: Optional[str]
    param symbol: Only transactions with the specified symbol will be returned.
    :type symbol: Optional[str]
    param start_date: Only transactions after the Start Date will be returned. \
        Note: The maximum date range is one year. Valid ISO-8601 formats are :yyyy-MM-dd.
    :type start_date: Optional[str]
    param end_date: Only transactions before the End Date will be returned. \
        Note: The maximum date range is one year. Valid ISO-8601 formats are :yyyy-MM-dd.
    :type end_date: Optional[str]
    :param jsonify: If set to false, will return the raw response object. \
        If set to True, will return a dictionary parsed using the JSON format.
    :type jsonify: Optional[str]
    :returns: Returns a tuple where the first entry in the tuple is a requests reponse object  \
        or a dictionary parsed using the JSON format and the second entry is an error string or \
        None if there was not an error.
    """
    url = URLS.transactions(id)
    payload = {}
    if type_value:
        payload["type"] = type_value
    if symbol:
        payload["symbol"] = symbol
    if start_date:
        payload["startDate"] = start_date
    if end_date:
        payload["endDate"] = end_date
    data, error = request_get(url, payload, jsonify)
    return data, error
예제 #11
0
def get_movers(market, direction, change, jsonify=None):
    """ Gets market hours for a specific market.

    :param market: The market for which you're requesting market hours, comma-separated. \
        Valid markets are $DJI, $COMPX, or $SPX.X.
    :type market: str
    :param direction: To return movers with the specified directions of "up" or "down".
    :type direction: str
    :param change: To return movers with the specified change types of "percent" or "value".
    :type change: str
    :param jsonify: If set to false, will return the raw response object. \
        If set to True, will return a dictionary parsed using the JSON format.
    :type jsonify: Optional[str]
    :returns: Returns a tuple where the first entry in the tuple is a requests reponse object  \
        or a dictionary parsed using the JSON format and the second entry is an error string or \
        None if there was not an error.

    """
    url = URLS.movers(market)
    payload = {"direction": direction, "change": change}
    data, error = request_get(url, payload, jsonify)
    return data, error
예제 #12
0
def search_instruments(ticker_string, projection, jsonify=None):
    """ Gets a list of all the instruments data for tickers that match a search string.

    :param ticker_string: Value to pass to the search. See projection description for more information.
    :type ticker_string: str
    :param projection: The type of request:\n
        * symbol-search: Retrieve instrument data of a specific symbol or cusip
        * symbol-regex: Retrieve instrument data for all symbols matching regex. Example: symbol=XYZ.* will return all symbols beginning with XYZ
        * desc-search: Retrieve instrument data for instruments whose description contains the word supplied. Example: symbol=FakeCompany will return all instruments with FakeCompany in the description.
        * desc-regex: Search description with full regex support. Example: symbol=XYZ.[A-C] returns all instruments whose descriptions contain a word beginning with XYZ followed by a character A through C.
        * fundamental: Returns fundamental data for a single instrument specified by exact symbol.
    :type projection: str
    :param jsonify: If set to false, will return the raw response object. \
        If set to True, will return a dictionary parsed using the JSON format.
    :type jsonify: Optional[str]
    :returns: Returns a tuple where the first entry in the tuple is a requests reponse object  \
        or a dictionary parsed using the JSON format and the second entry is an error string or \
        None if there was not an error.

    """
    url = URLS.instruments()
    payload = {"symbol": ticker_string, "projection": projection}
    data, error = request_get(url, payload, jsonify)
    return data, error
def login(encryption_passcode):
    """ Set the authorization token so the API can be used. Gets a new authorization token
    every 30 minutes using the refresh token. Gets a new refresh token every 60 days.

    :param encryption_passcode: Encryption key created by generate_encryption_passcode().
    :type encryption_passcode: str
    
    """
    if type(encryption_passcode) is str:
        encryption_passcode = encryption_passcode.encode()
    cipher_suite = Fernet(encryption_passcode)
    # Check that file exists before trying to read from it.
    data_dir = Path.home().joinpath(DATA_DIR_NAME)
    pickle_path = data_dir.joinpath(PICKLE_NAME)
    if not pickle_path.exists():
        raise FileExistsError(
            "Please Call login_first_time() to create pickle file.")
    # Read the information from the pickle file.
    with pickle_path.open("rb") as pickle_file:
        pickle_data = pickle.load(pickle_file)
        access_token = cipher_suite.decrypt(
            pickle_data['authorization_token']).decode()
        refresh_token = cipher_suite.decrypt(
            pickle_data['refresh_token']).decode()
        client_id = cipher_suite.decrypt(pickle_data['client_id']).decode()
        authorization_timestamp = pickle_data['authorization_timestamp']
        refresh_timestamp = pickle_data['refresh_timestamp']
    # Authorization tokens expire after 30 mins. Refresh tokens expire after 90 days,
    # but you need to request a fresh authorization and refresh token before it expires.
    authorization_delta = timedelta(seconds=1800)
    refresh_delta = timedelta(days=60)
    url = URLS.oauth()
    # If it has been longer than 60 days. Get a new refresh and authorization token.
    # Else if it has been longer than 30 minutes, get only a new authorization token.
    if (datetime.now() - refresh_timestamp > refresh_delta):
        payload = {
            "grant_type": "refresh_token",
            "access_type": "offline",
            "refresh_token": refresh_token,
            "client_id": client_id
        }
        data, _ = request_data(url, payload, True)
        if "access_token" not in data and "refresh_token" not in data:
            raise ValueError(
                "Refresh token is no longer valid. Call login_first_time() to get a new refresh token."
            )
        access_token = data["access_token"]
        refresh_token = data["refresh_token"]
        with pickle_path.open("wb") as pickle_file:
            pickle.dump(
                {
                    'authorization_token':
                    cipher_suite.encrypt(access_token.encode()),
                    'refresh_token':
                    cipher_suite.encrypt(refresh_token.encode()),
                    'client_id':
                    cipher_suite.encrypt(client_id.encode()),
                    'authorization_timestamp':
                    datetime.now(),
                    'refresh_timestamp':
                    datetime.now()
                }, pickle_file)
    elif (datetime.now() - authorization_timestamp > authorization_delta):
        payload = {
            "grant_type": "refresh_token",
            "refresh_token": refresh_token,
            "client_id": client_id
        }
        data, _ = request_data(url, payload, True)
        if "access_token" not in data:
            raise ValueError(
                "Refresh token is no longer valid. Call login_first_time() to get a new refresh token."
            )
        access_token = data["access_token"]
        # Write new data to file. Do not replace the refresh timestamp.
        with pickle_path.open("wb") as pickle_file:
            pickle.dump(
                {
                    'authorization_token':
                    cipher_suite.encrypt(access_token.encode()),
                    'refresh_token':
                    cipher_suite.encrypt(refresh_token.encode()),
                    'client_id':
                    cipher_suite.encrypt(client_id.encode()),
                    'authorization_timestamp':
                    datetime.now(),
                    'refresh_timestamp':
                    refresh_timestamp
                }, pickle_file)
    # Store authorization token in session information to be used with API calls.
    auth_token = "Bearer {0}".format(access_token)
    update_session("Authorization", auth_token)
    update_session("apikey", client_id)
    set_login_state(True)
    return auth_token
예제 #14
0
def get_price_history(ticker,
                      period_type,
                      frequency_type,
                      frequency,
                      period=None,
                      start_date=None,
                      end_date=None,
                      needExtendedHoursData=True,
                      jsonify=None):
    """ Gets the price history of a stock.

    :param ticker: The stock ticker.
    :type ticker: str
    :param period_type: The type of period to show. Valid values are day, month, year, or ytd (year to date). Default is day.
    :type period_type: str
    :param frequency_type: The type of frequency with which a new candle is formed. \
        Valid frequencyTypes by period_type (defaults marked with an asterisk):\n
        * day: minute*
        * month: daily, weekly* 
        * year: daily, weekly, monthly* 
        * ytd: daily, weekly*
    :type frequency_type: str
    :param frequency: The number of the frequencyType to be included in each candle. \
        Valid frequencies by frequencyType (defaults marked with an asterisk):\n
        * minute: 1*, 5, 10, 15, 30
        * daily: 1*
        * weekly: 1*
        * monthly: 1*
    :type frequency: str
    :param period: The number of periods to show. Valid periods by periodType (defaults marked with an asterisk):\n
        * day: 1, 2, 3, 4, 5, 10*
        * month: 1*, 2, 3, 6
        * year: 1*, 2, 3, 5, 10, 15, 20
        * ytd: 1*
    :type period: Optional[str]
    :param start_date: Start date as milliseconds since epoch. If startDate and endDate are provided, period should not be provided.
    :type start_date: Optional[str]
    :param end_date: End date as milliseconds since epoch. If startDate and endDate are provided, period should not be provided. Default is previous trading day.
    :type end_date: Optional[str]
    :param needExtendedHoursData: true to return extended hours data, false for regular market hours only. Default is true.
    :type needExtendedHoursData: Optional[str]
    :param jsonify: If set to false, will return the raw response object. \
        If set to True, will return a dictionary parsed using the JSON format.
    :type jsonify: Optional[str]
    :returns: Returns a tuple where the first entry in the tuple is a requests reponse object  \
        or a dictionary parsed using the JSON format and the second entry is an error string or \
        None if there was not an error.

    """
    if (start_date or end_date) and period:
        raise ValueError(
            "If start_date and end_date are provided, period should not be provided."
        )
    url = URLS.price_history(ticker)
    payload = {
        "periodType": period_type,
        "frequencyType": frequency_type,
        "frequency": frequency,
        "needExtendedHoursData": needExtendedHoursData
    }
    if period:
        payload["period"] = period
    if start_date:
        payload["startDate"] = start_date
    if end_date:
        payload["endDate"] = end_date
    data, error = request_get(url, payload, jsonify)
    return data, error
예제 #15
0
def get_option_chains(ticker,
                      contract_type="ALL",
                      strike_count="10",
                      include_quotes="FALSE",
                      strategy="SINGLE",
                      interval=None,
                      strike_price=None,
                      range_value="ALL",
                      from_date=None,
                      to_date=None,
                      volatility=None,
                      underlying_price=None,
                      interest_rate=None,
                      days_to_expiration=None,
                      exp_month="ALL",
                      option_type="ALL",
                      jsonify=None):
    """ Gets instrument data for a specific stock.

    :param ticker: The stock ticker.
    :type ticker: str
    :param contract_type: Type of contracts to return in the chain. Can be CALL, PUT, or ALL. Default is ALL.
    :type contract_type: Optional[str]
    :param strike_count: The number of strikes to return above and below the at-the-money price.
    :type strike_count: Optional[str]
    :param include_quotes: Include quotes for options in the option chain. Can be TRUE or FALSE. Default is FALSE.
    :type include_quotes: Optional[str]
    :param strategy: Passing a value returns a Strategy Chain. Possible values are SINGLE, ANALYTICAL (allows use of the volatility, \
        underlyingPrice, interestRate, and daysToExpiration params to calculate theoretical values), COVERED, VERTICAL, CALENDAR, \
        STRANGLE, STRADDLE, BUTTERFLY, CONDOR, DIAGONAL, COLLAR, or ROLL. Default is SINGLE.
    :type strategy: Optional[str]
    :param interval: Strike interval for spread strategy chains (see strategy param).
    :type interval: Optional[str]
    :param strike_price: Provide a strike price to return options only at that strike price.
    :type strike_price: Optional[str]
    :param range_value: Returns options for the given range. Default is ALL. Possible values are:\n
        * ITM: In-the-money
        * NTM: Near-the-money
        * OTM: Out-of-the-money
        * SAK: Strikes Above Market
        * SBK: Strikes Below Market
        * SNK: Strikes Near Market
        * ALL: All Strikes
    :type range_value: Optional[str]
    :param from_date: Only return expirations after this date. For strategies, expiration refers to the \
        nearest term expiration in the strategy. Valid ISO-8601 formats are: yyyy-MM-dd and yyyy-MM-dd'T'HH:mm:ssz.
    :type from_date: Optional[str]
    :param to_date: Only return expirations before this date. For strategies, expiration refers to the \
        nearest term expiration in the strategy. Valid ISO-8601 formats are: yyyy-MM-dd and yyyy-MM-dd'T'HH:mm:ssz.
    :type to_date: Optional[str]
    :param volatility: Volatility to use in calculations. Applies only to ANALYTICAL strategy chains (see strategy param).
    :type volatility: Optional[str]
    :param underlying_price: Underlying price to use in calculations. Applies only to ANALYTICAL strategy chains (see strategy param).
    :type underlying_price: Optional[str]
    :param interest_rate: Interest rate to use in calculations. Applies only to ANALYTICAL strategy chains (see strategy param).
    :type interest_rate: Optional[str]
    :param days_to_expiration: Days to expiration to use in calculations. Applies only to ANALYTICAL strategy chains (see strategy param).
    :type days_to_expiration: Optional[str]
    :param exp_month: Return only options expiring in the specified month. Month is given in the three character format. Example: JAN. Default is ALL.
    :type exp_month: Optional[str]
    :param option_type: Type of contracts to return. Default is ALL. Possible values are:\n
        * S: Standard contracts
        * NS: Non-standard contracts
        * ALL: All contracts
    :type option_type: Optional[str]
    :param jsonify: If set to false, will return the raw response object. \
        If set to True, will return a dictionary parsed using the JSON format.
    :type jsonify: Optional[str]
    :returns: Returns a tuple where the first entry in the tuple is a requests reponse object  \
        or a dictionary parsed using the JSON format and the second entry is an error string or \
        None if there was not an error.

    """
    url = URLS.option_chains()
    payload = {
        "symbol": ticker,
        "contractType": contract_type,
        "strikeCount": strike_count,
        "includeQuotes": include_quotes,
        "strategy": strategy,
        "range": range_value,
        "expMonth": exp_month,
        "optionType": option_type
    }
    if interval:
        payload["interval"] = interval
    if strike_price:
        payload["strike"] = strike_price
    if from_date:
        payload["fromDate"] = from_date
    if to_date:
        payload["toDate"] = to_date
    if volatility:
        payload["volatility"] = volatility
    if underlying_price:
        payload["underlyingPrice"] = underlying_price
    if interest_rate:
        payload["interestRate"] = interest_rate
    if days_to_expiration:
        payload["daysToExpiration"] = days_to_expiration
    data, error = request_get(url, payload, jsonify)
    return data, error