Improve some of the DPS commands based on user review (#700)

* fix dps/psi quandl source

* improve dps/prom

* improve ats/otc based on user request

* remove unused file
This commit is contained in:
DidierRLopes
2021-08-23 15:49:55 +01:00
committed by GitHub
parent 596ba6ff54
commit 1dbffcfb64
5 changed files with 133 additions and 153 deletions

View File

@@ -1,4 +1,4 @@
""" Disc Controller """
""" Dark Pool Shorts Controller """
__docformat__ = "numpy"
import argparse
@@ -266,12 +266,33 @@ Quandl/Stockgrid:
default=5,
help="List of tickers from most promising with better linear regression slope.",
)
parser.add_argument(
"--tier",
action="store",
dest="tier",
type=str,
choices=["T1", "T2", "OTCE"],
default="",
help="Tier to process data from.",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
finra_view.darkpool_otc(num=ns_parser.n_num, promising=ns_parser.n_top)
finra_view.darkpool_otc(
num=ns_parser.n_num,
promising=ns_parser.n_top,
tier=ns_parser.tier,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
@@ -387,6 +408,13 @@ Quandl/Stockgrid:
prog="dpotc",
description="Display barchart of dark pool (ATS) and OTC (Non ATS) data. [Source: FINRA]",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
@@ -395,7 +423,10 @@ Quandl/Stockgrid:
print("No ticker loaded.\n")
return
finra_view.darkpool_ats_otc(ticker=self.ticker)
finra_view.darkpool_ats_otc(
ticker=self.ticker,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
@@ -546,7 +577,7 @@ Quandl/Stockgrid:
action="store",
dest="n_days",
type=check_positive,
default=10,
default=10 if "-r" in other_args else 120,
help="Number of latest days to print data.",
)
else:
@@ -558,13 +589,13 @@ Quandl/Stockgrid:
default=10 if "-r" in other_args else 120,
dest="num",
)
parser.add_argument(
"-r",
action="store_true",
default=False,
help="Flag to print raw data instead",
dest="raw",
)
parser.add_argument(
"-r",
action="store_true",
default=False,
help="Flag to print raw data instead",
dest="raw",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
@@ -583,9 +614,9 @@ Quandl/Stockgrid:
if "quandl" in other_args:
quandl_view.short_interest(
ticker=self.ticker,
start=self.start,
nyse=ns_parser.b_nyse,
days=ns_parser.n_days,
raw=ns_parser.raw,
export=ns_parser.export,
)
else:

View File

@@ -199,13 +199,15 @@ def getFINRAdata(
)
def getATSdata(num_tickers_to_filter: int) -> Tuple[pd.DataFrame, Dict]:
def getATSdata(num_tickers_to_filter: int, tier_ats: str) -> Tuple[pd.DataFrame, Dict]:
"""Get all FINRA ATS data, and parse most promising tickers based on linear regression
Parameters
----------
num_tickers_to_filter : int
Number of tickers to filter from entire ATS data based on the sum of the total weekly shares quantity
tier_ats : int
Tier to process data from
Returns
-------
@@ -214,7 +216,10 @@ def getATSdata(num_tickers_to_filter: int) -> Tuple[pd.DataFrame, Dict]:
Dict
Tickers from Dark Pools with better regression slope
"""
tiers = ["T1", "T2", "OTCE"]
if tier_ats:
tiers = [tier_ats]
else:
tiers = ["T1", "T2", "OTCE"]
df_ats = pd.DataFrame()
for tier in tiers:

View File

@@ -1,13 +1,15 @@
""" FINRA View """
__docformat__ = "numpy"
import os
from typing import List
import pandas as pd
from matplotlib import pyplot as plt
import matplotlib.dates as mdates
from gamestonk_terminal.stocks.dark_pool_shorts import finra_model
from gamestonk_terminal.config_plot import PLOT_DPI
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.helper_funcs import plot_autoscale
from gamestonk_terminal.helper_funcs import plot_autoscale, export_data
def plot_dark_pools(ticker: str, ats: pd.DataFrame, otc: pd.DataFrame):
@@ -83,6 +85,8 @@ def plot_dark_pools(ticker: str, ats: pd.DataFrame, otc: pd.DataFrame):
plt.ylabel("Shares per Trade")
plt.grid(b=True, which="major", color="#666666", linestyle="-", alpha=0.2)
plt.gcf().autofmt_xdate()
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%m/%d"))
plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=4))
plt.xlabel("Weeks")
if gtff.USE_ION:
@@ -91,13 +95,15 @@ def plot_dark_pools(ticker: str, ats: pd.DataFrame, otc: pd.DataFrame):
plt.show()
def darkpool_ats_otc(ticker: str):
"""Display barchart of dark pool (ATS) and OTC (Non ATS) data
def darkpool_ats_otc(ticker: str, export: str):
"""Display barchart of dark pool (ATS) and OTC (Non ATS) data. [Source: FINRA]
Parameters
----------
ticker : str
Stock ticker
export : str
Export dataframe data to csv,json,xlsx file
"""
df_ats, df_otc = finra_model.getTickerFINRAdata(ticker)
@@ -107,6 +113,19 @@ def darkpool_ats_otc(ticker: str):
plot_dark_pools(ticker, df_ats, df_otc)
print("")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"dpotc_ats",
df_ats,
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"dpotc_otc",
df_otc,
)
def plot_dark_pools_ats(ats: pd.DataFrame, top_ats_tickers: List):
"""Plots promising tickers based on growing ATS data
@@ -142,8 +161,8 @@ def plot_dark_pools_ats(ats: pd.DataFrame, top_ats_tickers: List):
plt.show()
def darkpool_otc(num: int, promising: int):
"""Display dark pool (ATS) data of tickers with growing trades activity
def darkpool_otc(num: int, promising: int, tier: str, export: str):
"""Display dark pool (ATS) data of tickers with growing trades activity. [Source: FINRA]
Parameters
----------
@@ -153,8 +172,12 @@ def darkpool_otc(num: int, promising: int):
promising : int
Number of tickers to display from most promising with
better linear regression slope
tier : int
Tier to process data from
export : str
Export dataframe data to csv,json,xlsx file
"""
df_ats, d_ats_reg = finra_model.getATSdata(num)
df_ats, d_ats_reg = finra_model.getATSdata(num, tier)
top_ats_tickers = list(
dict(sorted(d_ats_reg.items(), key=lambda item: item[1], reverse=True)).keys()
@@ -162,3 +185,10 @@ def darkpool_otc(num: int, promising: int):
plot_dark_pools_ats(df_ats, top_ats_tickers)
print("")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"prom",
df_ats,
)

View File

@@ -5,6 +5,7 @@ import os
import matplotlib.ticker
from matplotlib import pyplot as plt
import pandas as pd
from tabulate import tabulate
from gamestonk_terminal.stocks.dark_pool_shorts import quandl_model
from gamestonk_terminal.helper_funcs import (
long_number_format,
@@ -12,9 +13,7 @@ from gamestonk_terminal.helper_funcs import (
)
def plot_short_interest(
ticker: str, start: str, nyse: bool, days: int, df_short_interest: pd.DataFrame
):
def plot_short_interest(ticker: str, nyse: bool, df_short_interest: pd.DataFrame):
"""Plots the short interest of a stock. This corresponds to the
number of shares that have been sold short but have not yet been
covered or closed out. Either NASDAQ or NYSE [Source: Quandl]
@@ -27,21 +26,9 @@ def plot_short_interest(
start date to start displaying short interest volume
nyse : bool
data from NYSE if true, otherwise NASDAQ
days : int
Number of past days to show short interest
df_short_interest: pd.DataFrame
Short interest dataframe
"""
df_short_interest = df_short_interest[start:] # type: ignore
df_short_interest.columns = [
"".join(" " + char if char.isupper() else char.strip() for char in idx).strip()
for idx in df_short_interest.columns.tolist()
]
df_short_interest["% of Volume Shorted"] = round(
100 * df_short_interest["Short Volume"] / df_short_interest["Total Volume"],
2,
)
_, ax = plt.subplots()
ax.bar(df_short_interest.index, df_short_interest["Short Volume"], 0.3, color="r")
ax.bar(
@@ -53,15 +40,9 @@ def plot_short_interest(
)
ax.set_ylabel("Shares")
ax.set_xlabel("Date")
ax.set_title(f"{('NASDAQ', 'NYSE')[nyse]} Short Interest on {ticker}")
if start:
ax.set_title(
f"{('NASDAQ', 'NYSE')[nyse]} Short Interest on {ticker} from {start.date()}" # type: ignore
)
else:
ax.set_title(f"{('NASDAQ', 'NYSE')[nyse]} Short Interest on {ticker}")
ax.legend(labels=["Short Volume", "Total Volume"])
ax.legend(labels=["Short Volume", "Total Volume"], loc="best")
ax.tick_params(axis="both", which="major")
ax.yaxis.set_major_formatter(matplotlib.ticker.EngFormatter())
ax_twin = ax.twinx()
@@ -75,21 +56,12 @@ def plot_short_interest(
ax_twin.tick_params(axis="y", which="major", color="green")
ax_twin.yaxis.set_major_formatter(matplotlib.ticker.FormatStrFormatter("%.0f%%"))
plt.xlim([df_short_interest.index[0], df_short_interest.index[-1]])
plt.gcf().autofmt_xdate()
df_short_interest["% of Volume Shorted"] = df_short_interest[
"% of Volume Shorted"
].apply(lambda x: f"{x/100:.2%}")
df_short_interest = df_short_interest.applymap(
lambda x: long_number_format(x)
).sort_index(ascending=False)
pd.set_option("display.max_colwidth", 70)
print(df_short_interest.head(n=days).to_string())
print("")
plt.show()
def short_interest(ticker: str, start: str, nyse: bool, days: int, export: str):
def short_interest(ticker: str, nyse: bool, days: int, raw: bool, export: str):
"""Plots the short interest of a stock. This corresponds to the
number of shares that have been sold short but have not yet been
covered or closed out. Either NASDAQ or NYSE [Source: Quandl]
@@ -98,22 +70,59 @@ def short_interest(ticker: str, start: str, nyse: bool, days: int, export: str):
----------
ticker : str
ticker to get short interest from
start : str
start date to start displaying short interest volume
nyse : bool
data from NYSE if true, otherwise NASDAQ
days : int
Number of past days to show short interest
raw : bool
Flag to print raw data instead
export : str
Export dataframe data to csv,json,xlsx file
"""
df_short_interest = quandl_model.get_short_interest(ticker, nyse)
plot_short_interest(ticker, start, nyse, days, df_short_interest)
df_short_interest = df_short_interest.tail(days)
df_short_interest.columns = [
"".join(" " + char if char.isupper() else char.strip() for char in idx).strip()
for idx in df_short_interest.columns.tolist()
]
pd.options.mode.chained_assignment = None
vol_pct = (
100
* df_short_interest["Short Volume"].values
/ df_short_interest["Total Volume"].values
)
df_short_interest["% of Volume Shorted"] = [round(pct, 2) for pct in vol_pct]
if raw:
df_short_interest["% of Volume Shorted"] = df_short_interest[
"% of Volume Shorted"
].apply(lambda x: f"{x/100:.2%}")
df_short_interest = df_short_interest.applymap(
lambda x: long_number_format(x)
).sort_index(ascending=False)
df_short_interest.index = df_short_interest.index.date
print(
tabulate(
df_short_interest,
headers=df_short_interest.columns,
floatfmt=".2f",
showindex=True,
tablefmt="fancy_grid",
)
)
else:
plot_short_interest(ticker, nyse, df_short_interest)
print("")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"shortint(quandl)",
"psi(quandl)",
df_short_interest,
)

View File

@@ -1,95 +0,0 @@
""" Market Watch View """
__docformat__ = "numpy"
import argparse
from typing import List
import requests
import pandas as pd
from bs4 import BeautifulSoup
from gamestonk_terminal.helper_funcs import (
check_positive,
get_user_agent,
parse_known_args_and_warn,
)
# pylint: disable=too-many-branches
def sec_fillings(other_args: List[str], ticker: str):
"""Display SEC filings for a given stock ticker
Parameters
----------
other_args : List[str]
argparse other args - ["-n", "10"]
ticker : str
Stock ticker
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="sec",
description="""
Prints SEC filings of the company. The following fields are expected: Filing Date,
Document Date, Type, Category, Amended, and Link. [Source: Market Watch]
""",
)
parser.add_argument(
"-n",
"--num",
action="store",
dest="n_num",
type=check_positive,
default=5,
help="number of latest SEC filings.",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
pd.set_option("display.max_colwidth", None)
url_financials = f"https://www.marketwatch.com/investing/stock/{ticker}/financials/secfilings"
text_soup_financials = BeautifulSoup(
requests.get(url_financials, headers={"User-Agent": get_user_agent()}).text,
"lxml",
)
# a_financials_header = []
df_financials = None
b_ready_to_process_info = False
soup_financials = text_soup_financials.findAll("tr", {"class": "table__row"})
for financials_info in soup_financials:
a_financials = financials_info.text.split("\n")
# If header has been processed and dataframe created ready to populate the SEC information
if b_ready_to_process_info:
l_financials_info = [a_financials[2]]
l_financials_info.extend(a_financials[5:-1])
l_financials_info.append(financials_info.a["href"])
# Append data values to financials
df_financials.loc[len(df_financials.index)] = l_financials_info # type: ignore
if "Filing Date" in a_financials:
l_financials_header = [a_financials[2]]
l_financials_header.extend(a_financials[5:-1])
l_financials_header.append("Link")
df_financials = pd.DataFrame(columns=l_financials_header)
df_financials.set_index("Filing Date")
b_ready_to_process_info = True
# Set Filing Date as index
df_financials = df_financials.set_index("Filing Date") # type: ignore
print(df_financials.head(n=ns_parser.n_num).to_string())
print("")
except Exception as e:
print(e)
print("")
return