Git Product home page Git Product logo

webull's Introduction

Webull

APIs for webull, you are free to use, but code not extensively checked and Webull may update the APIs or the endpoints at any time. https://www.webull.com/

Feel free to sign-up for a webull account through here, you will be able to help me to get referral stocks. You can also get 2 stocks for free:

https://www.webull.com/activity?inviteCode=oqJvTY3rJNyR&source=invite_gw&inviteSource=wb_oversea

Sorry for procrastinating in answering the questions and updating the packages. But if you really like the package or really like to motivate me. Materialist appreciations would really motivate me to responding you faster πŸ˜‚:

Install

pip install webull

or

python3 -m pip install webull

Run tests

pip install pytest requests_mock
python -m pytest -v

Usage

How to login with your email

Webull has made Multi-Factor Authentication (MFA) mandatory since 2020/05/28, if you are having issues, take a look at here: https://github.com/tedchou12/webull/wiki/MFA-&-Security

Or Authenticate without Login completely 2021/02/14: https://github.com/tedchou12/webull/wiki/Workaround-for-Login

from webull import webull # for paper trading, import 'paper_webull'

wb = webull()
wb.login('[email protected]', 'pa$$w0rd')

How to login with your mobile

from webull import webull # for paper trading, import 'paper_webull'

wb = webull()
wb.login('+1-1112223333', 'pa$$w0rd') # phone must be in format +[country_code]-[your number]

How to order stock

from webull import webull
wb = webull()
wb.login('[email protected]', 'pa$$w0rd')

wb.get_trade_token('123456')
wb.place_order(stock='AAPL', price=90.0, qty=2)

How to check standing orders

from webull import webull
wb = webull()
wb.login('[email protected]', 'pa$$w0rd')

wb.get_trade_token('123456')
orders = wb.get_current_orders()

How to cancel standing orders

from webull import webull
wb = webull()
wb.login('[email protected]', 'pa$$w0rd')

wb.get_trade_token('123456')
wb.cancel_all_orders()

FAQ

Thank you so much, I have received Emails and messages on reddit from many traders/developers that liked this project. Thanks to many that helped and contributed to this project too! There are quite a few repeated questions on the same topic, so I have utilized the Wiki section for them. If you have troubles regarding Login/MFA Logins, Real Time Quote Data, What is Trade PIN/Trade Token, or How to buy me a coffee please take a look at the Wiki pages first. https://github.com/tedchou12/webull/wiki

Stream Quotes

https://github.com/tedchou12/webull/wiki/How-to-use-Streaming-Quotes%3F

Disclaimer

This software is not extensively tested, please use at your own risk.

Developers

If you are interested to join and help me improve this, feel free to message me.

webull's People

Contributors

adriandliu avatar alancuriel avatar alexonab avatar b0b5h4rp13 avatar boonyeow avatar calrider avatar cliu18 avatar dan-biwott avatar dependabot[bot] avatar dosemwengie avatar eugenepeh avatar gamesover avatar hisenzhang avatar icantfindausernameatall avatar igoramidzic avatar imvinaypatil avatar itsjafer avatar jonecg avatar josephcottingham avatar jpobeid avatar knackepizza avatar knurts avatar pagemastr avatar same-code-different-day avatar storrealba09 avatar tedchou12 avatar urahara avatar xbeninni avatar xeicoco avatar zenhorace avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

webull's Issues

cant download

i am very new to this im not sure how to install and get it running

Webull account locking due to too many failed trading password verification attempts

My online account keeps getting locked while using the webull api,
The email says "Trading password locked, Your Webull account has been locked because of too many failed trading password verification attempts"

From the code perspective everything works fine and I can execute all commands but when I try to view my account on my cell phone it says it locked and I have to wait 5 minutes up to 2 hours if it keeps being locked.

I am using the wb.refresh_login() every time I run the script and only use the wb.login() after a long time of not using the script. Have you experience this account locking?

Here is my exact code:

        # First time login if access token expires
        get_access_code = False
        if get_access_code:
            self.wb.get_mfa(self.webull_email)
            # Check email for 6 digit access code. Enter it below
            access_code = '123456'
            data = self.wb.login(self.webull_email, self.webull_password,'windows', access_code)
            self.logger.info(data)

        # Get login token for session
        data = self.wb.refresh_login()
        # I think this is the line that is causing the account locking
        data = self.wb.login(self.webull_email, self.webull_password) 

        if 'accessToken' in data :
            self.logger.info("successful login")

        # Get trade token for session
        self.wb.get_trade_token(self.webull_password)

Unable to login

Every time I try to login I get the error {'msg': 'deviceId=null','traceId':'xxx','code':'500'}

Active Gainers / Losers List

Hey guys,

Great job so far on all of the work that's been done here. I've been able to connect up and place an order using this API so far and it's been rather painless.

One of my objectives here is to be able to pull out the active gainers / losers lists that are on webull's app (market section) to use for further analysis. When pulling this info using get_active_gainers_losers(), I get a list of names (about 20 long). However, this list does not match up with the gainers list (1-day) when comparing to the app.

My question is: Is there a option to choose the time frame of the list (i.e. 5-minute, 1-day, pre-market, after-hours, etc.) of the list that's being produced?
To build further, is there an option to choose the length of the list being returned (it seems the Webull lists have no limit)?

Let me know when you get the chance. Looking forward to helping out any way I can.

Thanks!

Websocket handshake error

Most of the time I get the Websocket handshake error when trying to connect to streaming quotes. Only out of 10 or more attempts it succeeds once.
Any clue on why it's happening? or Is it only me?

self.streamConnection.connect(did=self.wb._get_did()) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/webull/streamconn.py", line 166, in connect self.client_streaming_quotes.connect('wspush.webullbroker.com', 443, 30) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/paho/mqtt/client.py", line 937, in connect return self.reconnect() File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/paho/mqtt/client.py", line 1107, in reconnect sock = WebsocketWrapper(sock, self._host, self._port, self._ssl, File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/paho/mqtt/client.py", line 3556, in __init__ self._do_handshake(extra_headers) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/paho/mqtt/client.py", line 3640, in _do_handshake raise WebsocketConnectionError("WebSocket handshake error") paho.mqtt.client.WebsocketConnectionError: WebSocket handshake error

Trouble working in colab

Hello,
I am working on this in colab and keep ending up with the same message after trying multiple workarounds. I have a True when I log in but with the next line 'get_account_info()' I continue to get this message. Thank you in advance.
`---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
in ()
2 webull = webull()
3 webull.login('j**********', '*********')
----> 4 webull.get_account_id()
5 #webull.get_trade_token('123456')
6 #print(webull.get_account())

in get_account_id(self)
276
277 if result['success']:
--> 278 self.account_id = str(result['data'][0]['secAccountId'])
279 return True
280 else:

KeyError: 'secAccountId'`

When I comment out the above code the results show as
'{'success': True,
'data': [{'brokerId': 8, 'brokerName': 'Individual', 'status': 'unopen', 'registerTradeUrl':
'/mgt/redirect/tradeh5', 'openAccountUrl':
'https://tradeh5.webull.com/register/ib/continue.html', 'supportOutsideRth': True,
'userTradePermissionVOs': [{'type': 'stock', 'hasPermission': False, 'brokerId': 8}],
'supportClickIPO': True, 'isDefaultChecked': False, 'supportOpenOption': True}]}'

Getting "code":"trade.webull.DAY_BUYING_POWER_INSUFFICIENT"

I am getting below response when i am trying to place order.. Did you see error like below, your input would be appreciated.

<200,{"success":false,"code":"trade.webull.DAY_BUYING_POWER_INSUFFICIENT","msg":"Buying power is insufficient, please cancel open buy orders(if there is any) and try again

right now I don't have 25k in my account . Is it because of that ??.. Just FYI I am able to place order from mobile app.

Thanks

trade_token expired

hi, got trade_token expired sometimes. Is there a way to refresh it gracefully? I assume we can call get_trade_token(password) periodically.

Mobile Login

Does login method support both mobil and email login?

get_bars method is not calling the right api ?

I am getting the below as result for the method. Is the api changed ?

{'msg': 'Failed to convert value of type 'java.lang.String' to required type 'java.util.Set'; nested exception is java.lang.NumberFormatException: For input string: "AAPL"', 'traceId': 'd104228cfba340d0b8c986fda5a4f263', 'code': '400'}

I found the below api but it has different structure

'https://quoteapi.webullbroker.com/api/quote/tickerRealTimes/v5?tickerIds=913256135%2C913256135%2C913255598%2C913243251%2C925299128'

Option Support

With options trading being added on Webull it would be nice to see this supported.

order history

could you add function to retrieve historical orders, including those filled or canceled, and including those closed positions? thanks

API is rejecting orders with GFV warning even though you can make these orders in the app

gfv

Here is an example response from the API when I attempt to make an order on my cash account with unsettled funds.

On the app, you can make these orders as long as you tap the circle that says you understand a good faith violation (GFV) will occur if you sell before funds are settled. However, with this API, the order just gets rejected.

I am able to make other orders through this API just fine.

Scraper to extract Webull market information

It would be great to add a method to Webull class to extract the various ticks for Movers, gainers, and losers. This way, one can use the market information on Webull website to create a strategy for their trading rules.

Option Order doesnot work.

Option Order doesn't work. I am able to find it and added below code to my local copy. Still need formatting.

I just changed for first one, lmtPrice is string, at least that how portal works.
if orderType == 'LMT' and lmtPrice:
data['lmtPrice'] = lmtPrice #removed float
if orderType == 'STP' and stpPrice:
data['auxPrice'] = float(stpPrice)
if orderType == 'STP LMT' and lmtPrice and stpPrice:
data['lmtPrice'] = float(lmtPrice)
data['auxPrice'] = float(stpPrice)

Made few changes....
response = requests.post(self.urls.place_option_orders(self.account_id), json=data, headers=headers)
data1 = json.loads(response.content) # reading response in json; This is to capture order message 8:00 AM to 4:00PM.
if response.status_code != 200 or not data1["forward"]: # added a check to see if its success; you will see status code 200 but there will no order placed after 4:00 PM so we need to capture that.
raise Exception('place_option_order failed', response.status_code, response.reason,
data1["checkResultList"][0]["msg"]) #Added message here
response = requests.post(self.urls.place_option_orders1(self.account_id), json=data, headers=headers) # this is the actual trade url; just placed URL under endpoints.py
return True

endpoint.py

def place_option_orders(self, account_id):
    return f'{self.base_trade_url}/v2/option/checkOrder/{account_id}'

Added below code

def place_option_orders1(self, account_id):
    return f'{self.base_trade_url}/v2/option/placeOrder/{account_id}'

streaming quotes via websockets

The web sockets appear to be MQTT based, which after some googling is a common internet of things format --- go figure. There appears to be two sockets open, one (wss://platpush.webullbroker.com/mqtt port 443) just for order status updates (fill, cancel, modify), spends most of its time doing a keep-alive message to keep the socket open. The other (wss://wspush.webullbroker.com/mqtt port 443) does streaming quotes for the charts/screens, there appear to be at least thee different price update formats for the different parts of the app

Login using accesstoken and refresh token

Found that the access/refresh token is valid for 90 days.
Why NOT we use that instead of MFA everytime.. if we can personally manage and cache.

Can we have API added api_login(id, access_token, refresh_token) ?

KeyError: 'secAccountId'

I'm trying to get account details via .get_account_id():

from webull import webull

wb = webull()
pw = "MY PASSWORD"
un = 'MY USERNAME'
wb.login(un, pw,"Max's Python", '423251')
print(wb.get_account_id())
wb.logout()

I keep getting the following response:

Traceback (most recent call last):
File "D:/Trading Bots/Webull Trading.py", line 7, in
{'success': True, 'data': [{'brokerId': 8, 'brokerName': 'Individual', 'status': 'unopen', 'registerTradeUrl': '/mgt/redirect/tradeh5', 'openAccountUrl': 'https://tradeh5.webull.com/register/ib/continue.html', 'supportOutsideRth': True, 'userTradePermissionVOs': [{'type': 'stock', 'hasPermission': False, 'brokerId': 8}, {'type': 'crypto', 'hasPermission': False, 'brokerId': 8}], 'supportClickIPO': True, 'isDefaultChecked': False, 'supportOpenOption': True}]}
print(wb.get_account_id())
File "D:\Trading Bots\venv\lib\site-packages\webull\webull.py", line 188, in get_account_id
id = str(result['data'][0]['secAccountId'])
KeyError: 'secAccountId'

I was trying to troubleshoot the code by putting a print statement into project. It keeps saying that my account status is unopen. However, when I request the mfa I can get it using the same password and username. I'm not sure what to do at this point.

Any advice is much appreciated. Fairly new to coding.

Wrapper for paper Trading

It would be great to add a method for paper trading in the Webull class so one can test their trading strategy without losing money.

Issue with get_ticker() / hasMore variable

Printed the response in the get_ticker() function. It checked for "hasMore" false and dies. The tickerId is still there in the list. Stock is SPLK as example

Started to see this issue.{'categoryId': 0, 'categoryName': '综合', 'hasMore': False, 'list': [{'tickerId': 913255699, 'exchangeId': 96, 'type': 2, 'secType': [61], 'regionId': 6, 'regionCode': 'US', 'currencyId': 247, 'name': 'Splunk', 'symbol': 'SPLK', 'disSymbol': 'SPLK', 'disExchangeCode': 'NASDAQ', 'exchangeCode': 'NSQ', 'listStatus': 1, 'template': 'stock', 'derivativeSupport': 1}]}

def get_ticker(self, stock=''):
'''
Lookup ticker_id
'''
ticker_id = 0
if stock and isinstance(stock, str):
response = requests.get(self._urls.stock_id(stock))
result = response.json()
if result['hasMore'] == False:
raise ValueError('TickerId could not be found for stock {}'.format(stock))

elif result['list']:
for item in result['list']: # implies multiple tickers, but only assigns last one?
ticker_id = item['tickerId']
else:
raise ValueError('Stock symbol is required')
return ticker_id

No data for some Webull stocks

Hi. I noticed that for some Webull stocks, BNGO and TTNP for example, are not supported by the api. I get a "Could not find ticker BNGO" error when I try to access the data or place an order for BNGO. I this correct that the api does not support some Webull stocks. Thanks.

"The system is busy"

When trying to place an order, I get this:
{'success': False, 'code': 'trade.system.exception', 'msg': 'The system is busy', 'data': {'lastSerialId': '5f0c8537ca18e90001147115'}}

Is this just due to webull servers being overloaded or am I facing locked account issues?

'hasMore' error when using get_quote()

The KeyError 'hasMore' is printed out everytime I try to get quote information from a stock. It had worked perfectly fine for 2 months up until now. I'm not sure what that error means so I have no idea what the problem is. Is there a reason why get_quote() is doing this?

unable to login even with MFA

  1. The default one is phone number, instead of email address. I tried wb.get_mfa('+65-XXXXXXXX') but msg saying number invalid.
  2. after input verification code, got a page to input more info to verify
    wb2
    wb1

When placing order, outsideRegularTradingHour is default true

When I check the source code, I find when placing order, 'outsideRegularTradingHour': True. May I ask what's the extra benefit to trade before or after regular market time?

May be it is a biz question more than coding question ;). Having extra hours to trade is always a good thing?

Shall we give people an option to trade only at market time?

Consideration for async client(s)

Hey @tedchou12, sweet project :)

I'm wondering how you'd feel about an async client particularly for streaming quotes.
There's already an effort to get trio support for paho.mqtt: trio-paho-mqtt so it should be a mostly minimal addition.

I'm personally after trio support for my infra and am happy to help, make a PR, etc.
I figured I'd ask if you'd take the contribution before going off on my own; it seems like there's already a lot of good stuff here!

Cheers.

option orders giving a 403

I have the following option from a webull.get_options(stock="JCP", expireDate="2020-05-01")

{'strikePrice': '2.00', 'call': {'tickerId': 1014438795, 'close': '0.0100', 'change': '0.000', 'changeRatio': '0.0000', 'volume': '12', 'preClose': '0.0100', 'open': '0.0100', 'high': '0.0100', 'low': '0.0100', 'askList': [{'price': '0.0100', 'volume': '6'}, {}, {}, {}, {}, {}, {}, {}, {}, {}], 'bidList': [{'price': '0.0000', 'volume': '0'}, {}, {}, {}, {}, {}, {}, {}, {}, {}], 'strikePrice': '2.00', 'direction': 'call', 'expireDate': '2020-05-01', 'openInterest': 11, 'openIntChange': 0, 'impVol': '8.4971', 'gamma': '0.0000', 'theta': '0.0000', 'vega': '0.0000', 'rho': '0.0000', 'delta': '0.0000', 'activeLevel': 4, 'weekly': 1, 'quoteMultiplier': 100, 'unSymbol': 'JCP'}, 'put': {'tickerId': 1014438799, 'close': '1.960', 'change': '0.210', 'changeRatio': '0.1200', 'volume': '18', 'preClose': '1.750', 'open': '1.580', 'high': '1.960', 'low': '1.580', 'askList': [{'price': '1.960', 'volume': '9'}, {}, {}, {}, {}, {}, {}, {}, {}, {}], 'bidList': [{'price': '1.310', 'volume': '1'}, {}, {}, {}, {}, {}, {}, {}, {}, {}], 'strikePrice': '2.00', 'direction': 'put', 'expireDate': '2020-05-01', 'openInterest': 1, 'openIntChange': 0, 'gamma': '0.0000', 'theta': '0.0000', 'vega': '0.0000', 'rho': '0.0000', 'delta': '-1.0000', 'activeLevel': 4, 'weekly': 1, 'quoteMultiplier': 100, 'unSymbol': 'JCP'}}

I'm using the tickerId as the optionId which seems to be the same as the webull client is going on network inspecting

I'm trying this

webull.place_option_order(optionId="1014438795", lmtPrice=0.01, action='BUY', orderType='LMT', enforce='DAY', quant=1)

I'm getting a 403

Traceback (most recent call last):
  File "./main.py", line 19, in <module>
    webull.place_option_order(optionId=1014438795, lmtPrice="0.01", action='BUY', orderType='LMT', enforce='DAY', quant=1)
  File "/Users/mzupan/mz/option-trader/webull.py", line 443, in place_option_order
    raise Exception('place_option_order failed', response.status_code, response.reason)
Exception: ('place_option_order failed', 403, 'Forbidden')

Is this because of the issue of not being able to trade options on webull over the weekend? The web client does a 200 but my guess is the endpoint might be different.

Paper Options Trading

I want to test my strategies on a paper account before trying it with real money. Ideally every function in the webull class should be identical to the paper class to have the easiest migration.

404 error on place order

Please help me. Thanks

wb.place_order('SBUX', 913257472, 70, 'BUY', 'LMT', 'GTC', 1)
{'timestamp': '2020-07-14T18:02:17.598+0000', 'status': 404, 'error': 'Not Found', 'message': 'No message available', 'path': '/webull-paper-center/api/paper/1/acc//orderop/place/913257472'}

not callable

so right now all i have is:

import pytest
import webull
webull = webull()
webull.login('************', '*********')
webull.get_account_id()
webull.get_trade_token('123456')
print(webull.get_account())

and all I'm getting right now is:

    webull = webull()
TypeError: 'module' object is not callable

how do I fix this

The hasMore check in webull.py on line 268 is limiting returned good stocks from AMEX

if result['hasMore'] == False:

for instance...

>>> wb.get_quote('NNVC')
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/webull/webull.py", line 445, in get_quote
    tId = str(self.get_ticker(stock))
  File "/usr/local/lib/python3.7/site-packages/webull/webull.py", line 269, in get_ticker
    raise ValueError('TickerId could not be found for stock {}'.format(stock))
  ValueError: TickerId could not be found for stock NNVC

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.7/site-packages/webull/webull.py", line 447, in get_quote
    raise ValueError("Could not find ticker for stock {}".format(stock))
ValueError: Could not find ticker for stock NNVC

But, NNVC is an actual good stock with a valid ticker ID

curl -k 'https://infoapi.webull.com/api/search/tickers5?keys=NNVC&queryNumber=1'| jq -r
{
  "categoryId": 0,
  "categoryName": "综合",
  "hasMore": false,
  "list": [
    {
      "tickerId": 913303706,
      "exchangeId": 12,
      "type": 2,
      "secType": [
        61
      ],
      "regionId": 6,
      "regionCode": "US",
      "currencyId": 247,
      "name": "NANOVIRICIDES",
      "symbol": "NNVC",
      "disSymbol": "NNVC",
      "disExchangeCode": "AMEX",
      "exchangeCode": "ASE",
      "listStatus": 1,
      "template": "stock"
    }
  ]
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.