Exemplo n.º 1
0
def load_portfolio_profile(info=None):
    """Gets the information associated with the portfolios profile,
    such as withdrawable amount, market value of account, and excess margin.

    :param info: The name of the key whose value is to be returned from the function.
    :type info: Optional[str]
    :returns: The function returns a dictionary of key/value pairs. \
    If a string is passed in to the info parameter, then the function will return \
    a string corresponding to the value of the key whose name matches the info parameter.

    """
    url = urls.portfolio_profile()
    data = helper.request_get(url, 'indexzero')
    return (helper.filter(data, info))
Exemplo n.º 2
0
def load_portfolio_profile(info=None):
    """Gets the information associated with the portfolios profile,
    such as withdrawable amount, market value of account, and excess margin.

    :param info: The name of the key whose value is to be returned from the function.
    :type info: Optional[str]
    :returns: The function returns a dictionary of key/value pairs. \
    If a string is passed in to the info parameter, then the function will return \
    a string corresponding to the value of the key whose name matches the info parameter.
    :Dictionary Keys: * url
                      * account
                      * start_date
                      * market_value
                      * equity
                      * extended_hours_market_value
                      * extended_hours_equity
                      * extended_hours_portfolio_equity
                      * last_core_market_value
                      * last_core_equity
                      * last_core_portfolio_equity
                      * excess_margin
                      * excess_maintenance
                      * excess_margin_with_uncleared_deposits
                      * excess_maintenance_with_uncleared_deposits
                      * equity_previous_close
                      * portfolio_equity_previous_close
                      * adjusted_equity_previous_close
                      * adjusted_portfolio_equity_previous_close
                      * withdrawable_amount
                      * unwithdrawable_deposits
                      * unwithdrawable_grants

    """
    url = urls.portfolio_profile()
    data = helper.request_get(url, 'indexzero')
    return (helper.filter_data(data, info))
Exemplo n.º 3
0
def login(username,
          password,
          expiresIn=86400,
          scope='internal',
          by_sms=True,
          store_session=True):
    """This function will effectivly log the user into robinhood by getting an
    authentication token and saving it to the session header. By default, it will store the authentication
    token in a pickle file and load that value on subsequent logins.

    :param username: The username for your robinhood account. Usually your email.
    :type username: str
    :param password: The password for your robinhood account.
    :type password: str
    :param expiresIn: The time until your login session expires. This is in seconds.
    :type expiresIn: Optional[int]
    :param scope: Specifies the scope of the authentication.
    :type scope: Optional[str]
    :param by_sms: Specifies whether to send an email(False) or an sms(True)
    :type by_sms: Optional[boolean]
    :param store_session: Specifies whether to save the log in authorization for future log ins.
    :type store_session: Optional[boolean]
    :returns:  A dictionary with log in information. The 'access_token' keyword contains the access token, and the 'detail' keyword \
    contains information on whether the access token was generated or loaded from pickle file.

    """
    device_token = generate_device_token()
    dir_path = os.path.dirname(os.path.realpath(__file__))
    pickle_path = os.path.join(dir_path, "data.pickle")
    # Challenge type is used if not logging in with two-factor authentication.
    if by_sms:
        challenge_type = "sms"
    else:
        challenge_type = "email"

    url = urls.login_url()
    payload = {
        'client_id': 'c82SH0WZOsabOXGP2sxqcj34FxkvfnWRZBKlBjFS',
        'expires_in': expiresIn,
        'grant_type': 'password',
        'password': password,
        'scope': scope,
        'username': username,
        'challenge_type': challenge_type,
        'device_token': device_token
    }
    # If authentication has been stored in pickle file then load it. Stops login server from being pinged so much.
    if os.path.isfile(pickle_path):
        # If store_session has been set to false then delete the pickle file, otherwise try to load it.
        # Loading pickle file will fail if the acess_token has expired.
        if store_session:
            try:
                with open(pickle_path, 'rb') as f:
                    pickle_data = pickle.load(f)
                    access_token = pickle_data['access_token']
                    token_type = pickle_data['token_type']
                    refresh_token = pickle_data['refresh_token']
                    # Set device_token to be the original device token when first logged in.
                    pickle_device_token = pickle_data['device_token']
                    payload['device_token'] = pickle_device_token
                    # Set login status to True in order to try and get account info.
                    helper.set_login_state(True)
                    helper.update_session(
                        'Authorization',
                        '{0} {1}'.format(token_type, access_token))
                    # Try to load account profile to check that authorization token is still valid.
                    res = helper.request_get(urls.portfolio_profile(),
                                             'regular',
                                             payload,
                                             jsonify_data=False)
                    # Raises exception is response code is not 200.
                    res.raise_for_status()
                    return ({
                        'access_token': access_token,
                        'token_type': token_type,
                        'expires_in': expiresIn,
                        'scope': scope,
                        'detail':
                        'logged in using authentication in data.pickle',
                        'backup_code': None,
                        'refresh_token': refresh_token
                    })
            except:
                print(
                    "ERROR: There was an issue loading pickle file. Authentication may be expired - logging in normally."
                )
                helper.set_login_state(False)
                helper.update_session('Authorization', None)
        else:
            os.remove(pickle_path)
    # Try to log in normally.
    data = helper.request_post(url, payload)
    # Handle case where mfa or challenge is required.
    if 'mfa_required' in data:
        mfa_token = input("Please type in the MFA code: ")
        payload['mfa_code'] = mfa_token
        res = helper.request_post(url, payload, jsonify_data=False)
        while (res.status_code != 200):
            mfa_token = input(
                "That MFA code was not correct. Please type in another MFA code: "
            )
            payload['mfa_code'] = mfa_token
            res = helper.request_post(url, payload, jsonify_data=False)
        data = res.json()
    elif 'challenge' in data:
        challenge_id = data['challenge']['id']
        sms_code = input('Enter Robinhood code for validation: ')
        res = respond_to_challenge(challenge_id, sms_code)
        while 'challenge' in res and res['challenge']['remaining_attempts'] > 0:
            sms_code = input(
                'That code was not correct. {0} tries remaining. Please type in another code: '
                .format(res['challenge']['remaining_attempts']))
            res = respond_to_challenge(challenge_id, sms_code)
        helper.update_session('X-ROBINHOOD-CHALLENGE-RESPONSE-ID',
                              challenge_id)
        data = helper.request_post(url, payload)
    # Update Session data with authorization or raise exception with the information present in data.
    if 'access_token' in data:
        token = '{0} {1}'.format(data['token_type'], data['access_token'])
        helper.update_session('Authorization', token)
        helper.set_login_state(True)
        data['detail'] = "logged in with brand new authentication code."
        if store_session:
            with open(pickle_path, 'wb') as f:
                pickle.dump(
                    {
                        'token_type': data['token_type'],
                        'access_token': data['access_token'],
                        'refresh_token': data['refresh_token'],
                        'device_token': device_token
                    }, f)
    else:
        raise Exception(data['detail'])
    return (data)
Exemplo n.º 4
0
def login():
    """This function will effectively log the user into robinhood by getting an
    authentication token and saving it to the session header. By default, it
    will store the authentication token in a pickle file and load that value
    on subsequent logins.
    :param username: The username for your robinhood account, usually your email.
        Not required if credentials are already cached and valid.
    :type username: Optional[str]
    :param password: The password for your robinhood account. Not required if
        credentials are already cached and valid.
    :type password: Optional[str]
    :param expiresIn: The time until your login session expires. This is in seconds.
    :type expiresIn: Optional[int]
    :param scope: Specifies the scope of the authentication.
    :type scope: Optional[str]
    :param by_sms: Specifies whether to send an email(False) or an sms(True)
    :type by_sms: Optional[boolean]
    :param store_session: Specifies whether to save the log in authorization
        for future log ins.
    :type store_session: Optional[boolean]
    :param mfa_code: MFA token if enabled.
    :type mfa_code: Optional[str]
    :returns:  A dictionary with log in information. The 'access_token' keyword contains the access token, and the 'detail' keyword \
    contains information on whether the access token was generated or loaded from pickle file.
    """
    print('logging in')
    username = None
    password = None
    expiresIn = 86400
    scope = 'internal'
    by_sms = True
    store_session = True
    mfa_code = None

    device_token = generate_device_token()
    # home_dir = path if path else os.path.expanduser("~")
    home_dir = os.path.expanduser("~")
    data_dir = os.path.join(home_dir, ".tokens")
    if not os.path.exists(data_dir):
        os.makedirs(data_dir)
    creds_file = "robinhood.pickle"
    pickle_path = os.path.join(data_dir, creds_file)
    print(pickle_path)
    # Challenge type is used if not logging in with two-factor authentication.
    if by_sms:
        challenge_type = "sms"
    else:
        challenge_type = "email"

    url = urls.login_url()
    payload = {
        'client_id': 'c82SH0WZOsabOXGP2sxqcj34FxkvfnWRZBKlBjFS',
        'expires_in': expiresIn,
        'grant_type': 'password',
        'password': password,
        'scope': scope,
        'username': username,
        'challenge_type': challenge_type,
        'device_token': device_token
    }

    if mfa_code:
        payload['mfa_code'] = mfa_code

    # If authentication has been stored in pickle file then load it. Stops login server from being pinged so much.
    if os.path.isfile(pickle_path):
    # if blob_pickle_path:
        # If store_session has been set to false then delete the pickle file, otherwise try to load it.
        # Loading pickle file will fail if the acess_token has expired.
        if store_session:
            try:
                with open(pickle_path, 'rb') as f:
                # if blob_pickle_path:
                    pickle_data = pickle.load(f)
                    print('loaded pickle')
                    # pickle_data = pickle.loads(blob_pickle)
                    # print('loaded blob_pickle')
                    access_token = pickle_data['access_token']
                    token_type = pickle_data['token_type']
                    refresh_token = pickle_data['refresh_token']
                    # Set device_token to be the original device token when first logged in.
                    pickle_device_token = pickle_data['device_token']
                    payload['device_token'] = pickle_device_token
                    # Set login status to True in order to try and get account info.
                    helper.set_login_state(True)
                    helper.update_session(
                        'Authorization', '{0} {1}'.format(token_type, access_token))
                    # Try to load account profile to check that authorization token is still valid.
                    res = helper.request_get(
                        urls.portfolio_profile(), 'regular', payload, jsonify_data=False)
                    # Raises exception is response code is not 200.
                    res.raise_for_status()
                    return({'access_token': access_token, 'token_type': token_type,
                            'expires_in': expiresIn, 'scope': scope, 'detail': 'logged in using authentication in {0}'.format(creds_file),
                            'backup_code': None, 'refresh_token': refresh_token})
            except:
                print(
                    "ERROR: There was an issue loading pickle file. Authentication may be expired - logging in normally.", file=helper.get_output())

                helper.set_login_state(False)
                helper.update_session('Authorization', None)
        else:
            os.remove(pickle_path)

    # Try to log in normally.
    if not username:
        # username = input("Robinhood username: "******"RB_USER")

    if not password:
        # password = getpass.getpass("Robinhood password: "******"RB_PASS")

    data = helper.request_post(url, payload)
    # Handle case where mfa or challenge is required.
    if data:
        if 'mfa_required' in data:
            # totp = str(pyotp.TOTP(access_secret_version('quantwannabe', 'RB_TOKEN', 'latest')).now())
            totp = str(pyotp.TOTP(os.environ.get("RB_TOKEN")).now())
            print(f"logging in with {totp} at {str(datetime.now())}")
            # mfa_token = input("Please type in the MFA code: ")
            mfa_token=totp
            payload['mfa_code'] = mfa_token
            res = helper.request_post(url, payload, jsonify_data=False)
            while (res.status_code != 200):
                mfa_token = input(
                    "That MFA code was not correct. Please type in another MFA code: ")
                payload['mfa_code'] = mfa_token
                res = helper.request_post(url, payload, jsonify_data=False)
            data = res.json()
        elif 'challenge' in data:
            challenge_id = data['challenge']['id']
            sms_code = input('Enter Robinhood code for validation: ')
            res = respond_to_challenge(challenge_id, sms_code)
            while 'challenge' in res and res['challenge']['remaining_attempts'] > 0:
                sms_code = input('That code was not correct. {0} tries remaining. Please type in another code: '.format(
                    res['challenge']['remaining_attempts']))
                res = respond_to_challenge(challenge_id, sms_code)
            helper.update_session(
                'X-ROBINHOOD-CHALLENGE-RESPONSE-ID', challenge_id)
            data = helper.request_post(url, payload)
        # Update Session data with authorization or raise exception with the information present in data.
        if 'access_token' in data:
            token = '{0} {1}'.format(data['token_type'], data['access_token'])
            helper.update_session('Authorization', token)
            helper.set_login_state(True)
            data['detail'] = "logged in with brand new authentication code."
            if store_session:
                with open(pickle_path, 'wb') as f:
                    pickle.dump({'token_type': data['token_type'],
                                 'access_token': data['access_token'],
                                 'refresh_token': data['refresh_token'],
                                 'device_token': device_token}, f)
                print(f'updated pickle in {pickle_path}')
                # blob = bucket.blob(blob_pickle_path)
                # print(f'upload blob from {pickle_path} to {blob_pickle_path}')
                # with open(pickle_path, 'rb') as f:
                #     new_pickle = f.read()
                # blob.upload_from_string(new_pickle)
        else:
            raise Exception(data['detail'])
    else:
        raise Exception('Error: Trouble connecting to robinhood API. Check internet connection.')
    return data
Exemplo n.º 5
0
def login(username=None,
          password=None,
          expiresIn=86400,
          scope='internal',
          by_sms=True,
          store_session=True,
          mfa_code=None):
    """This function will effectively log the user into robinhood by getting an
    authentication token and saving it to the session header. By default, it
    will store the authentication token in a pickle file and load that value
    on subsequent logins.

    :param username: The username for your robinhood account, usually your email.
        Not required if credentials are already cached and valid.
    :type username: Optional[str]
    :param password: The password for your robinhood account. Not required if
        credentials are already cached and valid.
    :type password: Optional[str]
    :param expiresIn: The time until your login session expires. This is in seconds.
    :type expiresIn: Optional[int]
    :param scope: Specifies the scope of the authentication.
    :type scope: Optional[str]
    :param by_sms: Specifies whether to send an email(False) or an sms(True)
    :type by_sms: Optional[boolean]
    :param store_session: Specifies whether to save the log in authorization
        for future log ins.
    :type store_session: Optional[boolean]
    :param mfa_code: MFA token if enabled.
    :type mfa_code: Optional[str]
    :returns:  A dictionary with log in information. The 'access_token' keyword contains the access token, and the 'detail' keyword \
    contains information on whether the access token was generated or loaded from pickle file.

    """
    device_token = generate_device_token()
    home_dir = os.path.expanduser("~")
    data_dir = os.path.join(home_dir, ".tokens")
    if not os.path.exists(data_dir):
        os.makedirs(data_dir)
    creds_file = "robinhood.pickle"
    pickle_path = os.path.join(data_dir, creds_file)
    # Challenge type is used if not logging in with two-factor authentication.
    if by_sms:
        challenge_type = "sms"
    else:
        challenge_type = "email"

    url = urls.login_url()
    payload = {
        'client_id': 'c82SH0WZOsabOXGP2sxqcj34FxkvfnWRZBKlBjFS',
        'expires_in': expiresIn,
        'grant_type': 'password',
        'password': password,
        'scope': scope,
        'username': username,
        'challenge_type': challenge_type,
        'device_token': device_token
    }

    if mfa_code:
        payload['mfa_code'] = mfa_code

    # If authentication has been stored in pickle file then load it. Stops login server from being pinged so much.
    if os.path.isfile(pickle_path):
        # If store_session has been set to false then delete the pickle file, otherwise try to load it.
        # Loading pickle file will fail if the access_token has expired.
        if store_session:
            try:
                with open(pickle_path, 'rb') as f:
                    pickle_data = pickle.load(f)
                    access_token = pickle_data['access_token']
                    token_type = pickle_data['token_type']
                    refresh_token = pickle_data['refresh_token']
                    # Set device_token to be the original device token when first logged in.
                    pickle_device_token = pickle_data['device_token']
                    payload['device_token'] = pickle_device_token
                    # Set login status to True in order to try and get account info.
                    helper.set_login_state(True)
                    helper.update_session(
                        'Authorization',
                        '{0} {1}'.format(token_type, access_token))
                    # Try to load account profile to check that authorization token is still valid.
                    res = helper.request_get(urls.portfolio_profile(),
                                             'regular',
                                             payload,
                                             jsonify_data=False)
                    # Raises exception is response code is not 200.
                    res.raise_for_status()
                    return ({
                        'access_token':
                        access_token,
                        'token_type':
                        token_type,
                        'expires_in':
                        expiresIn,
                        'scope':
                        scope,
                        'detail':
                        'logged in using authentication in {0}'.format(
                            creds_file),
                        'backup_code':
                        None,
                        'refresh_token':
                        refresh_token
                    })
            except:
                print(
                    "ERROR: There was an issue loading pickle file. Authentication may be expired - logging in normally."
                )
                helper.set_login_state(False)
                helper.update_session('Authorization', None)
        else:
            os.remove(pickle_path)

    # Try to log in normally.
    if not username:
        username = input("Robinhood username: "******"Robinhood password: ")
        payload['password'] = password

    data = helper.request_post(url, payload)
    return data, payload, url, pickle_path, device_token