mirror of
https://gitlab.com/simple-stock-bots/simple-telegram-stock-bot.git
synced 2025-06-16 15:06:53 +00:00
start on #18
This commit is contained in:
parent
baf45e09c8
commit
acc0ebdd28
@ -9,7 +9,7 @@ import requests as r
|
|||||||
import schedule
|
import schedule
|
||||||
from fuzzywuzzy import fuzz
|
from fuzzywuzzy import fuzz
|
||||||
import os
|
import os
|
||||||
|
from logging import warning
|
||||||
from Symbol import Stock
|
from Symbol import Stock
|
||||||
|
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ class IEX_Symbol:
|
|||||||
self.IEX_TOKEN = os.environ["IEX"]
|
self.IEX_TOKEN = os.environ["IEX"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
self.IEX_TOKEN = ""
|
self.IEX_TOKEN = ""
|
||||||
print(
|
warning(
|
||||||
"Starting without an IEX Token will not allow you to get market data!"
|
"Starting without an IEX Token will not allow you to get market data!"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
72
bot.py
72
bot.py
@ -7,6 +7,8 @@ import html
|
|||||||
import json
|
import json
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
from logging import debug, info, warning, error, critical
|
||||||
|
|
||||||
import mplfinance as mpf
|
import mplfinance as mpf
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
@ -36,7 +38,7 @@ try:
|
|||||||
STRIPE_TOKEN = os.environ["STRIPE"]
|
STRIPE_TOKEN = os.environ["STRIPE"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
STRIPE_TOKEN = ""
|
STRIPE_TOKEN = ""
|
||||||
print("Starting without a STRIPE Token will not allow you to accept Donations!")
|
warning("Starting without a STRIPE Token will not allow you to accept Donations!")
|
||||||
|
|
||||||
s = Router()
|
s = Router()
|
||||||
t = T_info()
|
t = T_info()
|
||||||
@ -47,11 +49,12 @@ logging.basicConfig(
|
|||||||
)
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
print("Bot Online")
|
info("Bot script started.")
|
||||||
|
|
||||||
|
|
||||||
def start(update: Update, context: CallbackContext):
|
def start(update: Update, context: CallbackContext):
|
||||||
"""Send a message when the command /start is issued."""
|
"""Send a message when the command /start is issued."""
|
||||||
|
info(f"Start command ran by {update.message.chat.username}")
|
||||||
update.message.reply_text(
|
update.message.reply_text(
|
||||||
text=t.help_text,
|
text=t.help_text,
|
||||||
parse_mode=telegram.ParseMode.MARKDOWN,
|
parse_mode=telegram.ParseMode.MARKDOWN,
|
||||||
@ -61,6 +64,7 @@ def start(update: Update, context: CallbackContext):
|
|||||||
|
|
||||||
def help(update: Update, context: CallbackContext):
|
def help(update: Update, context: CallbackContext):
|
||||||
"""Send link to docs when the command /help is issued."""
|
"""Send link to docs when the command /help is issued."""
|
||||||
|
info(f"Help command ran by {update.message.chat.username}")
|
||||||
update.message.reply_text(
|
update.message.reply_text(
|
||||||
text=t.help_text,
|
text=t.help_text,
|
||||||
parse_mode=telegram.ParseMode.MARKDOWN,
|
parse_mode=telegram.ParseMode.MARKDOWN,
|
||||||
@ -70,6 +74,7 @@ def help(update: Update, context: CallbackContext):
|
|||||||
|
|
||||||
def license(update: Update, context: CallbackContext):
|
def license(update: Update, context: CallbackContext):
|
||||||
"""Return bots license agreement"""
|
"""Return bots license agreement"""
|
||||||
|
info(f"License command ran by {update.message.chat.username}")
|
||||||
update.message.reply_text(
|
update.message.reply_text(
|
||||||
text=t.license,
|
text=t.license,
|
||||||
parse_mode=telegram.ParseMode.MARKDOWN,
|
parse_mode=telegram.ParseMode.MARKDOWN,
|
||||||
@ -78,6 +83,7 @@ def license(update: Update, context: CallbackContext):
|
|||||||
|
|
||||||
|
|
||||||
def status(update: Update, context: CallbackContext):
|
def status(update: Update, context: CallbackContext):
|
||||||
|
warning(f"Status command ran by {update.message.chat.username}")
|
||||||
bot_resp = datetime.datetime.now(update.message.date.tzinfo) - update.message.date
|
bot_resp = datetime.datetime.now(update.message.date.tzinfo) - update.message.date
|
||||||
|
|
||||||
update.message.reply_text(
|
update.message.reply_text(
|
||||||
@ -90,6 +96,7 @@ def status(update: Update, context: CallbackContext):
|
|||||||
|
|
||||||
|
|
||||||
def donate(update: Update, context: CallbackContext):
|
def donate(update: Update, context: CallbackContext):
|
||||||
|
info(f"Donate command ran by {update.message.chat.username}")
|
||||||
chat_id = update.message.chat_id
|
chat_id = update.message.chat_id
|
||||||
|
|
||||||
if update.message.text.strip() == "/donate":
|
if update.message.text.strip() == "/donate":
|
||||||
@ -107,7 +114,7 @@ def donate(update: Update, context: CallbackContext):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
update.message.reply_text(f"{amount} is not a valid donation amount or number.")
|
update.message.reply_text(f"{amount} is not a valid donation amount or number.")
|
||||||
return
|
return
|
||||||
print(price)
|
info(f"Donation amount: {price}")
|
||||||
|
|
||||||
context.bot.send_invoice(
|
context.bot.send_invoice(
|
||||||
chat_id=chat_id,
|
chat_id=chat_id,
|
||||||
@ -126,6 +133,7 @@ def donate(update: Update, context: CallbackContext):
|
|||||||
|
|
||||||
|
|
||||||
def precheckout_callback(update: Update, context: CallbackContext):
|
def precheckout_callback(update: Update, context: CallbackContext):
|
||||||
|
info(f"precheckout_callback queried")
|
||||||
query = update.pre_checkout_query
|
query = update.pre_checkout_query
|
||||||
|
|
||||||
query.answer(ok=True)
|
query.answer(ok=True)
|
||||||
@ -138,6 +146,7 @@ def precheckout_callback(update: Update, context: CallbackContext):
|
|||||||
|
|
||||||
|
|
||||||
def successful_payment_callback(update: Update, context: CallbackContext):
|
def successful_payment_callback(update: Update, context: CallbackContext):
|
||||||
|
info(f"Successful payment!")
|
||||||
update.message.reply_text(
|
update.message.reply_text(
|
||||||
"Thank you for your donation! It goes a long way to keeping the bot free!"
|
"Thank you for your donation! It goes a long way to keeping the bot free!"
|
||||||
)
|
)
|
||||||
@ -148,6 +157,7 @@ def symbol_detect(update: Update, context: CallbackContext):
|
|||||||
Runs on any message that doesn't have a command and searches for symbols,
|
Runs on any message that doesn't have a command and searches for symbols,
|
||||||
then returns the prices of any symbols found.
|
then returns the prices of any symbols found.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
message = update.message.text
|
message = update.message.text
|
||||||
chat_id = update.message.chat_id
|
chat_id = update.message.chat_id
|
||||||
symbols = s.find_symbols(message)
|
symbols = s.find_symbols(message)
|
||||||
@ -155,7 +165,9 @@ def symbol_detect(update: Update, context: CallbackContext):
|
|||||||
if symbols:
|
if symbols:
|
||||||
# Let user know bot is working
|
# Let user know bot is working
|
||||||
context.bot.send_chat_action(chat_id=chat_id, action=telegram.ChatAction.TYPING)
|
context.bot.send_chat_action(chat_id=chat_id, action=telegram.ChatAction.TYPING)
|
||||||
print(symbols)
|
info(f"User called for symbols: {update.message.chat.username}")
|
||||||
|
info(f"Symbols found: {symbols}")
|
||||||
|
|
||||||
for reply in s.price_reply(symbols):
|
for reply in s.price_reply(symbols):
|
||||||
update.message.reply_text(
|
update.message.reply_text(
|
||||||
text=reply,
|
text=reply,
|
||||||
@ -168,6 +180,7 @@ def dividend(update: Update, context: CallbackContext):
|
|||||||
"""
|
"""
|
||||||
waits for /dividend or /div command and then finds dividend info on that symbol.
|
waits for /dividend or /div command and then finds dividend info on that symbol.
|
||||||
"""
|
"""
|
||||||
|
info(f"Dividend command ran by {update.message.chat.username}")
|
||||||
message = update.message.text
|
message = update.message.text
|
||||||
chat_id = update.message.chat_id
|
chat_id = update.message.chat_id
|
||||||
|
|
||||||
@ -193,6 +206,7 @@ def news(update: Update, context: CallbackContext):
|
|||||||
"""
|
"""
|
||||||
waits for /news command and then finds news info on that symbol.
|
waits for /news command and then finds news info on that symbol.
|
||||||
"""
|
"""
|
||||||
|
info(f"News command ran by {update.message.chat.username}")
|
||||||
message = update.message.text
|
message = update.message.text
|
||||||
chat_id = update.message.chat_id
|
chat_id = update.message.chat_id
|
||||||
|
|
||||||
@ -215,10 +229,11 @@ def news(update: Update, context: CallbackContext):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def info(update: Update, context: CallbackContext):
|
def information(update: Update, context: CallbackContext):
|
||||||
"""
|
"""
|
||||||
waits for /info command and then finds info on that symbol.
|
waits for /info command and then finds info on that symbol.
|
||||||
"""
|
"""
|
||||||
|
info(f"Information command ran by {update.message.chat.username}")
|
||||||
message = update.message.text
|
message = update.message.text
|
||||||
chat_id = update.message.chat_id
|
chat_id = update.message.chat_id
|
||||||
|
|
||||||
@ -242,6 +257,7 @@ def info(update: Update, context: CallbackContext):
|
|||||||
|
|
||||||
|
|
||||||
def search(update: Update, context: CallbackContext):
|
def search(update: Update, context: CallbackContext):
|
||||||
|
info(f"Search command ran by {update.message.chat.username}")
|
||||||
message = update.message.text.replace("/search ", "")
|
message = update.message.text.replace("/search ", "")
|
||||||
chat_id = update.message.chat_id
|
chat_id = update.message.chat_id
|
||||||
|
|
||||||
@ -265,6 +281,7 @@ def search(update: Update, context: CallbackContext):
|
|||||||
|
|
||||||
|
|
||||||
def intra(update: Update, context: CallbackContext):
|
def intra(update: Update, context: CallbackContext):
|
||||||
|
info(f"Intra command ran by {update.message.chat.username}")
|
||||||
# TODO: Document usage of this command. https://iexcloud.io/docs/api/#historical-prices
|
# TODO: Document usage of this command. https://iexcloud.io/docs/api/#historical-prices
|
||||||
|
|
||||||
message = update.message.text
|
message = update.message.text
|
||||||
@ -320,6 +337,7 @@ def intra(update: Update, context: CallbackContext):
|
|||||||
|
|
||||||
|
|
||||||
def chart(update: Update, context: CallbackContext):
|
def chart(update: Update, context: CallbackContext):
|
||||||
|
info(f"Chart command ran by {update.message.chat.username}")
|
||||||
# TODO: Document usage of this command. https://iexcloud.io/docs/api/#historical-prices
|
# TODO: Document usage of this command. https://iexcloud.io/docs/api/#historical-prices
|
||||||
|
|
||||||
message = update.message.text
|
message = update.message.text
|
||||||
@ -350,7 +368,7 @@ def chart(update: Update, context: CallbackContext):
|
|||||||
context.bot.send_chat_action(
|
context.bot.send_chat_action(
|
||||||
chat_id=chat_id, action=telegram.ChatAction.UPLOAD_PHOTO
|
chat_id=chat_id, action=telegram.ChatAction.UPLOAD_PHOTO
|
||||||
)
|
)
|
||||||
print(symbol)
|
|
||||||
buf = io.BytesIO()
|
buf = io.BytesIO()
|
||||||
mpf.plot(
|
mpf.plot(
|
||||||
df,
|
df,
|
||||||
@ -375,6 +393,7 @@ def stat(update: Update, context: CallbackContext):
|
|||||||
"""
|
"""
|
||||||
https://iexcloud.io/docs/api/#key-stats
|
https://iexcloud.io/docs/api/#key-stats
|
||||||
"""
|
"""
|
||||||
|
info(f"Stat command ran by {update.message.chat.username}")
|
||||||
message = update.message.text
|
message = update.message.text
|
||||||
chat_id = update.message.chat_id
|
chat_id = update.message.chat_id
|
||||||
|
|
||||||
@ -401,6 +420,7 @@ def cap(update: Update, context: CallbackContext):
|
|||||||
"""
|
"""
|
||||||
Market Cap Information
|
Market Cap Information
|
||||||
"""
|
"""
|
||||||
|
info(f"Cap command ran by {update.message.chat.username}")
|
||||||
message = update.message.text
|
message = update.message.text
|
||||||
chat_id = update.message.chat_id
|
chat_id = update.message.chat_id
|
||||||
|
|
||||||
@ -427,6 +447,7 @@ def trending(update: Update, context: CallbackContext):
|
|||||||
"""
|
"""
|
||||||
Trending Symbols
|
Trending Symbols
|
||||||
"""
|
"""
|
||||||
|
info(f"Trending command ran by {update.message.chat.username}")
|
||||||
|
|
||||||
chat_id = update.message.chat_id
|
chat_id = update.message.chat_id
|
||||||
|
|
||||||
@ -444,14 +465,14 @@ def inline_query(update: Update, context: CallbackContext):
|
|||||||
Handles inline query.
|
Handles inline query.
|
||||||
Does a fuzzy search on input and returns stocks that are close.
|
Does a fuzzy search on input and returns stocks that are close.
|
||||||
"""
|
"""
|
||||||
|
info(f"Inline command ran by {update.message.chat.username}")
|
||||||
|
info(f"Query: {update.inline_query.query}")
|
||||||
matches = s.inline_search(update.inline_query.query)[:5]
|
matches = s.inline_search(update.inline_query.query)[:5]
|
||||||
|
|
||||||
symbols = " ".join([match[1].split(":")[0] for match in matches])
|
symbols = " ".join([match[1].split(":")[0] for match in matches])
|
||||||
prices = s.batch_price_reply(s.find_symbols(symbols))
|
prices = s.batch_price_reply(s.find_symbols(symbols))
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
print(update.inline_query.query)
|
|
||||||
for match, price in zip(matches, prices):
|
for match, price in zip(matches, prices):
|
||||||
try:
|
try:
|
||||||
results.append(
|
results.append(
|
||||||
@ -464,16 +485,20 @@ def inline_query(update: Update, context: CallbackContext):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
logging.warning(str(match))
|
warning(f"{match} caused error in inline query.")
|
||||||
pass
|
pass
|
||||||
print(match[0], "\n\n\n")
|
|
||||||
if len(results) == 5:
|
if len(results) == 5:
|
||||||
update.inline_query.answer(results)
|
update.inline_query.answer(results)
|
||||||
|
info("Inline Command was successful")
|
||||||
return
|
return
|
||||||
update.inline_query.answer(results)
|
update.inline_query.answer(results)
|
||||||
|
|
||||||
|
|
||||||
def rand_pick(update: Update, context: CallbackContext):
|
def rand_pick(update: Update, context: CallbackContext):
|
||||||
|
info(
|
||||||
|
f"Someone is gambling! Random_pick command ran by {update.message.chat.username}"
|
||||||
|
)
|
||||||
|
|
||||||
update.message.reply_text(
|
update.message.reply_text(
|
||||||
text=s.random_pick(),
|
text=s.random_pick(),
|
||||||
@ -484,22 +509,25 @@ def rand_pick(update: Update, context: CallbackContext):
|
|||||||
|
|
||||||
def error(update: Update, context: CallbackContext):
|
def error(update: Update, context: CallbackContext):
|
||||||
"""Log Errors caused by Updates."""
|
"""Log Errors caused by Updates."""
|
||||||
logger.warning('Update "%s" caused error "%s"', update, error)
|
warning('Update "%s" caused error "%s"', update, error)
|
||||||
|
|
||||||
tb_list = traceback.format_exception(
|
tb_list = traceback.format_exception(
|
||||||
None, context.error, context.error.__traceback__
|
None, context.error, context.error.__traceback__
|
||||||
)
|
)
|
||||||
tb_string = "".join(tb_list)
|
tb_string = "".join(tb_list)
|
||||||
print(tb_string)
|
|
||||||
# if update:
|
if update:
|
||||||
# message = (
|
message = (
|
||||||
# f"An exception was raised while handling an update\n"
|
f"An exception was raised while handling an update\n"
|
||||||
# f"<pre>update = {html.escape(json.dumps(update.to_dict(), indent=2, ensure_ascii=False))}"
|
f"<pre>update = {html.escape(json.dumps(update.to_dict(), indent=2, ensure_ascii=False))}"
|
||||||
# "</pre>\n\n"
|
"</pre>\n\n"
|
||||||
# f"<pre>context.chat_data = {html.escape(str(context.chat_data))}</pre>\n\n"
|
f"<pre>context.chat_data = {html.escape(str(context.chat_data))}</pre>\n\n"
|
||||||
# f"<pre>context.user_data = {html.escape(str(context.user_data))}</pre>\n\n"
|
f"<pre>context.user_data = {html.escape(str(context.user_data))}</pre>\n\n"
|
||||||
# f"<pre>{html.escape(tb_string)}</pre>"
|
f"<pre>{html.escape(tb_string)}</pre>"
|
||||||
# )
|
)
|
||||||
|
warning(message)
|
||||||
|
else:
|
||||||
|
warning(tb_string)
|
||||||
update.message.reply_text(
|
update.message.reply_text(
|
||||||
text="An error has occured. Please inform @MisterBiggs if the error persists."
|
text="An error has occured. Please inform @MisterBiggs if the error persists."
|
||||||
)
|
)
|
||||||
@ -524,7 +552,7 @@ def main():
|
|||||||
dp.add_handler(CommandHandler("dividend", dividend))
|
dp.add_handler(CommandHandler("dividend", dividend))
|
||||||
dp.add_handler(CommandHandler("div", dividend))
|
dp.add_handler(CommandHandler("div", dividend))
|
||||||
dp.add_handler(CommandHandler("news", news))
|
dp.add_handler(CommandHandler("news", news))
|
||||||
dp.add_handler(CommandHandler("info", info))
|
dp.add_handler(CommandHandler("info", information))
|
||||||
dp.add_handler(CommandHandler("stat", stat))
|
dp.add_handler(CommandHandler("stat", stat))
|
||||||
dp.add_handler(CommandHandler("stats", stat))
|
dp.add_handler(CommandHandler("stats", stat))
|
||||||
dp.add_handler(CommandHandler("cap", cap))
|
dp.add_handler(CommandHandler("cap", cap))
|
||||||
|
@ -7,7 +7,7 @@ import random
|
|||||||
import datetime
|
import datetime
|
||||||
from fuzzywuzzy import fuzz
|
from fuzzywuzzy import fuzz
|
||||||
|
|
||||||
from typing import List, Tuple
|
from logging import debug, info, warning, error, critical
|
||||||
|
|
||||||
from IEX_Symbol import IEX_Symbol
|
from IEX_Symbol import IEX_Symbol
|
||||||
from cg_Crypto import cg_Crypto
|
from cg_Crypto import cg_Crypto
|
||||||
@ -24,7 +24,7 @@ class Router:
|
|||||||
self.stock = IEX_Symbol()
|
self.stock = IEX_Symbol()
|
||||||
self.crypto = cg_Crypto()
|
self.crypto = cg_Crypto()
|
||||||
|
|
||||||
def find_symbols(self, text: str) -> List[Symbol]:
|
def find_symbols(self, text: str) -> list[Symbol]:
|
||||||
"""Finds stock tickers starting with a dollar sign, and cryptocurrencies with two dollar signs
|
"""Finds stock tickers starting with a dollar sign, and cryptocurrencies with two dollar signs
|
||||||
in a blob of text and returns them in a list.
|
in a blob of text and returns them in a list.
|
||||||
Only returns each match once. Example: Whats the price of $tsla?
|
Only returns each match once. Example: Whats the price of $tsla?
|
||||||
@ -36,7 +36,7 @@ class Router:
|
|||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
List[str]
|
list[str]
|
||||||
List of stock symbols as strings without dollar sign.
|
List of stock symbols as strings without dollar sign.
|
||||||
"""
|
"""
|
||||||
symbols = []
|
symbols = []
|
||||||
@ -45,15 +45,15 @@ class Router:
|
|||||||
if stock.upper() in self.stock.symbol_list["symbol"].values:
|
if stock.upper() in self.stock.symbol_list["symbol"].values:
|
||||||
symbols.append(Stock(stock))
|
symbols.append(Stock(stock))
|
||||||
else:
|
else:
|
||||||
print(f"{stock} is not in list of stocks")
|
info(f"{stock} is not in list of stocks")
|
||||||
|
|
||||||
coins = set(re.findall(self.CRYPTO_REGEX, text))
|
coins = set(re.findall(self.CRYPTO_REGEX, text))
|
||||||
for coin in coins:
|
for coin in coins:
|
||||||
if coin.lower() in self.crypto.symbol_list["symbol"].values:
|
if coin.lower() in self.crypto.symbol_list["symbol"].values:
|
||||||
symbols.append(Coin(coin.lower()))
|
symbols.append(Coin(coin.lower()))
|
||||||
else:
|
else:
|
||||||
print(f"{coin} is not in list of coins")
|
info(f"{coin} is not in list of coins")
|
||||||
print(symbols)
|
info(symbols)
|
||||||
return symbols
|
return symbols
|
||||||
|
|
||||||
def status(self, bot_resp) -> str:
|
def status(self, bot_resp) -> str:
|
||||||
@ -65,7 +65,7 @@ class Router:
|
|||||||
Human readable text on status of the bot and relevant APIs
|
Human readable text on status of the bot and relevant APIs
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return f"""
|
stats = f"""
|
||||||
Bot Status:
|
Bot Status:
|
||||||
{bot_resp}
|
{bot_resp}
|
||||||
|
|
||||||
@ -76,7 +76,11 @@ class Router:
|
|||||||
{self.crypto.status()}
|
{self.crypto.status()}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def search_symbols(self, search: str) -> List[Tuple[str, str]]:
|
warning(stats)
|
||||||
|
|
||||||
|
return stats
|
||||||
|
|
||||||
|
def search_symbols(self, search: str) -> list[tuple[str, str]]:
|
||||||
"""Performs a fuzzy search to find stock symbols closest to a search term.
|
"""Performs a fuzzy search to find stock symbols closest to a search term.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
@ -86,7 +90,7 @@ class Router:
|
|||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
List[tuple[str, str]]
|
list[tuple[str, str]]
|
||||||
A list tuples of every stock sorted in order of how well they match. Each tuple contains: (Symbol, Issue Name).
|
A list tuples of every stock sorted in order of how well they match. Each tuple contains: (Symbol, Issue Name).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -113,7 +117,7 @@ class Router:
|
|||||||
self.searched_symbols[search] = symbol_list
|
self.searched_symbols[search] = symbol_list
|
||||||
return symbol_list
|
return symbol_list
|
||||||
|
|
||||||
def inline_search(self, search: str) -> List[Tuple[str, str]]:
|
def inline_search(self, search: str) -> list[tuple[str, str]]:
|
||||||
"""Searches based on the shortest symbol that contains the same string as the search.
|
"""Searches based on the shortest symbol that contains the same string as the search.
|
||||||
Should be very fast compared to a fuzzy search.
|
Should be very fast compared to a fuzzy search.
|
||||||
|
|
||||||
@ -124,7 +128,7 @@ class Router:
|
|||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
List[tuple[str, str]]
|
list[tuple[str, str]]
|
||||||
Each tuple contains: (Symbol, Issue Name).
|
Each tuple contains: (Symbol, Issue Name).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -141,7 +145,7 @@ class Router:
|
|||||||
self.searched_symbols[search] = symbol_list
|
self.searched_symbols[search] = symbol_list
|
||||||
return symbol_list
|
return symbol_list
|
||||||
|
|
||||||
def price_reply(self, symbols: list[Symbol]) -> List[str]:
|
def price_reply(self, symbols: list[Symbol]) -> list[str]:
|
||||||
"""Returns current market price or after hours if its available for a given stock symbol.
|
"""Returns current market price or after hours if its available for a given stock symbol.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
@ -158,17 +162,17 @@ class Router:
|
|||||||
replies = []
|
replies = []
|
||||||
|
|
||||||
for symbol in symbols:
|
for symbol in symbols:
|
||||||
print(symbol)
|
info(symbol)
|
||||||
if isinstance(symbol, Stock):
|
if isinstance(symbol, Stock):
|
||||||
replies.append(self.stock.price_reply(symbol))
|
replies.append(self.stock.price_reply(symbol))
|
||||||
elif isinstance(symbol, Coin):
|
elif isinstance(symbol, Coin):
|
||||||
replies.append(self.crypto.price_reply(symbol))
|
replies.append(self.crypto.price_reply(symbol))
|
||||||
else:
|
else:
|
||||||
print(f"{symbol} is not a Stock or Coin")
|
info(f"{symbol} is not a Stock or Coin")
|
||||||
|
|
||||||
return replies
|
return replies
|
||||||
|
|
||||||
def dividend_reply(self, symbols: list) -> List[str]:
|
def dividend_reply(self, symbols: list) -> list[str]:
|
||||||
"""Returns the most recent, or next dividend date for a stock symbol.
|
"""Returns the most recent, or next dividend date for a stock symbol.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
@ -192,7 +196,7 @@ class Router:
|
|||||||
|
|
||||||
return replies
|
return replies
|
||||||
|
|
||||||
def news_reply(self, symbols: list) -> List[str]:
|
def news_reply(self, symbols: list) -> list[str]:
|
||||||
"""Gets recent english news on stock symbols.
|
"""Gets recent english news on stock symbols.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
@ -220,12 +224,12 @@ class Router:
|
|||||||
|
|
||||||
return replies
|
return replies
|
||||||
|
|
||||||
def info_reply(self, symbols: list) -> List[str]:
|
def info_reply(self, symbols: list) -> list[str]:
|
||||||
"""Gets information on stock symbols.
|
"""Gets information on stock symbols.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
symbols : List[str]
|
symbols : list[str]
|
||||||
List of stock symbols.
|
List of stock symbols.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
@ -289,12 +293,12 @@ class Router:
|
|||||||
print(f"{symbol} is not a Stock or Coin")
|
print(f"{symbol} is not a Stock or Coin")
|
||||||
return pd.DataFrame()
|
return pd.DataFrame()
|
||||||
|
|
||||||
def stat_reply(self, symbols: List[Symbol]) -> List[str]:
|
def stat_reply(self, symbols: list[Symbol]) -> list[str]:
|
||||||
"""Gets key statistics for each symbol in the list
|
"""Gets key statistics for each symbol in the list
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
symbols : List[str]
|
symbols : list[str]
|
||||||
List of stock symbols
|
List of stock symbols
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
@ -314,12 +318,12 @@ class Router:
|
|||||||
|
|
||||||
return replies
|
return replies
|
||||||
|
|
||||||
def cap_reply(self, symbols: List[Symbol]) -> List[str]:
|
def cap_reply(self, symbols: list[Symbol]) -> list[str]:
|
||||||
"""Gets market cap for each symbol in the list
|
"""Gets market cap for each symbol in the list
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
symbols : List[str]
|
symbols : list[str]
|
||||||
List of stock symbols
|
List of stock symbols
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
@ -375,7 +379,7 @@ class Router:
|
|||||||
|
|
||||||
return f"{choice}\nBuy and hold until: {hold}"
|
return f"{choice}\nBuy and hold until: {hold}"
|
||||||
|
|
||||||
def batch_price_reply(self, symbols: list[Symbol]) -> List[str]:
|
def batch_price_reply(self, symbols: list[Symbol]) -> list[str]:
|
||||||
"""Returns current market price or after hours if its available for a given stock symbol.
|
"""Returns current market price or after hours if its available for a given stock symbol.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
|
Loading…
x
Reference in New Issue
Block a user