tedchou12 / webull

Unofficial APIs for Webull.
MIT License
596 stars 181 forks source link

Errors when you have 2 webull accounts - think it's picking the wrong one #426

Open ctoday1 opened 7 months ago

ctoday1 commented 7 months ago

I have one cash and one margin account with webull. I think it's picking the newest account by default when logging in. Is there any way to specify which account to use?

I'm using the "workaround" login method. But - the tokens seem to be the same no matter which account i choose in the web ui.

Thanks for any help.

cjszk commented 7 months ago

def get_account_id(self): <- this is the method that needs to be modified.

The method as its written by the author will only retrieve the first account among the list of accounts. You want to change this to the correct one in the list. Assuming you only have two accounts (the first in the list being the cash account), you would change:

id = str(result['data'][0]['secAccountId'])

to:

id = str(result['data'][1]['secAccountId'])

To confirm this is correct, you could print out the response and confirm the data matches the account.

    def get_account_id(self):
        '''
        get account id
        call account id before trade actions
        '''
        headers = self.build_req_headers()

        response = requests.get(self._urls.account_id(), headers=headers)
        result = response.json()
        if result['success'] :
            self.zone_var = str(result['data'][0]['rzone'])
            # id = str(result['data'][0]['secAccountId']) # Cash Account
            id = str(result['data'][1]['secAccountId']) # Margin Account
            print(str(result['data']))
            self._account_id = id
            return id
        else:
            return None
ctoday1 commented 7 months ago

def get_account_id(self): <- this is the method that needs to be modified.

The method as its written by the author will only retrieve the first account among the list of accounts. You want to change this to the correct one in the list. Assuming you only have two accounts (the first in the list being the cash account), you would change:

id = str(result['data'][0]['secAccountId'])

to:

id = str(result['data'][1]['secAccountId'])

To confirm this is correct, you could print out the response and confirm the data matches the account.

    def get_account_id(self):
        '''
        get account id
        call account id before trade actions
        '''
        headers = self.build_req_headers()

        response = requests.get(self._urls.account_id(), headers=headers)
        result = response.json()
        if result['success'] :
            self.zone_var = str(result['data'][0]['rzone'])
            # id = str(result['data'][0]['secAccountId']) # Cash Account
            id = str(result['data'][1]['secAccountId']) # Margin Account
            print(str(result['data']))
            self._account_id = id
            return id
        else:
            return None

Interesting. Mine looks a little different:

def get_account_id(self, id=0):
        headers = self.build_req_headers()

        response = requests.get(self._urls.account_id(), headers=headers, timeout=self.timeout)
        result = response.json()
        if result['success'] and len(result['data']) > 0 :
            self.zone_var = str(result['data'][int(id)]['rzone'])
            self._account_id = str(result['data'][int(id)]['secAccountId'])
            return self._account_id
        else:
            return None

setting "id=0" to "id=1" does make it successfully place a trade to the margin account. BUT - i'm still getting an error from the request.push in place_option_order, even though the trade was successfull placed. Here's the json and the resp code:

{'msg': 'The system is busy', 'code': 'trade.system.exception', 'data': {}, 'success': False} 500

I guess i'm good now that its actually placing the order. Very confused as to why it's throwing an error though.