tedchou12 / webull

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

place_order returns 405 error #386

Closed acelearns closed 1 year ago

acelearns commented 1 year ago

Here's my code,

from webull import webull
wb._access_token = "XX"
print(wb.place_order("NVOS", action="BUY", quant=1))

it throws this error

Traceback (most recent call last):
  File "C:\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\models.py", line 971, in json
    return complexjson.loads(self.text, **kwargs)
  File "C:\AppData\Local\Programs\Python\Python39\lib\json\__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "C:\AppData\Local\Programs\Python\Python39\lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "C:\AppData\Local\Programs\Python\Python39\lib\json\decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "d:\webull_handler.py", line 16, in <module>
    p = wb.place_order("NVOS", action="BUY", quant=1)
  File "C:\AppData\Local\Programs\Python\Python39\lib\site-packages\webull\webull.py", line 624, in place_order
    return response.json()
  File "C:\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\models.py", line 975, in json
    raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

is there any fix to this?

webullstocktrader commented 1 year ago

I have same issue. Anyone else have order issues?

ICANTFINDAUSERNAMEATALL commented 1 year ago

Usually 405 error has something to do with not having the funds to place the trade or you just can't place it.

  1. You might be trying to do options but don't have it enabled
  2. It could be outside trading hours
  3. If your trying to sell an option, you don't have enough capital to cover the contract(it might go ITM)
  4. You don't have any settled cash to do trades with

There might be other reasons but those were what happened to me with the 405 errors.

ICANTFINDAUSERNAMEATALL commented 1 year ago

Here's my code,

from webull import webull
wb._access_token = "XX"
print(wb.place_order("NVOS", action="BUY", quant=1))

it throws this error

Traceback (most recent call last):
  File "C:\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\models.py", line 971, in json
    return complexjson.loads(self.text, **kwargs)
  File "C:\AppData\Local\Programs\Python\Python39\lib\json\__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "C:\AppData\Local\Programs\Python\Python39\lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "C:\AppData\Local\Programs\Python\Python39\lib\json\decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "d:\webull_handler.py", line 16, in <module>
    p = wb.place_order("NVOS", action="BUY", quant=1)
  File "C:\AppData\Local\Programs\Python\Python39\lib\site-packages\webull\webull.py", line 624, in place_order
    return response.json()
  File "C:\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\models.py", line 975, in json
    raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

is there any fix to this?

print(wb.place_order("NVOS", action="BUY", quant=1))

For this, you need to have a limit price or update the ordertype so that its MKT. Your trying to place a limit order of 1 share of NVOS at an undefined price.

You could try:

wb.place_order("NVOS", action="BUY", quant=1, orderType = "MKT")

or

wb.place_order("NVOS", action="BUY", quant=1, price = 50) # update the price to the limit price you want

ICANTFINDAUSERNAMEATALL commented 1 year ago

Can you buy shares at all? Try to place an order to buy a share of a penny stock. If it still causes that error, can you send your code over and a screenshot of the error?

webullstocktrader commented 1 year ago

Can you buy shares at all? Try to place an order to buy a share of a penny stock. If it still causes that error, can you send your code over and a screenshot of the error?

We tried to buy a few different stocks. As Market buys. We tried on a 2 dollar stock just to buy a single share, during market hours and as a mkt buy, and still no luck. We will keep trying and will try to see what we can do. Everything else is working besides placing orders. Thank you very much for replying sir. We will try tomorrow and reach back out then to see if we have found a solution. God bless.

webullstocktrader commented 1 year ago

All cash is settled. And just trying to be shares, not options.

ICANTFINDAUSERNAMEATALL commented 1 year ago

Did you login to webull and set your device id? Heres an example of how to do it:

from webull import webull
wb = webull()

# SET YOUR DID
wb._set_did("whatever your device id is") # If you haven't "verified" your device, get a verifified did from webull.
# to get did: inspect, network, refresh webull's page, open up any package that is sent and look for the did in the request headers

print(wb.login(email, pw, "my pc lol")) # should print out a long list of info. You can ignore this
print(wb.get_trade_token(code)) # enter you trading 6 digit number here

print(wb.get_account()) # this should print your account info. If you aren't logged in, this will return an error I think

# you should be able to place orders now

Lmk how it goes.

acelearns commented 1 year ago

@ICANTFINDAUSERNAMEATALL Thanks for the reply!

Here is my exact code i have now.

from webull import paper_webull, webull
from credentials import WEBULL_USERNAME, WEBULL_PASSWORD

wb = webull()
wb._did = "XX"
wb._access_token = "XX"

ac = wb.get_account()
print(ac) # im able to get account info

wb._trade_token = "XX"

p = wb.place_order("UNCY",
                   action="BUY",
                   quant=2,
                   orderType="MKT",
                   enforce="DAY")
print(p)

i have enough amount to buy in account

The error is exactly same mentioned above, i tried to print the response in webull's place order function and it printed <Response 405>

ICANTFINDAUSERNAMEATALL commented 1 year ago

Use the code I showed in the previous message. Lets get the order function working first before moving on to using the access token.

try:

from webull import webull
wb = webull()

wb._set_did("whatever your device id is") # If you haven't "verified" your device, get a verifified did from webull.

print(wb.login(email, pw, "webull api, you can put whatever here"))
print(wb.get_trade_token(code))

print(wb.get_account())

You are just setting stuffing the information into the webull object and then not doing anything with it. You need to login and the "get_trade_token" function to actually run it.

It seems like you don't really know the difference between modifying the variables in an object and calling an object's functions. Make sure you understand this because it seems like your just copying/pasting code but you don't really know whats going on. Just google this or ask chat gpt.

acelearns commented 1 year ago

Use the code I showed in the previous message. Lets get the order function working first before moving on to using the access token.

try:

from webull import webull
wb = webull()

wb._set_did("whatever your device id is") # If you haven't "verified" your device, get a verifified did from webull.

print(wb.login(email, pw, "webull api, you can put whatever here"))
print(wb.get_trade_token(code))

print(wb.get_account())

You are just setting stuffing the information into the webull object and then not doing anything with it. You need to login and the "get_trade_token" function to actually run it.

It seems like you don't really know the difference between modifying the variables in an object and calling an object's functions. Make sure you understand this because it seems like your just copying/pasting code but you don't really know whats going on. Just google this or ask chat gpt.

i know, i have already tried that but by using access token i was able to login and get some info, if i try wb.login method it returns following error

{'msg': 'Fail to verify image verification code.', 'traceId': 'XX', 'code': 'user.check.slider.pic.fail'}
False
{'msg': 'AccessToken is expire', 'traceId': 'XX', 'code': 'auth.token.expire', 'data': {}, 'success': False}

And I went through some similar issues before but none of them helped thats why i was doing it this way.

how do i even fix the image verification?

ICANTFINDAUSERNAMEATALL commented 1 year ago

366 Solved here.

Theres been like this same issue come up like 3-4 times already. I'll write up a quick summary on how to get the did.

acelearns commented 1 year ago

366 Solved here.

Theres been like this same issue come up like 3-4 times already. I'll write up a quick summary on how to get the did.

Hey, thanks for that! I was not able to login by did method yesterday but now it seems working,

I'm able to login and getting account info by did method but there is another issue, while placing order

{'msg': 'Your session has expired, please login again.', 'traceId': 'XX', 'code': 'trade.token.expire', 'data': {'lock': xx, 'retry': -2}, 'success': False}

I re-logged in on browser but its the same error, now

ICANTFINDAUSERNAMEATALL commented 1 year ago

Don't do any of this:

wb._did = "XX"
wb._access_token = "XX"

When you run the login function, it will automatically generate the access token for you instead of using an old one. Just set the did and login.

acelearns commented 1 year ago

Don't do any of this:

wb._did = "XX"
wb._access_token = "XX"

When you run the login function, it will automatically generate the access token for you instead of using an old one. Just set the did and login.

As you said, here is my code,

from webull import webull
from credentials import WEBULL_USERNAME, WEBULL_PASSWORD

wb = webull()

wb._set_did(
    "XX"
)  
wb.login(WEBULL_USERNAME, WEBULL_PASSWORD, "webull api")
wb.get_trade_token("XX")

q = wb.get_account()
print(q)
p = wb.place_order("UNCY", action="BUY", quant=1, orderType="MKT")
print(p)

Session is expiring somehow, here is the error

{'msg': 'Your session has expired, please login again.', 'traceId': 'XX', 'code': 'trade.token.expire', 'data': {'lock': xx, 'retry': -2}, 'success': False}

ICANTFINDAUSERNAMEATALL commented 1 year ago

https://github.com/tedchou12/webull/wiki/Workaround-for-Login-Method-2

I wrote a quick summary of the new workaround. lmk if anything is confusing.

acelearns commented 1 year ago

Yeah, thanks for that. I already did that. can you check the above comment by me?

ICANTFINDAUSERNAMEATALL commented 1 year ago

Try getting a new did? Hmm... after I updated my did manually this way, it worked.

I was typing up the response while you were sending yours lmao

acelearns commented 1 year ago

its the same did 💀 it did create a did.bin file and i used wb._did = "didhere" but that didnt work either

ICANTFINDAUSERNAMEATALL commented 1 year ago

Hmmm... I get the same thing as well when I completely delete the did and used a new one.

I'll see what I can do. I just used a previous did and it just worked out for me. Theres probably another new verification ugh

ICANTFINDAUSERNAMEATALL commented 1 year ago

I just got it to work. Did you login to webull web?

This is the exact code I used:

from webull import webull
from creds import code, email, pw

wb = webull()

wb._set_did("did here")

print(wb.login(email, pw))

print(wb.get_trade_token(code))

print(wb.get_account())
acelearns commented 1 year ago

I just got it to work. Did you login to webull web?

This is the exact code I used:

from webull import webull
from creds import code, email, pw

wb = webull()

wb._set_did("did here")

print(wb.login(email, pw))

print(wb.get_trade_token(code))

print(wb.get_account())

Yeah bro, im able to log in but can't place order

acelearns commented 1 year ago

place order function is returning {'msg': 'Your session has expired, please login again.', 'traceId': 'XX', 'code': 'trade.token.expire', 'data': {'lock': xx, 'retry': -2}, 'success': False}

despite that, im able to get account info as well but just cant place order

acelearns commented 1 year ago

oh well, I got it working, I was using the wrong trade token , Now everything is working including placing order,

Thank you for the help. @ICANTFINDAUSERNAMEATALL it meant a lot to me!

acelearns commented 1 year ago

A question, will this did or whatever thing expire and will i have to go through the manual login process again? If yes how to avoid that and keep the script running forever?

tedchou12 commented 1 year ago

no did don't expire as far as I know. As for the trade token, I think it is configured in your App, you can adjust the trade token expire duration. For access token, it will expire (24 hours if I remembered correctly), so you will have to use your refresh token to update your access token.

acelearns commented 1 year ago

no did don't expire as far as I know. As for the trade token, I think it is configured in your App, you can adjust the trade token expire duration. For access token, it will expire (24 hours if I remembered correctly), so you will have to use your refresh token to update your access token.

Will I need to use an access token any further or does it just expire every 24hrs and I'll need to update it, While I'm using the wb.login with did method?

tedchou12 commented 1 year ago

this is the way to update your accesstoken

fh = open('webull_credentials.json', 'r')
credential_data = json.load(fh)
fh.close()

wb._refresh_token = credential_data['refreshToken']
wb._access_token = credential_data['accessToken']
wb._token_expire = credential_data['tokenExpireTime']
wb._uuid = credential_data['uuid']

n_data = wb.refresh_login()

credential_data['refreshToken'] = n_data['refreshToken']
credential_data['accessToken'] = n_data['accessToken']
credential_data['tokenExpireTime'] = n_data['tokenExpireTime']

file = open('webull_credentials.json', 'w')
json.dump(credential_data, file)
file.close()

# important to get the account_id
wb.get_account_id()
acelearns commented 1 year ago

Alright, thank you so much! That was helpful