1
0
mirror of https://gitlab.com/simple-stock-bots/simple-stock-bot.git synced 2025-06-15 23:06:40 +00:00

updated all docstrings

This commit is contained in:
MisterBiggs 2021-07-02 12:41:36 -07:00
parent acc0ebdd28
commit 43976e873a
8 changed files with 114 additions and 359 deletions

View File

@ -30,7 +30,7 @@ class IEX_Symbol:
Parameters
----------
IEX_TOKEN : str
IEX Token
IEX API Token
"""
try:
self.IEX_TOKEN = os.environ["IEX"]
@ -47,12 +47,28 @@ class IEX_Symbol:
schedule.every().day.do(self.clear_charts)
def clear_charts(self) -> None:
"""Clears cache of chart data."""
"""
Clears cache of chart data.
Charts are cached so that only 1 API call per 24 hours is needed since the
chart data is expensive and a large download.
"""
self.charts = {}
def get_symbol_list(
self, return_df=False
) -> Optional[Tuple[pd.DataFrame, datetime]]:
"""Gets list of all symbols supported by IEX
Parameters
----------
return_df : bool, optional
return the dataframe of all stock symbols, by default False
Returns
-------
Optional[Tuple[pd.DataFrame, datetime]]
If `return_df` is set to `True` returns a dataframe, otherwise returns `None`.
"""
reg_symbols = r.get(
f"https://cloud.iexapis.com/stable/ref-data/symbols?token={self.IEX_TOKEN}",
@ -145,18 +161,16 @@ class IEX_Symbol:
return symbol_list
def price_reply(self, symbol: Stock) -> str:
"""Returns current market price or after hours if its available for a given stock symbol.
"""Returns price movement of Stock for the last market day, or after hours.
Parameters
----------
symbols : list
List of stock symbols.
symbol : Stock
Returns
-------
Dict[str, str]
Each symbol passed in is a key with its value being a human readable
markdown formatted string of the symbols price and movement.
str
Formatted markdown
"""
IEXurl = f"https://cloud.iexapis.com/stable/stock/{symbol.id}/quote?token={self.IEX_TOKEN}"
@ -223,13 +237,12 @@ class IEX_Symbol:
Parameters
----------
symbols : list
List of stock symbols.
symbol : Stock
Returns
-------
Dict[str, str]
Each symbol passed in is a key with its value being a human readable formatted string of the symbols div dates.
str
Formatted markdown
"""
if symbol.symbol.upper() in self.otc_list:
return "OTC stocks do not currently support any commands."
@ -284,17 +297,16 @@ class IEX_Symbol:
return f"${symbol.id.upper()} either doesn't exist or pays no dividend."
def news_reply(self, symbol: Stock) -> str:
"""Gets recent english news on stock symbols.
"""Gets most recent, english, non-paywalled news
Parameters
----------
symbols : list
List of stock symbols.
symbol : Stock
Returns
-------
Dict[str, str]
Each symbol passed in is a key with its value being a human readable markdown formatted string of the symbols news.
str
Formatted markdown
"""
if symbol.symbol.upper() in self.otc_list:
return "OTC stocks do not currently support any commands."
@ -323,17 +335,16 @@ class IEX_Symbol:
return f"News for **{symbol.id.upper()}**:\n" + "\n".join(line[:5])
def info_reply(self, symbol: Stock) -> str:
"""Gets information on stock symbols.
"""Gets description for Stock
Parameters
----------
symbols : List[str]
List of stock symbols.
symbol : Stock
Returns
-------
Dict[str, str]
Each symbol passed in is a key with its value being a human readable formatted string of the symbols information.
str
Formatted text
"""
if symbol.symbol.upper() in self.otc_list:
return "OTC stocks do not currently support any commands."
@ -354,17 +365,16 @@ class IEX_Symbol:
return f"No information found for: {symbol}\nEither today is boring or the symbol does not exist."
def stat_reply(self, symbol: Stock) -> str:
"""Gets key statistics for each symbol in the list
"""Key statistics on a Stock
Parameters
----------
symbols : List[str]
List of stock symbols
symbol : Stock
Returns
-------
Dict[str, str]
Each symbol passed in is a key with its value being a human readable formatted string of the symbols statistics.
str
Formatted markdown
"""
if symbol.symbol.upper() in self.otc_list:
return "OTC stocks do not currently support any commands."
@ -503,7 +513,7 @@ class IEX_Symbol:
Returns
-------
list[str]
list of $ID: NAME
list of $ID: NAME, CHANGE%
"""
stocks = r.get(

View File

@ -25,6 +25,8 @@ class Symbol:
class Stock(Symbol):
"""Stock Market Object. Gets data from IEX Cloud"""
def __init__(self, symbol: str) -> None:
self.symbol = symbol
self.id = symbol
@ -36,6 +38,8 @@ coins = r.get("https://api.coingecko.com/api/v3/coins/list").json()
class Coin(Symbol):
"""Cryptocurrency Object. Gets data from CoinGecko."""
@functools.cache
def __init__(self, symbol: str) -> None:
self.symbol = symbol

View File

@ -21,7 +21,7 @@ Keep up with the latest news for the bot in its Telegram Channel: https://t.me/s
Full documentation on using and running your own stock bot can be found [on the bots website.](https://simple-stock-bots.gitlab.io/site)
The bot detects _"Symbols"_ using either one or two dollar signs before the symbol. One dollar sign is for a stock market ticker, while two is for a cryptocurrency coin. `/chart $$eth` would return a chart of the past month of data for Ethereum, while `/dividend $psec` returns dividend information for Prospect Capital stock.
The bot detects _"Symbols"_ using either one `$` or two `$$` dollar signs before the symbol. One dollar sign is for a stock market ticker, while two is for a cryptocurrency coin. `/chart $$eth` would return a chart of the past month of data for Ethereum, while `/dividend $psec` returns dividend information for Prospect Capital stock.
Simply calling a symbol in any message that the bot can see will also return the price. So a message like: `I wonder if $$btc will go to the Moon now that $tsla accepts it as payment` would return the current price for both Bitcoin and Tesla.
@ -67,7 +67,7 @@ info - $[symbol] General information about the symbol.
news - $[symbol] News about the symbol. 📰
stat - $[symbol] Key statistics about the symbol. 🔢
dividend - $[symbol] Dividend info 📅
intra - $[symbol] Plot since the last market open. 📈
trending - Trending Stocks and Cryptos. 💬
intra - $[symbol] Plot since the last market open. 📈
chart - $[chart] Plot of the past month. 📊
""" # Not used by the bot but for updaing commands with BotFather

57
bot.py
View File

@ -53,7 +53,7 @@ info("Bot script started.")
def start(update: Update, context: CallbackContext):
"""Send a message when the command /start is issued."""
"""Send help text when the command /start is issued."""
info(f"Start command ran by {update.message.chat.username}")
update.message.reply_text(
text=t.help_text,
@ -63,7 +63,7 @@ def start(update: Update, context: CallbackContext):
def help(update: Update, context: CallbackContext):
"""Send link to docs when the command /help is issued."""
"""Send help text when the command /help is issued."""
info(f"Help command ran by {update.message.chat.username}")
update.message.reply_text(
text=t.help_text,
@ -73,7 +73,7 @@ def help(update: Update, context: CallbackContext):
def license(update: Update, context: CallbackContext):
"""Return bots license agreement"""
"""Send bots license when the /license command is issued."""
info(f"License command ran by {update.message.chat.username}")
update.message.reply_text(
text=t.license,
@ -83,6 +83,7 @@ def license(update: Update, context: CallbackContext):
def status(update: Update, context: CallbackContext):
"""Gather status of bot and dependant services and return important status updates."""
warning(f"Status command ran by {update.message.chat.username}")
bot_resp = datetime.datetime.now(update.message.date.tzinfo) - update.message.date
@ -96,6 +97,7 @@ def status(update: Update, context: CallbackContext):
def donate(update: Update, context: CallbackContext):
"""Sets up donation."""
info(f"Donate command ran by {update.message.chat.username}")
chat_id = update.message.chat_id
@ -133,6 +135,7 @@ def donate(update: Update, context: CallbackContext):
def precheckout_callback(update: Update, context: CallbackContext):
"""Approves donation"""
info(f"precheckout_callback queried")
query = update.pre_checkout_query
@ -146,6 +149,7 @@ def precheckout_callback(update: Update, context: CallbackContext):
def successful_payment_callback(update: Update, context: CallbackContext):
"""Thanks user for donation"""
info(f"Successful payment!")
update.message.reply_text(
"Thank you for your donation! It goes a long way to keeping the bot free!"
@ -177,9 +181,7 @@ def symbol_detect(update: Update, context: CallbackContext):
def dividend(update: Update, context: CallbackContext):
"""
waits for /dividend or /div command and then finds dividend info on that symbol.
"""
"""/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
chat_id = update.message.chat_id
@ -203,9 +205,7 @@ def dividend(update: Update, context: CallbackContext):
def news(update: Update, context: CallbackContext):
"""
waits for /news command and then finds news info on that symbol.
"""
"""/news command then finds news info on that symbol."""
info(f"News command ran by {update.message.chat.username}")
message = update.message.text
chat_id = update.message.chat_id
@ -230,9 +230,7 @@ def news(update: Update, context: CallbackContext):
def information(update: Update, context: CallbackContext):
"""
waits for /info command and then finds info on that symbol.
"""
"""/info command then finds info on that symbol."""
info(f"Information command ran by {update.message.chat.username}")
message = update.message.text
chat_id = update.message.chat_id
@ -257,6 +255,10 @@ def information(update: Update, context: CallbackContext):
def search(update: Update, context: CallbackContext):
"""
Uses fuzzy search on full list of stocks and crypto names
and descriptions then returns the top matches in order.
"""
info(f"Search command ran by {update.message.chat.username}")
message = update.message.text.replace("/search ", "")
chat_id = update.message.chat_id
@ -281,8 +283,8 @@ def search(update: Update, context: CallbackContext):
def intra(update: Update, context: CallbackContext):
"""returns a chart of intraday data for a symbol"""
info(f"Intra command ran by {update.message.chat.username}")
# TODO: Document usage of this command. https://iexcloud.io/docs/api/#historical-prices
message = update.message.text
chat_id = update.message.chat_id
@ -337,8 +339,8 @@ def intra(update: Update, context: CallbackContext):
def chart(update: Update, context: CallbackContext):
"""returns a chart of the past month of data for a symbol"""
info(f"Chart command ran by {update.message.chat.username}")
# TODO: Document usage of this command. https://iexcloud.io/docs/api/#historical-prices
message = update.message.text
chat_id = update.message.chat_id
@ -390,9 +392,7 @@ def chart(update: Update, context: CallbackContext):
def stat(update: Update, context: CallbackContext):
"""
https://iexcloud.io/docs/api/#key-stats
"""
"""returns key statistics on symbol"""
info(f"Stat command ran by {update.message.chat.username}")
message = update.message.text
chat_id = update.message.chat_id
@ -417,9 +417,7 @@ def stat(update: Update, context: CallbackContext):
def cap(update: Update, context: CallbackContext):
"""
Market Cap Information
"""
"""returns market cap for symbol"""
info(f"Cap command ran by {update.message.chat.username}")
message = update.message.text
chat_id = update.message.chat_id
@ -444,9 +442,7 @@ def cap(update: Update, context: CallbackContext):
def trending(update: Update, context: CallbackContext):
"""
Trending Symbols
"""
"""returns currently trending symbols and how much they've moved in the past trading day."""
info(f"Trending command ran by {update.message.chat.username}")
chat_id = update.message.chat_id
@ -462,8 +458,8 @@ def trending(update: Update, context: CallbackContext):
def inline_query(update: Update, context: CallbackContext):
"""
Handles inline query.
Does a fuzzy search on input and returns stocks that are close.
Handles inline query. Searches by looking if query is contained
in the symbol and returns matches in alphabetical order.
"""
info(f"Inline command ran by {update.message.chat.username}")
info(f"Query: {update.inline_query.query}")
@ -496,6 +492,7 @@ def inline_query(update: Update, context: CallbackContext):
def rand_pick(update: Update, context: CallbackContext):
"""For the gamblers. Returns a random symbol to buy and a sell date"""
info(
f"Someone is gambling! Random_pick command ran by {update.message.chat.username}"
)
@ -558,13 +555,17 @@ def main():
dp.add_handler(CommandHandler("cap", cap))
dp.add_handler(CommandHandler("trending", trending))
dp.add_handler(CommandHandler("search", search))
dp.add_handler(CommandHandler("intraday", intra))
dp.add_handler(CommandHandler("intra", intra, run_async=True))
dp.add_handler(CommandHandler("chart", chart, run_async=True))
dp.add_handler(CommandHandler("random", rand_pick))
dp.add_handler(CommandHandler("donate", donate))
dp.add_handler(CommandHandler("status", status))
# Charting can be slow so they run async.
dp.add_handler(CommandHandler("intra", intra, run_async=True))
dp.add_handler(CommandHandler("intraday", intra, run_async=True))
dp.add_handler(CommandHandler("day", intra, run_async=True))
dp.add_handler(CommandHandler("chart", chart, run_async=True))
dp.add_handler(CommandHandler("month", chart, run_async=True))
# on noncommand i.e message - echo the message on Telegram
dp.add_handler(MessageHandler(Filters.text, symbol_detect))

View File

@ -220,18 +220,18 @@ class cg_Crypto:
return pd.DataFrame()
def stat_reply(self, symbol: Coin) -> str:
"""Gets key statistics for each symbol in the list
"""Gathers key statistics on coin. Mostly just CoinGecko scores.
Parameters
----------
symbols : List[str]
List of coin symbols
symbol : Coin
Returns
-------
Dict[str, str]
Each symbol passed in is a key with its value being a human readable formatted string of the symbols statistics.
str
Preformatted markdown.
"""
response = r.get(
f"https://api.coingecko.com/api/v3/coins/{symbol.id}?localization=false",
timeout=5,
@ -253,17 +253,16 @@ class cg_Crypto:
return f"{symbol.symbol} returned an error."
def cap_reply(self, coin: Coin) -> str:
"""Gets market Cap for each symbol in the list
"""Gets market cap for Coin
Parameters
----------
symbols : List[str]
List of coin symbols
coin : Coin
Returns
-------
Dict[str, str]
Each symbol passed in is a key with its value being a human readable formatted string of the symbols markey cap.
str
Preformatted markdown.
"""
response = r.get(
f"https://api.coingecko.com/api/v3/simple/price?ids={coin.id}&vs_currencies={self.vs_currency}&include_market_cap=true",
@ -290,17 +289,16 @@ class cg_Crypto:
return message
def info_reply(self, symbol: Coin) -> str:
"""Gets information on stock symbols.
"""Gets coin description
Parameters
----------
symbols : List[str]
List of stock symbols.
symbol : Coin
Returns
-------
Dict[str, str]
Each symbol passed in is a key with its value being a human readable formatted string of the symbols information.
str
Preformatted markdown.
"""
response = r.get(
@ -322,7 +320,7 @@ class cg_Crypto:
Returns
-------
list[str]
list of $$ID: NAME
list of $$ID: NAME, CHANGE%
"""
coins = r.get(
@ -352,6 +350,17 @@ class cg_Crypto:
return trending
def batch_price(self, coins: list[Coin]) -> list[str]:
"""Gets price of a list of coins all in one API call
Parameters
----------
coins : list[Coin]
Returns
-------
list[str]
returns preformatted list of strings detailing price movement of each coin passed in.
"""
query = ",".join([c.id for c in coins])
prices = r.get(

Binary file not shown.

View File

@ -1,276 +0,0 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.0-final"
},
"orig_nbformat": 2,
"kernelspec": {
"name": "python3",
"display_name": "Python 3.9.0 64-bit",
"metadata": {
"interpreter": {
"hash": "36cf16204b8548560b1c020c4e8fb5b57f0e4c58016f52f2d4be01e192833930"
}
}
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"cell_type": "code",
"execution_count": 62,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Requirement already satisfied: tqdm in /home/anson/.local/lib/python3.8/site-packages (4.59.0)\n"
]
}
],
"source": [
"!pip install tqdm"
]
},
{
"cell_type": "code",
"execution_count": 64,
"metadata": {},
"outputs": [],
"source": [
"import requests as r\n",
"import pandas as pd\n",
"from fuzzywuzzy import fuzz\n",
"from functools import cache\n",
"from tqdm import tqdm"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [],
"source": [
" def stocks():\n",
"\n",
" raw_symbols = r.get(\n",
" f\"https://cloud.iexapis.com/stable/ref-data/symbols?token=WOOOPS\"\n",
" ).json()\n",
" symbols = pd.DataFrame(data=raw_symbols)\n",
"\n",
" symbols[\"description\"] = \"$\" + symbols[\"symbol\"] + \": \" + symbols[\"name\"]\n",
" symbols[\"id\"] = symbols[\"symbol\"]\n",
"\n",
" symbols = symbols[[\"id\", \"symbol\", \"name\", \"description\"]]\n",
"\n",
" return symbols\n",
"\n",
"\n",
"\n",
" def coins():\n",
"\n",
" raw_symbols = r.get(\"https://api.coingecko.com/api/v3/coins/list\").json()\n",
" symbols = pd.DataFrame(data=raw_symbols)\n",
"\n",
" symbols[\"description\"] = \"$$\" + symbols[\"symbol\"] + \": \" + symbols[\"name\"]\n",
" symbols = symbols[[\"id\", \"symbol\", \"name\", \"description\"]]\n",
"\n",
" return symbols"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
" id symbol \\\n",
"0 A A \n",
"1 AA AA \n",
"2 AAA AAA \n",
"3 AAAU AAAU \n",
"4 AAC AAC \n",
"... ... ... \n",
"6565 zyro zyro \n",
"6566 zytara-dollar zusd \n",
"6567 zyx zyx \n",
"6568 zzz-finance zzz \n",
"6569 zzz-finance-v2 zzzv2 \n",
"\n",
" name \\\n",
"0 Agilent Technologies Inc. \n",
"1 Alcoa Corp \n",
"2 Listed Funds Trust - AAF First Priority CLO Bo... \n",
"3 Goldman Sachs Physical Gold ETF Shares - Goldm... \n",
"4 Ares Acquisition Corporation - Class A \n",
"... ... \n",
"6565 Zyro \n",
"6566 Zytara Dollar \n",
"6567 ZYX \n",
"6568 zzz.finance \n",
"6569 zzz.finance v2 \n",
"\n",
" description \n",
"0 $A: Agilent Technologies Inc. \n",
"1 $AA: Alcoa Corp \n",
"2 $AAA: Listed Funds Trust - AAF First Priority ... \n",
"3 $AAAU: Goldman Sachs Physical Gold ETF Shares ... \n",
"4 $AAC: Ares Acquisition Corporation - Class A \n",
"... ... \n",
"6565 $$zyro: Zyro \n",
"6566 $$zusd: Zytara Dollar \n",
"6567 $$zyx: ZYX \n",
"6568 $$zzz: zzz.finance \n",
"6569 $$zzzv2: zzz.finance v2 \n",
"\n",
"[16946 rows x 4 columns]"
],
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>id</th>\n <th>symbol</th>\n <th>name</th>\n <th>description</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>A</td>\n <td>A</td>\n <td>Agilent Technologies Inc.</td>\n <td>$A: Agilent Technologies Inc.</td>\n </tr>\n <tr>\n <th>1</th>\n <td>AA</td>\n <td>AA</td>\n <td>Alcoa Corp</td>\n <td>$AA: Alcoa Corp</td>\n </tr>\n <tr>\n <th>2</th>\n <td>AAA</td>\n <td>AAA</td>\n <td>Listed Funds Trust - AAF First Priority CLO Bo...</td>\n <td>$AAA: Listed Funds Trust - AAF First Priority ...</td>\n </tr>\n <tr>\n <th>3</th>\n <td>AAAU</td>\n <td>AAAU</td>\n <td>Goldman Sachs Physical Gold ETF Shares - Goldm...</td>\n <td>$AAAU: Goldman Sachs Physical Gold ETF Shares ...</td>\n </tr>\n <tr>\n <th>4</th>\n <td>AAC</td>\n <td>AAC</td>\n <td>Ares Acquisition Corporation - Class A</td>\n <td>$AAC: Ares Acquisition Corporation - Class A</td>\n </tr>\n <tr>\n <th>...</th>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n </tr>\n <tr>\n <th>6565</th>\n <td>zyro</td>\n <td>zyro</td>\n <td>Zyro</td>\n <td>$$zyro: Zyro</td>\n </tr>\n <tr>\n <th>6566</th>\n <td>zytara-dollar</td>\n <td>zusd</td>\n <td>Zytara Dollar</td>\n <td>$$zusd: Zytara Dollar</td>\n </tr>\n <tr>\n <th>6567</th>\n <td>zyx</td>\n <td>zyx</td>\n <td>ZYX</td>\n <td>$$zyx: ZYX</td>\n </tr>\n <tr>\n <th>6568</th>\n <td>zzz-finance</td>\n <td>zzz</td>\n <td>zzz.finance</td>\n <td>$$zzz: zzz.finance</td>\n </tr>\n <tr>\n <th>6569</th>\n <td>zzz-finance-v2</td>\n <td>zzzv2</td>\n <td>zzz.finance v2</td>\n <td>$$zzzv2: zzz.finance v2</td>\n </tr>\n </tbody>\n</table>\n<p>16946 rows × 4 columns</p>\n</div>"
},
"metadata": {},
"execution_count": 51
}
],
"source": [
"df = pd.concat([stocks(), coins()])\n",
"df"
]
},
{
"cell_type": "code",
"execution_count": 79,
"metadata": {},
"outputs": [],
"source": [
" def search_symbols(search: str):\n",
" \"\"\"Performs a fuzzy search to find stock symbols closest to a search term.\n",
"\n",
" Parameters\n",
" ----------\n",
" search : str\n",
" String used to search, could be a company name or something close to the companies stock ticker.\n",
"\n",
" Returns\n",
" -------\n",
" List[tuple[str, str]]\n",
" A list tuples of every stock sorted in order of how well they match. Each tuple contains: (Symbol, Issue Name).\n",
" \"\"\"\n",
"\n",
" try:\n",
" if search_index[search]: return search_index[search]\n",
" except KeyError:\n",
" pass\n",
"\n",
"\n",
"\n",
" search = search.lower()\n",
"\n",
" df[\"Match\"] = df.apply(\n",
" lambda x: fuzz.ratio(search, f\"{x['symbol']}\".lower()),\n",
" axis=1,\n",
" )\n",
"\n",
" df.sort_values(by=\"Match\", ascending=False, inplace=True)\n",
" if df[\"Match\"].head().sum() < 300:\n",
" df[\"Match\"] = df.apply(\n",
" lambda x: fuzz.partial_ratio(search, x[\"name\"].lower()),\n",
" axis=1,\n",
" )\n",
"\n",
" df.sort_values(by=\"Match\", ascending=False, inplace=True)\n",
"\n",
" symbols = df.head(20)\n",
" symbol_list = list(zip(list(symbols[\"symbol\"]), list(symbols[\"description\"])))\n",
" \n",
" return symbol_list"
]
},
{
"cell_type": "code",
"execution_count": 91,
"metadata": {},
"outputs": [],
"source": [
"search_list = df['id'].to_list() + df['description'].to_list()\n",
"search_index = {}"
]
},
{
"cell_type": "code",
"execution_count": 92,
"metadata": {
"tags": []
},
"outputs": [
{
"output_type": "stream",
"name": "stderr",
"text": [
" 5%|▍ | 1545/33892 [06:51<2:23:40, 3.75it/s]\n"
]
},
{
"output_type": "error",
"ename": "KeyboardInterrupt",
"evalue": "",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-92-559f57361529>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mtqdm\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msearch_list\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0msearch_index\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msearch_symbols\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;32m<ipython-input-79-2cfb15c9428a>\u001b[0m in \u001b[0;36msearch_symbols\u001b[0;34m(search)\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0msearch\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msearch\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlower\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 23\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 24\u001b[0;31m df[\"Match\"] = df.apply(\n\u001b[0m\u001b[1;32m 25\u001b[0m \u001b[0;32mlambda\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mfuzz\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mratio\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msearch\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34mf\"{x['symbol']}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlower\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 26\u001b[0m \u001b[0maxis\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/.local/lib/python3.9/site-packages/pandas/core/frame.py\u001b[0m in \u001b[0;36mapply\u001b[0;34m(self, func, axis, raw, result_type, args, **kwds)\u001b[0m\n\u001b[1;32m 7763\u001b[0m \u001b[0mkwds\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkwds\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7764\u001b[0m )\n\u001b[0;32m-> 7765\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mop\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_result\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 7766\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7767\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mapplymap\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mna_action\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mOptional\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mstr\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m->\u001b[0m \u001b[0mDataFrame\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/.local/lib/python3.9/site-packages/pandas/core/apply.py\u001b[0m in \u001b[0;36mget_result\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 183\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mapply_raw\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 184\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 185\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mapply_standard\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 186\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 187\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mapply_empty_result\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/.local/lib/python3.9/site-packages/pandas/core/apply.py\u001b[0m in \u001b[0;36mapply_standard\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 274\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 275\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mapply_standard\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 276\u001b[0;31m \u001b[0mresults\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mres_index\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mapply_series_generator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 277\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 278\u001b[0m \u001b[0;31m# wrap results\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/.local/lib/python3.9/site-packages/pandas/core/apply.py\u001b[0m in \u001b[0;36mapply_series_generator\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 286\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 287\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0moption_context\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"mode.chained_assignment\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 288\u001b[0;31m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32min\u001b[0m \u001b[0menumerate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mseries_gen\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 289\u001b[0m \u001b[0;31m# ignore SettingWithCopy here in case the user mutates\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 290\u001b[0m \u001b[0mresults\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/.local/lib/python3.9/site-packages/pandas/core/apply.py\u001b[0m in \u001b[0;36mseries_generator\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 408\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0marr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalues\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 409\u001b[0m \u001b[0;31m# GH#35462 re-pin mgr in case setitem changed it\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 410\u001b[0;31m \u001b[0mser\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_mgr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmgr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 411\u001b[0m \u001b[0mblk\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalues\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0marr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 412\u001b[0m \u001b[0mser\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/.local/lib/python3.9/site-packages/pandas/core/generic.py\u001b[0m in \u001b[0;36m__setattr__\u001b[0;34m(self, name, value)\u001b[0m\n\u001b[1;32m 5473\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5474\u001b[0m \u001b[0mobject\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__getattribute__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 5475\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mobject\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__setattr__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5476\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mAttributeError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5477\u001b[0m \u001b[0;32mpass\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mKeyboardInterrupt\u001b[0m: "
]
}
],
"source": [
"\n",
"for i in tqdm(search_list):\n",
" search_index[i] = search_symbols(i)"
]
},
{
"cell_type": "code",
"execution_count": 89,
"metadata": {},
"outputs": [],
"source": [
"import pickle\n",
"\n",
"\n",
"\n",
"with open('search_index.pickle', 'wb') as handle:\n",
" pickle.dump(search_index, handle, protocol=pickle.HIGHEST_PROTOCOL)\n",
"\n",
"# with open('filename.pickle', 'rb') as handle:\n",
"# b = pickle.load(handle)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
]
}

View File

@ -27,7 +27,6 @@ class Router:
def find_symbols(self, text: str) -> list[Symbol]:
"""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.
Only returns each match once. Example: Whats the price of $tsla?
Parameters
----------
@ -91,7 +90,8 @@ class Router:
Returns
-------
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).
"""
df = pd.concat([self.stock.symbol_list, self.crypto.symbol_list])
@ -183,7 +183,8 @@ class Router:
Returns
-------
Dict[str, str]
Each symbol passed in is a key with its value being a human readable formatted string of the symbols div dates.
Each symbol passed in is a key with its value being a human readable
formatted string of the symbols div dates.
"""
replies = []
for symbol in symbols:
@ -207,7 +208,8 @@ class Router:
Returns
-------
Dict[str, str]
Each symbol passed in is a key with its value being a human readable markdown formatted string of the symbols news.
Each symbol passed in is a key with its value being a human
readable markdown formatted string of the symbols news.
"""
replies = []
@ -235,7 +237,8 @@ class Router:
Returns
-------
Dict[str, str]
Each symbol passed in is a key with its value being a human readable formatted string of the symbols information.
Each symbol passed in is a key with its value being a human readable formatted
string of the symbols information.
"""
replies = []
@ -260,7 +263,8 @@ class Router:
Returns
-------
pd.DataFrame
Returns a timeseries dataframe with high, low, and volume data if its available. Otherwise returns empty pd.DataFrame.
Returns a timeseries dataframe with high, low, and volume data if its available.
Otherwise returns empty pd.DataFrame.
"""
if isinstance(symbol, Stock):
@ -283,7 +287,8 @@ class Router:
Returns
-------
pd.DataFrame
Returns a timeseries dataframe with high, low, and volume data if its available. Otherwise returns empty pd.DataFrame.
Returns a timeseries dataframe with high, low, and volume data if its available.
Otherwise returns empty pd.DataFrame.
"""
if isinstance(symbol, Stock):
return self.stock.chart_reply(symbol)
@ -304,7 +309,8 @@ class Router:
Returns
-------
Dict[str, str]
Each symbol passed in is a key with its value being a human readable formatted string of the symbols statistics.
Each symbol passed in is a key with its value being a human readable
formatted string of the symbols statistics.
"""
replies = []
@ -329,7 +335,8 @@ class Router:
Returns
-------
Dict[str, str]
Each symbol passed in is a key with its value being a human readable formatted string of the symbols market cap.
Each symbol passed in is a key with its value being a human readable
formatted string of the symbols market cap.
"""
replies = []