tradezero_api.watchlist
1from __future__ import annotations 2 3import time 4import warnings 5 6import pandas as pd 7from selenium.webdriver.common.by import By 8from selenium.webdriver.common.keys import Keys 9 10 11class Watchlist: 12 """ 13 this class is for managing the data withing the watchlist container 14 note that if the container is placed on the left side of the UI it will show 15 only about half of the properties (Last, Bid, Ask, %Chg, Chg, Vol) instead of all 12. 16 """ 17 def __init__(self, driver): 18 self.driver = driver 19 self.symbols = set() 20 21 def add(self, symbol: str): 22 """ 23 add symbol to watchlist 24 25 :param symbol: 26 :raises Exception: if given symbol is not valid 27 """ 28 symbol = symbol.upper() 29 symbol_input = self.driver.find_element(By.ID, 'trading-l1-input-symbol') 30 symbol_input.send_keys(symbol, Keys.RETURN) 31 32 time.sleep(0.4) 33 if self._symbol_valid(symbol): 34 self.symbols.add(symbol) 35 else: 36 raise Exception(f'Error: Given symbol is not valid ({symbol})') 37 38 def remove(self, symbol: str): 39 """ 40 remove symbol from watchlist 41 42 :param symbol: 43 """ 44 symbol = symbol.upper() 45 if symbol not in self._get_current_symbols(): 46 warnings.warn(f'Given Symbol is not present in watchlist ({symbol})') 47 return 48 49 delete_button = f'//*[@id="wl-{symbol}"]/td[1]' 50 self.driver.find_element(By.XPATH, delete_button).click() 51 self.symbols.remove(symbol) 52 53 def reset(self): 54 """ 55 remove all symbols from watchlist 56 """ 57 rows = self.driver.find_elements(By.XPATH, '//*[@id="trading-l1-tbody"]/tr/td[1]') 58 for delete_button in rows: 59 delete_button.click() 60 self.symbols = set() 61 62 def restore(self): 63 """ 64 make sure all symbols that have been added, 65 are present in the watchlist (after refresh the watchlist resets) 66 """ 67 current_list = set(self._get_current_symbols()) # set because the order might be different 68 if self.symbols != current_list: 69 for symbol in self.symbols: 70 if symbol not in current_list: 71 self.add(symbol) 72 73 def _get_current_symbols(self): 74 """ 75 return list with current symbols on watchlist 76 """ 77 rows = self.driver.find_elements(By.XPATH, '//*[@id="trading-l1-tbody"]/tr/td[2]') 78 if len(rows) == 0: 79 return [] 80 81 data = self.data('dict') 82 return list(data.keys()) 83 84 def _symbol_valid(self, symbol: str): 85 """ 86 check if a symbol is valid 87 88 :param symbol: 89 :return: bool 90 """ 91 last_notif_message = self.driver.find_element(By.CSS_SELECTOR, 'span.message').text 92 if last_notif_message == f'Symbol not found: {symbol.upper()}': 93 return False 94 return True 95 96 def data(self, return_type: str = 'df'): 97 """ 98 returns the watchlist table as either a DataFrame or Dict, 99 if return_type is equal to: 'df' it will return a pandas.DataFrame 100 or if return_type equal to: 'dict' it will return a Dictionary with the symbols as keys 101 and the data as values. 102 note that if there are no symbols in the watchlist, Pandas will not be able 103 to locate the table and therefore will return False 104 105 :param return_type: 'df' or 'dict' 106 :return: None if empty, else: DF or dict 107 """ 108 symbols_lst = self.driver.find_elements(By.XPATH, '//*[@id="trading-l1-tbody"]//td[2]') 109 if len(symbols_lst) == 0: 110 warnings.warn('There are no symbols present in your watchlist') 111 return None 112 113 # selenium can only read visible rows, while pandas can find also non-visible text 114 # if there are no rows pandas will not be able to locate the table, and throw an error 115 df = pd.read_html(self.driver.page_source, attrs={'id': 'trading-l1-table'})[0] 116 117 if len(df.columns) == 8: 118 df = df.drop(columns=[0]) # drop 'x' 119 df.columns = ['symbol', 'last', 'bid', 'ask', '%chg', 'chg', 'vol'] 120 121 elif len(df.columns) == 14: 122 df = df.drop(columns=[0, 2]) # drop 'x' and currency_get_current_symbols 123 df.columns = ['symbol', 'open', 'close', 'last', 'bid', 'ask', 124 'high', 'low', '%chg', 'chg', 'vol', 'time'] 125 126 df = df.set_index('symbol') 127 if return_type == 'dict': 128 return df.to_dict('index') 129 return df
12class Watchlist: 13 """ 14 this class is for managing the data withing the watchlist container 15 note that if the container is placed on the left side of the UI it will show 16 only about half of the properties (Last, Bid, Ask, %Chg, Chg, Vol) instead of all 12. 17 """ 18 def __init__(self, driver): 19 self.driver = driver 20 self.symbols = set() 21 22 def add(self, symbol: str): 23 """ 24 add symbol to watchlist 25 26 :param symbol: 27 :raises Exception: if given symbol is not valid 28 """ 29 symbol = symbol.upper() 30 symbol_input = self.driver.find_element(By.ID, 'trading-l1-input-symbol') 31 symbol_input.send_keys(symbol, Keys.RETURN) 32 33 time.sleep(0.4) 34 if self._symbol_valid(symbol): 35 self.symbols.add(symbol) 36 else: 37 raise Exception(f'Error: Given symbol is not valid ({symbol})') 38 39 def remove(self, symbol: str): 40 """ 41 remove symbol from watchlist 42 43 :param symbol: 44 """ 45 symbol = symbol.upper() 46 if symbol not in self._get_current_symbols(): 47 warnings.warn(f'Given Symbol is not present in watchlist ({symbol})') 48 return 49 50 delete_button = f'//*[@id="wl-{symbol}"]/td[1]' 51 self.driver.find_element(By.XPATH, delete_button).click() 52 self.symbols.remove(symbol) 53 54 def reset(self): 55 """ 56 remove all symbols from watchlist 57 """ 58 rows = self.driver.find_elements(By.XPATH, '//*[@id="trading-l1-tbody"]/tr/td[1]') 59 for delete_button in rows: 60 delete_button.click() 61 self.symbols = set() 62 63 def restore(self): 64 """ 65 make sure all symbols that have been added, 66 are present in the watchlist (after refresh the watchlist resets) 67 """ 68 current_list = set(self._get_current_symbols()) # set because the order might be different 69 if self.symbols != current_list: 70 for symbol in self.symbols: 71 if symbol not in current_list: 72 self.add(symbol) 73 74 def _get_current_symbols(self): 75 """ 76 return list with current symbols on watchlist 77 """ 78 rows = self.driver.find_elements(By.XPATH, '//*[@id="trading-l1-tbody"]/tr/td[2]') 79 if len(rows) == 0: 80 return [] 81 82 data = self.data('dict') 83 return list(data.keys()) 84 85 def _symbol_valid(self, symbol: str): 86 """ 87 check if a symbol is valid 88 89 :param symbol: 90 :return: bool 91 """ 92 last_notif_message = self.driver.find_element(By.CSS_SELECTOR, 'span.message').text 93 if last_notif_message == f'Symbol not found: {symbol.upper()}': 94 return False 95 return True 96 97 def data(self, return_type: str = 'df'): 98 """ 99 returns the watchlist table as either a DataFrame or Dict, 100 if return_type is equal to: 'df' it will return a pandas.DataFrame 101 or if return_type equal to: 'dict' it will return a Dictionary with the symbols as keys 102 and the data as values. 103 note that if there are no symbols in the watchlist, Pandas will not be able 104 to locate the table and therefore will return False 105 106 :param return_type: 'df' or 'dict' 107 :return: None if empty, else: DF or dict 108 """ 109 symbols_lst = self.driver.find_elements(By.XPATH, '//*[@id="trading-l1-tbody"]//td[2]') 110 if len(symbols_lst) == 0: 111 warnings.warn('There are no symbols present in your watchlist') 112 return None 113 114 # selenium can only read visible rows, while pandas can find also non-visible text 115 # if there are no rows pandas will not be able to locate the table, and throw an error 116 df = pd.read_html(self.driver.page_source, attrs={'id': 'trading-l1-table'})[0] 117 118 if len(df.columns) == 8: 119 df = df.drop(columns=[0]) # drop 'x' 120 df.columns = ['symbol', 'last', 'bid', 'ask', '%chg', 'chg', 'vol'] 121 122 elif len(df.columns) == 14: 123 df = df.drop(columns=[0, 2]) # drop 'x' and currency_get_current_symbols 124 df.columns = ['symbol', 'open', 'close', 'last', 'bid', 'ask', 125 'high', 'low', '%chg', 'chg', 'vol', 'time'] 126 127 df = df.set_index('symbol') 128 if return_type == 'dict': 129 return df.to_dict('index') 130 return df
this class is for managing the data withing the watchlist container note that if the container is placed on the left side of the UI it will show only about half of the properties (Last, Bid, Ask, %Chg, Chg, Vol) instead of all 12.
22 def add(self, symbol: str): 23 """ 24 add symbol to watchlist 25 26 :param symbol: 27 :raises Exception: if given symbol is not valid 28 """ 29 symbol = symbol.upper() 30 symbol_input = self.driver.find_element(By.ID, 'trading-l1-input-symbol') 31 symbol_input.send_keys(symbol, Keys.RETURN) 32 33 time.sleep(0.4) 34 if self._symbol_valid(symbol): 35 self.symbols.add(symbol) 36 else: 37 raise Exception(f'Error: Given symbol is not valid ({symbol})')
add symbol to watchlist
Parameters
- symbol:
Raises
- Exception: if given symbol is not valid
39 def remove(self, symbol: str): 40 """ 41 remove symbol from watchlist 42 43 :param symbol: 44 """ 45 symbol = symbol.upper() 46 if symbol not in self._get_current_symbols(): 47 warnings.warn(f'Given Symbol is not present in watchlist ({symbol})') 48 return 49 50 delete_button = f'//*[@id="wl-{symbol}"]/td[1]' 51 self.driver.find_element(By.XPATH, delete_button).click() 52 self.symbols.remove(symbol)
remove symbol from watchlist
Parameters
- symbol:
54 def reset(self): 55 """ 56 remove all symbols from watchlist 57 """ 58 rows = self.driver.find_elements(By.XPATH, '//*[@id="trading-l1-tbody"]/tr/td[1]') 59 for delete_button in rows: 60 delete_button.click() 61 self.symbols = set()
remove all symbols from watchlist
63 def restore(self): 64 """ 65 make sure all symbols that have been added, 66 are present in the watchlist (after refresh the watchlist resets) 67 """ 68 current_list = set(self._get_current_symbols()) # set because the order might be different 69 if self.symbols != current_list: 70 for symbol in self.symbols: 71 if symbol not in current_list: 72 self.add(symbol)
make sure all symbols that have been added, are present in the watchlist (after refresh the watchlist resets)
97 def data(self, return_type: str = 'df'): 98 """ 99 returns the watchlist table as either a DataFrame or Dict, 100 if return_type is equal to: 'df' it will return a pandas.DataFrame 101 or if return_type equal to: 'dict' it will return a Dictionary with the symbols as keys 102 and the data as values. 103 note that if there are no symbols in the watchlist, Pandas will not be able 104 to locate the table and therefore will return False 105 106 :param return_type: 'df' or 'dict' 107 :return: None if empty, else: DF or dict 108 """ 109 symbols_lst = self.driver.find_elements(By.XPATH, '//*[@id="trading-l1-tbody"]//td[2]') 110 if len(symbols_lst) == 0: 111 warnings.warn('There are no symbols present in your watchlist') 112 return None 113 114 # selenium can only read visible rows, while pandas can find also non-visible text 115 # if there are no rows pandas will not be able to locate the table, and throw an error 116 df = pd.read_html(self.driver.page_source, attrs={'id': 'trading-l1-table'})[0] 117 118 if len(df.columns) == 8: 119 df = df.drop(columns=[0]) # drop 'x' 120 df.columns = ['symbol', 'last', 'bid', 'ask', '%chg', 'chg', 'vol'] 121 122 elif len(df.columns) == 14: 123 df = df.drop(columns=[0, 2]) # drop 'x' and currency_get_current_symbols 124 df.columns = ['symbol', 'open', 'close', 'last', 'bid', 'ask', 125 'high', 'low', '%chg', 'chg', 'vol', 'time'] 126 127 df = df.set_index('symbol') 128 if return_type == 'dict': 129 return df.to_dict('index') 130 return df
returns the watchlist table as either a DataFrame or Dict, if return_type is equal to: 'df' it will return a pandas.DataFrame or if return_type equal to: 'dict' it will return a Dictionary with the symbols as keys and the data as values. note that if there are no symbols in the watchlist, Pandas will not be able to locate the table and therefore will return False
Parameters
- return_type: 'df' or 'dict'
Returns
None if empty, else: DF or dict