Branden Nevius
Branden Nevius

Reputation: 21

Python Get Account using tda-api returns ValueError

I have the following api call to tda-api

    orders = client.get_account(config.account_id,fields=['positions'])

Gives the Error:

File "/opt/anaconda3/lib/python3.7/site-packages/tda/client/base.py", line 361, in get_account fields = self.convert_enum_iterable(fields, self.Account.Fields) File "/opt/anaconda3/lib/python3.7/site-packages/tda/utils.py", line 66, in convert_enum_iterable self.type_error(value, required_enum_type) File "/opt/anaconda3/lib/python3.7/site-packages/tda/utils.py", line 41, in type_error possible_members_message)) ValueError: expected type "Fields", got type "str". (initialize with enforce_enums=False to disable this checking)

the documentation follows:

Client.get_account(account_id, *, fields=None)

and if i replace with: client.get_account(config.account_id,fields=positions)

'positions' is not defined

And if i look into the api the code for the get_account() function looks like:

class Fields(Enum):
            '''Account fields passed to :meth:`get_account` and
            :meth:`get_accounts`'''
            POSITIONS = 'positions'
            ORDERS = 'orders'
def get_account(self, account_id, *, fields=None):
        fields = self.convert_enum_iterable(fields, self.Account.Fields)

        params = {}
        if fields:
            params['fields'] = ','.join(fields)

Upvotes: 1

Views: 581

Answers (2)

Branden Nevius
Branden Nevius

Reputation: 21

Most likely not the correct way to go about this but I found a fix for now.

I commented out the following that checks for the type in the utils.py file for the tda package.

   def convert_enum_iterable(self, iterable, required_enum_type):
    if iterable is None:
        return None

    if isinstance(iterable, required_enum_type):
        return [iterable.value]

    values = []
    for value in iterable:
        if isinstance(value, required_enum_type):
            values.append(value.value)
        # elif self.enforce_enums:
        #     self.type_error(value, required_enum_type)
        else:
            values.append(value)
    return values

I believe if you create your own client you can set this property to false as well.

And then I am able to use the following to get my current positions:

data = client.get_account(config.account_id,fields=['positions'])

Upvotes: 1

Jonathan Leon
Jonathan Leon

Reputation: 5648

At one point, I had these working but haven't tried in a while. I do recall it being difficult to decipher what a field type was. Depending on your import statements, you might need the entire tda.client.Client.Account.Fields.POSITIONS, for example.

r_acct_orders = client.get_account(config.ACCOUNT_ID, fields=tda.client.Client.Account.Fields.ORDERS).json() # field options None, ORDERS, POSITIONS
r = client.get_account(config.ACCOUNT_ID, fields=tda.client.Client.Account.Fields.POSITIONS).json() # field options None, ORDERS, POSITIONS
r = client.get_accounts(fields=tda.client.Client.Account.Fields.ORDERS).json() # field options None, ORDERS, POSITIONS
r = client.get_accounts(fields=None).json() # field options None, ORDERS, POSITIONS

Also, I use a config.py for account_id but you can just use your syntax as needed.

Upvotes: 0

Related Questions