mirror of
https://gitlab.com/simple-stock-bots/simple-stock-bot.git
synced 2025-06-16 07:16:40 +00:00
Happy with current coverage close # 46
This commit is contained in:
parent
a44008234a
commit
9b100f4926
6
bot.py
6
bot.py
@ -182,11 +182,9 @@ def dividend(update: Update, context: CallbackContext):
|
||||
|
||||
if symbols:
|
||||
context.bot.send_chat_action(chat_id=chat_id, action=telegram.ChatAction.TYPING)
|
||||
|
||||
for reply in s.dividend_reply(symbols).items():
|
||||
|
||||
for symbol in symbols:
|
||||
update.message.reply_text(
|
||||
text=reply[1], parse_mode=telegram.ParseMode.MARKDOWN
|
||||
text=s.dividend_reply(symbol), parse_mode=telegram.ParseMode.MARKDOWN
|
||||
)
|
||||
|
||||
|
||||
|
119
functions.py
119
functions.py
@ -1,6 +1,6 @@
|
||||
import re
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from typing import Optional, List, Tuple, Dict
|
||||
|
||||
import pandas as pd
|
||||
import requests as r
|
||||
@ -130,16 +130,18 @@ _Donations can only be made in a chat directly with @simplestockbot_
|
||||
usage = r.get(
|
||||
f"https://cloud.iexapis.com/stable/account/metadata?token={self.IEX_TOKEN}"
|
||||
).json()
|
||||
try:
|
||||
if (
|
||||
usage["messagesUsed"] >= usage["messageLimit"] - 10000
|
||||
and not usage["payAsYouGoEnabled"]
|
||||
):
|
||||
return "Bot may be out of IEX Credits."
|
||||
else:
|
||||
return "Bot has available IEX Credits."
|
||||
except KeyError:
|
||||
return "**IEX API could not be reached.**"
|
||||
|
||||
if (
|
||||
usage["messagesUsed"] >= usage["messageLimit"] - 10000
|
||||
and not usage["payAsYouGoEnabled"]
|
||||
):
|
||||
return "Bot may be out of IEX Credits."
|
||||
else:
|
||||
return "Bot has available IEX Credits"
|
||||
|
||||
def search_symbols(self, search: str) -> list[list[str, str]]:
|
||||
def search_symbols(self, search: str) -> List[Tuple[str, str]]:
|
||||
"""Performs a fuzzy search to find stock symbols closest to a search term.
|
||||
|
||||
Parameters
|
||||
@ -149,7 +151,7 @@ _Donations can only be made in a chat directly with @simplestockbot_
|
||||
|
||||
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).
|
||||
"""
|
||||
|
||||
@ -179,7 +181,7 @@ _Donations can only be made in a chat directly with @simplestockbot_
|
||||
self.searched_symbols[search] = symbol_list
|
||||
return symbol_list
|
||||
|
||||
def find_symbols(self, text: str) -> list[str]:
|
||||
def find_symbols(self, text: str) -> List[str]:
|
||||
"""Finds stock tickers starting with a dollar sign in a blob of text and returns them in a list.
|
||||
Only returns each match once. Example: Whats the price of $tsla?
|
||||
|
||||
@ -190,13 +192,13 @@ _Donations can only be made in a chat directly with @simplestockbot_
|
||||
|
||||
Returns
|
||||
-------
|
||||
list[str]
|
||||
List[str]
|
||||
List of stock symbols as strings without dollar sign.
|
||||
"""
|
||||
|
||||
return list(set(re.findall(self.SYMBOL_REGEX, text)))
|
||||
|
||||
def price_reply(self, symbols: list) -> dict[str, str]:
|
||||
def price_reply(self, symbols: list) -> Dict[str, str]:
|
||||
"""Returns current market price or after hours if its available for a given stock symbol.
|
||||
|
||||
Parameters
|
||||
@ -206,8 +208,9 @@ _Donations can only be made in a chat directly with @simplestockbot_
|
||||
|
||||
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.
|
||||
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.
|
||||
"""
|
||||
dataMessages = {}
|
||||
for symbol in symbols:
|
||||
@ -216,33 +219,45 @@ _Donations can only be made in a chat directly with @simplestockbot_
|
||||
response = r.get(IEXurl)
|
||||
if response.status_code == 200:
|
||||
IEXData = response.json()
|
||||
keys = (
|
||||
"isUSMarketOpen",
|
||||
"extendedChangePercent",
|
||||
"extendedPrice",
|
||||
"companyName",
|
||||
"latestPrice",
|
||||
"changePercent",
|
||||
)
|
||||
|
||||
try: # Some symbols dont return if the market is open
|
||||
IEXData["isUSMarketOpen"]
|
||||
except KeyError:
|
||||
IEXData["isUSMarketOpen"] = True
|
||||
if set(keys).issubset(IEXData):
|
||||
|
||||
if (
|
||||
IEXData["isUSMarketOpen"]
|
||||
or (IEXData["extendedChangePercent"] is None)
|
||||
or (IEXData["extendedPrice"] is None)
|
||||
): # Check if market is open.
|
||||
message = f"The current stock price of {IEXData['companyName']} is $**{IEXData['latestPrice']}**"
|
||||
change = round(IEXData["changePercent"] * 100, 2)
|
||||
try: # Some symbols dont return if the market is open
|
||||
IEXData["isUSMarketOpen"]
|
||||
except KeyError:
|
||||
IEXData["isUSMarketOpen"] = True
|
||||
|
||||
if (
|
||||
IEXData["isUSMarketOpen"]
|
||||
or (IEXData["extendedChangePercent"] is None)
|
||||
or (IEXData["extendedPrice"] is None)
|
||||
): # Check if market is open.
|
||||
message = f"The current stock price of {IEXData['companyName']} is $**{IEXData['latestPrice']}**"
|
||||
change = round(IEXData["changePercent"] * 100, 2)
|
||||
else:
|
||||
message = (
|
||||
f"{IEXData['companyName']} closed at $**{IEXData['latestPrice']}**,"
|
||||
+ f" after hours _(15 minutes delayed)_ the stock price is $**{IEXData['extendedPrice']}**"
|
||||
)
|
||||
change = round(IEXData["extendedChangePercent"] * 100, 2)
|
||||
|
||||
# Determine wording of change text
|
||||
if change > 0:
|
||||
message += f", the stock is currently **up {change}%**"
|
||||
elif change < 0:
|
||||
message += f", the stock is currently **down {change}%**"
|
||||
else:
|
||||
message += ", the stock hasn't shown any movement today."
|
||||
else:
|
||||
message = (
|
||||
f"{IEXData['companyName']} closed at $**{IEXData['latestPrice']}**,"
|
||||
+ f" after hours _(15 minutes delayed)_ the stock price is $**{IEXData['extendedPrice']}**"
|
||||
)
|
||||
change = round(IEXData["extendedChangePercent"] * 100, 2)
|
||||
|
||||
# Determine wording of change text
|
||||
if change > 0:
|
||||
message += f", the stock is currently **up {change}%**"
|
||||
elif change < 0:
|
||||
message += f", the stock is currently **down {change}%**"
|
||||
else:
|
||||
message += ", the stock hasn't shown any movement today."
|
||||
message = f"The symbol: {symbol} encountered and error. This could be due to "
|
||||
|
||||
else:
|
||||
message = f"The symbol: {symbol} was not found."
|
||||
@ -251,7 +266,7 @@ _Donations can only be made in a chat directly with @simplestockbot_
|
||||
|
||||
return dataMessages
|
||||
|
||||
def dividend_reply(self, symbols: list) -> dict[str, str]:
|
||||
def dividend_reply(self, symbol: str) -> Dict[str, str]:
|
||||
"""Returns the most recent, or next dividend date for a stock symbol.
|
||||
|
||||
Parameters
|
||||
@ -261,10 +276,9 @@ _Donations can only be made in a chat directly with @simplestockbot_
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict[str, str]
|
||||
Dict[str, str]
|
||||
Each symbol passed in is a key with its value being a human readable formatted string of the symbols div dates.
|
||||
"""
|
||||
divMessages = {}
|
||||
|
||||
IEXurl = f"https://cloud.iexapis.com/stable/stock/msft/dividends/next?token={self.IEX_TOKEN}"
|
||||
response = r.get(IEXurl)
|
||||
@ -287,11 +301,8 @@ _Donations can only be made in a chat directly with @simplestockbot_
|
||||
else:
|
||||
price = f"{IEXData['amount']} {IEXData['currency']}"
|
||||
|
||||
# extract date from json
|
||||
date = response.json()
|
||||
# Pattern IEX uses for dividend date.
|
||||
pattern = "%Y-%m-%d"
|
||||
divDate = datetime.strptime(date, pattern)
|
||||
|
||||
declared = datetime.strptime(IEXData["declaredDate"], pattern).strftime(
|
||||
"%A, %B %w"
|
||||
@ -304,7 +315,7 @@ _Donations can only be made in a chat directly with @simplestockbot_
|
||||
daysDelta = (
|
||||
datetime.strptime(IEXData["paymentDate"], pattern) - datetime.now()
|
||||
).days
|
||||
print(self.symbol_list)
|
||||
|
||||
return (
|
||||
f"The next dividend for ${self.symbol_list[self.symbol_list['symbol']==symbol.upper()]['description'].item()}"
|
||||
+ f" is on {payment} which is in {daysDelta} days."
|
||||
@ -314,7 +325,7 @@ _Donations can only be made in a chat directly with @simplestockbot_
|
||||
|
||||
return f"{symbol} either doesn't exist or pays no dividend."
|
||||
|
||||
def news_reply(self, symbols: list) -> dict[str, str]:
|
||||
def news_reply(self, symbols: list) -> Dict[str, str]:
|
||||
"""Gets recent english news on stock symbols.
|
||||
|
||||
Parameters
|
||||
@ -351,17 +362,17 @@ _Donations can only be made in a chat directly with @simplestockbot_
|
||||
|
||||
return newsMessages
|
||||
|
||||
def info_reply(self, symbols: list[str]) -> dict[str, str]:
|
||||
def info_reply(self, symbols: List[str]) -> Dict[str, str]:
|
||||
"""Gets information on stock symbols.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
symbols : list[str]
|
||||
symbols : List[str]
|
||||
List of stock symbols.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict[str, str]
|
||||
Dict[str, str]
|
||||
Each symbol passed in is a key with its value being a human readable formatted string of the symbols information.
|
||||
"""
|
||||
infoMessages = {}
|
||||
@ -449,17 +460,17 @@ _Donations can only be made in a chat directly with @simplestockbot_
|
||||
|
||||
return pd.DataFrame()
|
||||
|
||||
def stat_reply(self, symbols: list[str]) -> dict[str, str]:
|
||||
def stat_reply(self, symbols: List[str]) -> Dict[str, str]:
|
||||
"""Gets key statistics for each symbol in the list
|
||||
|
||||
Parameters
|
||||
----------
|
||||
symbols : list[str]
|
||||
symbols : List[str]
|
||||
List of stock symbols
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict[str, str]
|
||||
Dict[str, str]
|
||||
Each symbol passed in is a key with its value being a human readable formatted string of the symbols statistics.
|
||||
"""
|
||||
infoMessages = {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user