def get_mfa(): email = request.args.get('email') if email is None: return 'Invalid Request', 400 wb = webull() wb.get_mfa(email) return "ok"
def initWebull(): # set up webull (first account) WB1_ACCESS_TOKEN = os.environ.get("WB1_ACCESS_TOKEN") WB1_REFRESH_TOKEN = os.environ.get("WB1_REFRESH_TOKEN") WB1_TOKEN_EXPIRATION = os.environ.get("WB1_TOKEN_EXPIRATION") WB1_UUID = os.environ.get("WB1_UUID") WB1_TRADE_TOKEN = os.environ.get("WB1_TRADE_TOKEN") if not (WB1_TRADE_TOKEN and WB1_ACCESS_TOKEN and WB1_REFRESH_TOKEN and WB1_TOKEN_EXPIRATION and WB1_UUID): print("No WeBull credentials given, skipping") return None, None wb1 = webull() wb1.api_login(access_token=WB1_ACCESS_TOKEN, refresh_token=WB1_REFRESH_TOKEN, token_expire=WB1_TOKEN_EXPIRATION, uuid=WB1_UUID) wb1.get_trade_token(WB1_TRADE_TOKEN) # set up webull (second account) WB2_ACCESS_TOKEN = os.environ.get("WB2_ACCESS_TOKEN") WB2_REFRESH_TOKEN = os.environ.get("WB2_REFRESH_TOKEN") WB2_TOKEN_EXPIRATION = os.environ.get("WB2_TOKEN_EXPIRATION") WB2_UUID = os.environ.get("WB2_UUID") WB2_TRADE_TOKEN = os.environ.get("WB2_TRADE_TOKEN") if not (WB2_TRADE_TOKEN and WB2_ACCESS_TOKEN and WB2_REFRESH_TOKEN and WB2_TOKEN_EXPIRATION and WB2_UUID): print( "Only one Webull account was given, credentials for second account were incomplete" ) return wb1, None wb2 = webull() wb2.api_login(access_token=WB2_ACCESS_TOKEN, refresh_token=WB2_REFRESH_TOKEN, token_expire=WB2_TOKEN_EXPIRATION, uuid=WB2_UUID) wb2.get_trade_token(WB2_TRADE_TOKEN) return wb1, wb2
def login(): if not ('email' in request.json and 'password' in request.json and 'mfa' in request.json): return 'Invalid Request', 400 wb = webull() print('login creds:', request.json['email'], request.json['password']) login_response = wb.login(request.json['email'], request.json['password'], 'finhub', request.json['mfa']) print('login_response:', login_response) account_id = wb.get_account_id() response = { 'access_token': login_response['accessToken'], 'account_id': account_id, 'refresh_token': login_response['refreshToken'], 'expirationTime': login_response['tokenExpireTime'] } return response
def get_webull_balance(): w = webull() ''' content of the file. <username> <password> <code> ''' with open("/Users/iniyanparamasivam/webull.txt", encoding='utf-8') as f: username = f.readline().rstrip() password = f.readline().rstrip() code = f.readline().rstrip() w.login(username, password) w.get_trade_token(code) acc = w.get_account() return acc['netLiquidation']
def setupWebull(account=1): # Get webull information WB1_USERNAME = input(f"Webull Account #{account} Username (email/phone): ") WB1_PASSWORD = input(f"Webull Account #{account} Password: "******"Webull Account #{account} Trade Token (6 digit trading code): ") WB1_QUESTION = "" WB1_QUESTION_ID = "" WB1_ACCESS_TOKEN = os.environ.get(f"WB{account}_ACCESS_TOKEN") WB1_REFRESH_TOKEN = os.environ.get(f"WB{account}_REFRESH_TOKEN") WB1_TOKEN_EXPIRATION = os.environ.get(f"WB{account}_TOKEN_EXPIRATION") WB1_UUID = os.environ.get(f"WB{account}_UUID") if WB1_USERNAME: wb = webull() data = wb.get_security(WB1_USERNAME) #get your security question. wb.get_mfa(WB1_USERNAME) #mobile number should be okay as well. WB1_CODE = input("You will receive a verification code to your email / phone number. Please enter it now: ") WB1_QUESTION_ID = data[0]['questionId'] WB1_QUESTION = data[0]['questionName'] print("Webull requested an answer to the following security question: ") WB1_ANSWER = input(WB1_QUESTION + " ") wb.login( username=WB1_USERNAME, password=WB1_PASSWORD, device_name="RSA", mfa=WB1_CODE, question_id=WB1_QUESTION_ID, question_answer=WB1_ANSWER ) WB1_UUID = wb._uuid WB1_ACCESS_TOKEN = wb._access_token WB1_REFRESH_TOKEN = wb._refresh_token WB1_TOKEN_EXPIRATION = wb._token_expire os.environ[f'RSA_WB{account}_ACCESS_TOKEN'] = WB1_ACCESS_TOKEN or "" os.environ[f'RSA_WB{account}_REFRESH_TOKEN'] = WB1_REFRESH_TOKEN or "" os.environ[f'RSA_WB{account}_TOKEN_EXPIRATION'] = WB1_TOKEN_EXPIRATION or "" os.environ[f'RSA_WB{account}_UUID'] = WB1_UUID or "" os.environ[f'RSA_WB{account}_TRADE_TOKEN'] = WB1_TRADE_TOKEN or os.getenv(f"WB{account}_TRADE_TOKEN") or ""
def main(sym="GME"): now = datetime.now() ym = now.strftime('%Y%m') day = now.strftime('%d') hms = now.strftime('%H%M%S') wb = webull() wb.login(*json.load(open('.wb-creds.json'))) os.makedirs(f'{ROOT}/{ym}', exist_ok=True) f = open(f'{ROOT}/{ym}/{sym}-opchain-{ym}{day}{hms}.txt', 'w') f.write('|'.join(OP_KEYS + ['ask', 'avol', 'bid', 'bvol']) + '\n') for exp in wb.get_options_expiration_dates(stock=sym): ops = wb.get_options(stock=sym, expireDate=exp['date']) for op in ops: call = op['call'] put = op['put'] exp = call['expireDate'] strike = call['strikePrice'] print_op(f, call) print_op(f, put)
from getpass import getpass from pprint import pprint def on_order_message(topic, data): pprint(f'Topic: {topic}') pprint(f'Webull order confirmation: {data}') # Webull doesn't send full options info on order confirmation # i.e. Mobile notification message does not have the full info # instead we try to print the latest activity as a temporary workaround activities = wb.get_activities() pprint(activities['items'][0]['description']) wb = webull() # `token.json` will not and should not be uploaded to git. # gitignore should have this file name to avoid accidental uploads credentials_file = 'token.json' credential_data = None try: f = open(credentials_file, "r") credential_data = json.load(f) f.close() except: print("Login info not stored. Please follow the prompts...") webull_phone = str(
def test_login(self): webull_obj = webull.webull() assert True == webull_obj.login_prompt()
def test_logout(self): webull_obj = webull.webull() print("Login success: {}".format(webull_obj.login_prompt())) assert True == webull_obj.logout()
time.sleep(2) # so theres time for message to print os._exit(6) def subscribe(self, tId=None, level=105): #you can only use curly brackets for variables in a f string self.client_streaming_quotes.subscribe( '{' + f'"tickerIds":[{tId}],"type":"{level}"' + '}') self.client_streaming_quotes.loop() def unsubscribe(self, tId=None, level=105): self.client_streaming_quotes.unsubscribe(f'["type={level}&tid={tId}"]') #self.client_streaming_quotes.loop() #no need for this, you should already be in a loop if __name__ == '__main__': webull = webull(cmd=True) # for demo purpose webull.login('*****@*****.**', 'xxxxx') webull.get_trade_token('xxxxxx') # set self.account_id first webull.get_account_id() # webull.place_order('NKTR', 21.0, 1) orders = webull.get_current_orders() for order in orders: # print(order) webull.cancel_order(order['orderId']) # print(webull.get_serial_id()) # print(webull.get_ticker('BABA')) #test streaming
def __init__(self): self.wb = webull() print('TopComTickersTool Meathods') print('findStringValues()')
def main(cfg): if cfg.steps_to_run.download_data: today = datetime.today() date_end = today.strftime('%Y-%m-%d') date_start = (today - timedelta(365)).strftime('%Y-%m-%d') week_start = (today - timedelta(today.weekday())).strftime('%Y-%m-%d') month_start = (today - timedelta(today.day - 1)).strftime('%Y-%m-%d') wb = webull.webull() wb.login(cfg.account_info.phone_number, cfg.account_info.password) wb.secondary_login(cfg.account_info.secondary_pass) logging.info('Logging Success!') if cfg.download_steps.stock_performance.overall: logging.info('Download overall stock performance') get_stock_performace(wb.get_stock_performance( date_start, date_end )).to_csv( '../../../python/account_detail/overall_stock_performance.csv') if cfg.download_steps.stock_performance.monthly: logging.info('Download overall monthly performance') get_stock_performace( wb.get_stock_performance(month_start, date_end) ).to_csv( '../../../python/account_detail/monthly_stock_performance.csv') if cfg.download_steps.stock_performance.weekly: logging.info('Download overall weekly performance') get_stock_performace(wb.get_stock_performance( week_start, date_end )).to_csv( '../../../python/account_detail/weekly_stock_performance.csv') if cfg.download_steps.profit_loss_history: logging.info('Download Profit Loss History') pd.DataFrame(wb.get_proft_loss_history()).to_csv( '../../../python/account_detail/profit_loss_history.csv') if cfg.download_steps.trading_history: logging.info('Download Trading History') get_trading_history( wb.get_history_orders( date_start, date_end, status='FILLED', count=10000)).to_csv( '../../../python/account_detail/historical_order.csv') if cfg.download_steps.trading_history: logging.info('Download Net Liquidity') pd.DataFrame(wb.get_net_liquidity()).to_csv( '../../../python/account_detail/net_liquidity_history.csv') if cfg.download_steps.yield_rate.my_portfolio: logging.info('Download Portfolio Performance') yield_rate_dia = wb.get_yield_rate(date_start, index='DIA') yield_rate_ixic = wb.get_yield_rate(date_start, index='IXIC') yield_rate_spy = wb.get_yield_rate(date_start, index='SPY') yield_rate = pd.DataFrame(yield_rate_dia) yield_rate_ixic = pd.DataFrame(yield_rate_ixic) yield_rate_spy = pd.DataFrame(yield_rate_spy) yield_rate['yield_rate_dia'] = yield_rate.indexYieldRate yield_rate['yield_rate_ixic'] = yield_rate_ixic.indexYieldRate yield_rate['yield_rate_spy'] = yield_rate_spy.indexYieldRate yield_rate.to_csv('../../../python/account_detail/yield_rate.csv') if cfg.download_steps.current_holding: logging.info('Download Current_holding') current_holding = wb.get_positions() current_holding = get_current_holding(current_holding).assign( Date=date_end) current_holding.to_csv( '../../../python/account_detail/current_holding.csv')