def get_quote(self, symbol): try: self.access_header except AttributeError: if self.verbose: print('access header not defined') raise utility_exceptions.AccountError(header_error=True) self.quote_endpoint = r'https://api.tdameritrade.com/v1/marketdata/{}/quotes'.format( symbol) # add a line to describe the type of request to the website self.options_access_header = self.access_header.copy() self.options_access_header['Content-Type'] = 'application/json' # post the request self.account_reply = requests.get(url=self.quote_endpoint, headers=self.access_header) if self.account_reply.status_code == utility_exceptions.AccessSuccess.account_success.value: # read out the status of the request if self.verbose: print(self.account_reply.status_code) quote_dict = self.account_reply.json() sym, quote = list(quote_dict.items())[0] return quote else: raise utility_exceptions.AccessError( ErrorCode=self.account_reply.status_code, url=self.options_chain_endpoint, headers=self.options_access_header)
def get_order(self, order_id): try: self.access_header except AttributeError: if self.verbose: print('access header not defined') raise utility_exceptions.AccountError(header_error=True) try: self.account_id except AttributeError: if self.verbose: print('account id not defined') raise utility_exceptions.AccountError(id_error=True) self.order_endpoint = r'https://api.tdameritrade.com/v1/accounts/{}/orders/{}'.format( self.account_id, order_id) self.account_reply = requests.get(url=self.order_endpoint, headers=self.access_header) if self.account_reply.status_code == utility_exceptions.AccessSuccess.account_success.value: # read out the status of the request if self.verbose: print(self.account_reply.status_code) return self.account_reply.json() else: raise utility_exceptions.AccessError( ErrorCode=self.account_reply.status_code, url=self.order_endpoint, headers=self.order_access_header)
def get_price_history(self, symbol, payload): try: self.access_header except AttributeError: if self.verbose: print('access header not defined') raise utility_exceptions.AccountError(header_error=True) self.price_history_endpoint = r'https://api.tdameritrade.com/v1/marketdata/{}/pricehistory'.format( symbol) self.account_reply = requests.get(url=self.price_history_endpoint, params=payload, headers=self.access_header) if self.account_reply.status_code == utility_exceptions.AccessSuccess.account_success.value: # read out the status of the request if self.verbose: print(self.account_reply.status_code) return self.account_reply.json() else: raise utility_exceptions.AccessError( ErrorCode=self.account_reply.status_code, url=self.price_history_endpoint, params=payload) pass
def place_order(self, payload): try: self.access_header except AttributeError: if self.verbose: print('access header not defined') raise utility_exceptions.AccountError(header_error=True) try: self.account_id except AttributeError: if self.verbose: print('account id not defined') raise utility_exceptions.AccountError(id_error=True) self.order_endpoint = r'https://api.tdameritrade.com/v1/accounts/{}/orders'.format( self.account_id) # add a line to describe the type of request to the website self.order_access_header = self.access_header.copy() self.order_access_header['Content-Type'] = 'application/json' # define the payload ''' payload = { "complexOrderStrategyType": "NONE", "orderType": "LIMIT", "session": "NORMAL", "price": "6.45", "duration": "DAY", "orderStrategyType": "SINGLE", "orderLegCollection": [ { "instruction": "BUY_TO_OPEN", "quantity": 10, "instrument": { "symbol": "XYZ_032015C49", "assetType": "OPTION" } } orderId: 1111111 ] } ''' # post the request self.account_reply = requests.post(url=self.order_endpoint, json=payload, headers=self.order_access_header) if self.account_reply.status_code == utility_exceptions.AccessSuccess.order_success.value: # read out the status of the request if self.verbose: print(self.account_reply.status_code) else: raise utility_exceptions.AccessError( ErrorCode=self.account_reply.status_code, url=self.order_endpoint, headers=self.order_access_header) # record whether the the order state has changed self.orders_state_has_changed = True return True
def delete_order(self, order_id): try: self.access_header except AttributeError: if self.verbose: print('access header not defined') raise utility_exceptions.AccountError(header_error=True) try: self.account_id except AttributeError: if self.verbose: print('account id not defined') raise utility_exceptions.AccountError(id_error=True) self.order_endpoint = r'https://api.tdameritrade.com/v1/accounts/{}/orders/{}'.format( self.account_id, order_id) # post the request self.account_reply = requests.delete(url=self.order_endpoint, headers=self.access_header) if self.account_reply.status_code == utility_exceptions.AccessSuccess.account_success.value: if self.verbose: print('deleted order'.format(order_id)) else: raise utility_exceptions.AccessError( ErrorCode=self.account_reply.status_code, url=self.order_endpoint, headers=self.access_header) # record whether the the order state has changed self.orders_state_has_changed = True
def access_single_account(self, account_id): ''' Access the single account to get data :param account_id: :return: ''' try: self.access_header except AttributeError: if self.verbose: print('access header not defined') raise utility_exceptions.AccountError(header_error=True) try: self.account_id except AttributeError: if self.verbose: print('account id not defined') raise utility_exceptions.AccountError(id_error=True) # define the accounts endpoint self.account_endpoint = r'https://api.tdameritrade.com/v1/accounts/{}'.format( account_id) # POST data to get access token self.account_reply = requests.get(url=self.account_endpoint, headers=self.access_header) if self.account_reply.status_code == utility_exceptions.AccessSuccess.account_success.value: self.account_data_dict[str(account_id)] = self.account_reply.json() if self.verbose: print(self.account_data) else: raise utility_exceptions.AccessError( ErrorCode=self.account_reply.status_code, url=self.account_endpoint, headers=self.access_header)
def authenticate(self): ''' Take the access key and get the access and refresh token for the account. :return: ''' try: self.parse_url except AttributeError: if self.verbose: print('token url not parsed') raise utility_exceptions.AccountError(parse_url_error=True) # create access point url self.token_endpoint = r'https://api.tdameritrade.com/v1/oauth2/token' # define headers headers = {'content-type': "application/x-www-form-urlencoded"} # define payload payload = { 'grant_type': 'authorization_code', 'access_type': 'offline', 'code': self.parse_url, 'client_id': apikey, 'redirect_uri': 'http://localhost/callback' } # POST data to get access token self.authenticate_reply = requests.post(url=self.token_endpoint, headers=headers, data=payload) if self.authenticate_reply.status_code == utility_exceptions.AccessSuccess.account_success.value: # convert json reply to dictionary self.token_data = self.authenticate_reply.json() self.access_token = self.token_data['access_token'] self.access_header = { 'Authorization': "Bearer {}".format(self.access_token) } self.refresh_token = self.token_data['refresh_token'] if self.verbose: print(self.access_header) self.utility_path = os.path.abspath(os.path.dirname(__file__)) filepath = self.utility_path + '/' + self.refresh_token_filename file = open(filepath, mode='w') file.write(self.refresh_token) file.close() self.account_authenticated = True self.time_of_last_refresh = arrow.now('America/New_York') else: raise utility_exceptions.AccessError(url=self.token_endpoint, headers=headers, data=payload)
def refresh_authentication(self): ''' Use the refresh token to get a new access_token :return: ''' try: self.refresh_token except AttributeError: if self.verbose: print('refresh token not initialized') raise utility_exceptions.AccountError(refresh_token_error=True) # create access point url self.token_endpoint = r'https://api.tdameritrade.com/v1/oauth2/token' # define headers headers = {'content-type': "application/x-www-form-urlencoded"} # define payload payload = { 'grant_type': 'refresh_token', 'access_type': 'offline', 'refresh_token': self.refresh_token, 'client_id': apikey, 'redirect_uri': 'http://localhost/callback' } # POST data to get access token self.authenticate_reply = requests.post(url=self.token_endpoint, headers=headers, data=payload) if self.authenticate_reply.status_code == utility_exceptions.AccessSuccess.account_success.value: # convert json reply to dictionary self.token_data = self.authenticate_reply.json() self.access_token = self.token_data['access_token'] self.access_header = { 'Authorization': "Bearer {}".format(self.access_token) } if self.verbose: print(self.access_header) self.account_authenticated = True self.time_of_last_refresh = arrow.now('America/New_York') else: raise utility_exceptions.AccessError( url=self.token_endpoint, headers=headers, data=payload, ErrorCode=self.authenticate_reply.status_code)
def get_account_positions(self): ''' Access the single account to get data :param account_id: :return: ''' try: self.access_header except AttributeError: if self.verbose: print('access header not defined') raise utility_exceptions.AccountError(header_error=True) try: self.account_id except AttributeError: if self.verbose: print('account id not defined') raise utility_exceptions.AccountError(id_error=True) # define the accounts endpoint self.account_endpoint = r'https://api.tdameritrade.com/v1/accounts/{}'.format( self.account_id) # define payload payload = {'fields': 'positions'} # GET account data self.account_reply = requests.get(url=self.account_endpoint, params=payload, headers=self.access_header) if self.account_reply.status_code == utility_exceptions.AccessSuccess.account_success.value: if self.verbose: print(self.account_data) try: return self.account_reply.json( )['securitiesAccount']['positions'] # TODO: catch json decode error here as well. except KeyError: # if no entry, then there are no positions, and return empty list. return [] else: raise utility_exceptions.AccessError( ErrorCode=self.account_reply.status_code, url=self.account_endpoint, headers=self.access_header)
def access_accounts(self): ''' Access accounts to get the account ID :return: ''' self.account_access_attempt = False try: self.access_header except AttributeError: if self.verbose: print('access header not defined') raise utility_exceptions.AccountError(header_error=True) # define the accounts endpoint self.accounts_endpoint = r'https://api.tdameritrade.com/v1/accounts' # POST data to get access token self.account_reply = requests.get(url=self.accounts_endpoint, headers=self.access_header) if self.account_reply.status_code == utility_exceptions.AccessSuccess.account_success.value: self.account_data = self.account_reply.json() self.account_id = self.account_data[0]['securitiesAccount'][ 'accountId'] return self.account_data if self.verbose: print(self.account_data) elif self.account_reply.status_code == utility_exceptions.AccessSuccess.account_partial_success.value \ and not self.account_access_attempt: # wait 5 seconds and then attempt again. time.sleep(5) if self.verbose: print('Account data partial success, calling again..') self.account_reply = requests.get(url=self.accounts_endpoint, headers=self.access_header) self.account_data = self.account_reply.json() self.account_id = self.account_data[0]['securitiesAccount'][ 'accountId'] return self.account_data if self.verbose: print(self.account_data) else: raise utility_exceptions.AccessError( ErrorCode=self.account_reply.status_code, url=self.accounts_endpoint, headers=self.access_header)