GithubHelp home page GithubHelp logo

tedchou12 / webull Goto Github PK

View Code? Open in Web Editor NEW
588.0 588.0 180.0 323 KB

Unofficial APIs for Webull.

License: MIT License

Python 100.00%
algotrade algotrading broker broker-api python python-framework trading webull webull-api

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

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

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

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"
    }
  ]
}

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.

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.

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) ?

Mobile Login

Does login method support both mobil and email login?

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.

order history

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

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

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)

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.

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!

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

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'

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.

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}]}'

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?

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}'

Unable to login

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

cant download

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

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.

Option Support

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

"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?

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'}

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.

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.

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

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

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.