mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-11-07 18:01:10 +00:00
Discordbot screener (#1087)
* improve screener on discordbot * improve screener code of discordbot * linter * line length
This commit is contained in:
committed by
GitHub
parent
52d9c29242
commit
2d14890c41
@@ -2,18 +2,18 @@ import difflib
|
||||
import discord
|
||||
import pandas as pd
|
||||
|
||||
from gamestonk_terminal.stocks.screener.finviz_model import get_screener_data
|
||||
import discordbot.config_discordbot as cfg
|
||||
from discordbot.helpers import pagination
|
||||
|
||||
from gamestonk_terminal.stocks.screener.finviz_model import get_screener_data
|
||||
from discordbot.stocks.screener import screener_options as so
|
||||
|
||||
|
||||
async def financial_command(
|
||||
ctx, preset="template", sort="", limit="25", ascend="False"
|
||||
):
|
||||
async def financial_command(ctx, preset="template", sort="", limit="5", ascend="False"):
|
||||
"""Displays returned results from preset by financial metrics [Finviz]"""
|
||||
try:
|
||||
preset_error = False
|
||||
# Check for argument
|
||||
if preset == "template" or preset not in so.all_presets:
|
||||
raise Exception("Invalid preset selected!")
|
||||
|
||||
# Debug
|
||||
if cfg.DEBUG:
|
||||
@@ -36,39 +36,14 @@ async def financial_command(
|
||||
raise Exception("ascend argument has to be true or false")
|
||||
|
||||
# Output Data
|
||||
preset_error = True
|
||||
df_screen = get_screener_data(
|
||||
preset,
|
||||
"overview",
|
||||
"financial",
|
||||
limit,
|
||||
ascend,
|
||||
)
|
||||
preset_error = False
|
||||
|
||||
d_cols_to_sort = {
|
||||
"financial": [
|
||||
"Ticker",
|
||||
"Market Cap",
|
||||
"Dividend",
|
||||
"ROA",
|
||||
"ROE",
|
||||
"ROI",
|
||||
"Curr R",
|
||||
"Quick R",
|
||||
"LTDebt/Eq",
|
||||
"Debt/Eq",
|
||||
"Gross M",
|
||||
"Oper M",
|
||||
"Profit M",
|
||||
"Earnings",
|
||||
"Price",
|
||||
"Change",
|
||||
"Volume",
|
||||
],
|
||||
}
|
||||
|
||||
description = ""
|
||||
|
||||
if isinstance(df_screen, pd.DataFrame):
|
||||
if df_screen.empty:
|
||||
return []
|
||||
@@ -76,7 +51,7 @@ async def financial_command(
|
||||
df_screen = df_screen.dropna(axis="columns", how="all")
|
||||
|
||||
if sort:
|
||||
if " ".join(sort) in d_cols_to_sort["financial"]:
|
||||
if " ".join(sort) in so.d_cols_to_sort["financial"]:
|
||||
df_screen = df_screen.sort_values(
|
||||
by=[" ".join(sort)],
|
||||
ascending=ascend,
|
||||
@@ -85,7 +60,7 @@ async def financial_command(
|
||||
else:
|
||||
similar_cmd = difflib.get_close_matches(
|
||||
" ".join(sort),
|
||||
d_cols_to_sort["financial"],
|
||||
so.d_cols_to_sort["financial"],
|
||||
n=1,
|
||||
cutoff=0.7,
|
||||
)
|
||||
@@ -98,7 +73,7 @@ async def financial_command(
|
||||
)
|
||||
else:
|
||||
raise ValueError(
|
||||
f"Wrong sort column provided! Provide one of these: {', '.join(d_cols_to_sort['financial'])}"
|
||||
f"Wrong sort column provided! Select from: {', '.join(so.d_cols_to_sort['financial'])}"
|
||||
)
|
||||
|
||||
df_screen = df_screen.fillna("")
|
||||
@@ -140,19 +115,11 @@ async def financial_command(
|
||||
await pagination(columns, ctx)
|
||||
|
||||
except Exception as e:
|
||||
if not preset_error:
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: [Finviz] Financial Screener",
|
||||
colour=cfg.COLOR,
|
||||
description=e,
|
||||
)
|
||||
else:
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: [Finviz] Financial Screener",
|
||||
colour=cfg.COLOR,
|
||||
description=f"Wrong preset parameter entered. Use the command '{cfg.COMMAND_PREFIX}stocks.scr.presets' "
|
||||
"in order to see the available presets.",
|
||||
)
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: [Finviz] Financial Screener",
|
||||
colour=cfg.COLOR,
|
||||
description=e,
|
||||
)
|
||||
embed.set_author(
|
||||
name=cfg.AUTHOR_NAME,
|
||||
icon_url=cfg.AUTHOR_ICON_URL,
|
||||
|
||||
@@ -7,19 +7,19 @@ from matplotlib import pyplot as plt
|
||||
import yfinance as yf
|
||||
from pandas.plotting import register_matplotlib_converters
|
||||
from finvizfinance.screener import ticker
|
||||
import discordbot.config_discordbot as cfg
|
||||
|
||||
from discordbot.run_discordbot import gst_imgur
|
||||
|
||||
from gamestonk_terminal.config_plot import PLOT_DPI
|
||||
from gamestonk_terminal.stocks.screener import finviz_view
|
||||
from gamestonk_terminal.stocks.screener import finviz_model
|
||||
from gamestonk_terminal.helper_funcs import plot_autoscale
|
||||
|
||||
import discordbot.config_discordbot as cfg
|
||||
from discordbot.run_discordbot import gst_imgur
|
||||
from discordbot.stocks.screener import screener_options as so
|
||||
|
||||
# pylint:disable=no-member
|
||||
|
||||
|
||||
async def historical_command(ctx, signal="most_volatile", start=""):
|
||||
async def historical_command(ctx, signal="", start=""):
|
||||
"""Displays historical price comparison between similar companies [Yahoo Finance]"""
|
||||
try:
|
||||
|
||||
@@ -27,9 +27,11 @@ async def historical_command(ctx, signal="most_volatile", start=""):
|
||||
if cfg.DEBUG:
|
||||
print(f"!stocks.scr.historical {signal} {start}")
|
||||
|
||||
register_matplotlib_converters()
|
||||
# Check for argument
|
||||
if signal == "" or signal not in list(so.d_signals_desc.keys):
|
||||
raise Exception("Invalid preset selected!")
|
||||
|
||||
presets_path = os.path.join(cfg.GST_PATH, "stocks", "screener", "presets", "")
|
||||
register_matplotlib_converters()
|
||||
|
||||
screen = ticker.Ticker()
|
||||
|
||||
@@ -39,7 +41,7 @@ async def historical_command(ctx, signal="most_volatile", start=""):
|
||||
else:
|
||||
preset_filter = configparser.RawConfigParser()
|
||||
preset_filter.optionxform = str # type: ignore
|
||||
preset_filter.read(presets_path + signal + ".ini")
|
||||
preset_filter.read(so.presets_path + signal + ".ini")
|
||||
|
||||
d_general = preset_filter["General"]
|
||||
d_filters = {
|
||||
@@ -118,7 +120,7 @@ async def historical_command(ctx, signal="most_volatile", start=""):
|
||||
|
||||
if signal:
|
||||
plt.title(
|
||||
f"Screener Historical Price using {finviz_view.d_signals[signal]} signal"
|
||||
f"Screener Historical Price using {finviz_model.d_signals[signal]} signal"
|
||||
)
|
||||
else:
|
||||
plt.title(f"Screener Historical Price using {signal} preset")
|
||||
|
||||
@@ -2,16 +2,18 @@ import difflib
|
||||
import discord
|
||||
import pandas as pd
|
||||
|
||||
from gamestonk_terminal.stocks.screener.finviz_model import get_screener_data
|
||||
import discordbot.config_discordbot as cfg
|
||||
from discordbot.helpers import pagination
|
||||
|
||||
from gamestonk_terminal.stocks.screener.finviz_model import get_screener_data
|
||||
from discordbot.stocks.screener import screener_options as so
|
||||
|
||||
|
||||
async def overview_command(ctx, preset="template", sort="", limit="25", ascend="False"):
|
||||
async def overview_command(ctx, preset="template", sort="", limit="5", ascend="False"):
|
||||
"""Displays stocks with overview data such as Sector and Industry [Finviz]"""
|
||||
try:
|
||||
preset_error = False
|
||||
# Check for argument
|
||||
if preset == "template" or preset not in so.all_presets:
|
||||
raise Exception("Invalid preset selected!")
|
||||
|
||||
# Debug
|
||||
if cfg.DEBUG:
|
||||
@@ -34,29 +36,12 @@ async def overview_command(ctx, preset="template", sort="", limit="25", ascend="
|
||||
raise Exception("ascend argument has to be true or false")
|
||||
|
||||
# Output Data
|
||||
preset_error = True
|
||||
df_screen = get_screener_data(
|
||||
preset,
|
||||
"overview",
|
||||
limit,
|
||||
ascend,
|
||||
)
|
||||
preset_error = False
|
||||
|
||||
d_cols_to_sort = {
|
||||
"overview": [
|
||||
"Ticker",
|
||||
"Company",
|
||||
"Sector",
|
||||
"Industry",
|
||||
"Country",
|
||||
"Market Cap",
|
||||
"P/E",
|
||||
"Price",
|
||||
"Change",
|
||||
"Volume",
|
||||
],
|
||||
}
|
||||
|
||||
description = ""
|
||||
|
||||
@@ -67,7 +52,7 @@ async def overview_command(ctx, preset="template", sort="", limit="25", ascend="
|
||||
df_screen = df_screen.dropna(axis="columns", how="all")
|
||||
|
||||
if sort:
|
||||
if " ".join(sort) in d_cols_to_sort["overview"]:
|
||||
if " ".join(sort) in so.d_cols_to_sort["overview"]:
|
||||
df_screen = df_screen.sort_values(
|
||||
by=[" ".join(sort)],
|
||||
ascending=ascend,
|
||||
@@ -76,7 +61,7 @@ async def overview_command(ctx, preset="template", sort="", limit="25", ascend="
|
||||
else:
|
||||
similar_cmd = difflib.get_close_matches(
|
||||
" ".join(sort),
|
||||
d_cols_to_sort["overview"],
|
||||
so.d_cols_to_sort["overview"],
|
||||
n=1,
|
||||
cutoff=0.7,
|
||||
)
|
||||
@@ -89,7 +74,7 @@ async def overview_command(ctx, preset="template", sort="", limit="25", ascend="
|
||||
)
|
||||
else:
|
||||
raise ValueError(
|
||||
f"Wrong sort column provided! Provide one of these: {', '.join(d_cols_to_sort['overview'])}"
|
||||
f"Wrong sort column provided! Select from: {', '.join(so.d_cols_to_sort['overview'])}"
|
||||
)
|
||||
|
||||
df_screen = df_screen.fillna("")
|
||||
@@ -131,19 +116,11 @@ async def overview_command(ctx, preset="template", sort="", limit="25", ascend="
|
||||
await pagination(columns, ctx)
|
||||
|
||||
except Exception as e:
|
||||
if not preset_error:
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: [Finviz] Overview Screener",
|
||||
colour=cfg.COLOR,
|
||||
description=e,
|
||||
)
|
||||
else:
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: [Finviz] Overview Screener",
|
||||
colour=cfg.COLOR,
|
||||
description=f"Wrong preset parameter entered. Use the command '{cfg.COMMAND_PREFIX}stocks.scr.presets' "
|
||||
"in order to see the available presets.",
|
||||
)
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: [Finviz] Overview Screener",
|
||||
colour=cfg.COLOR,
|
||||
description=e,
|
||||
)
|
||||
embed.set_author(
|
||||
name=cfg.AUTHOR_NAME,
|
||||
icon_url=cfg.AUTHOR_ICON_URL,
|
||||
|
||||
@@ -2,18 +2,18 @@ import difflib
|
||||
import discord
|
||||
import pandas as pd
|
||||
|
||||
from gamestonk_terminal.stocks.screener.finviz_model import get_screener_data
|
||||
import discordbot.config_discordbot as cfg
|
||||
from discordbot.helpers import pagination
|
||||
|
||||
from gamestonk_terminal.stocks.screener.finviz_model import get_screener_data
|
||||
from discordbot.stocks.screener import screener_options as so
|
||||
|
||||
|
||||
async def ownership_command(
|
||||
ctx, preset="template", sort="", limit="25", ascend="False"
|
||||
):
|
||||
async def ownership_command(ctx, preset="template", sort="", limit="5", ascend="False"):
|
||||
"""Displays stocks based on own share float and ownership data [Finviz]"""
|
||||
try:
|
||||
preset_error = False
|
||||
# Check for argument
|
||||
if preset == "template" or preset not in so.all_presets:
|
||||
raise Exception("Invalid preset selected!")
|
||||
|
||||
# Debug
|
||||
if cfg.DEBUG:
|
||||
@@ -36,33 +36,12 @@ async def ownership_command(
|
||||
raise Exception("ascend argument has to be true or false")
|
||||
|
||||
# Output Data
|
||||
preset_error = True
|
||||
df_screen = get_screener_data(
|
||||
preset,
|
||||
"overview",
|
||||
"ownership",
|
||||
limit,
|
||||
ascend,
|
||||
)
|
||||
preset_error = False
|
||||
|
||||
d_cols_to_sort = {
|
||||
"ownership": [
|
||||
"Ticker",
|
||||
"Market Cap",
|
||||
"Outstanding",
|
||||
"Float",
|
||||
"Insider Own",
|
||||
"Insider Trans",
|
||||
"Inst Own",
|
||||
"Inst Trans",
|
||||
"Float Short",
|
||||
"Short Ratio",
|
||||
"Avg Volume",
|
||||
"Price",
|
||||
"Change",
|
||||
"Volume",
|
||||
],
|
||||
}
|
||||
|
||||
description = ""
|
||||
|
||||
@@ -73,7 +52,7 @@ async def ownership_command(
|
||||
df_screen = df_screen.dropna(axis="columns", how="all")
|
||||
|
||||
if sort:
|
||||
if " ".join(sort) in d_cols_to_sort["ownership"]:
|
||||
if " ".join(sort) in so.d_cols_to_sort["ownership"]:
|
||||
df_screen = df_screen.sort_values(
|
||||
by=[" ".join(sort)],
|
||||
ascending=ascend,
|
||||
@@ -82,7 +61,7 @@ async def ownership_command(
|
||||
else:
|
||||
similar_cmd = difflib.get_close_matches(
|
||||
" ".join(sort),
|
||||
d_cols_to_sort["ownership"],
|
||||
so.d_cols_to_sort["ownership"],
|
||||
n=1,
|
||||
cutoff=0.7,
|
||||
)
|
||||
@@ -95,7 +74,7 @@ async def ownership_command(
|
||||
)
|
||||
else:
|
||||
raise ValueError(
|
||||
f"Wrong sort column provided! Provide one of these: {', '.join(d_cols_to_sort['ownership'])}"
|
||||
f"Wrong sort column provided! Select from: {', '.join(so.d_cols_to_sort['ownership'])}"
|
||||
)
|
||||
|
||||
df_screen = df_screen.fillna("")
|
||||
@@ -137,19 +116,11 @@ async def ownership_command(
|
||||
await pagination(columns, ctx)
|
||||
|
||||
except Exception as e:
|
||||
if not preset_error:
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: [Finviz] Ownership Screener",
|
||||
colour=cfg.COLOR,
|
||||
description=e,
|
||||
)
|
||||
else:
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: [Finviz] Ownership Screener",
|
||||
colour=cfg.COLOR,
|
||||
description=f"Wrong preset parameter entered. Use the command '{cfg.COMMAND_PREFIX}stocks.scr.presets' "
|
||||
"in order to see the available presets.",
|
||||
)
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: [Finviz] Ownership Screener",
|
||||
colour=cfg.COLOR,
|
||||
description=e,
|
||||
)
|
||||
embed.set_author(
|
||||
name=cfg.AUTHOR_NAME,
|
||||
icon_url=cfg.AUTHOR_ICON_URL,
|
||||
|
||||
@@ -2,18 +2,20 @@ import difflib
|
||||
import discord
|
||||
import pandas as pd
|
||||
|
||||
from gamestonk_terminal.stocks.screener.finviz_model import get_screener_data
|
||||
import discordbot.config_discordbot as cfg
|
||||
from discordbot.helpers import pagination
|
||||
|
||||
from gamestonk_terminal.stocks.screener.finviz_model import get_screener_data
|
||||
from discordbot.stocks.screener import screener_options as so
|
||||
|
||||
|
||||
async def performance_command(
|
||||
ctx, preset="template", sort="", limit="25", ascend="False"
|
||||
ctx, preset="template", sort="", limit="5", ascend="False"
|
||||
):
|
||||
"""Displays stocks and sort by performance categories [Finviz]"""
|
||||
try:
|
||||
preset_error = False
|
||||
# Check for argument
|
||||
if preset == "template" or preset not in so.all_presets:
|
||||
raise Exception("Invalid preset selected!")
|
||||
|
||||
# Debug
|
||||
if cfg.DEBUG:
|
||||
@@ -36,14 +38,12 @@ async def performance_command(
|
||||
raise Exception("ascend argument has to be true or false")
|
||||
|
||||
# Output Data
|
||||
preset_error = True
|
||||
df_screen = get_screener_data(
|
||||
preset,
|
||||
"overview",
|
||||
"performance",
|
||||
limit,
|
||||
ascend,
|
||||
)
|
||||
preset_error = False
|
||||
|
||||
d_cols_to_sort = {
|
||||
"performance": [
|
||||
@@ -139,19 +139,11 @@ async def performance_command(
|
||||
await pagination(columns, ctx)
|
||||
|
||||
except Exception as e:
|
||||
if not preset_error:
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: [Finviz] Performance Screener",
|
||||
colour=cfg.COLOR,
|
||||
description=e,
|
||||
)
|
||||
else:
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: [Finviz] Performance Screener",
|
||||
colour=cfg.COLOR,
|
||||
description=f"Wrong preset parameter entered. Use the command '{cfg.COMMAND_PREFIX}stocks.scr.presets' "
|
||||
"in order to see the available presets.",
|
||||
)
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: [Finviz] Performance Screener",
|
||||
colour=cfg.COLOR,
|
||||
description=e,
|
||||
)
|
||||
embed.set_author(
|
||||
name=cfg.AUTHOR_NAME,
|
||||
icon_url=cfg.AUTHOR_ICON_URL,
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
import os
|
||||
import discord
|
||||
|
||||
import discordbot.config_discordbot as cfg
|
||||
from discordbot.helpers import pagination
|
||||
|
||||
|
||||
async def presets_command(ctx):
|
||||
"""Displays every preset"""
|
||||
try:
|
||||
|
||||
# Debug
|
||||
if cfg.DEBUG:
|
||||
print("!stocks.scr.presets")
|
||||
|
||||
presets_path = os.path.join(
|
||||
cfg.GST_PATH, "gamestonk_terminal", "stocks", "screener", "presets", ""
|
||||
)
|
||||
|
||||
d_signals_desc = {
|
||||
"top_gainers": "stocks with the highest %% price gain today",
|
||||
"top_losers": "stocks with the highest %% price loss today",
|
||||
"new_high": "stocks making 52-week high today",
|
||||
"new_low": "stocks making 52-week low today",
|
||||
"most_volatile": "stocks with the highest widest high/low trading range today",
|
||||
"most_active": "stocks with the highest trading volume today",
|
||||
"unusual_volume": "stocks with unusually high volume today - the highest relative volume ratio",
|
||||
"overbought": "stock is becoming overvalued and may experience a pullback.",
|
||||
"oversold": "oversold stocks may represent a buying opportunity for investors",
|
||||
"downgrades": "stocks downgraded by analysts today",
|
||||
"upgrades": "stocks upgraded by analysts today",
|
||||
"earnings_before": "companies reporting earnings today, before market open",
|
||||
"earnings_after": "companies reporting earnings today, after market close",
|
||||
"recent_insider_buying": "stocks with recent insider buying activity",
|
||||
"recent_insider_selling": "stocks with recent insider selling activity",
|
||||
"major_news": "stocks with the highest news coverage today",
|
||||
"horizontal_sr": "horizontal channel of price range between support and resistance trendlines",
|
||||
"tl_resistance": "once a rising trendline is broken",
|
||||
"tl_support": "once a falling trendline is broken",
|
||||
"wedge_up": "upward trendline support and upward trendline resistance (reversal)",
|
||||
"wedge_down": "downward trendline support and downward trendline resistance (reversal)",
|
||||
"wedge": "upward trendline support, downward trendline resistance (contiunation)",
|
||||
"triangle_ascending": "upward trendline support and horizontal trendline resistance",
|
||||
"triangle_descending": "horizontal trendline support and downward trendline resistance",
|
||||
"channel_up": "both support and resistance trendlines slope upward",
|
||||
"channel_down": "both support and resistance trendlines slope downward",
|
||||
"channel": "both support and resistance trendlines are horizontal",
|
||||
"double_top": "stock with 'M' shape that indicates a bearish reversal in trend",
|
||||
"double_bottom": "stock with 'W' shape that indicates a bullish reversal in trend",
|
||||
"multiple_top": "same as double_top hitting more highs",
|
||||
"multiple_bottom": "same as double_bottom hitting more lows",
|
||||
"head_shoulders": "chart formation that predicts a bullish-to-bearish trend reversal",
|
||||
"head_shoulders_inverse": "chart formation that predicts a bearish-to-bullish trend reversal",
|
||||
}
|
||||
|
||||
presets = [
|
||||
preset.split(".")[0]
|
||||
for preset in os.listdir(presets_path)
|
||||
if preset[-4:] == ".ini"
|
||||
]
|
||||
|
||||
description = "***Custom Presets:***\n"
|
||||
|
||||
for preset in presets:
|
||||
with open(
|
||||
presets_path + preset + ".ini",
|
||||
encoding="utf8",
|
||||
) as f:
|
||||
preset_line = ""
|
||||
for line in f:
|
||||
if line.strip() == "[General]":
|
||||
break
|
||||
preset_line += line.strip()
|
||||
description += f"**{preset}:** *{preset_line.split('Description: ')[1].replace('#', '')}*\n"
|
||||
|
||||
description += "\n\n***Default Presets:***\n"
|
||||
for signame, sigdesc in d_signals_desc.items():
|
||||
description += f"**{signame}:** *{sigdesc}*\n"
|
||||
|
||||
if len(description) <= 4000:
|
||||
embed = discord.Embed(
|
||||
title="Stocks: Screener Presets",
|
||||
description=description,
|
||||
colour=cfg.COLOR,
|
||||
)
|
||||
embed.set_author(
|
||||
name=cfg.AUTHOR_NAME,
|
||||
icon_url=cfg.AUTHOR_ICON_URL,
|
||||
)
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
else:
|
||||
i = 0
|
||||
str_start = 0
|
||||
str_end = 4000
|
||||
columns = []
|
||||
while i <= len(description) / 4000:
|
||||
columns.append(
|
||||
discord.Embed(
|
||||
title="Stocks: Screener Presets",
|
||||
description=description[str_start:str_end],
|
||||
colour=cfg.COLOR,
|
||||
).set_author(
|
||||
name=cfg.AUTHOR_NAME,
|
||||
icon_url=cfg.AUTHOR_ICON_URL,
|
||||
)
|
||||
)
|
||||
str_end = str_start
|
||||
str_start += 4000
|
||||
i += 1
|
||||
|
||||
await pagination(columns, ctx)
|
||||
|
||||
except Exception as e:
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: Screener Presets",
|
||||
colour=cfg.COLOR,
|
||||
description=e,
|
||||
)
|
||||
embed.set_author(
|
||||
name=cfg.AUTHOR_NAME,
|
||||
icon_url=cfg.AUTHOR_ICON_URL,
|
||||
)
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
52
discordbot/stocks/screener/presets_custom.py
Normal file
52
discordbot/stocks/screener/presets_custom.py
Normal file
@@ -0,0 +1,52 @@
|
||||
import discord
|
||||
|
||||
import discordbot.config_discordbot as cfg
|
||||
|
||||
from discordbot.stocks.screener import screener_options as so
|
||||
|
||||
|
||||
async def presets_custom_command(ctx):
|
||||
"""Displays every custom preset"""
|
||||
try:
|
||||
|
||||
# Debug
|
||||
if cfg.DEBUG:
|
||||
print("!stocks.scr.presets")
|
||||
|
||||
description = ""
|
||||
for preset in so.presets:
|
||||
with open(
|
||||
so.presets_path + preset + ".ini",
|
||||
encoding="utf8",
|
||||
) as f:
|
||||
preset_line = ""
|
||||
for line in f:
|
||||
if line.strip() == "[General]":
|
||||
break
|
||||
preset_line += line.strip()
|
||||
description += f"**{preset}:** *{preset_line.split('Description: ')[1].replace('#', '')}*\n"
|
||||
|
||||
embed = discord.Embed(
|
||||
title="Stocks: Screener Custom Presets",
|
||||
description=description,
|
||||
colour=cfg.COLOR,
|
||||
)
|
||||
embed.set_author(
|
||||
name=cfg.AUTHOR_NAME,
|
||||
icon_url=cfg.AUTHOR_ICON_URL,
|
||||
)
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
except Exception as e:
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: Screener Presets",
|
||||
colour=cfg.COLOR,
|
||||
description=e,
|
||||
)
|
||||
embed.set_author(
|
||||
name=cfg.AUTHOR_NAME,
|
||||
icon_url=cfg.AUTHOR_ICON_URL,
|
||||
)
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
42
discordbot/stocks/screener/presets_default.py
Normal file
42
discordbot/stocks/screener/presets_default.py
Normal file
@@ -0,0 +1,42 @@
|
||||
import discord
|
||||
|
||||
import discordbot.config_discordbot as cfg
|
||||
|
||||
from discordbot.stocks.screener import screener_options as so
|
||||
|
||||
|
||||
async def presets_default_command(ctx):
|
||||
"""Displays default presets"""
|
||||
try:
|
||||
|
||||
# Debug
|
||||
if cfg.DEBUG:
|
||||
print("!stocks.scr.presets")
|
||||
|
||||
description = ""
|
||||
for signame, sigdesc in so.d_signals_desc.items():
|
||||
description += f"**{signame}:** *{sigdesc}*\n"
|
||||
embed = discord.Embed(
|
||||
title="Stocks: Screener Default Presets",
|
||||
description=description,
|
||||
colour=cfg.COLOR,
|
||||
)
|
||||
embed.set_author(
|
||||
name=cfg.AUTHOR_NAME,
|
||||
icon_url=cfg.AUTHOR_ICON_URL,
|
||||
)
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
except Exception as e:
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: Screener Presets",
|
||||
colour=cfg.COLOR,
|
||||
description=e,
|
||||
)
|
||||
embed.set_author(
|
||||
name=cfg.AUTHOR_NAME,
|
||||
icon_url=cfg.AUTHOR_ICON_URL,
|
||||
)
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
@@ -5,14 +5,19 @@ import discordbot.config_discordbot as cfg
|
||||
|
||||
from discordbot.run_discordbot import gst_bot
|
||||
|
||||
from discordbot.stocks.screener.presets import presets_command
|
||||
from discordbot.stocks.screener.historical import historical_command
|
||||
from discordbot.stocks.screener.overview import overview_command
|
||||
from discordbot.stocks.screener.presets_custom import presets_custom_command
|
||||
from discordbot.stocks.screener.presets_default import presets_default_command
|
||||
from discordbot.stocks.screener.valuation import valuation_command
|
||||
from discordbot.stocks.screener.financial import financial_command
|
||||
from discordbot.stocks.screener.ownership import ownership_command
|
||||
from discordbot.stocks.screener.performance import performance_command
|
||||
from discordbot.stocks.screener.technical import technical_command
|
||||
from discordbot.stocks.screener import screener_options as so
|
||||
|
||||
|
||||
# pylint: disable=R0912
|
||||
|
||||
|
||||
class ScreenerCommands(discord.ext.commands.Cog):
|
||||
@@ -21,10 +26,15 @@ class ScreenerCommands(discord.ext.commands.Cog):
|
||||
def __init__(self, bot: discord.ext.commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
@discord.ext.commands.command(name="stocks.scr.presets")
|
||||
async def presets(self, ctx: discord.ext.commands.Context):
|
||||
@discord.ext.commands.command(name="stocks.scr.presets_default")
|
||||
async def presets_default(self, ctx: discord.ext.commands.Context):
|
||||
"""Displays every available preset"""
|
||||
await presets_command(ctx)
|
||||
await presets_default_command(ctx)
|
||||
|
||||
@discord.ext.commands.command(name="stocks.scr.presets_custom")
|
||||
async def presets_custom(self, ctx: discord.ext.commands.Context):
|
||||
"""Displays every available preset"""
|
||||
await presets_custom_command(ctx)
|
||||
|
||||
@discord.ext.commands.command(name="stocks.scr.historical")
|
||||
async def historical(
|
||||
@@ -50,7 +60,7 @@ class ScreenerCommands(discord.ext.commands.Cog):
|
||||
ctx: discord.ext.commands.Context,
|
||||
preset="template",
|
||||
sort="",
|
||||
limit="25",
|
||||
limit="5",
|
||||
ascend="False",
|
||||
):
|
||||
"""Displays stocks with overview data such as Sector and Industry [Finviz]
|
||||
@@ -74,7 +84,7 @@ class ScreenerCommands(discord.ext.commands.Cog):
|
||||
ctx: discord.ext.commands.Context,
|
||||
preset="template",
|
||||
sort="",
|
||||
limit="25",
|
||||
limit="5",
|
||||
ascend="False",
|
||||
):
|
||||
"""Displays results from chosen preset focusing on valuation metrics [Finviz]
|
||||
@@ -98,7 +108,7 @@ class ScreenerCommands(discord.ext.commands.Cog):
|
||||
ctx: discord.ext.commands.Context,
|
||||
preset="template",
|
||||
sort="",
|
||||
limit="25",
|
||||
limit="5",
|
||||
ascend="False",
|
||||
):
|
||||
"""Displays returned results from preset by financial metrics [Finviz]
|
||||
@@ -122,7 +132,7 @@ class ScreenerCommands(discord.ext.commands.Cog):
|
||||
ctx: discord.ext.commands.Context,
|
||||
preset="template",
|
||||
sort="",
|
||||
limit="25",
|
||||
limit="5",
|
||||
ascend="False",
|
||||
):
|
||||
"""Displays stocks based on own share float and ownership data [Finviz]
|
||||
@@ -146,7 +156,7 @@ class ScreenerCommands(discord.ext.commands.Cog):
|
||||
ctx: discord.ext.commands.Context,
|
||||
preset="template",
|
||||
sort="",
|
||||
limit="25",
|
||||
limit="5",
|
||||
ascend="False",
|
||||
):
|
||||
"""Displays stocks and sort by performance categories [Finviz]
|
||||
@@ -170,7 +180,7 @@ class ScreenerCommands(discord.ext.commands.Cog):
|
||||
ctx: discord.ext.commands.Context,
|
||||
preset="template",
|
||||
sort="",
|
||||
limit="25",
|
||||
limit="5",
|
||||
ascend="False",
|
||||
):
|
||||
"""Displays stocks according to chosen preset, sorting by technical factors [Finviz]
|
||||
@@ -189,7 +199,7 @@ class ScreenerCommands(discord.ext.commands.Cog):
|
||||
await technical_command(ctx, preset, sort, limit, ascend)
|
||||
|
||||
@discord.ext.commands.command(name="stocks.scr")
|
||||
async def scr(self, ctx: discord.ext.commands.Context):
|
||||
async def scr(self, ctx: discord.ext.commands.Context, preset=""):
|
||||
"""Screener Context Menu
|
||||
|
||||
Returns
|
||||
@@ -198,19 +208,36 @@ class ScreenerCommands(discord.ext.commands.Cog):
|
||||
The user can then select a reaction to trigger a command.
|
||||
"""
|
||||
|
||||
if preset != "" and preset not in so.all_presets:
|
||||
raise Exception("Invalid preset selected!")
|
||||
|
||||
if cfg.DEBUG:
|
||||
print("!stocks.scr")
|
||||
|
||||
text = (
|
||||
"0️⃣ !stocks.scr.presets\n"
|
||||
"1️⃣ !stocks.scr.historical <SIGNAL> <START>\n"
|
||||
"2️⃣ !stocks.scr.overview <PRESET> <SORT> <LIMIT> <ASCEND>\n"
|
||||
"3️⃣ !stocks.scr.valuation <PRESET> <SORT> <LIMIT> <ASCEND>\n"
|
||||
"4️⃣ !stocks.scr.financial <PRESET> <SORT> <LIMIT> <ASCEND>\n"
|
||||
"5️⃣ !stocks.scr.ownership <PRESET> <SORT> <LIMIT> <ASCEND>\n"
|
||||
"6️⃣ !stocks.scr.performance <PRESET> <SORT> <LIMIT> <ASCEND>\n"
|
||||
"7️⃣ !stocks.scr.technical <PRESET> <SORT> <LIMIT> <ASCEND>"
|
||||
)
|
||||
if preset:
|
||||
text = (
|
||||
"0️⃣ !stocks.scr.presets_default\n"
|
||||
"1️⃣ !stocks.scr.presets_custom\n"
|
||||
"2️⃣ !stocks.scr.historical <SIGNAL> <START>\n"
|
||||
f"3️⃣ !stocks.scr.overview {preset} <SORT> <LIMIT> <ASCEND>\n"
|
||||
f"4️⃣ !stocks.scr.valuation {preset} <SORT> <LIMIT> <ASCEND>\n"
|
||||
f"5️⃣ !stocks.scr.financial {preset} <SORT> <LIMIT> <ASCEND>\n"
|
||||
f"6️⃣ !stocks.scr.ownership {preset} <SORT> <LIMIT> <ASCEND>\n"
|
||||
f"7️⃣ !stocks.scr.performance {preset} <SORT> <LIMIT> <ASCEND>\n"
|
||||
f"8️⃣ !stocks.scr.technical {preset} <SORT> <LIMIT> <ASCEND>"
|
||||
)
|
||||
else:
|
||||
text = (
|
||||
"0️⃣ !stocks.scr.presets_default\n"
|
||||
"1️⃣ !stocks.scr.presets_custom\n"
|
||||
"2️⃣ !stocks.scr.historical <SIGNAL> <START>\n"
|
||||
"3️⃣ !stocks.scr.overview <PRESET> <SORT> <LIMIT> <ASCEND>\n"
|
||||
"4️⃣ !stocks.scr.valuation <PRESET> <SORT> <LIMIT> <ASCEND>\n"
|
||||
"5️⃣ !stocks.scr.financial <PRESET> <SORT> <LIMIT> <ASCEND>\n"
|
||||
"6️⃣ !stocks.scr.ownership <PRESET> <SORT> <LIMIT> <ASCEND>\n"
|
||||
"7️⃣ !stocks.scr.performance <PRESET> <SORT> <LIMIT> <ASCEND>\n"
|
||||
"8️⃣ !stocks.scr.technical <PRESET> <SORT> <LIMIT> <ASCEND>"
|
||||
)
|
||||
|
||||
title = "Screener Menu"
|
||||
embed = discord.Embed(title=title, description=text, colour=cfg.COLOR)
|
||||
@@ -220,7 +247,7 @@ class ScreenerCommands(discord.ext.commands.Cog):
|
||||
)
|
||||
msg = await ctx.send(embed=embed)
|
||||
|
||||
emoji_list = ["0️⃣", "1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣"]
|
||||
emoji_list = ["0️⃣", "1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣"]
|
||||
|
||||
for emoji in emoji_list:
|
||||
await msg.add_reaction(emoji)
|
||||
@@ -235,35 +262,39 @@ class ScreenerCommands(discord.ext.commands.Cog):
|
||||
if reaction.emoji == "0️⃣":
|
||||
if cfg.DEBUG:
|
||||
print("Reaction selected: 0")
|
||||
await presets_command(ctx)
|
||||
await presets_default_command(ctx)
|
||||
elif reaction.emoji == "1️⃣":
|
||||
if cfg.DEBUG:
|
||||
print("Reaction selected: 1")
|
||||
await historical_command(ctx)
|
||||
await presets_custom_command(ctx)
|
||||
elif reaction.emoji == "2️⃣":
|
||||
if cfg.DEBUG:
|
||||
print("Reaction selected: 2")
|
||||
await overview_command(ctx)
|
||||
await historical_command(ctx, preset)
|
||||
elif reaction.emoji == "3️⃣":
|
||||
if cfg.DEBUG:
|
||||
print("Reaction selected: 3")
|
||||
await valuation_command(ctx)
|
||||
await overview_command(ctx, preset)
|
||||
elif reaction.emoji == "4️⃣":
|
||||
if cfg.DEBUG:
|
||||
print("Reaction selected: 4")
|
||||
await financial_command(ctx)
|
||||
await valuation_command(ctx, preset)
|
||||
elif reaction.emoji == "5️⃣":
|
||||
if cfg.DEBUG:
|
||||
print("Reaction selected: 5")
|
||||
await ownership_command(ctx)
|
||||
await financial_command(ctx, preset)
|
||||
elif reaction.emoji == "6️⃣":
|
||||
if cfg.DEBUG:
|
||||
print("Reaction selected: 6")
|
||||
await performance_command(ctx)
|
||||
await ownership_command(ctx, preset)
|
||||
elif reaction.emoji == "7️⃣":
|
||||
if cfg.DEBUG:
|
||||
print("Reaction selected: 7")
|
||||
await technical_command(ctx)
|
||||
await performance_command(ctx, preset)
|
||||
elif reaction.emoji == "8️⃣":
|
||||
if cfg.DEBUG:
|
||||
print("Reaction selected: 8")
|
||||
await technical_command(ctx, preset)
|
||||
|
||||
for emoji in emoji_list:
|
||||
await msg.remove_reaction(emoji, ctx.bot.user)
|
||||
|
||||
152
discordbot/stocks/screener/screener_options.py
Normal file
152
discordbot/stocks/screener/screener_options.py
Normal file
@@ -0,0 +1,152 @@
|
||||
import os
|
||||
|
||||
import discordbot.config_discordbot as cfg
|
||||
|
||||
presets_path = os.path.join(
|
||||
cfg.GST_PATH, "gamestonk_terminal", "stocks", "screener", "presets", ""
|
||||
)
|
||||
|
||||
d_signals_desc = {
|
||||
"top_gainers": "stocks with the highest %% price gain today",
|
||||
"top_losers": "stocks with the highest %% price loss today",
|
||||
"new_high": "stocks making 52-week high today",
|
||||
"new_low": "stocks making 52-week low today",
|
||||
"most_volatile": "stocks with the highest widest high/low trading range today",
|
||||
"most_active": "stocks with the highest trading volume today",
|
||||
"unusual_volume": "stocks with unusually high volume today - the highest relative volume ratio",
|
||||
"overbought": "stock is becoming overvalued and may experience a pullback.",
|
||||
"oversold": "oversold stocks may represent a buying opportunity for investors",
|
||||
"downgrades": "stocks downgraded by analysts today",
|
||||
"upgrades": "stocks upgraded by analysts today",
|
||||
"earnings_before": "companies reporting earnings today, before market open",
|
||||
"earnings_after": "companies reporting earnings today, after market close",
|
||||
"recent_insider_buying": "stocks with recent insider buying activity",
|
||||
"recent_insider_selling": "stocks with recent insider selling activity",
|
||||
"major_news": "stocks with the highest news coverage today",
|
||||
"horizontal_sr": "horizontal channel of price range between support and resistance trendlines",
|
||||
"tl_resistance": "once a rising trendline is broken",
|
||||
"tl_support": "once a falling trendline is broken",
|
||||
"wedge_up": "upward trendline support and upward trendline resistance (reversal)",
|
||||
"wedge_down": "downward trendline support and downward trendline resistance (reversal)",
|
||||
"wedge": "upward trendline support, downward trendline resistance (contiunation)",
|
||||
"triangle_ascending": "upward trendline support and horizontal trendline resistance",
|
||||
"triangle_descending": "horizontal trendline support and downward trendline resistance",
|
||||
"channel_up": "both support and resistance trendlines slope upward",
|
||||
"channel_down": "both support and resistance trendlines slope downward",
|
||||
"channel": "both support and resistance trendlines are horizontal",
|
||||
"double_top": "stock with 'M' shape that indicates a bearish reversal in trend",
|
||||
"double_bottom": "stock with 'W' shape that indicates a bullish reversal in trend",
|
||||
"multiple_top": "same as double_top hitting more highs",
|
||||
"multiple_bottom": "same as double_bottom hitting more lows",
|
||||
"head_shoulders": "chart formation that predicts a bullish-to-bearish trend reversal",
|
||||
"head_shoulders_inverse": "chart formation that predicts a bearish-to-bullish trend reversal",
|
||||
}
|
||||
|
||||
presets = [
|
||||
preset.split(".")[0] for preset in os.listdir(presets_path) if preset[-4:] == ".ini"
|
||||
]
|
||||
|
||||
all_presets = list(d_signals_desc.keys()) + presets
|
||||
|
||||
|
||||
d_cols_to_sort = {
|
||||
"overview": [
|
||||
"Ticker",
|
||||
"Company",
|
||||
"Sector",
|
||||
"Industry",
|
||||
"Country",
|
||||
"Market Cap",
|
||||
"P/E",
|
||||
"Price",
|
||||
"Change",
|
||||
"Volume",
|
||||
],
|
||||
"valuation": [
|
||||
"Ticker",
|
||||
"Market Cap",
|
||||
"P/E",
|
||||
"Fwd P/E",
|
||||
"PEG",
|
||||
"P/S",
|
||||
"P/B",
|
||||
"P/C",
|
||||
"P/FCF",
|
||||
"EPS this Y",
|
||||
"EPS next Y",
|
||||
"EPS past 5Y",
|
||||
"EPS next 5Y",
|
||||
"Sales past 5Y",
|
||||
"Price",
|
||||
"Change",
|
||||
"Volume",
|
||||
],
|
||||
"financial": [
|
||||
"Ticker",
|
||||
"Market Cap",
|
||||
"Dividend",
|
||||
"ROA",
|
||||
"ROE",
|
||||
"ROI",
|
||||
"Curr R",
|
||||
"Quick R",
|
||||
"LTDebt/Eq",
|
||||
"Debt/Eq",
|
||||
"Gross M",
|
||||
"Oper M",
|
||||
"Profit M",
|
||||
"Earnings",
|
||||
"Price",
|
||||
"Change",
|
||||
"Volume",
|
||||
],
|
||||
"ownership": [
|
||||
"Ticker",
|
||||
"Market Cap",
|
||||
"Outstanding",
|
||||
"Float",
|
||||
"Insider Own",
|
||||
"Insider Trans",
|
||||
"Inst Own",
|
||||
"Inst Trans",
|
||||
"Float Short",
|
||||
"Short Ratio",
|
||||
"Avg Volume",
|
||||
"Price",
|
||||
"Change",
|
||||
"Volume",
|
||||
],
|
||||
"performance": [
|
||||
"Ticker",
|
||||
"Perf Week",
|
||||
"Perf Month",
|
||||
"Perf Quart",
|
||||
"Perf Half",
|
||||
"Perf Year",
|
||||
"Perf YTD",
|
||||
"Volatility W",
|
||||
"Volatility M",
|
||||
"Recom",
|
||||
"Avg Volume",
|
||||
"Rel Volume",
|
||||
"Price",
|
||||
"Change",
|
||||
"Volume",
|
||||
],
|
||||
"technical": [
|
||||
"Ticker",
|
||||
"Beta",
|
||||
"ATR",
|
||||
"SMA20",
|
||||
"SMA50",
|
||||
"SMA200",
|
||||
"52W High",
|
||||
"52W Low",
|
||||
"RSI",
|
||||
"Price",
|
||||
"Change",
|
||||
"from Open",
|
||||
"Gap",
|
||||
"Volume",
|
||||
],
|
||||
}
|
||||
@@ -2,18 +2,18 @@ import difflib
|
||||
import discord
|
||||
import pandas as pd
|
||||
|
||||
from gamestonk_terminal.stocks.screener.finviz_model import get_screener_data
|
||||
import discordbot.config_discordbot as cfg
|
||||
from discordbot.helpers import pagination
|
||||
|
||||
from gamestonk_terminal.stocks.screener.finviz_model import get_screener_data
|
||||
from discordbot.stocks.screener import screener_options as so
|
||||
|
||||
|
||||
async def technical_command(
|
||||
ctx, preset="template", sort="", limit="25", ascend="False"
|
||||
):
|
||||
async def technical_command(ctx, preset="template", sort="", limit="5", ascend="False"):
|
||||
"""Displays stocks according to chosen preset, sorting by technical factors [Finviz]"""
|
||||
try:
|
||||
preset_error = False
|
||||
# Check for argument
|
||||
if preset == "template" or preset not in so.all_presets:
|
||||
raise Exception("Invalid preset selected!")
|
||||
|
||||
# Debug
|
||||
if cfg.DEBUG:
|
||||
@@ -36,33 +36,12 @@ async def technical_command(
|
||||
raise Exception("ascend argument has to be true or false")
|
||||
|
||||
# Output Data
|
||||
preset_error = True
|
||||
df_screen = get_screener_data(
|
||||
preset,
|
||||
"overview",
|
||||
"technical",
|
||||
limit,
|
||||
ascend,
|
||||
)
|
||||
preset_error = False
|
||||
|
||||
d_cols_to_sort = {
|
||||
"technical": [
|
||||
"Ticker",
|
||||
"Beta",
|
||||
"ATR",
|
||||
"SMA20",
|
||||
"SMA50",
|
||||
"SMA200",
|
||||
"52W High",
|
||||
"52W Low",
|
||||
"RSI",
|
||||
"Price",
|
||||
"Change",
|
||||
"from Open",
|
||||
"Gap",
|
||||
"Volume",
|
||||
],
|
||||
}
|
||||
|
||||
description = ""
|
||||
|
||||
@@ -73,7 +52,7 @@ async def technical_command(
|
||||
df_screen = df_screen.dropna(axis="columns", how="all")
|
||||
|
||||
if sort:
|
||||
if " ".join(sort) in d_cols_to_sort["technical"]:
|
||||
if " ".join(sort) in so.d_cols_to_sort["technical"]:
|
||||
df_screen = df_screen.sort_values(
|
||||
by=[" ".join(sort)],
|
||||
ascending=ascend,
|
||||
@@ -82,7 +61,7 @@ async def technical_command(
|
||||
else:
|
||||
similar_cmd = difflib.get_close_matches(
|
||||
" ".join(sort),
|
||||
d_cols_to_sort["technical"],
|
||||
so.d_cols_to_sort["technical"],
|
||||
n=1,
|
||||
cutoff=0.7,
|
||||
)
|
||||
@@ -95,7 +74,7 @@ async def technical_command(
|
||||
)
|
||||
else:
|
||||
raise ValueError(
|
||||
f"Wrong sort column provided! Provide one of these: {', '.join(d_cols_to_sort['technical'])}"
|
||||
f"Wrong sort column provided! Select from: {', '.join(so.d_cols_to_sort['technical'])}"
|
||||
)
|
||||
|
||||
df_screen = df_screen.fillna("")
|
||||
@@ -137,19 +116,11 @@ async def technical_command(
|
||||
await pagination(columns, ctx)
|
||||
|
||||
except Exception as e:
|
||||
if not preset_error:
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: [Finviz] Technical Screener",
|
||||
colour=cfg.COLOR,
|
||||
description=e,
|
||||
)
|
||||
else:
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: [Finviz] Technical Screener",
|
||||
colour=cfg.COLOR,
|
||||
description=f"Wrong preset parameter entered. Use the command '{cfg.COMMAND_PREFIX}stocks.scr.presets' "
|
||||
"in order to see the available presets.",
|
||||
)
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: [Finviz] Technical Screener",
|
||||
colour=cfg.COLOR,
|
||||
description=e,
|
||||
)
|
||||
embed.set_author(
|
||||
name=cfg.AUTHOR_NAME,
|
||||
icon_url=cfg.AUTHOR_ICON_URL,
|
||||
|
||||
@@ -2,18 +2,18 @@ import difflib
|
||||
import discord
|
||||
import pandas as pd
|
||||
|
||||
from gamestonk_terminal.stocks.screener.finviz_model import get_screener_data
|
||||
import discordbot.config_discordbot as cfg
|
||||
from discordbot.helpers import pagination
|
||||
|
||||
from gamestonk_terminal.stocks.screener.finviz_model import get_screener_data
|
||||
from discordbot.stocks.screener import screener_options as so
|
||||
|
||||
|
||||
async def valuation_command(
|
||||
ctx, preset="template", sort="", limit="25", ascend="False"
|
||||
):
|
||||
async def valuation_command(ctx, preset="template", sort="", limit="5", ascend="False"):
|
||||
"""Displays results from chosen preset focusing on valuation metrics [Finviz]"""
|
||||
try:
|
||||
preset_error = False
|
||||
# Check for argument
|
||||
if preset == "template" or preset not in so.all_presets:
|
||||
raise Exception("Invalid preset selected!")
|
||||
|
||||
# Debug
|
||||
if cfg.DEBUG:
|
||||
@@ -36,36 +36,12 @@ async def valuation_command(
|
||||
raise Exception("ascend argument has to be true or false")
|
||||
|
||||
# Output Data
|
||||
preset_error = True
|
||||
df_screen = get_screener_data(
|
||||
preset,
|
||||
"overview",
|
||||
"valuation",
|
||||
limit,
|
||||
ascend,
|
||||
)
|
||||
preset_error = False
|
||||
|
||||
d_cols_to_sort = {
|
||||
"valuation": [
|
||||
"Ticker",
|
||||
"Market Cap",
|
||||
"P/E",
|
||||
"Fwd P/E",
|
||||
"PEG",
|
||||
"P/S",
|
||||
"P/B",
|
||||
"P/C",
|
||||
"P/FCF",
|
||||
"EPS this Y",
|
||||
"EPS next Y",
|
||||
"EPS past 5Y",
|
||||
"EPS next 5Y",
|
||||
"Sales past 5Y",
|
||||
"Price",
|
||||
"Change",
|
||||
"Volume",
|
||||
],
|
||||
}
|
||||
|
||||
description = ""
|
||||
|
||||
@@ -76,7 +52,7 @@ async def valuation_command(
|
||||
df_screen = df_screen.dropna(axis="columns", how="all")
|
||||
|
||||
if sort:
|
||||
if " ".join(sort) in d_cols_to_sort["valuation"]:
|
||||
if " ".join(sort) in so.d_cols_to_sort["valuation"]:
|
||||
df_screen = df_screen.sort_values(
|
||||
by=[" ".join(sort)],
|
||||
ascending=ascend,
|
||||
@@ -85,7 +61,7 @@ async def valuation_command(
|
||||
else:
|
||||
similar_cmd = difflib.get_close_matches(
|
||||
" ".join(sort),
|
||||
d_cols_to_sort["valuation"],
|
||||
so.d_cols_to_sort["valuation"],
|
||||
n=1,
|
||||
cutoff=0.7,
|
||||
)
|
||||
@@ -98,7 +74,7 @@ async def valuation_command(
|
||||
)
|
||||
else:
|
||||
raise ValueError(
|
||||
f"Wrong sort column provided! Provide one of these: {', '.join(d_cols_to_sort['valuation'])}"
|
||||
f"Wrong sort column provided! Select from: {', '.join(so.d_cols_to_sort['valuation'])}"
|
||||
)
|
||||
|
||||
df_screen = df_screen.fillna("")
|
||||
@@ -140,19 +116,11 @@ async def valuation_command(
|
||||
await pagination(columns, ctx)
|
||||
|
||||
except Exception as e:
|
||||
if not preset_error:
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: [Finviz] Valuation Screener",
|
||||
colour=cfg.COLOR,
|
||||
description=e,
|
||||
)
|
||||
else:
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: [Finviz] Valuation Screener",
|
||||
colour=cfg.COLOR,
|
||||
description=f"Wrong preset parameter entered. Use the command '{cfg.COMMAND_PREFIX}stocks.scr.presets' "
|
||||
"in order to see the available presets.",
|
||||
)
|
||||
embed = discord.Embed(
|
||||
title="ERROR Stocks: [Finviz] Valuation Screener",
|
||||
colour=cfg.COLOR,
|
||||
description=e,
|
||||
)
|
||||
embed.set_author(
|
||||
name=cfg.AUTHOR_NAME,
|
||||
icon_url=cfg.AUTHOR_ICON_URL,
|
||||
|
||||
Reference in New Issue
Block a user