From e7fa0ced5c4473d78815f3cd17a3f7f4c5fbc8bb Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Sat, 24 Apr 2021 11:36:02 -0700 Subject: [PATCH 01/12] Fixes #60 Changed Date Formatting for intra reply --- bot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot.py b/bot.py index a8a6207..e2a5888 100644 --- a/bot.py +++ b/bot.py @@ -314,8 +314,8 @@ def intra(update: Update, context: CallbackContext): update.message.reply_photo( photo=buf, - caption=f"\nIntraday chart for {symbol.name} from {df.first_valid_index().strftime('%I:%M')} to" - + f" {df.last_valid_index().strftime('%I:%M')} ET on" + caption=f"\nIntraday chart for {symbol.name} from {df.first_valid_index().strftime('%H:%M')} to" + + f" {df.last_valid_index().strftime('%H:%M %Z')} on" + f" {datetime.date.today().strftime('%d, %b %Y')}\n\n{s.price_reply([symbol])[0]}", parse_mode=telegram.ParseMode.MARKDOWN, disable_notification=True, From 0b4432175420c95e9e7b7a595a639e1f1fa8b828 Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Sat, 24 Apr 2021 11:42:47 -0700 Subject: [PATCH 02/12] bandaid on #55 --- symbol_router.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/symbol_router.py b/symbol_router.py index bbca1ed..ec98720 100644 --- a/symbol_router.py +++ b/symbol_router.py @@ -100,13 +100,13 @@ class Router: ) df.sort_values(by="Match", ascending=False, inplace=True) - if df["Match"].head().sum() < 300: - df["Match"] = df.apply( - lambda x: fuzz.partial_ratio(search, x["name"].lower()), - axis=1, - ) + # if df["Match"].head().sum() < 300: + # df["Match"] = df.apply( + # lambda x: fuzz.partial_ratio(search, x["name"].lower()), + # axis=1, + # ) - df.sort_values(by="Match", ascending=False, inplace=True) + # df.sort_values(by="Match", ascending=False, inplace=True) symbols = df.head(20) symbol_list = list(zip(list(symbols["symbol"]), list(symbols["description"]))) From 8e6425e75678069023f3bde85f6bab7206a2211e Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Wed, 5 May 2021 20:46:18 -0700 Subject: [PATCH 03/12] Close #55 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 74ecaef..45e4aa1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -python-telegram-bot==13.2 +python-telegram-bot==13.5 requests==2.25.1 pandas==1.2.1 fuzzywuzzy==0.18.0 From 610dbc3492b0598bbbd8f84e502c2b7a208478fd Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Wed, 5 May 2021 20:48:25 -0700 Subject: [PATCH 04/12] Started #61 --- bot.py | 48 +++++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/bot.py b/bot.py index e2a5888..5bd7b79 100644 --- a/bot.py +++ b/bot.py @@ -98,17 +98,9 @@ def donate(update: Update, context: CallbackContext): parse_mode=telegram.ParseMode.MARKDOWN, disable_notification=True, ) - return + amount = 1 else: amount = update.message.text.replace("/donate", "").replace("$", "").strip() - title = "Simple Stock Bot Donation" - description = f"Simple Stock Bot Donation of ${amount}" - payload = "simple-stock-bot" - provider_token = STRIPE_TOKEN - start_parameter = str(chat_id) - - print(start_parameter) - currency = "USD" try: price = int(float(amount) * 100) @@ -117,32 +109,38 @@ def donate(update: Update, context: CallbackContext): return print(price) - prices = [LabeledPrice("Donation:", price)] - context.bot.send_invoice( - chat_id, - title, - description, - payload, - provider_token, - start_parameter, - currency, - prices, + chat_id=chat_id, + title="Simple Stock Bot Donation", + description=f"Simple Stock Bot Donation of ${amount}", + payload=f"simple-stock-bot-{chat_id}", + provider_token=STRIPE_TOKEN, + currency="USD", + prices=[LabeledPrice("Donation:", price)], + start_parameter="", + # suggested_tip_amounts=[100, 500, 1000, 2000], + photo_url="https://simple-stock-bots.gitlab.io/site/img/Telegram.png", + photo_width=500, + photo_height=500, ) def precheckout_callback(update: Update, context: CallbackContext): query = update.pre_checkout_query - if query.invoice_payload == "simple-stock-bot": - # answer False pre_checkout_query - query.answer(ok=True) - else: - query.answer(ok=False, error_message="Something went wrong...") + query.answer(ok=True) + # I dont think I need to check since its only donations. + # if query.invoice_payload == "simple-stock-bot": + # # answer False pre_checkout_query + # query.answer(ok=True) + # else: + # query.answer(ok=False, error_message="Something went wrong...") def successful_payment_callback(update: Update, context: CallbackContext): - update.message.reply_text("Thank you for your donation!") + update.message.reply_text( + "Thank you for your donation! It goes a long way to keeping the bot free!" + ) def symbol_detect(update: Update, context: CallbackContext): From f9b8921ba8883d089dd64cc9668278c8c7f90bda Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Fri, 21 May 2021 16:50:29 -0700 Subject: [PATCH 05/12] Close #66 --- IEX_Symbol.py | 47 ++++++++++++++++++++++++++++++++++++----------- cg_Crypto.py | 35 ++++++++++++++++++++++++----------- 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/IEX_Symbol.py b/IEX_Symbol.py index 4acf549..1faa913 100644 --- a/IEX_Symbol.py +++ b/IEX_Symbol.py @@ -55,10 +55,12 @@ class IEX_Symbol: ) -> Optional[Tuple[pd.DataFrame, datetime]]: reg_symbols = r.get( - f"https://cloud.iexapis.com/stable/ref-data/symbols?token={self.IEX_TOKEN}" + f"https://cloud.iexapis.com/stable/ref-data/symbols?token={self.IEX_TOKEN}", + timeout=5, ).json() otc_symbols = r.get( - f"https://cloud.iexapis.com/stable/ref-data/otc/symbols?token={self.IEX_TOKEN}" + f"https://cloud.iexapis.com/stable/ref-data/otc/symbols?token={self.IEX_TOKEN}", + timeout=5, ).json() reg = pd.DataFrame(data=reg_symbols) @@ -83,7 +85,10 @@ class IEX_Symbol: str Human readable text on status of IEX API """ - resp = r.get("https://pjmps0c34hp7.statuspage.io/api/v2/status.json") + resp = r.get( + "https://pjmps0c34hp7.statuspage.io/api/v2/status.json", + timeout=5, + ) if resp.status_code == 200: status = resp.json()["status"] @@ -155,7 +160,10 @@ class IEX_Symbol: IEXurl = f"https://cloud.iexapis.com/stable/stock/{symbol.id}/quote?token={self.IEX_TOKEN}" - response = r.get(IEXurl) + response = r.get( + IEXurl, + timeout=5, + ) if response.status_code == 200: IEXData = response.json() @@ -226,7 +234,10 @@ class IEX_Symbol: return "OTC stocks do not currently support any commands." IEXurl = f"https://cloud.iexapis.com/stable/stock/{symbol}/dividends/next?token={self.IEX_TOKEN}" - response = r.get(IEXurl) + response = r.get( + IEXurl, + timeout=5, + ) if response.status_code == 200 and response.json(): IEXData = response.json()[0] keys = ( @@ -288,7 +299,10 @@ class IEX_Symbol: return "OTC stocks do not currently support any commands." IEXurl = f"https://cloud.iexapis.com/stable/stock/{symbol}/news/last/15?token={self.IEX_TOKEN}" - response = r.get(IEXurl) + response = r.get( + IEXurl, + timeout=5, + ) if response.status_code == 200: data = response.json() if data: @@ -324,7 +338,10 @@ class IEX_Symbol: return "OTC stocks do not currently support any commands." IEXurl = f"https://cloud.iexapis.com/stable/stock/{symbol}/company?token={self.IEX_TOKEN}" - response = r.get(IEXurl) + response = r.get( + IEXurl, + timeout=5, + ) if response.status_code == 200: data = response.json() @@ -352,7 +369,10 @@ class IEX_Symbol: return "OTC stocks do not currently support any commands." IEXurl = f"https://cloud.iexapis.com/stable/stock/{symbol}/stats?token={self.IEX_TOKEN}" - response = r.get(IEXurl) + response = r.get( + IEXurl, + timeout=5, + ) if response.status_code == 200: data = response.json() @@ -399,7 +419,10 @@ class IEX_Symbol: return pd.DataFrame() IEXurl = f"https://cloud.iexapis.com/stable/stock/{symbol}/intraday-prices?token={self.IEX_TOKEN}" - response = r.get(IEXurl) + response = r.get( + IEXurl, + timeout=5, + ) if response.status_code == 200: df = pd.DataFrame(response.json()) df.dropna(inplace=True, subset=["date", "minute", "high", "low", "volume"]) @@ -437,7 +460,8 @@ class IEX_Symbol: pass response = r.get( - f"https://cloud.iexapis.com/stable/stock/{symbol}/chart/1mm?token={self.IEX_TOKEN}&chartInterval=3&includeToday=false" + f"https://cloud.iexapis.com/stable/stock/{symbol}/chart/1mm?token={self.IEX_TOKEN}&chartInterval=3&includeToday=false", + timeout=5, ) if response.status_code == 200: @@ -460,7 +484,8 @@ class IEX_Symbol: """ stocks = r.get( - f"https://cloud.iexapis.com/stable/stock/market/list/mostactive?token={self.IEX_TOKEN}" + f"https://cloud.iexapis.com/stable/stock/market/list/mostactive?token={self.IEX_TOKEN}", + timeout=5, ).json() return [f"${s['symbol']}: {s['companyName']}" for s in stocks] diff --git a/cg_Crypto.py b/cg_Crypto.py index e1f9ad8..1b6d4c6 100644 --- a/cg_Crypto.py +++ b/cg_Crypto.py @@ -44,7 +44,10 @@ class cg_Crypto: self, return_df=False ) -> Optional[Tuple[pd.DataFrame, datetime]]: - raw_symbols = r.get("https://api.coingecko.com/api/v3/coins/list").json() + raw_symbols = r.get( + "https://api.coingecko.com/api/v3/coins/list", + timeout=5, + ).json() symbols = pd.DataFrame(data=raw_symbols) symbols["description"] = "$$" + symbols["symbol"] + ": " + symbols["name"] @@ -62,7 +65,10 @@ class cg_Crypto: str Human readable text on status of CoinGecko API """ - status = r.get("https://api.coingecko.com/api/v3/ping") + status = r.get( + "https://api.coingecko.com/api/v3/ping", + timeout=5, + ) if status.status_code == 200: return f"CoinGecko API responded that it was OK in {status.elapsed.total_seconds()} Seconds." @@ -124,7 +130,8 @@ class cg_Crypto: """ response = r.get( - f"https://api.coingecko.com/api/v3/coins/{symbol.id}?localization=false" + f"https://api.coingecko.com/api/v3/coins/{symbol.id}?localization=false", + timeout=5, ) if response.status_code == 200: data = response.json() @@ -167,7 +174,8 @@ class cg_Crypto: Returns a timeseries dataframe with high, low, and volume data if its available. Otherwise returns empty pd.DataFrame. """ response = r.get( - f"https://api.coingecko.com/api/v3/coins/{symbol.id}/ohlc?vs_currency=usd&days=1" + f"https://api.coingecko.com/api/v3/coins/{symbol.id}/ohlc?vs_currency=usd&days=1", + timeout=5, ) if response.status_code == 200: df = pd.DataFrame( @@ -194,7 +202,8 @@ class cg_Crypto: Returns a timeseries dataframe with high, low, and volume data if its available. Otherwise returns empty pd.DataFrame. """ response = r.get( - f"https://api.coingecko.com/api/v3/coins/{symbol.id}/ohlc?vs_currency=usd&days=30" + f"https://api.coingecko.com/api/v3/coins/{symbol.id}/ohlc?vs_currency=usd&days=30", + timeout=5, ) if response.status_code == 200: @@ -221,7 +230,8 @@ class cg_Crypto: Each symbol passed in is a key with its value being a human readable formatted string of the symbols statistics. """ response = r.get( - f"https://api.coingecko.com/api/v3/coins/{symbol.id}?localization=false" + f"https://api.coingecko.com/api/v3/coins/{symbol.id}?localization=false", + timeout=5, ) if response.status_code == 200: data = response.json() @@ -253,7 +263,8 @@ class cg_Crypto: """ response = r.get( - f"https://api.coingecko.com/api/v3/coins/{symbol.id}?localization=false" + f"https://api.coingecko.com/api/v3/coins/{symbol.id}?localization=false", + timeout=5, ) if response.status_code == 200: data = response.json() @@ -273,9 +284,10 @@ class cg_Crypto: list of $$ID: NAME """ - coins = r.get("https://api.coingecko.com/api/v3/search/trending").json()[ - "coins" - ] + coins = r.get( + "https://api.coingecko.com/api/v3/search/trending", + timeout=5, + ).json()["coins"] return [f"$${c['item']['symbol'].upper()}: {c['item']['name']}" for c in coins] @@ -283,7 +295,8 @@ class cg_Crypto: query = ",".join([c.id for c in coins]) prices = r.get( - f"https://api.coingecko.com/api/v3/simple/price?ids={query}&vs_currencies=usd&include_24hr_change=true" + f"https://api.coingecko.com/api/v3/simple/price?ids={query}&vs_currencies=usd&include_24hr_change=true", + timeout=5, ).json() replies = [] From d8bbfb057ffabca0e2ab111886a24c401c5258ef Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Fri, 21 May 2021 19:46:01 -0700 Subject: [PATCH 06/12] removed moving average from intra plot --- bot.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bot.py b/bot.py index 5bd7b79..ecfbd13 100644 --- a/bot.py +++ b/bot.py @@ -305,7 +305,6 @@ def intra(update: Update, context: CallbackContext): title=f"\n{symbol.name}", volume="volume" in df.keys(), style="yahoo", - mav=20, savefig=dict(fname=buf, dpi=400, bbox_inches="tight"), ) buf.seek(0) From fcd6afec60161a823cd6bdc999041d6be5848d8e Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Fri, 21 May 2021 19:53:46 -0700 Subject: [PATCH 07/12] Closes #62 --- cg_Crypto.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cg_Crypto.py b/cg_Crypto.py index 1b6d4c6..9c8c056 100644 --- a/cg_Crypto.py +++ b/cg_Crypto.py @@ -238,7 +238,8 @@ class cg_Crypto: return f""" [{data['name']}]({data['links']['homepage'][0]}) Statistics: - Maket Cap Ranking: {data.get('market_cap_rank',"Not Available")} + Market Cap: {data['market_cap'][self.vs_currency]} + Market Cap Ranking: {data.get('market_cap_rank',"Not Available")} CoinGecko Scores: Overall: {data.get('coingecko_score','Not Available')} Development: {data.get('developer_score','Not Available')} From a07d29cbfe34fc1b7232c81b72dcccf8b0bbae0b Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Fri, 21 May 2021 19:58:56 -0700 Subject: [PATCH 08/12] #62 --- IEX_Symbol.py | 2 +- cg_Crypto.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/IEX_Symbol.py b/IEX_Symbol.py index 1faa913..b99ce06 100644 --- a/IEX_Symbol.py +++ b/IEX_Symbol.py @@ -382,7 +382,7 @@ class IEX_Symbol: if "companyName" in data: m += f"Company Name: {data['companyName']}\n" if "marketcap" in data: - m += f"Market Cap: {data['marketcap']:,}\n" + m += f"Market Cap: ${data['marketcap']:,}\n" if "week52high" in data: m += f"52 Week (high-low): {data['week52high']:,} " if "week52low" in data: diff --git a/cg_Crypto.py b/cg_Crypto.py index 9c8c056..09fb135 100644 --- a/cg_Crypto.py +++ b/cg_Crypto.py @@ -238,7 +238,7 @@ class cg_Crypto: return f""" [{data['name']}]({data['links']['homepage'][0]}) Statistics: - Market Cap: {data['market_cap'][self.vs_currency]} + Market Cap: ${data['market_data']['market_cap'][self.vs_currency]:,} Market Cap Ranking: {data.get('market_cap_rank',"Not Available")} CoinGecko Scores: Overall: {data.get('coingecko_score','Not Available')} From 15a62b7989aed905f513b769a075d8705f4560dc Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Fri, 21 May 2021 20:01:07 -0700 Subject: [PATCH 09/12] #54 --- symbol_router.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/symbol_router.py b/symbol_router.py index ec98720..247daa3 100644 --- a/symbol_router.py +++ b/symbol_router.py @@ -184,7 +184,9 @@ class Router: replies.append(self.stock.news_reply(symbol)) elif isinstance(symbol, Coin): # replies.append(self.crypto.news_reply(symbol)) - replies.append("News is not yet supported for cryptocurrencies.") + replies.append( + "News is not yet supported for cryptocurrencies. If you have any suggestions for news sources please contatct @MisterBiggs" + ) else: print(f"{symbol} is not a Stock or Coin") From e6ebd81928075d924b5eb6fd936047665264219f Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Fri, 21 May 2021 20:16:36 -0700 Subject: [PATCH 10/12] #56 added message when errors occur. --- bot.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/bot.py b/bot.py index ecfbd13..81a2e9a 100644 --- a/bot.py +++ b/bot.py @@ -466,19 +466,22 @@ def error(update: Update, context: CallbackContext): ) tb_string = "".join(tb_list) print(tb_string) - if update: - message = ( - f"An exception was raised while handling an update\n" - f"
update = {html.escape(json.dumps(update.to_dict(), indent=2, ensure_ascii=False))}"
-            "
\n\n" - f"
context.chat_data = {html.escape(str(context.chat_data))}
\n\n" - f"
context.user_data = {html.escape(str(context.user_data))}
\n\n" - f"
{html.escape(tb_string)}
" - ) + # if update: + # message = ( + # f"An exception was raised while handling an update\n" + # f"
update = {html.escape(json.dumps(update.to_dict(), indent=2, ensure_ascii=False))}"
+    #         "
\n\n" + # f"
context.chat_data = {html.escape(str(context.chat_data))}
\n\n" + # f"
context.user_data = {html.escape(str(context.user_data))}
\n\n" + # f"
{html.escape(tb_string)}
" + # ) + update.message.reply_text( + text="An error has occured. Please inform @MisterBiggs if the error persists." + ) - # Finally, send the message - # update.message.reply_text(text=message, parse_mode=telegram.ParseMode.HTML) - # update.message.reply_text(text="Please inform the bot admin of this issue.") + # Finally, send the message + # update.message.reply_text(text=message, parse_mode=telegram.ParseMode.HTML) + # update.message.reply_text(text="Please inform the bot admin of this issue.") def main(): From c082761990163bce243c5e55a2387cb3c3915090 Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Fri, 21 May 2021 20:22:23 -0700 Subject: [PATCH 11/12] Closes #60 --- bot.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bot.py b/bot.py index 81a2e9a..c97436e 100644 --- a/bot.py +++ b/bot.py @@ -311,9 +311,9 @@ def intra(update: Update, context: CallbackContext): update.message.reply_photo( photo=buf, - caption=f"\nIntraday chart for {symbol.name} from {df.first_valid_index().strftime('%H:%M')} to" - + f" {df.last_valid_index().strftime('%H:%M %Z')} on" - + f" {datetime.date.today().strftime('%d, %b %Y')}\n\n{s.price_reply([symbol])[0]}", + caption=f"\nIntraday chart for {symbol.name} from {df.first_valid_index().strftime('%d %b at %H:%M')} to" + + f" {df.last_valid_index().strftime('%d %b at %H:%M')}" + + f"\n\n{s.price_reply([symbol])[0]}", parse_mode=telegram.ParseMode.MARKDOWN, disable_notification=True, ) From aba71208894627be376b43588175e1298fe8d7c5 Mon Sep 17 00:00:00 2001 From: Anson Date: Wed, 26 May 2021 22:16:41 -0700 Subject: [PATCH 12/12] Fixes #55 --- IEX_Symbol.py | 3 ++- bot.py | 5 ++--- cg_Crypto.py | 25 ++++++++++++------------- symbol_router.py | 35 +++++++++++++++++++++++++++++++---- 4 files changed, 47 insertions(+), 21 deletions(-) diff --git a/IEX_Symbol.py b/IEX_Symbol.py index 4acf549..9b2fe27 100644 --- a/IEX_Symbol.py +++ b/IEX_Symbol.py @@ -69,8 +69,9 @@ class IEX_Symbol: symbols["description"] = "$" + symbols["symbol"] + ": " + symbols["name"] symbols["id"] = symbols["symbol"] + symbols["type_id"] = "$" + symbols["symbol"].str.lower() - symbols = symbols[["id", "symbol", "name", "description"]] + symbols = symbols[["id", "symbol", "name", "description", "type_id"]] self.symbol_list = symbols if return_df: return symbols, datetime.now() diff --git a/bot.py b/bot.py index a8a6207..1cd0d5c 100644 --- a/bot.py +++ b/bot.py @@ -422,12 +422,11 @@ def inline_query(update: Update, context: CallbackContext): Does a fuzzy search on input and returns stocks that are close. """ - matches = s.search_symbols(update.inline_query.query)[:] + matches = s.inline_search(update.inline_query.query)[:5] symbols = " ".join([match[1].split(":")[0] for match in matches]) prices = s.batch_price_reply(s.find_symbols(symbols)) - # print(len(matches), len(prices)) - # print(prices) + results = [] print(update.inline_query.query) for match, price in zip(matches, prices): diff --git a/cg_Crypto.py b/cg_Crypto.py index e1f9ad8..5323fc5 100644 --- a/cg_Crypto.py +++ b/cg_Crypto.py @@ -47,8 +47,11 @@ class cg_Crypto: raw_symbols = r.get("https://api.coingecko.com/api/v3/coins/list").json() symbols = pd.DataFrame(data=raw_symbols) - symbols["description"] = "$$" + symbols["symbol"] + ": " + symbols["name"] + symbols["description"] = ( + "$$" + symbols["symbol"].str.upper() + ": " + symbols["name"] + ) symbols = symbols[["id", "symbol", "name", "description"]] + symbols["type_id"] = "$$" + symbols["id"] self.symbol_list = symbols if return_df: @@ -287,19 +290,15 @@ class cg_Crypto: ).json() replies = [] - for name, val in prices.items(): - if price := val.get("usd"): - price = val.get("usd") - else: - replies.append(f"{name} price data unavailable.") - break + for coin in coins: + if coin.id in prices: + p = prices[coin.id] - change = 0 - if val.get("usd_24h_change") is not None: - change = val.get("usd_24h_change") + if p.get("usd_24h_change") is None: + p["usd_24h_change"] = 0 - replies.append( - f"{name}: ${price:,} and has moved {change:.2f}% in the past 24 hours." - ) + replies.append( + f"{coin.name}: ${p.get('usd',0):,} and has moved {p.get('usd_24h_change',0.0):.2f}% in the past 24 hours." + ) return replies diff --git a/symbol_router.py b/symbol_router.py index bbca1ed..233d269 100644 --- a/symbol_router.py +++ b/symbol_router.py @@ -113,6 +113,34 @@ class Router: self.searched_symbols[search] = symbol_list return symbol_list + def inline_search(self, search: str) -> List[Tuple[str, str]]: + """Searches based on the shortest symbol that contains the same string as the search. + Should be very fast compared to a fuzzy search. + + Parameters + ---------- + search : str + String used to match against symbols. + + Returns + ------- + List[tuple[str, str]] + Each tuple contains: (Symbol, Issue Name). + """ + + df = pd.concat([self.stock.symbol_list, self.crypto.symbol_list]) + + search = search.lower() + + df = df[df["type_id"].str.contains(search, regex=False)].sort_values( + by="type_id", key=lambda x: x.str.len() + ) + + symbols = df.head(20) + symbol_list = list(zip(list(symbols["symbol"]), list(symbols["description"]))) + self.searched_symbols[search] = symbol_list + return symbol_list + def price_reply(self, symbols: list[Symbol]) -> List[str]: """Returns current market price or after hours if its available for a given stock symbol. @@ -347,11 +375,10 @@ class Router: print(f"{symbol} is not a Stock or Coin") if stocks: - for ( - stock - ) in stocks: # IEX batch endpoint doesnt seem to be working right now + # IEX batch endpoint doesnt seem to be working right now + for stock in stocks: replies.append(self.stock.price_reply(stock)) if coins: - replies.append(self.crypto.batch_price(coins)) + replies = replies + self.crypto.batch_price(coins) return replies