Refactor/multi img (#1535)

* few changes

* import fix

* missed removing test config

* column order fix

* import fix

* removed df2img add new deps

* req

* update readme

* add dep for image export, fix

* get rid of yahoo-fin, add image export lib

* import issues in some machines fix

* images dir fix

* init fix

* fix?

* test

* test

* Fixed text handling

* missed a tbl

* refactor

* poetry

* update dict/ fix slack image upload

* Update config_discordbot.py

* fixes

* black

* fix

* import

* fix nan on smile

* added env settings

* add cmds_text dict, some chgs

* make own file for help_text

* better feargreed handling

* plt close

Co-authored-by: Colin Delahunty <72827203+colin99d@users.noreply.github.com>
Co-authored-by: DjangoServer <colin99delahunty@gmail.com>
Co-authored-by: Chavithra <chavithra@gmail.com>
This commit is contained in:
teh_coderer
2022-03-25 15:39:31 -05:00
committed by GitHub
parent 600590f1aa
commit 8fe51328d9
70 changed files with 731 additions and 562 deletions

View File

@@ -3,6 +3,7 @@ import disnake
from disnake.ext import commands
from bots import config_discordbot as cfg
from bots.common.help_text import cmds_text
from bots.menus.menu import Menu
@@ -15,124 +16,21 @@ class CmdsCommands(commands.Cog):
@commands.slash_command(name="cmds")
async def cmds(self, ctx: disnake.AppCmdInter):
"""Stocks Command List"""
siatext = (
"```md\n[sia metrics](ticker) <METRIC>\n"
"[sia cps]() <COUNTRY>\n"
"[sia cpic]() <INDUSTRY>\n```"
)
etftext = (
"```md\n[etfs disc-tops]() <SORT>\n"
"[etfs holdings by-etf](etf) <NUM>\n"
"[etfs holdings by-ticker](ticker) <NUM>\n```"
)
disctext = (
"```md\n[disc fidelity]()\n"
"[disc ugs]() <NUM>\n"
"[disc tops]() <SORT> <NUM>\n```"
)
misctext = (
"```md\n[futures]()\n"
"[quote](ticker)\n"
"[support]() *Mods Only\n"
"[ins-last](ticker) <NUM>\n"
"[btc]() <INTERVAL> <PAST_DAYS> <START> <END>\n"
"[eth]() <INTERVAL> <PAST_DAYS> <START> <END>\n"
"[sol]() <INTERVAL> <PAST_DAYS> <START> <END>\n"
"[candle](ticker) <INTERVAL> <PAST_DAYS> <EXTENDED_HOURS> <START> <END> <HEIKIN_CANDLES> <NEWS>\n```"
)
opttext = (
"```md\n[opt unu]()\n"
"[opt info](ticker)\n"
"[opt vsurf](ticker) <z>\n"
"[opt oi](ticker) <EXPIRATION> <MIN-SP> <MAX-SP>\n"
"[opt vol](ticker) <EXPIRATION> <MIN-SP> <MAX-SP>\n"
"[opt overview](ticker) <EXPIRATION> <MIN-SP> <MAX-SP>\n"
"[opt hist](ticker) <STRIKE> <EXPIRATION> <OPT-TYPE>\n"
"[opt grhist](ticker) <STRIKE> <EXPIRATION> <OPT-TYPE> <GREEK>\n"
"[opt chain](ticker) <EXPIRATION> <OPT-TYPE> <MIN-SP> <MAX-SP>\n```"
)
siatext = f"```md{cmds_text['sia']}```"
etftext = f"```md{cmds_text['etf']}```"
disctext = f"```md{cmds_text['disc']}```"
misctext = f"```md{cmds_text['misc']}```"
opttext = f"```md{cmds_text['opt']}```"
tatext = (
"```md\n[ta summary](ticker)\n"
"[ta view](ticker)\n"
"[ta recom](ticker)\n"
"[ta fib](ticker) <START> <END>\n```"
"```md\n[ta-vol obv](ticker) <START> <END>\n"
"[ta-vol ad](ticker) <OPEN> <START> <END>\n"
"[ta-mom cg](ticker) <LENGTH> <START> <END>\n"
"[ta-mom fisher](ticker) <LENGTH> <START> <END>\n"
"[ta-mom cci](ticker) <LENGTH> <SCALAR> <START> <END>\n"
"[ta ma](ticker) <WINDOW> <OFFSET> <START> <END>\n"
"[ta-trend aroon](ticker) <LENGTH> <SCALAR> <START> <END>\n"
"[ta-vol adosc](ticker) <OPEN> <FAST> <SLOW> <START> <END>\n"
"[ta-mom macd](ticker) <FAST> <SLOW> <SIGNAL> <START> <END>\n"
"[ta-vlt kc](ticker) <LENGTH> <SCALAR> <MA_MODE> <START> <END>\n"
"[ta-trend adx](ticker) <LENGTH> <SCALAR> <DRIFT> <START> <END>\n"
"[ta-mom rsi](ticker) <LENGTH> <SCALAR> <DRIFT> <START> <END>\n"
"[ta-mom stoch](ticker) <FAST_K> <SLOW_D> <SLOW_K> <START> <END>\n"
"[ta-vlt bbands](ticker) <LENGTH> <SCALAR> <MA_MODE> <START> <END>\n"
"[ta-vlt donchian](ticker) <LWR_LENGTH> <UPR_LENGTH> <START> <END>\n```"
"```md\n👆<INTERVAL> <PAST_DAYS> <EXTENDED_HOURS> <HEIKIN_CANDLES>👆\n```"
)
ddtext = (
"```md\n[dd est](ticker)\n"
"[dd sec](ticker)\n"
"[dd analyst](ticker)\n"
"[dd supplier](ticker)\n"
"[dd customer](ticker)\n"
"[dd arktrades](ticker)\n"
"[dd pt](ticker) <RAW> <DATE_START>\n```"
)
dpstext = (
"```md\n[dps hsi]() <NUM>\n"
"[dps shorted](NUM)\n"
"[dps psi](ticker)\n"
"[dps spos](ticker)\n"
"[dps dpotc](ticker)\n"
"[dps pos]() <SORT> <NUM> <ASCENDING>\n"
"[dps sidtc]() <SORT> <NUM>\n"
"[dps ftd](ticker) <DATE_START> <DATE_END>\n```"
)
scrtext = (
"```md\n[scr presets_default]()\n"
"[scr presets_custom]()\n"
"[scr historical](SIGNAL) <START>\n"
"[scr overview](PRESET) <SORT> <LIMIT> <ASCEND>\n"
"[scr technical](PRESET) <SORT> <LIMIT> <ASCEND>\n"
"[scr valuation](PRESET) <SORT> <LIMIT> <ASCEND>\n"
"[scr financial](PRESET) <SORT> <LIMIT> <ASCEND>\n"
"[scr ownership](PRESET) <SORT> <LIMIT> <ASCEND>\n"
"[scr performance](PRESET) <SORT> <LIMIT> <ASCEND>\n```"
)
govtext = (
"```md\n[gov histcont](ticker)\n"
"[gov lobbying](ticker) <NUM>\n"
"[gov toplobbying]() <NUM> <RAW>\n"
"[gov lastcontracts]() <DAYS> <NUM>\n"
"[gov contracts](ticker) <DAYS> <RAW>\n"
"[gov qtrcontracts]() <ANALYSIS> <NUM>\n"
"[gov lasttrades]() <GOV_TYPE> <DAYS> <REP>\n"
"[gov gtrades](ticker) <GOV_TYPE> <MONTHS> <RAW>\n"
"[gov topbuys]() <GOV_TYPE> <MONTHS> <NUM> <RAW>\n"
"[gov topsells]() <GOV_TYPE> <MONTHS> <NUM> <RAW>\n```"
"\n`<DAYS> = Past Transaction Days`\n"
"`<MONTHS> = Past Transaction Months`"
)
econtext = (
"```md\n[econ softs]()\n"
"[econ meats]()\n"
"[econ energy]()\n"
"[econ metals]()\n"
"[econ grains]()\n"
"[econ futures]()\n"
"[econ usbonds]()\n"
"[econ glbonds]()\n"
"[econ indices]()\n"
"[econ overview]()\n"
"[econ feargreed]()\n"
"[econ currencies]()\n"
"[econ valuation]() <GROUP>\n"
"[econ performance]() <GROUP>\n```"
f"```md{cmds_text['ta']}```"
f"```md{cmds_text['ta_candle']}```"
f"```md{cmds_text['ta_ext']}```"
)
ddtext = f"```md{cmds_text['dd']}```"
dpstext = f"```md{cmds_text['dps']}```"
scrtext = f"```md{cmds_text['scr']}```"
govtext = f"```md{cmds_text['gov']}```" f"{cmds_text['gov_ext']}"
econtext = f"```md{cmds_text['econ']}```"
options = [disnake.SelectOption(label="Home", value="0", emoji="🟢")]
embeds = [
disnake.Embed(

View File

@@ -137,13 +137,13 @@ class EconomyCommands(commands.Cog):
async def repo(
self,
inter: disnake.AppCmdInter,
days: int = 100,
days: int = 50,
):
"""Displays Reverse Repo [Stocksera]
Parameters
-----------
days: Number of days to display. Default: 100
days: Number of days to display. Default: 50
"""
await ShowView().discord(reverse_repo_command, inter, "econ repo", days)

View File

@@ -11,6 +11,7 @@ from bots.stocks.options.iv import iv_command
from bots.stocks.options.oi import oi_command
from bots.stocks.options.opt_chain import chain_command
from bots.stocks.options.overview import overview_command
from bots.stocks.options.smile import smile_command
from bots.stocks.options.unu import unu_command
from bots.stocks.options.vol import vol_command
from bots.stocks.options.vsurf import vsurf_command
@@ -72,6 +73,28 @@ class SlashCommands(commands.Cog):
oi_command, inter, "opt oi", ticker, expiry, min_sp, max_sp
)
@opt.sub_command(name="smile")
async def smile(
self,
inter: disnake.AppCmdInter,
ticker: str = commands.Param(autocomplete=ticker_autocomp),
expiry: str = commands.Param(autocomplete=expiry_autocomp),
min_sp: float = None,
max_sp: float = None,
):
"""Displays Options Volatility Smile [Yahoo Finance]
Parameters
----------
ticker: Stock Ticker
expiry: Expiration Date
min_sp: Minimum Strike Price
max_sp: Maximum Strike Price
"""
await ShowView().discord(
smile_command, inter, "opt smile", ticker, expiry, min_sp, max_sp
)
@opt.sub_command(name="info")
async def iv(
self,

View File

@@ -8,6 +8,7 @@ from bots.economy.currencies import currencies_command
from bots.economy.energy import energy_command
from bots.economy.feargreed import feargreed_command
from bots.economy.futures import futures_command
from bots.economy.futures_coms import futures_coms_command
from bots.economy.glbonds import glbonds_command
from bots.economy.grains import grains_command
from bots.economy.indices import indices_command
@@ -15,9 +16,13 @@ from bots.economy.meats import meats_command
from bots.economy.metals import metals_command
from bots.economy.overview import overview_command
from bots.economy.performance import performance_command
from bots.economy.reverse_repo import reverse_repo_command
from bots.economy.softs import softs_command
from bots.economy.usbonds import usbonds_command
from bots.economy.valuation import valuation_command
from bots.etf.holdings import holdings_command
from bots.etf.tops import etfs_disc_command
from bots.etf.whatetf import by_ticker_command
from bots.stocks.candle import candle_command
from bots.stocks.dark_pool_shorts.dpotc import dpotc_command
from bots.stocks.dark_pool_shorts.ftd import ftd_command
@@ -27,9 +32,14 @@ from bots.stocks.dark_pool_shorts.psi import psi_command
from bots.stocks.dark_pool_shorts.shorted import shorted_command
from bots.stocks.dark_pool_shorts.sidtc import sidtc_command
from bots.stocks.dark_pool_shorts.spos import spos_command
from bots.stocks.disc.active import active_command
from bots.stocks.disc.ford import ford_command
from bots.stocks.disc.topgainers import gainers_command
from bots.stocks.disc.toplosers import losers_command
from bots.stocks.disc.ugs import ugs_command
from bots.stocks.due_diligence.analyst import analyst_command
from bots.stocks.due_diligence.arktrades import arktrades_command
from bots.stocks.due_diligence.borrowed import borrowed_command
from bots.stocks.due_diligence.customer import customer_command
from bots.stocks.due_diligence.est import est_command
from bots.stocks.due_diligence.pt import pt_command
@@ -52,6 +62,7 @@ from bots.stocks.options.iv import iv_command
from bots.stocks.options.oi import oi_command
from bots.stocks.options.opt_chain import chain_command
from bots.stocks.options.overview import overview_command as overview_opt_command
from bots.stocks.options.smile import smile_command
from bots.stocks.options.unu import unu_command
from bots.stocks.options.vol import vol_command
from bots.stocks.options.vsurf import vsurf_command
@@ -88,11 +99,11 @@ from bots.stocks.technical_analysis.stoch import stoch_command
from bots.stocks.technical_analysis.summary import summary_command
from bots.stocks.technical_analysis.view import view_command
re_date = re.compile(r"/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/")
re_int = re.compile(r"^[1-9]\d*$")
re_float = re.compile(r"^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$")
re_name = re.compile(r"(?s).*")
re_window = re.compile(r"(?s).*")
re_date = re_name
gov_type = ["congress", "senate", "house"]
@@ -352,7 +363,7 @@ def get_tickers() -> List[str]:
return df.tolist()
tickers = get_tickers()
tickers = re_name
commands = {
"dd_analyst": {
"function": analyst_command,
@@ -369,6 +380,10 @@ commands = {
"function": supplier_command,
"required": {"ticker": tickers},
},
"dd_borrowed": {
"function": borrowed_command,
"required": {"ticker": tickers},
},
"dd_customer": {
"function": customer_command,
"required": {"ticker": tickers},
@@ -413,7 +428,7 @@ commands = {
"function": indices_command,
},
"econ_futures": {
"function": futures_command,
"function": futures_coms_command,
},
"econ_usbonds": {
"function": usbonds_command,
@@ -436,6 +451,10 @@ commands = {
"econ_softs": {
"function": softs_command,
},
"econ_repo": {
"function": reverse_repo_command,
"required": {"days": re_int},
},
"econ_currencies": {
"function": currencies_command,
},
@@ -447,6 +466,23 @@ commands = {
"function": performance_command,
"required": {"economy_group": econ_group},
},
"etf_tops": {
"function": etfs_disc_command,
"required": {"sort": ["gainers", "decliners", "active"]},
},
"etf_holdings": {
"function": holdings_command,
"required": {"etf": re_name},
"optional": {"num": re_int},
},
"etf_byticker": {
"function": by_ticker_command,
"required": {"ticker": re_name, "sort": ["fund_percent", "mkt_value"]},
"optional": {"num": re_int},
},
"futures": {
"function": futures_command,
},
"gov_lasttrades": {
"function": lasttrades_command,
"required": {"gov_type": gov_type},
@@ -527,12 +563,29 @@ commands = {
"function": iv_command,
"required": {"ticker": tickers},
},
"opt_smile": {
"function": smile_command,
"required": {"ticker": tickers, "expiry": re_date},
"optional": {"min_sp": re_float, "max_sp": re_float},
},
"opt_unu": {
"function": unu_command,
},
"q": {"function": quote_command, "required": {"ticker": tickers}},
"disc_ford": {
"function": ford_command,
},
"opt_unu": {
"function": unu_command,
"disc_active": {
"function": active_command,
},
"disc_gainers": {
"function": gainers_command,
},
"disc_losers": {
"function": losers_command,
},
"disc_ugs": {
"function": ugs_command,
},
"ins_last": {
"function": lins_command,
@@ -541,8 +594,8 @@ commands = {
},
"candle": {
"function": candle_command,
"required": {"ticker": tickers, "interval": opt_intervals},
"optional": {"past_days": re_int, "start": re_date, "end": re_date},
"required": {"ticker": tickers, "interval": opt_intervals, "past_days": re_int},
"optional": {"start": re_date, "end": re_date},
},
"opt_overview": {
"function": overview_opt_command,
@@ -560,7 +613,7 @@ commands = {
"function": vsurf_command,
"required": {"ticker": tickers, "z": options_vsurf_choices.values()},
},
"opt_hist": {
"opt_grhist": {
"function": hist_command,
"required": {
"ticker": tickers,
@@ -621,7 +674,7 @@ commands = {
"optional": {"limit": re_int, "ascend": [True, False]},
},
# TODO Add ta candle args
"ta-ma": {
"ta_ma": {
"function": ma_command,
"required": {"ticker": tickers, "interval": opt_intervals, "ma_mode": ma_mode},
"optional": {
@@ -636,12 +689,15 @@ commands = {
},
"ta_cci": {
"function": cci_command,
"required": {"ticker": tickers},
"required": {"ticker": tickers, "interval": opt_intervals},
"optional": {
"past_days": re_int,
"length": re_int,
"scalar": re_float,
"start": re_date,
"end": re_date,
"extended_hours": [True, False],
"heikin_candles": [True, False],
},
},
"ta_macd": {
@@ -674,19 +730,29 @@ commands = {
},
"ta_stoch": {
"function": stoch_command,
"required": {"ticker": tickers},
"required": {"ticker": tickers, "interval": opt_intervals},
"optional": {
"past_days": re_int,
"fast_k": re_int,
"slow_k": re_int,
"slow_d": re_int,
"start": re_date,
"end": re_date,
"extended_hours": [True, False],
"heikin_candles": [True, False],
},
},
"ta_fisher": {
"function": fisher_command,
"required": {"ticker": tickers},
"optional": {"length": re_int, "start": re_date, "end": re_date},
"required": {"ticker": tickers, "interval": opt_intervals},
"optional": {
"past_days": re_int,
"length": re_int,
"start": re_date,
"end": re_date,
"extended_hours": [True, False],
"heikin_candles": [True, False],
},
},
"ta_cg": {
"function": fisher_command,
@@ -759,8 +825,15 @@ commands = {
},
"ta_ad": {
"function": ad_command,
"required": {"ticker": tickers},
"optional": {"is_open": ["True", "False"], "start": re_date, "end": re_date},
"required": {"ticker": tickers, "interval": opt_intervals},
"optional": {
"past_days": re_int,
"is_open": [True, False],
"start": re_date,
"end": re_date,
"extended_hours": [True, False],
"heikin_candles": [True, False],
},
},
"ta_adosc": {
"function": adosc_command,
@@ -789,8 +862,14 @@ commands = {
},
"ta_fib": {
"function": fib_command,
"required": {"ticker": tickers},
"optional": {"start": re_date, "end": re_date},
"required": {"ticker": tickers, "interval": opt_intervals},
"optional": {
"past_days": re_int,
"start": re_date,
"end": re_date,
"extended_hours": [True, False],
"heikin_candles": [True, False],
},
},
"ta_view": {"function": view_command, "required": {"ticker": tickers}},
"ta_summary": {"function": summary_command, "required": {"ticker": tickers}},

124
bots/common/help_text.py Normal file
View File

@@ -0,0 +1,124 @@
cmds_text = {
"sia": (
"\n[sia metrics](ticker) <METRIC>\n"
"[sia cps]() <COUNTRY>\n"
"[sia cpic]() <INDUSTRY>\n"
),
"etf": (
"\n[etfs disc-tops]() <SORT>\n"
"[etfs holdings by-etf](etf) <NUM>\n"
"[etfs holdings by-ticker](ticker) <NUM>\n"
),
"disc": (
"\n[disc fidelity]()\n" "[disc ugs]() <NUM>\n" "[disc tops]() <SORT> <NUM>\n"
),
"misc": (
"\n[futures]()\n"
"[quote](ticker)\n"
"[support]() *Mods Only*\n"
"[ins-last](ticker) <NUM>\n"
"[btc]() <INTERVAL> <PAST_DAYS> <START> <END>\n"
"[eth]() <INTERVAL> <PAST_DAYS> <START> <END>\n"
"[sol]() <INTERVAL> <PAST_DAYS> <START> <END>\n"
"[candle](ticker) <INTERVAL> <PAST_DAYS> <EXTENDED_HOURS> <START> <END> <HEIKIN_CANDLES> <NEWS>\n"
),
"opt": (
"\n[opt unu]()\n"
"[opt info](ticker)\n"
"[opt vsurf](ticker) <z>\n"
"[opt oi](ticker) <EXPIRATION> <MIN-SP> <MAX-SP>\n"
"[opt vol](ticker) <EXPIRATION> <MIN-SP> <MAX-SP>\n"
"[opt smile](ticker) <EXPIRATION> <MIN-SP> <MAX-SP>\n"
"[opt overview](ticker) <EXPIRATION> <MIN-SP> <MAX-SP>\n"
"[opt hist](ticker) <STRIKE> <EXPIRATION> <OPT-TYPE>\n"
"[opt grhist](ticker) <STRIKE> <EXPIRATION> <OPT-TYPE> <GREEK>\n"
"[opt chain](ticker) <EXPIRATION> <OPT-TYPE> <MIN-SP> <MAX-SP>\n"
),
"ta": (
"\n[ta summary](ticker)\n"
"[ta view](ticker)\n"
"[ta recom](ticker)\n"
"[ta-mom cg](ticker) <LENGTH> <START> <END>\n"
"[ta-vlt donchian](ticker) <LWR_LENGTH> <UPR_LENGTH> <START> <END>\n"
),
"ta_candle": (
"\n[ta-vol obv](ticker) <START> <END>\n"
"[ta fib](ticker) <START> <END>\n"
"[ta-vol ad](ticker) <OPEN> <START> <END>\n"
"[ta-mom fisher](ticker) <LENGTH> <START> <END>\n"
"[ta-mom cci](ticker) <LENGTH> <SCALAR> <START> <END>\n"
"[ta ma](ticker) <WINDOW> <OFFSET> <START> <END>\n"
"[ta-trend aroon](ticker) <LENGTH> <SCALAR> <START> <END>\n"
"[ta-vol adosc](ticker) <OPEN> <FAST> <SLOW> <START> <END>\n"
"[ta-mom macd](ticker) <FAST> <SLOW> <SIGNAL> <START> <END>\n"
"[ta-vlt kc](ticker) <LENGTH> <SCALAR> <MA_MODE> <START> <END>\n"
"[ta-trend adx](ticker) <LENGTH> <SCALAR> <DRIFT> <START> <END>\n"
"[ta-mom rsi](ticker) <LENGTH> <SCALAR> <DRIFT> <START> <END>\n"
"[ta-mom stoch](ticker) <FAST_K> <SLOW_D> <SLOW_K> <START> <END>\n"
"[ta-vlt bbands](ticker) <LENGTH> <SCALAR> <MA_MODE> <START> <END>\n"
),
"ta_ext": ("\n👆<INTERVAL> <PAST_DAYS> <EXTENDED_HOURS> <HEIKIN_CANDLES>👆\n"),
"dd": (
"\n[dd est](ticker)\n"
"[dd sec](ticker)\n"
"[dd borrowed](ticker)\n"
"[dd analyst](ticker)\n"
"[dd supplier](ticker)\n"
"[dd customer](ticker)\n"
"[dd arktrades](ticker)\n"
"[dd pt](ticker) <RAW> <DATE_START>\n"
),
"dps": (
"\n[dps hsi]() <NUM>\n"
"[dps shorted](NUM)\n"
"[dps psi](ticker)\n"
"[dps spos](ticker)\n"
"[dps dpotc](ticker)\n"
"[dps pos]() <SORT> <NUM> <ASCENDING>\n"
"[dps sidtc]() <SORT> <NUM>\n"
"[dps ftd](ticker) <DATE_START> <DATE_END>\n"
),
"scr": (
"\n[scr presets_default]()\n"
"[scr presets_custom]()\n"
"[scr historical](SIGNAL) <START>\n"
"[scr overview](PRESET) <SORT> <LIMIT> <ASCEND>\n"
"[scr technical](PRESET) <SORT> <LIMIT> <ASCEND>\n"
"[scr valuation](PRESET) <SORT> <LIMIT> <ASCEND>\n"
"[scr financial](PRESET) <SORT> <LIMIT> <ASCEND>\n"
"[scr ownership](PRESET) <SORT> <LIMIT> <ASCEND>\n"
"[scr performance](PRESET) <SORT> <LIMIT> <ASCEND>\n"
),
"gov": (
"\n[gov histcont](ticker)\n"
"[gov lobbying](ticker) <NUM>\n"
"[gov toplobbying]() <NUM> <RAW>\n"
"[gov lastcontracts]() <DAYS> <NUM>\n"
"[gov contracts](ticker) <DAYS> <RAW>\n"
"[gov qtrcontracts]() <ANALYSIS> <NUM>\n"
"[gov lasttrades]() <GOV_TYPE> <DAYS> <REP>\n"
"[gov gtrades](ticker) <GOV_TYPE> <MONTHS> <RAW>\n"
"[gov topbuys]() <GOV_TYPE> <MONTHS> <NUM> <RAW>\n"
"[gov topsells]() <GOV_TYPE> <MONTHS> <NUM> <RAW>\n"
),
"gov_ext": (
"\n`<DAYS> = Past Transaction Days`\n`<MONTHS> = Past Transaction Months`\n"
),
"econ": (
"\n[econ softs]()\n"
"[econ meats]()\n"
"[econ energy]()\n"
"[econ metals]()\n"
"[econ grains]()\n"
"[econ futures]()\n"
"[econ usbonds]()\n"
"[econ glbonds]()\n"
"[econ indices]()\n"
"[econ repo](DAYS)\n"
"[econ overview]()\n"
"[econ feargreed]()\n"
"[econ currencies]()\n"
"[econ valuation]() <GROUP>\n"
"[econ performance]() <GROUP>\n"
),
}

View File

@@ -8,9 +8,9 @@ import pyimgur
from dotenv import load_dotenv
# Path to bots
bots_path = Path(__file__).parent.absolute()
bots_path = Path(__file__).parent.resolve()
env_files = [f for f in bots_path.iterdir() if f.as_posix().endswith(".env")]
env_files = [f for f in bots_path.iterdir() if f.__str__().endswith(".env")]
if env_files:
load_dotenv(env_files[0])
@@ -41,21 +41,25 @@ SLASH_TESTING_SERVERS: Optional[
COMMAND_PREFIX = "!"
DATE_FORMAT = "%Y-%m-%d"
COLOR = disnake.Color.from_rgb(255, 0, 0)
INTERACTIVE = False
INTERACTIVE_DIR = bots_path / "interactive/"
# Interactive Chart Settings
INTERACTIVE = bool(os.getenv("GT_INTERACTIVE")) or False
INTERACTIVE_DIR = bots_path.joinpath("interactive/")
INTERACTIVE_URL = ""
IMG_DIR = bots_path / "interactive/images/"
# Image Settings
IMG_HOST_ACTIVE = bool(os.getenv("GT_IMG_HOST_ACTIVE")) or True
IMG_DIR = bots_path.joinpath("interactive/images/")
IMAGES_URL = "" # Ex. "http://your-site.com/images/"
# IMG_BG = bots_path.joinpath("files/bg.png") # Light BG
IMG_BG = bots_path.joinpath("files/bg-dark.png") # Dark BG
MENU_TIMEOUT = 30
DEBUG = False
DEBUG = bool(os.getenv("GT_DEBUG")) or False
GST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
gst_imgur = pyimgur.Imgur(IMGUR_CLIENT_ID) if IMGUR_CLIENT_ID != "REPLACE_ME" else None
gst_imgur = pyimgur.Imgur(IMGUR_CLIENT_ID)
AUTHOR_NAME = "Gamestonk Terminal"
AUTHOR_URL = "https://github.com/GamestonkTerminal/GamestonkTerminal"

View File

@@ -52,7 +52,7 @@ def energy_command():
)
font_color = ["white"] * 3 + [
["#e4003a" if boolv else "#00ACFF" for boolv in df["Yld Chg"].str.contains("-")]
["#e4003a" if boolv else "#00ACFF" for boolv in df["Change"].str.contains("-")]
]
fig = imps.plot_df(

View File

@@ -1,12 +1,14 @@
import datetime
import io
import logging
import os
import matplotlib.pyplot as plt
from bots import config_discordbot as cfg
from bots.helpers import image_border
from gamestonk_terminal.config_plot import PLOT_DPI
from gamestonk_terminal.decorators import log_start_end
from gamestonk_terminal.economy import cnn_model, cnn_view
from gamestonk_terminal.economy import cnn_model
from gamestonk_terminal.helper_funcs import plot_autoscale
logger = logging.getLogger(__name__)
@@ -26,36 +28,28 @@ def feargreed_command(indicator=""):
raise Exception(
f"Select a valid indicator from {', '.join(possible_indicators)}" # nosec
)
# Output data
# Retrieve data
fig = plt.figure(figsize=[1, 1], dpi=10)
fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
report, _ = cnn_model.get_feargreed_report(indicator, fig)
cnn_view.fear_and_greed_index(indicator=indicator, export="png")
report, im = cnn_model.get_feargreed_report(indicator, fig)
ax.axes.xaxis.set_visible(False)
ax.axes.yaxis.set_visible(False)
if indicator:
ax.imshow(im)
imagefile = "feargreed.png"
dataBytesIO = io.BytesIO()
plt.savefig(dataBytesIO)
plt.close("all")
# Output data
now = datetime.datetime.now()
image_path = os.path.join(
cfg.GST_PATH,
"exports",
"economy",
f"feargreed_{now.strftime('%Y%m%d_%H%M%S')}.png",
)
i = 0
while not os.path.exists(image_path) and i < 10:
now -= datetime.timedelta(seconds=1)
image_path = os.path.join(
cfg.GST_PATH,
"exports",
"economy",
f"feargreed_{now.strftime('%Y%m%d_%H%M%S')}.png",
)
i += 1
dataBytesIO.seek(0)
imagefile = image_border(imagefile, base64=dataBytesIO)
return {
"title": "Economy: [CNN] Fear Geed Index",
"imagefile": image_path,
"imagefile": imagefile,
"description": report,
}

View File

@@ -1,5 +1,4 @@
import logging
import os
import disnake
import pandas as pd
@@ -96,16 +95,11 @@ def futures_command():
imagefile = "econ-futures.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -1,5 +1,4 @@
import logging
import os
import disnake
import pandas as pd
@@ -125,16 +124,11 @@ def performance_command(economy_group="sector"):
imagefile = "econ_performance.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -1,5 +1,4 @@
import logging
import os
import disnake
import pandas as pd
@@ -12,7 +11,7 @@ logger = logging.getLogger(__name__)
@log_start_end(log=logger)
def reverse_repo_command(days: int = 100):
def reverse_repo_command(days: int = 50):
"""Displays Reverse Repo [Stocksera.com]"""
# Debug user input
@@ -40,6 +39,9 @@ def reverse_repo_command(days: int = 100):
for col, value in formats.items():
df[col] = df[col].map(lambda x: value.format(x)) # pylint: disable=W0640
df = df.drop(columns="Moving Avg")
df = df.sort_values(by="Date", ascending=False)
font_color = ["white"] * 4 + [
[
"#e4003a" if boolv else "#00ACFF"
@@ -47,8 +49,6 @@ def reverse_repo_command(days: int = 100):
] # type: ignore
]
df = df.drop(columns="Moving Avg")
df = df.sort_values(by="Date", ascending=False)
df.set_index("Date", inplace=True)
df.columns = df.columns.str.capitalize()
@@ -88,16 +88,11 @@ def reverse_repo_command(days: int = 100):
imagefile = "dd_r_repo.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -1,5 +1,4 @@
import logging
import os
import disnake
import pandas as pd
@@ -92,16 +91,11 @@ def valuation_command(economy_group="sector"):
imagefile = "econ_valuation.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -1,5 +1,4 @@
import logging
import os
import disnake
@@ -48,16 +47,11 @@ def holdings_command(etf="", num: int = 15):
imagefile = "etf-holdings.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -1,5 +1,4 @@
import logging
import os
import disnake
import pandas as pd
@@ -12,7 +11,7 @@ logger = logging.getLogger(__name__)
@log_start_end(log=logger)
def etfs_disc_command(sort=""):
def etfs_disc_command(sort="gainers"):
"""Displays ETF's Top Gainers/Decliners, Most Active [Wall Street Journal]"""
# Debug
@@ -69,16 +68,11 @@ def etfs_disc_command(sort=""):
imagefile = "disc-etfs.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -1,5 +1,4 @@
import logging
import os
import time
import bs4
@@ -104,16 +103,11 @@ def by_ticker_command(ticker="", sort="fund_percent", num: int = 15):
imagefile = "etf-byticker.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -365,7 +365,7 @@ def inter_chart(fig: plotly.graph_objects, filename: str, **data) -> str:
"""
# Write out HTML file
with open(f"{imps.INTERACTIVE_DIR / filename}", "w") as f:
with open(f"{imps.INTERACTIVE_DIR.joinpath(filename)}", "w") as f:
f.write(html_str)
plt_link = f"[Interactive]({imps.INTERACTIVE_URL}/{filename})"
return plt_link
@@ -387,11 +387,12 @@ def save_image(filename: str, fig: plotly.graph_objects) -> str:
filename with UUID added to use for bot processing
"""
imagefile = f"{filename.replace('.png', '')}_{uuid_get()}.png"
filesave = imps.IMG_DIR / imagefile
filesave = imps.IMG_DIR.joinpath(imagefile)
fig.write_image(filesave)
image = Image.open(filesave)
image = autocrop_image(image, 0)
image.save(filesave, "PNG", quality=100)
image.close()
return imagefile
@@ -412,7 +413,7 @@ def image_border(filename: str, **kwargs) -> str:
filename with UUID added to use for bot processing
"""
imagefile = f"{filename.replace('.png', '')}_{uuid_get()}.png"
filesave = imps.IMG_DIR / imagefile
filesave = imps.IMG_DIR.joinpath(imagefile)
if "fig" in kwargs:
fig = kwargs["fig"]
fig.write_image(filesave)
@@ -434,13 +435,40 @@ def image_border(filename: str, **kwargs) -> str:
y2 = int(0.5 * im_bg.size[1]) + int(0.5 * img.size[1])
img = img.convert("RGB")
im_bg.paste(img, box=(x1 - 5, y1, x2 - 5, y2))
img.close()
im_bg.save(filesave, "PNG", quality=100)
im_bg.close()
image = Image.open(filesave)
image = autocrop_image(image, 0)
image.save(filesave, "PNG", quality=100)
image.close()
return imagefile
def multi_image(filename: str, **kwargs) -> str:
"""Uploads to an image host and returns image url.
Parameters
----------
filename : str
Image filename
Returns
-------
str
Image url
"""
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.IMAGES_URL + filename
else:
imagefile_save = imps.IMG_DIR.joinpath(filename)
uploaded_image = imps.gst_imgur.upload_image(imagefile_save, title="something")
image_link = uploaded_image.link
os.remove(imagefile_save)
return image_link
class ShowView:
async def run_discord(self, func, inter, *args, **kwargs):
data = func(*args, **kwargs)
@@ -462,11 +490,12 @@ class ShowView:
)
if "imagefile" in data:
filename = data["imagefile"]
imagefile = (imps.IMG_DIR / filename).as_posix()
imagefile = imps.IMG_DIR.joinpath(filename)
image = disnake.File(imagefile, filename=filename)
embed.set_image(url=f"attachment://{filename}")
os.remove(imagefile)
await inter.send(embed=embed, file=image)
image.close()
os.remove(imagefile)
else:
await inter.send(embed=embed)
@@ -494,12 +523,12 @@ class ShowView:
def groupme(self, func, group_id, name, *args, **kwargs):
data = func(*args, **kwargs)
if "imagefile" in data:
imagefile = (imps.IMG_DIR / data["imagefile"]).as_posix()
imagefile = imps.IMG_DIR.joinpath(data["imagefile"])
send_image(imagefile, group_id, data.get("description", ""))
elif "embeds_img" in data:
imagefiles = data["images_list"]
for img in imagefiles:
imagefile = (imps.IMG_DIR / img).as_posix()
imagefile = imps.IMG_DIR.joinpath(img)
send_image(imagefile, group_id, data.get("description", ""))
elif "description" in data:
title = data.get("title", "")
@@ -523,9 +552,10 @@ class ShowView:
.replace(".html)", ".html\n\n")
)
message = f"{title}\n{description}"
imagefile = (imps.IMG_DIR / data["imagefile"]).as_posix()
imagefile = imps.IMG_DIR.joinpath(data["imagefile"]).__str__()
client.files_upload(
file=imagefile,
filename=data["imagefile"],
initial_comment=message,
channels=channel_id,
user_id=user_id,
@@ -540,7 +570,7 @@ class ShowView:
title = data["title"] if "titles" not in data else data["titles"][0]
N = 0
for img in data["images_list"]:
imagefile = (imps.IMG_DIR / img).as_posix()
imagefile = imps.IMG_DIR.joinpath(img).__str__()
if N == 0:
message = f"{title}\n{description}"
payload = {
@@ -550,10 +580,11 @@ class ShowView:
}
client.chat_postMessage(**payload)
title = ""
if N < len(data["titles"]) and N != 0:
title = data["titles"][N]
if N < len(title) and N != 0:
title = data["titles"][N] if "titles" in data else ""
client.files_upload(
file=imagefile,
filename=img,
initial_comment=title,
channels=channel_id,
user_id=user_id,
@@ -574,7 +605,7 @@ class ShowView:
def telegram(self, func, message, bot, cmd, *args, **kwargs):
data = func(*args, **kwargs)
if "imagefile" in data:
imagefile = (imps.IMG_DIR / data["imagefile"]).as_posix()
imagefile = imps.IMG_DIR.joinpath(data["imagefile"])
title = data["title"]
description = (
data.get("description", "")
@@ -591,7 +622,7 @@ class ShowView:
res_title = data["title"] if "titles" not in data else data["titles"][0]
N = 0
for img in data["images_list"]:
imagefile = (imps.IMG_DIR / img).as_posix()
imagefile = imps.IMG_DIR.joinpath(img)
if N == 0:
description = (
data.get("description", "")
@@ -599,8 +630,8 @@ class ShowView:
.replace(".html)", ".html\n\n")
)
res_title = f"{res_title}\n{description}"
if N < len(data["titles"]) and N != 0:
res_title = data["titles"][N]
if N < len(res_title) and N != 0:
res_title = data["titles"][N] if "titles" in data else ""
with open(imagefile, "rb") as image:
bot.reply_to(message, res_title)
bot.send_photo(message.chat.id, image)

View File

@@ -224,14 +224,8 @@ def stock_data(
df_stock = df_stock.set_index(
pd.to_datetime(df_stock["date"], unit="ms", utc=True)
).drop("date", axis=1)
df_stock["date_id"] = (
df_stock.index.date - df_stock.index.date.min()
).astype("timedelta64[D]")
df_stock["date_id"] = df_stock["date_id"].dt.days + 1
df_stock["OC_High"] = df_stock[["Open", "Close"]].max(axis=1)
df_stock["OC_Low"] = df_stock[["Open", "Close"]].min(axis=1)
df_stock["Adj Close"] = df_stock["Close"].copy() # For Technical Analysis
else:
d_granularity = {
"1m": past_days,
@@ -423,7 +417,9 @@ def candle_fig(
for article in articles:
dt_at = article["publishedAt"].replace("T", " ").replace("Z", "-05:00")
df_date.append(f"{datetime.strptime(dt_at, '%Y-%m-%d %H:%M:%S%z')}")
df_date.append(
f"{datetime.strptime(dt_at, '%Y-%m-%d %H:%M:%S%z').astimezone(est_tz)}"
)
df_title.append(article["title"])
grab_price = df_stock.iloc[
df_stock.index.get_loc(dt_at, method="nearest")

View File

@@ -13,7 +13,7 @@ import disnake
from disnake.ext import commands
from fastapi import FastAPI, Request
from bots import config_discordbot as cfg
import config_discordbot as cfg
from bots.groupme.run_groupme import handle_groupme
from gamestonk_terminal.decorators import log_start_end
from gamestonk_terminal.loggers import setup_logging

View File

@@ -147,8 +147,6 @@ def dpotc_command(ticker: str = ""):
)
if imps.PLT_WATERMARK:
fig.add_layout_image(imps.PLT_WATERMARK)
fig.update_xaxes(showspikes=True, spikesnap="cursor", spikemode="across")
fig.update_yaxes(showspikes=True, spikethickness=2)
fig.update_layout(
margin=dict(l=20, r=0, t=10, b=20),
template=imps.PLT_CANDLE_STYLE_TEMPLATE,
@@ -187,8 +185,8 @@ def dpotc_command(ticker: str = ""):
bargroupgap=0,
dragmode="pan",
hovermode="x unified",
spikedistance=1000,
hoverdistance=100,
spikedistance=1,
hoverdistance=1,
)
imagefile = "dps_dpotc.png"

View File

@@ -1,10 +1,10 @@
import logging
import os
import disnake
from bots import imps
from gamestonk_terminal.decorators import log_start_end
from gamestonk_terminal.helper_funcs import lambda_long_number_format
from gamestonk_terminal.stocks.dark_pool_shorts import stockgrid_model
logger = logging.getLogger(__name__)
@@ -41,33 +41,36 @@ def pos_command(sort="dpp_dollar", ascending: bool = False, num: int = 10):
# Output data
title = "Stocks: [Stockgrid] Dark Pool Short Position"
df = df.applymap(lambda x: lambda_long_number_format(x, 2))
df = df.drop(columns=["Date"])
df["Net Short Volume $"] = df["Net Short Volume $"] / 1_000_000
df["Short Volume"] = df["Short Volume"] / 1_000_000
df["Net Short Volume"] = df["Net Short Volume"] / 1_000_000
df["Short Volume %"] = df["Short Volume %"] * 100
df["Dark Pools Position $"] = df["Dark Pools Position $"] / (1_000_000_000)
df["Dark Pools Position"] = df["Dark Pools Position"] / 1_000_000
df.columns = [
"Ticker",
"Short Vol.",
"Short Vol. %",
"Net Short Vol.",
"Net Short Vol. ($)",
"DP Position",
"DP Position ($)",
]
formats = {
"Short Vol.": "{:.2f}M",
"Short Vol. %": "{:.2f}%",
"Net Short Vol.": "{:.2f}M",
"Net Short Vol. ($)": "${:.2f}M",
"DP Position": "{:.2f}M",
"DP Position ($)": "${:.2f}B",
"Short Volume %": "{}%",
"Net Short Volume $": "${}",
"Dark Pools Position $": "${}",
}
for col, f in formats.items():
df[col] = df[col].map(lambda x: f.format(x)) # pylint: disable=W0640
df["Short Volume"] = df.apply(
lambda x: f"{x['Short Volume']} (<b>{x['Short Volume %']}</b>)", axis=1
)
df["Net Short Volume"] = df.apply(
lambda x: f"{x['Net Short Volume']:>9} (<b>{x['Net Short Volume $']:>9}</b>)",
axis=1,
)
df["Dark Pools Position"] = df.apply(
lambda x: f"{x['Dark Pools Position']:>9} (<b>{x['Dark Pools Position $']:>9}</b>)",
axis=1,
)
df = df.drop(
columns=["Short Volume %", "Net Short Volume $", "Dark Pools Position $"]
)
df.columns = [
"Ticker",
"Short Vol.",
"Net Short Vol.",
"DP Position",
]
df.set_index("Ticker", inplace=True)
dindex = len(df.index)
if dindex > 15:
@@ -80,28 +83,23 @@ def pos_command(sort="dpp_dollar", ascending: bool = False, num: int = 10):
df_pg.append(df_pg)
fig = imps.plot_df(
df_pg,
fig_size=(900, (40 * dindex)),
col_width=[2, 3, 4, 3.5, 5, 4, 5],
fig_size=(720, (40 * dindex)),
col_width=[2, 4, 4, 4],
tbl_header=imps.PLT_TBL_HEADER,
tbl_cells=imps.PLT_TBL_CELLS,
font=imps.PLT_TBL_FONT,
row_fill_color=imps.PLT_TBL_ROW_COLORS,
paper_bgcolor="rgba(0, 0, 0, 0)",
)
fig.update_traces(cells=(dict(align=["center", "left"])))
fig.update_traces(cells=(dict(align=["center", "right"])))
imagefile = "dps-pos.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",
@@ -149,15 +147,15 @@ def pos_command(sort="dpp_dollar", ascending: bool = False, num: int = 10):
else:
fig = imps.plot_df(
df,
fig_size=(900, (40 * dindex)),
col_width=[2, 3, 4, 3.5, 5, 4, 5],
fig_size=(720, (40 * dindex)),
col_width=[2, 4, 4, 4],
tbl_header=imps.PLT_TBL_HEADER,
tbl_cells=imps.PLT_TBL_CELLS,
font=imps.PLT_TBL_FONT,
row_fill_color=imps.PLT_TBL_ROW_COLORS,
paper_bgcolor="rgba(0, 0, 0, 0)",
)
fig.update_traces(cells=(dict(align=["center", "left"])))
fig.update_traces(cells=(dict(align=["center", "right"])))
imagefile = imps.save_image("dps-pos.png", fig)
output = {

View File

@@ -96,14 +96,13 @@ def psi_command(ticker: str = ""):
if imps.PLT_WATERMARK:
fig.add_layout_image(imps.PLT_WATERMARK)
fig.update_traces(hovertemplate="%{y:.2f}")
fig.update_xaxes(showspikes=True, spikesnap="cursor", spikemode="across")
fig.update_yaxes(showspikes=True, spikethickness=2)
fig.update_layout(
margin=dict(l=10, r=0, t=40, b=20),
template=imps.PLT_TA_STYLE_TEMPLATE,
colorway=imps.PLT_TA_COLORWAY,
title=f"Price vs Short Volume Interest for {ticker}",
title_x=0.45,
title=f"<b>Price vs Short Volume Interest for {ticker}</b>",
title_x=0.025,
title_font_size=14,
yaxis_title="Stock Price ($)",
yaxis2_title="FINRA Volume [M]",
yaxis3_title="Short Vol. %",
@@ -111,6 +110,7 @@ def psi_command(ticker: str = ""):
yaxis=dict(
side="right",
fixedrange=False,
showgrid=False,
titlefont=dict(color="#fdc708"),
tickfont=dict(color="#fdc708"),
nticks=20,
@@ -137,8 +137,8 @@ def psi_command(ticker: str = ""):
dragmode="pan",
legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1),
hovermode="x unified",
spikedistance=1000,
hoverdistance=100,
spikedistance=1,
hoverdistance=1,
)
imagefile = "dps_psi.png"

View File

@@ -1,10 +1,11 @@
import logging
import os
import disnake
import pandas as pd
from bots import imps
from gamestonk_terminal.decorators import log_start_end
from gamestonk_terminal.helper_funcs import lambda_long_number_format
from gamestonk_terminal.stocks.dark_pool_shorts import yahoofinance_model
logger = logging.getLogger(__name__)
@@ -26,6 +27,7 @@ def shorted_command(num: int = 10):
df = yahoofinance_model.get_most_shorted().head(num)
if df.empty:
raise Exception("No available data found")
# Debug user output
if imps.DEBUG:
logger.debug(df.to_string())
@@ -34,9 +36,37 @@ def shorted_command(num: int = 10):
title = "Stocks: [Yahoo Finance] Most Shorted"
df.dropna(how="all", axis=1, inplace=True)
df = df.replace(float("NaN"), "")
df = df.drop(columns=["PE Ratio (TTM)"])
df.set_index("Symbol", inplace=True)
# Convert and format: str into float
for col in ["Volume", "Avg Vol (3 month)"]:
df[col] = [imps.unit_finder.sub(imps.unit_replacer, x) for x in df[col]]
df[col] = pd.to_numeric(df[col].astype(float))
df[col] = df[col].map(lambda x: lambda_long_number_format(x, 2))
for col in ["Price (Intraday)", "Change"]:
df[col] = df[col].apply(lambda x: f"${x:.2f}")
# Format "%% Change" columns then combine it into "Change"
df["% Change"] = df.apply(lambda x: f"(<b>{x['% Change']}</b>)", axis=1)
df["Change"] = df.apply(lambda x: f"{x['Change']} {x['% Change']}", axis=1)
# Combine "Volume" columns
df["Volume"] = df.apply(
lambda x: f"{x['Volume']:>8} (<b>{x['Avg Vol (3 month)']:>8}</b>)",
axis=1,
)
df = df.drop(columns=["% Change", "Avg Vol (3 month)", "PE Ratio (TTM)"])
df.columns = [
"Ticker",
"Name",
"Price",
"Change",
"Volume (Avg)",
"Mkt Cap",
]
df.set_index("Ticker", inplace=True)
dindex = len(df.index)
if dindex > 15:
embeds: list = []
@@ -48,28 +78,23 @@ def shorted_command(num: int = 10):
df_pg.append(df_pg)
fig = imps.plot_df(
df_pg,
fig_size=(900, (45 * dindex)),
col_width=[2, 9, 2.5, 2.5, 2.5, 3, 3, 3],
fig_size=(950, (45 * dindex)),
col_width=[2.1, 10, 2.5, 5, 5.2, 3],
tbl_header=imps.PLT_TBL_HEADER,
tbl_cells=imps.PLT_TBL_CELLS,
font=imps.PLT_TBL_FONT,
row_fill_color=imps.PLT_TBL_ROW_COLORS,
paper_bgcolor="rgba(0, 0, 0, 0)",
)
fig.update_traces(cells=(dict(align=["center", "left"])))
fig.update_traces(cells=(dict(align=["center", "center", "right"])))
imagefile = "etf-holdings.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",
@@ -117,15 +142,15 @@ def shorted_command(num: int = 10):
else:
fig = imps.plot_df(
df,
fig_size=(900, (45 * dindex)),
col_width=[2, 9, 2.5, 2.5, 2.5, 3, 3, 3],
fig_size=(950, (45 * dindex)),
col_width=[2.1, 10, 2.5, 5, 5.2, 3],
tbl_header=imps.PLT_TBL_HEADER,
tbl_cells=imps.PLT_TBL_CELLS,
font=imps.PLT_TBL_FONT,
row_fill_color=imps.PLT_TBL_ROW_COLORS,
paper_bgcolor="rgba(0, 0, 0, 0)",
)
fig.update_traces(cells=(dict(align=["left", "center"])))
fig.update_traces(cells=(dict(align=["center", "center", "right"])))
imagefile = imps.save_image("etf-holdings.png", fig)
output = {

View File

@@ -1,5 +1,4 @@
import logging
import os
import disnake
import pandas as pd
@@ -91,16 +90,11 @@ def active_command(num: int = 10):
imagefile = "disc-active.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -1,5 +1,4 @@
import logging
import os
import disnake
@@ -69,16 +68,11 @@ def ford_command():
imagefile = "disc-ford.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -1,5 +1,4 @@
import logging
import os
import disnake
import pandas as pd
@@ -91,16 +90,11 @@ def gainers_command(num: int = 10):
imagefile = "disc-gainers.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -1,5 +1,4 @@
import logging
import os
import disnake
import pandas as pd
@@ -91,16 +90,11 @@ def losers_command(num: int = 10):
imagefile = "disc-losers.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -1,5 +1,4 @@
import logging
import os
import disnake
import pandas as pd
@@ -91,16 +90,11 @@ def ugs_command(num: int = 10):
imagefile = "disc-ugs.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -1,5 +1,4 @@
import logging
import os
import disnake
@@ -54,16 +53,11 @@ def earnings_command():
imagefile = "disc-upcoming.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -1,5 +1,4 @@
import logging
import os
import disnake
import pandas as pd
@@ -73,16 +72,11 @@ def arktrades_command(ticker: str = "", num: int = 30):
)
imagefile = imps.save_image("dd-arktrades.png", fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -1,5 +1,4 @@
import logging
import os
import disnake
import pandas as pd
@@ -34,7 +33,7 @@ def borrowed_command(ticker: str = ""):
title = f"{ticker.upper()} Shares Available to Borrow [Stocksera]"
df = df.head(1000)
df = df.head(200)
df["changed"] = df["available"].astype(int).diff()
df = df[df["changed"] != 0.0]
df = df.drop(columns="changed")
@@ -72,16 +71,11 @@ def borrowed_command(ticker: str = ""):
imagefile = "dd_borrowed.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -1,5 +1,4 @@
import logging
import os
import disnake
@@ -55,14 +54,11 @@ def est_command(ticker: str = ""):
)
imagefile = imps.save_image("estimates.png", fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
link_estimates = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
link_estimates = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(imagefile_save, title="something")
link_estimates = uploaded_image.link
os.remove(imagefile_save)
link_estimates = imps.multi_image(imagefile)
fig = imps.plot_df(
df_quarter_earnings,
@@ -76,14 +72,11 @@ def est_command(ticker: str = ""):
)
imagefile = imps.save_image("earnings.png", fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
link_earnings = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
link_earnings = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(imagefile_save, title="something")
link_earnings = uploaded_image.link
os.remove(imagefile_save)
link_earnings = imps.multi_image(imagefile)
fig = imps.plot_df(
df_quarter_revenues,
@@ -97,14 +90,11 @@ def est_command(ticker: str = ""):
)
imagefile = imps.save_image("revenues.png", fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
link_revenues = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
link_revenues = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(imagefile_save, title="something")
link_revenues = uploaded_image.link
os.remove(imagefile_save)
link_revenues = imps.multi_image(imagefile)
embeds = [
disnake.Embed(

View File

@@ -55,6 +55,7 @@ def contracts_command(
imagefile = "gov_contracts.png"
dataBytesIO = io.BytesIO()
plt.savefig(dataBytesIO)
plt.close("all")
dataBytesIO.seek(0)
imagefile = imps.image_border(imagefile, base64=dataBytesIO)

View File

@@ -113,6 +113,7 @@ def gtrades_command(
dataBytesIO = io.BytesIO()
plt.savefig(dataBytesIO)
dataBytesIO.seek(0)
plt.close("all")
imagefile = imps.image_border(imagefile, base64=dataBytesIO)

View File

@@ -59,6 +59,7 @@ def histcont_command(ticker=""):
dataBytesIO = io.BytesIO()
plt.savefig(dataBytesIO)
dataBytesIO.seek(0)
plt.close("all")
imagefile = imps.image_border(imagefile, base64=dataBytesIO)

View File

@@ -86,6 +86,7 @@ def qtrcontracts_command(num: int = 20, analysis=""):
dataBytesIO = io.BytesIO()
plt.savefig(dataBytesIO)
dataBytesIO.seek(0)
plt.close("all")
imagefile = imps.image_border(imagefile, base64=dataBytesIO)
output = {

View File

@@ -108,6 +108,7 @@ def topbuys_command(
dataBytesIO = io.BytesIO()
plt.savefig(dataBytesIO)
dataBytesIO.seek(0)
plt.close("all")
imagefile = imps.image_border(imagefile, base64=dataBytesIO)

View File

@@ -41,8 +41,8 @@ def toplobbying_command(num: int = 10, raw: bool = False):
dataBytesIO = io.BytesIO()
plt.savefig(dataBytesIO)
plt.close("all")
dataBytesIO.seek(0)
plt.close("all")
imagefile = imps.image_border(imagefile, base64=dataBytesIO)

View File

@@ -119,6 +119,7 @@ def topsells_command(
dataBytesIO = io.BytesIO()
plt.savefig(dataBytesIO)
dataBytesIO.seek(0)
plt.close("all")
imagefile = imps.image_border(imagefile, base64=dataBytesIO)

View File

@@ -1,5 +1,4 @@
import logging
import os
import disnake
import pandas as pd
@@ -84,16 +83,11 @@ def lins_command(ticker: str = "", num: int = 30):
)
imagefile = imps.save_image("disc-insider.png", fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -70,7 +70,7 @@ def oi_command(
y=df_opt["OI_call"],
name="Calls",
mode="lines+markers",
line=dict(color="green", width=3),
line=dict(color="#00ACFF", width=3),
)
)
@@ -80,7 +80,7 @@ def oi_command(
y=df_opt["OI_put"],
name="Puts",
mode="lines+markers",
line=dict(color="red", width=3),
line=dict(color="#e4003a", width=3),
)
)
fig.add_trace(

View File

@@ -1,5 +1,4 @@
import logging
import os
import disnake
import numpy as np
@@ -102,16 +101,11 @@ def chain_command(
imagefile = "opt-chain.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -65,7 +65,7 @@ def options_run(
y=df_opt["OI_call"],
name="Calls",
mode="lines+markers",
line=dict(color="green", width=3),
line=dict(color="#00ACFF", width=3),
)
)
@@ -75,7 +75,7 @@ def options_run(
y=df_opt["OI_put"],
name="Puts",
mode="lines+markers",
line=dict(color="red", width=3),
line=dict(color="#e4003a", width=3),
)
)
fig.add_trace(
@@ -132,16 +132,11 @@ def options_run(
imagefile = imps.image_border(imagefile, fig=fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link_oi = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link_oi = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image_oi = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link_oi = uploaded_image_oi.link
os.remove(imagefile_save)
image_link_oi = imps.multi_image(imagefile)
calls_df = calls[columns].rename(columns=column_map)
calls_df = calls_df[calls_df["strike"] >= min_strike2]
@@ -211,16 +206,11 @@ def options_run(
imagefile = "opt-calls.png"
imagefile = imps.save_image(imagefile, figc)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",
@@ -290,16 +280,11 @@ def options_run(
imagefile = "opt-puts.png"
imagefile = imps.save_image(imagefile, figp)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -0,0 +1,127 @@
import logging
import plotly.graph_objects as go
from bots import imps
from gamestonk_terminal.decorators import log_start_end
from gamestonk_terminal.stocks.options import yfinance_model
logger = logging.getLogger(__name__)
@log_start_end(log=logger)
def smile_command(
ticker: str = None,
expiry: str = "",
min_sp: float = None,
max_sp: float = None,
):
"""Options Smile"""
# Debug
if imps.DEBUG:
logger.debug("opt smile %s %s %s %s", ticker, expiry, min_sp, max_sp)
# Check for argument
if ticker is None:
raise Exception("Stock ticker is required")
dates = yfinance_model.option_expirations(ticker)
if not dates:
raise Exception("Stock ticker is invalid")
options = yfinance_model.get_option_chain(ticker, expiry)
calls = options.calls.fillna(0.0)
puts = options.puts.fillna(0.0)
current_price = yfinance_model.get_price(ticker)
min_strike = 0.60 * current_price
max_strike = 1.95 * current_price
if len(calls) > 40:
min_strike = 0.60 * current_price
max_strike = 1.50 * current_price
if min_sp:
min_strike = min_sp
if max_sp:
max_strike = max_sp
fig = go.Figure()
fig.add_trace(
go.Scatter(
x=calls["strike"],
y=calls["impliedVolatility"].interpolate(method="nearest"),
name="Calls",
mode="lines+markers",
marker=dict(
color="#00ACFF",
size=4.5,
),
line=dict(color="#00ACFF", width=2, dash="dash"),
)
)
fig.add_trace(
go.Scatter(
x=puts["strike"],
y=puts["impliedVolatility"].interpolate(method="nearest"),
name="Puts",
mode="lines+markers",
marker=dict(
color="#e4003a",
size=4.5,
),
line=dict(color="#e4003a", width=2, dash="dash"),
)
)
if imps.PLT_WATERMARK:
fig.add_layout_image(imps.PLT_WATERMARK)
fig.update_xaxes(
range=[min_strike, max_strike],
constrain="domain",
)
fig.update_layout(
margin=dict(l=20, r=0, t=60, b=20),
template=imps.PLT_SCAT_STYLE_TEMPLATE,
font=imps.PLT_FONT,
title=f"<b>Implied Volatility vs. Strike for {ticker.upper()} expiring {expiry}</b>",
title_x=0.5,
legend_title="",
xaxis_title="Strike",
yaxis_title="Implied Volatility",
yaxis=dict(
side="right",
fixedrange=False,
nticks=20,
),
xaxis=dict(
rangeslider=dict(visible=False),
nticks=20,
),
legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
dragmode="pan",
)
imagefile = "opt_smile.png"
# Check if interactive settings are enabled
plt_link = ""
if imps.INTERACTIVE:
plt_link = imps.inter_chart(fig, imagefile, callback=False)
fig.update_layout(
width=800,
height=500,
)
imagefile = imps.image_border(imagefile, fig=fig)
return {
"title": f"Implied Volatility vs. Stirke for {ticker.upper()} expiring {expiry}",
"description": plt_link,
"imagefile": imagefile,
}

View File

@@ -1,5 +1,4 @@
import logging
import os
import disnake
import numpy as np
@@ -102,16 +101,11 @@ def unu_command(num: int = 20):
imagefile = "opt-unu.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -62,7 +62,7 @@ def vol_command(
y=call_v.values,
name="Calls",
mode="lines+markers",
line=dict(color="green", width=3),
line=dict(color="#00ACFF", width=3),
)
)
fig.add_trace(
@@ -71,7 +71,7 @@ def vol_command(
y=put_v.values,
name="Puts",
mode="lines+markers",
line=dict(color="red", width=3),
line=dict(color="#e4003a", width=3),
)
)
fig.add_trace(

View File

@@ -1,6 +1,5 @@
import difflib
import logging
import os
import disnake
import pandas as pd
@@ -94,16 +93,11 @@ def financial_command(preset="template", sort="", limit: int = 5, ascend: bool =
imagefile = "scr_financial.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -135,6 +135,7 @@ def historical_command(signal: str = "", start=""):
dataBytesIO = io.BytesIO()
plt.savefig(dataBytesIO)
dataBytesIO.seek(0)
plt.close("all")
imagefile = imps.image_border(imagefile, base64=dataBytesIO)

View File

@@ -1,6 +1,5 @@
import difflib
import logging
import os
import disnake
import pandas as pd
@@ -100,16 +99,11 @@ def overview_command(
imagefile = "scr_overview.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -1,6 +1,5 @@
import difflib
import logging
import os
import disnake
import pandas as pd
@@ -100,16 +99,11 @@ def ownership_command(
imagefile = "scr_ownership.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -1,6 +1,5 @@
import difflib
import logging
import os
import disnake
import pandas as pd
@@ -120,16 +119,11 @@ def performance_command(
imagefile = "scr_performance.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -1,6 +1,5 @@
import difflib
import logging
import os
import disnake
import pandas as pd
@@ -99,16 +98,11 @@ def technical_command(
imagefile = "scr_technical.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -1,6 +1,5 @@
import difflib
import logging
import os
import disnake
import pandas as pd
@@ -100,16 +99,11 @@ def valuation_command(
imagefile = "scr_valuation.png"
imagefile = imps.save_image(imagefile, fig)
if imps.IMAGES_URL or imps.IMGUR_CLIENT_ID != "REPLACE_ME":
image_link = imps.IMAGES_URL + imagefile
if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
image_link = imps.multi_image(imagefile)
images_list.append(imagefile)
else:
imagefile_save = imps.IMG_DIR / imagefile
uploaded_image = imps.gst_imgur.upload_image(
imagefile_save, title="something"
)
image_link = uploaded_image.link
os.remove(imagefile_save)
image_link = imps.multi_image(imagefile)
embeds_img.append(
f"{image_link}",

View File

@@ -65,6 +65,7 @@ def ad_command(
# Output Data
if interval != 1440:
df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
df_ta = df_ta.fillna(0.0)
plot = load_candle.candle_fig(
df_ta,
@@ -91,7 +92,7 @@ def ad_command(
go.Scatter(
name="A/D",
x=df_ta.index,
y=df_ta.iloc[:, 6].values,
y=df_ta.iloc[:, 6].values if interval != 1440 else df_ta.iloc[:, 11].values,
mode="lines",
line=dict(width=2),
opacity=1,

View File

@@ -75,6 +75,7 @@ def adosc_command(
# Output Data
if interval != 1440:
df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
df_ta = df_ta.fillna(0.0)
plot = load_candle.candle_fig(
df_ta,
@@ -102,7 +103,7 @@ def adosc_command(
name="AD Osc [M]",
mode="lines",
x=df_ta.index,
y=df_ta.iloc[:, 6].values,
y=df_ta.iloc[:, 6].values if interval != 1440 else df_ta.iloc[:, 11].values,
line=dict(width=2),
opacity=1,
),

View File

@@ -90,6 +90,7 @@ def adx_command(
# Output Data
if interval != 1440:
df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
df_ta = df_ta.fillna(0.0)
plot = load_candle.candle_fig(
df_ta,
@@ -108,13 +109,14 @@ def adx_command(
)
title = f"<b>{plot['plt_title']} Average Directional Movement Index</b>"
fig = plot["fig"]
idx = 6 if interval != 1440 else 11
fig.add_trace(
go.Scatter(
name=f"ADX ({length})",
mode="lines",
x=df_ta.index,
y=df_ta.iloc[:, 6].values,
y=df_ta.iloc[:, idx].values,
opacity=1,
line=dict(width=2),
),
@@ -127,7 +129,7 @@ def adx_command(
name=f"+DI ({length})",
mode="lines",
x=df_ta.index,
y=df_ta.iloc[:, 7].values,
y=df_ta.iloc[:, (idx + 1)].values,
opacity=1,
line=dict(width=1),
),
@@ -140,7 +142,7 @@ def adx_command(
name=f"-DI ({length})",
mode="lines",
x=df_ta.index,
y=df_ta.iloc[:, 8].values,
y=df_ta.iloc[:, (idx + 2)].values,
opacity=1,
line=dict(width=1),
),

View File

@@ -75,6 +75,7 @@ def aroon_command(
# Output Data
if interval != 1440:
df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
df_ta = df_ta.fillna(0.0)
plot = load_candle.candle_fig(
df_ta,
@@ -97,12 +98,13 @@ def aroon_command(
)
title = f"<b>{plot['plt_title']} Aroon ({length})</b>"
fig = plot["fig"]
idx = 6 if interval != 1440 else 11
fig.add_trace(
go.Scatter(
name="Aroon DOWN",
x=df_ta.index,
y=df_ta.iloc[:, 6].values,
y=df_ta.iloc[:, idx].values,
opacity=1,
),
row=2,
@@ -113,7 +115,7 @@ def aroon_command(
go.Scatter(
name="Aroon UP",
x=df_ta.index,
y=df_ta.iloc[:, 7].values,
y=df_ta.iloc[:, (idx + 1)].values,
opacity=1,
),
row=2,
@@ -124,7 +126,7 @@ def aroon_command(
go.Scatter(
name="Aroon OSC",
x=df_ta.index,
y=df_ta.iloc[:, 8].values,
y=df_ta.iloc[:, (idx + 2)].values,
opacity=1,
),
row=3,

View File

@@ -97,16 +97,18 @@ def bbands_command(
# Output Data
if interval != 1440:
df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
df_ta = df_ta.fillna(0.0)
plot = load_candle.candle_fig(df_ta, ticker, interval, extended_hours, news)
title = f"<b>{plot['plt_title']} Bollinger Bands ({ma_mode.upper()})</b>"
fig = plot["fig"]
idx = 6 if interval != 1440 else 11
fig.add_trace(
go.Scatter(
name=f"BBU_{length}_{n_std}",
x=df_ta.index,
y=df_ta.iloc[:, 8].values,
y=df_ta.iloc[:, (idx + 2)].values,
opacity=1,
mode="lines",
line_color="indigo",
@@ -119,7 +121,7 @@ def bbands_command(
go.Scatter(
name=f"BBL_{length}_{n_std}",
x=df_ta.index,
y=df_ta.iloc[:, 6].values,
y=df_ta.iloc[:, idx].values,
opacity=1,
mode="lines",
line_color="indigo",
@@ -134,7 +136,7 @@ def bbands_command(
go.Scatter(
name=f"BBM_{length}_{n_std}",
x=df_ta.index,
y=df_ta.iloc[:, 7].values,
y=df_ta.iloc[:, (idx + 1)].values,
opacity=1,
line=dict(
width=1.5,

View File

@@ -82,6 +82,7 @@ def cci_command(
# Output Data
if interval != 1440:
df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
df_ta = df_ta.fillna(0.0)
plot = load_candle.candle_fig(
df_ta,
@@ -100,15 +101,19 @@ def cci_command(
)
title = f"<b>{plot['plt_title']} Commodity-Channel-Index</b>"
fig = plot["fig"]
ta_values = (
df_ta.iloc[:, 6].values if interval != 1440 else df_ta.iloc[:, 11].values
)
dmin = ta_values.min()
dmax = ta_values.max()
dmin = df_ta.iloc[:, 6].values.values.min()
dmax = df_ta.iloc[:, 6].values.values.max()
fig.add_trace(
go.Scatter(
name=f"CCI ({length}) ({scalar})",
mode="lines",
x=df_ta.index,
y=df_ta.iloc[:, 6].values,
y=ta_values,
opacity=1,
),
row=2,

View File

@@ -57,6 +57,7 @@ def cg_command(ticker="", length="14", start="", end=""):
df_close = df_stock["Adj Close"]
df_close.columns = ["values"]
df_ta = momentum_model.cg(df_close, length)
df_ta = df_ta.fillna(0.0)
# Output Data
fig, axes = plt.subplots(2, 1, figsize=plot_autoscale(), dpi=PLOT_DPI)

View File

@@ -63,6 +63,7 @@ def donchian_command(
df_ta = volatility_model.donchian(
df_stock["High"], df_stock["Low"], upper_length, lower_length
)
df_ta = df_ta.fillna(0.0)
# Output Data
fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)

View File

@@ -37,7 +37,7 @@ def fib_command(
news,
)
past_days = past_days if (interval != 1440) or (start != "") else 365
past_days = (past_days + 1) if (interval != 1440) or (start != "") else 365
# Retrieve Data
(df_stock, start, end, bar_start,) = load_candle.stock_data(

View File

@@ -71,6 +71,7 @@ def fisher_command(
# Output Data
if interval != 1440:
df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
df_ta = df_ta.fillna(0.0)
plot = load_candle.candle_fig(
df_ta,
@@ -89,15 +90,16 @@ def fisher_command(
)
title = f"<b>{plot['plt_title']} Fisher Transform</b>"
fig = plot["fig"]
idx = 6 if interval != 1440 else 11
dmin = df_ta.iloc[:, 7].values.min()
dmax = df_ta.iloc[:, 7].values.max()
dmin = df_ta.iloc[:, (idx + 1)].values.min()
dmax = df_ta.iloc[:, (idx + 1)].values.max()
fig.add_trace(
go.Scatter(
name="Fisher",
mode="lines",
x=df_ta.index,
y=df_ta.iloc[:, 6].values,
y=df_ta.iloc[:, idx].values,
opacity=1,
),
row=2,
@@ -108,7 +110,7 @@ def fisher_command(
name="Signal",
mode="lines",
x=df_ta.index,
y=df_ta.iloc[:, 7].values,
y=df_ta.iloc[:, (idx + 1)].values,
opacity=1,
),
row=2,

View File

@@ -90,6 +90,7 @@ def kc_command(
# Output Data
if interval != 1440:
df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
df_ta = df_ta.fillna(0.0)
plot = load_candle.candle_fig(
df_ta,
@@ -104,12 +105,13 @@ def kc_command(
)
title = f"<b>{plot['plt_title']} Keltner Channels ({ma_mode.upper()})</b>"
fig = plot["fig"]
idx = 6 if interval != 1440 else 11
fig.add_trace(
go.Scatter(
name="upper",
x=df_ta.index,
y=df_ta.iloc[:, 8].values,
y=df_ta.iloc[:, (idx + 2)].values,
opacity=1,
mode="lines",
line_color="indigo",
@@ -123,7 +125,7 @@ def kc_command(
go.Scatter(
name="lower",
x=df_ta.index,
y=df_ta.iloc[:, 6].values,
y=df_ta.iloc[:, idx].values,
opacity=1,
mode="lines",
line_color="indigo",
@@ -139,7 +141,7 @@ def kc_command(
go.Scatter(
name="mid",
x=df_ta.index,
y=df_ta.iloc[:, 7].values,
y=df_ta.iloc[:, (idx + 1)].values,
opacity=1,
line=dict(
width=1.5,

View File

@@ -94,6 +94,7 @@ def ma_command(
# Output Data
if interval != 1440:
df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
df_ta = df_ta.fillna(0.0)
plot = load_candle.candle_fig(
df_ta,
@@ -107,7 +108,8 @@ def ma_command(
title = f"<b>{plot['plt_title']} Moving Average ({ma_mode.upper()})</b>"
fig = plot["fig"]
for i in range(6, df_ta.shape[1]):
i2 = 6 if interval != 1440 else 11
for i in range(i2, df_ta.shape[1]):
fig.add_trace(
go.Scatter(
name=f"{df_ta.iloc[:, i].name}",

View File

@@ -83,6 +83,7 @@ def macd_command(
# Output Data
if interval != 1440:
df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
df_ta = df_ta.fillna(0.0)
plot = load_candle.candle_fig(
df_ta,
@@ -101,12 +102,13 @@ def macd_command(
)
title = f"<b>{plot['plt_title']} MACD {fast} {slow} {signal}</b>"
fig = plot["fig"]
idx = 6 if interval != 1440 else 11
fig.add_trace(
go.Bar(
name="MACD Histogram",
x=df_ta.index,
y=df_ta.iloc[:, 7].values,
y=df_ta.iloc[:, (idx + 1)].values,
opacity=(plot["bar_opacity"] + 0.3),
marker_color="#d81aea",
),
@@ -119,7 +121,7 @@ def macd_command(
name="MACD Line",
mode="lines",
x=df_ta.index,
y=df_ta.iloc[:, 6].values,
y=df_ta.iloc[:, idx].values,
opacity=0.8,
line=dict(color="#00e6c3"),
),
@@ -132,7 +134,7 @@ def macd_command(
name="Signal Line",
mode="lines",
x=df_ta.index,
y=df_ta.iloc[:, 8].values,
y=df_ta.iloc[:, (idx + 2)].values,
opacity=1,
line=dict(color="#9467bd"),
),

View File

@@ -59,6 +59,7 @@ def obv_command(
# Output Data
if interval != 1440:
df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
df_ta = df_ta.fillna(0.0)
plot = load_candle.candle_fig(
df_ta,
@@ -86,7 +87,7 @@ def obv_command(
name="OBV",
mode="lines",
x=df_ta.index,
y=df_ta.iloc[:, 6].values,
y=df_ta.iloc[:, 6].values if interval != 1440 else df_ta.iloc[:, 11].values,
line=dict(width=2),
opacity=1,
),

View File

@@ -77,6 +77,7 @@ def rsi_command(
# Output Data
if interval != 1440:
df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
df_ta = df_ta.fillna(0.0)
plot = load_candle.candle_fig(
df_ta,
@@ -104,7 +105,7 @@ def rsi_command(
name=f"RSI {length}",
mode="lines",
x=df_ta.index,
y=df_ta.iloc[:, 6].values,
y=df_ta.iloc[:, 6].values if interval != 1440 else df_ta.iloc[:, 11].values,
opacity=1,
),
row=2,

View File

@@ -87,6 +87,7 @@ def stoch_command(
# Output Data
if interval != 1440:
df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
df_ta = df_ta.fillna(0.0)
plot = load_candle.candle_fig(
df_ta,
@@ -105,12 +106,13 @@ def stoch_command(
)
title = f"<b>{plot['plt_title']} STOCH RSI</b>"
fig = plot["fig"]
idx = 6 if interval != 1440 else 11
fig.add_trace(
go.Scatter(
name=f"%K {fast_k}, {slow_d}, {slow_k}",
x=df_ta.index,
y=df_ta.iloc[:, 6].values,
y=df_ta.iloc[:, idx].values,
line=dict(width=1.8),
mode="lines",
opacity=1,
@@ -122,7 +124,7 @@ def stoch_command(
go.Scatter(
name=f"%D {fast_k}, {slow_d}, {slow_k}",
x=df_ta.index,
y=df_ta.iloc[:, 7].values,
y=df_ta.iloc[:, (idx + 1)].values,
line=dict(width=1.8, dash="dash"),
opacity=1,
),

View File

@@ -32,6 +32,7 @@ def view_command(ticker=""):
im.save(dataBytesIO, "PNG", quality=100)
dataBytesIO.seek(0)
imagefile = image_border(imagefile, base64=dataBytesIO)
im.close()
return {
"title": f"Stocks: [Finviz] Trendlines & Data {ticker.upper()}",

9
poetry.lock generated vendored
View File

@@ -1653,7 +1653,7 @@ python-versions = ">=3.6"
[[package]]
name = "kaleido"
version = "0.2.1.post1"
version = "0.2.1"
description = "Static image export for web-based visualization libraries with zero dependencies"
category = "main"
optional = true
@@ -5366,7 +5366,12 @@ jupyterlab-widgets = [
{file = "jupyterlab_widgets-1.1.0.tar.gz", hash = "sha256:d5f41bc1713795385f718d44dcba47e1e1473c6289f28a95aa6b2c0782ee372a"},
]
kaleido = [
{file = "kaleido-0.2.1.post1-py2.py3-none-manylinux2014_armv7l.whl", hash = "sha256:d313940896c24447fc12c74f60d46ea826195fc991f58569a6e73864d53e5c20"},
{file = "kaleido-0.2.1-py2.py3-none-macosx_10_11_x86_64.whl", hash = "sha256:ca6f73e7ff00aaebf2843f73f1d3bacde1930ef5041093fe76b83a15785049a7"},
{file = "kaleido-0.2.1-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:bb9a5d1f710357d5d432ee240ef6658a6d124c3e610935817b4b42da9c787c05"},
{file = "kaleido-0.2.1-py2.py3-none-manylinux1_x86_64.whl", hash = "sha256:aa21cf1bf1c78f8fa50a9f7d45e1003c387bd3d6fe0a767cfbbf344b95bdc3a8"},
{file = "kaleido-0.2.1-py2.py3-none-manylinux2014_aarch64.whl", hash = "sha256:845819844c8082c9469d9c17e42621fbf85c2b237ef8a86ec8a8527f98b6512a"},
{file = "kaleido-0.2.1-py2.py3-none-win32.whl", hash = "sha256:ecc72635860be616c6b7161807a65c0dbd9b90c6437ac96965831e2e24066552"},
{file = "kaleido-0.2.1-py2.py3-none-win_amd64.whl", hash = "sha256:4670985f28913c2d063c5734d125ecc28e40810141bdb0a46f15b76c1d45f23c"},
]
keras = [
{file = "keras-2.8.0-py2.py3-none-any.whl", hash = "sha256:744d39dc6577dcd80ff4a4d41549e92b77d6a17e0edd58a431d30656e29bc94e"},