Update view plot (#541)

This commit is contained in:
jmaslek
2021-07-12 21:19:25 -04:00
committed by GitHub
parent 07fc037441
commit a57be3b9cc
9 changed files with 107 additions and 165 deletions

View File

@@ -49,18 +49,14 @@ usage: clear
* Clear previously loaded stock ticker.
```
usage: view [-t S_TICKER] [-s S_START_DATE] [-i {1,5,15,30,60}] [--type TYPE] [--raw] [--export {csv,json,xlsx}]
view
```
* Visualise historical data of a stock. An alpha_vantage key is necessary.
* -t : Stock ticker
* -s : The starting date (format YYYY-MM-DD) of the stock
* -i : Intraday stock minutes
* --type : 1234 corresponds to types: 1. open; 2. high; 3.low; 4. close; while 14 corresponds to types: 1.open; 4. close
* --raw : Print raw data.
* --export : Export dataframe data to csv,json,xlsx file
* Visualise historical data of a stock.
![AAPL](https://user-images.githubusercontent.com/18151143/125211301-69424800-e273-11eb-853d-0b7a0db8ffb7.png)
![GNUS](https://user-images.githubusercontent.com/25267873/108925137-f2920e80-7633-11eb-8274-6e3bb6a19592.png)
Line plot color is configurable in config_plot.py
```
quote -t S_TICKER

View File

@@ -20,3 +20,7 @@ PLOT_WIDTH_PERCENTAGE = 70
# When autoscaling is True, choose which monitor to scale to
# Primary monitor = 0, secondary monitor use 1
MONITOR = 0
# Color for `view` command data. All pyplot colors listed at:
# https://matplotlib.org/stable/gallery/color/named_colors.html
VIEW_COLOR = "tab:green"

View File

@@ -93,9 +93,16 @@ def plot_view_stock(df: pd.DataFrame, symbol: str, interval: str):
"""
df.sort_index(ascending=True, inplace=True)
bar_colors = ["r" if x[1].Open < x[1].Close else "g" for x in df.iterrows()]
try:
_, axVolume = plt.subplots(figsize=plot_autoscale(), dpi=cfgPlot.PLOT_DPI)
fig, ax = plt.subplots(
2,
1,
gridspec_kw={"height_ratios": [3, 1]},
figsize=plot_autoscale(),
dpi=cfgPlot.PLOT_DPI,
)
except Exception as e:
print(e)
print(
@@ -106,24 +113,47 @@ def plot_view_stock(df: pd.DataFrame, symbol: str, interval: str):
# In order to make nice Volume plot, make the bar width = interval
if interval == "1440min":
bar_width = timedelta(days=1)
title_string = "Daily"
else:
bar_width = timedelta(minutes=int(interval.split("m")[0]))
title_string = f"{int(interval.split('m')[0])} min"
plt.bar(df.index, df.iloc[:, -1], color="k", alpha=0.8, width=bar_width)
plt.ylabel("Volume")
_ = axVolume.twinx()
plt.plot(df.index, df.iloc[:, :-1])
plt.title(symbol.upper() + " (Time Series)")
plt.xlim(df.index[0], df.index[-1])
plt.xlabel("Time")
plt.ylabel("Share Price ($)")
plt.legend(df.columns)
plt.grid(b=True, which="major", color="#666666", linestyle="-")
plt.minorticks_on()
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
ax[0].yaxis.tick_right()
if "Adj Close" in df.columns:
ax[0].plot(df.index, df["Adj Close"], c=cfgPlot.VIEW_COLOR)
else:
ax[0].plot(df.index, df["Close"], c=cfgPlot.VIEW_COLOR)
ax[0].set_xlim(df.index[0], df.index[-1])
ax[0].set_xticks([])
ax[0].yaxis.set_label_position("right")
ax[0].set_ylabel("Share Price ($)")
ax[0].grid(axis="y", color="gainsboro", linestyle="-", linewidth=0.5)
ax[0].spines["top"].set_visible(False)
ax[0].spines["left"].set_visible(False)
ax[1].bar(
df.index, df.Volume / 1_000_000, color=bar_colors, alpha=0.8, width=bar_width
)
ax[1].set_xlim(df.index[0], df.index[-1])
ax[1].yaxis.tick_right()
ax[1].yaxis.set_label_position("right")
ax[1].set_ylabel("Volume (1M)")
ax[1].grid(axis="y", color="gainsboro", linestyle="-", linewidth=0.5)
ax[1].spines["top"].set_visible(False)
ax[1].spines["left"].set_visible(False)
ax[1].set_xlabel("Time")
fig.suptitle(
symbol + " " + title_string,
size=20,
x=0.15,
y=0.95,
fontfamily="serif",
fontstyle="italic",
)
if gtff.USE_ION:
plt.ion()
fig.tight_layout(pad=2)
plt.setp(ax[1].get_xticklabels(), rotation=20, horizontalalignment="right")
plt.show()
print("")

View File

@@ -27,8 +27,6 @@ from gamestonk_terminal.helper_funcs import (
valid_date,
plot_view_stock,
parse_known_args_and_warn,
check_ohlc,
lett_to_num,
plot_autoscale,
export_data,
)
@@ -526,7 +524,7 @@ def quote(other_args: List[str], s_ticker: str):
return
def view(other_args: List[str], s_ticker: str, s_start, s_interval, df_stock):
def view(other_args: List[str], s_ticker: str, s_interval, df_stock):
"""
Plot loaded ticker or load ticker and plot
Parameters
@@ -535,154 +533,63 @@ def view(other_args: List[str], s_ticker: str, s_start, s_interval, df_stock):
Argparse arguments
s_ticker: str
Ticker to load
s_start: str
Start date
s_interval: str
Interval tto get data for
df_stock: pd.Dataframe
Preloaded dataframe to plot
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="view",
description="Visualize historical data of a stock.",
)
if s_ticker:
parser.add_argument(
"-t",
"--ticker",
action="store",
dest="s_ticker",
default=s_ticker,
help="Stock ticker",
)
else:
parser.add_argument(
"-t",
"--ticker",
action="store",
dest="s_ticker",
required="-h" not in other_args,
help="Stock ticker",
)
parser.add_argument(
"-s",
"--start",
type=valid_date,
dest="s_start_date",
default=s_start if s_start else "2019-01-01",
help="The starting date (format YYYY-MM-DD) of the stock",
)
parser.add_argument(
"-i",
"--interval",
action="store",
dest="n_interval",
type=int,
default=0,
choices=[1, 5, 15, 30, 60],
help="Intraday stock minutes",
)
parser.add_argument(
"--type",
action="store",
dest="type",
type=check_ohlc,
default="a", # in case it's adjusted close
help=(
"ohlc corresponds to types: open; high; low; close; "
"while oc corresponds to types: open; close"
),
)
parser.add_argument(
"--raw",
action="store_true",
default=False,
dest="b_raw",
help="Print raw data.",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
dest="export",
help="Export dataframe data to csv,json,xlsx file",
add_help=False, prog="view", description="Visualize historical data of a stock."
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
# Update values:
if ns_parser.s_ticker != s_ticker:
if ns_parser.n_interval > 0:
s_ticker, s_start, s_interval, df_stock = load(
[
"-t",
ns_parser.s_ticker,
"-s",
ns_parser.s_start_date.strftime("%Y-%m-%d"),
"-i",
ns_parser.n_interval,
],
s_ticker,
s_start,
s_interval,
df_stock,
)
else:
s_ticker, s_start, s_interval, df_stock = load(
[
"-t",
ns_parser.s_ticker,
"-s",
ns_parser.s_start_date.strftime("%Y-%m-%d"),
],
s_ticker,
s_start,
s_interval,
df_stock,
)
# A new interval intraday period was given
if ns_parser.n_interval != 0:
s_interval = str(ns_parser.n_interval) + "min"
type_candles = lett_to_num(ns_parser.type)
df_stock.sort_index(ascending=True, inplace=True)
# Daily
if s_interval == "1440min":
# The default doesn't exist for intradaily data
ln_col_idx = [int(x) - 1 for x in list(type_candles)]
# Check that the types given are not bigger than 4, as there are only 5 types (0-4)
# pylint: disable=len-as-condition
if len([i for i in ln_col_idx if i > 4]) > 0:
print("An index bigger than 4 was given, which is wrong. Try again")
return
# Append last column of df to be filtered which corresponds to: Volume
ln_col_idx.append(5)
# Slice dataframe from the starting date YYYY-MM-DD selected
df_stock = df_stock[ns_parser.s_start_date :]
# Intraday
else:
# The default doesn't exist for intradaily data
# JM edit 6-7-21 -- It seems it does
if ns_parser.type == "a":
ln_col_idx = [4]
else:
ln_col_idx = [int(x) - 1 for x in list(type_candles)]
# Append last column of df to be filtered which corresponds to: 5. Volume
ln_col_idx.append(5)
# Slice dataframe from the starting date YYYY-MM-DD selected
df_stock = df_stock[ns_parser.s_start_date.strftime("%Y-%m-%d") :]
if not s_ticker:
print("No ticker loaded. First use `load {ticker}`")
print("")
return
# Plot view of the stock
plot_view_stock(df_stock.iloc[:, ln_col_idx], ns_parser.s_ticker, s_interval)
plot_view_stock(df_stock, s_ticker, s_interval)
except Exception as e:
print("Error in plotting:")
print(e, "\n")
except SystemExit:
print("")
return
def export(other_args: List[str], df_stock):
parser = argparse.ArgumentParser(
add_help=False,
prog="export",
description="Exports the historical data from this ticker to a file or stdout.",
)
parser.add_argument(
"-f",
"--filename",
type=str,
dest="s_filename",
default=sys.stdout,
help="Name of file to save the historical data exported (stdout if unspecified)",
)
parser.add_argument(
"-F",
"--format",
dest="s_format",
type=str,
default="csv",
help="Export historical data into following formats: csv, json, excel, clipboard",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
if ns_parser.b_raw:
print(
@@ -835,6 +742,7 @@ def bootup():
def reset():
print("resetting...")
plt.close("all")
completed_process = subprocess.run("python terminal.py", shell=True, check=False)
if completed_process.returncode != 0:
completed_process = subprocess.run(

10
poetry.lock generated
View File

@@ -2973,7 +2973,7 @@ typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""}
[[package]]
name = "yfinance"
version = "0.1.59"
version = "0.1.63"
description = "Yahoo! Finance market data downloader"
category = "main"
optional = false
@@ -3017,7 +3017,7 @@ prediction = ["tensorflow", "pmdarima"]
[metadata]
lock-version = "1.1"
python-versions = "^3.6.8"
content-hash = "d6c9d143d3bd881bb77cc1f46da2f70687505cc9c1a108deab377e56a249bfa5"
content-hash = "a0ecec577098898eb373d028394e82cde1c0dd91f4f2bd034559de7f6f9f2fef"
[metadata.files]
absl-py = [
@@ -4172,9 +4172,13 @@ protobuf = [
{file = "protobuf-3.17.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2ae692bb6d1992afb6b74348e7bb648a75bb0d3565a3f5eea5bec8f62bd06d87"},
{file = "protobuf-3.17.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:99938f2a2d7ca6563c0ade0c5ca8982264c484fdecf418bd68e880a7ab5730b1"},
{file = "protobuf-3.17.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6902a1e4b7a319ec611a7345ff81b6b004b36b0d2196ce7a748b3493da3d226d"},
{file = "protobuf-3.17.3-cp38-cp38-win32.whl", hash = "sha256:59e5cf6b737c3a376932fbfb869043415f7c16a0cf176ab30a5bbc419cd709c1"},
{file = "protobuf-3.17.3-cp38-cp38-win_amd64.whl", hash = "sha256:ebcb546f10069b56dc2e3da35e003a02076aaa377caf8530fe9789570984a8d2"},
{file = "protobuf-3.17.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4ffbd23640bb7403574f7aff8368e2aeb2ec9a5c6306580be48ac59a6bac8bde"},
{file = "protobuf-3.17.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:26010f693b675ff5a1d0e1bdb17689b8b716a18709113288fead438703d45539"},
{file = "protobuf-3.17.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e76d9686e088fece2450dbc7ee905f9be904e427341d289acbe9ad00b78ebd47"},
{file = "protobuf-3.17.3-cp39-cp39-win32.whl", hash = "sha256:a38bac25f51c93e4be4092c88b2568b9f407c27217d3dd23c7a57fa522a17554"},
{file = "protobuf-3.17.3-cp39-cp39-win_amd64.whl", hash = "sha256:85d6303e4adade2827e43c2b54114d9a6ea547b671cb63fafd5011dc47d0e13d"},
{file = "protobuf-3.17.3-py2.py3-none-any.whl", hash = "sha256:2bfb815216a9cd9faec52b16fd2bfa68437a44b67c56bee59bc3926522ecb04e"},
{file = "protobuf-3.17.3.tar.gz", hash = "sha256:72804ea5eaa9c22a090d2803813e280fb273b62d5ae497aaf3553d141c4fdd7b"},
]
@@ -5027,7 +5031,7 @@ yarl = [
{file = "yarl-1.6.3.tar.gz", hash = "sha256:8a9066529240171b68893d60dca86a763eae2139dd42f42106b03cf4b426bf10"},
]
yfinance = [
{file = "yfinance-0.1.59.tar.gz", hash = "sha256:fe4dc46807eceadc6604bf51ece7297b752dc5402a38a87385094fbfc7565fa0"},
{file = "yfinance-0.1.63.tar.gz", hash = "sha256:11364fe94f1cf7811c45fc620acb61c8c45fcb88de317c7718bbdbc9c1573a4c"},
]
zipp = [
{file = "zipp-3.4.1-py3-none-any.whl", hash = "sha256:51cb66cc54621609dd593d1787f286ee42a5c0adbb4b29abea5a63edc3e03098"},

View File

@@ -21,7 +21,7 @@ alpha-vantage = "^2.3.1"
finviz = "^1.3.4"
bs4 = "^0.0.1"
rapidfuzz = "^1.1.1"
yfinance = "^0.1.55"
yfinance = "^0.1.63"
pandas-ta = "^0.2.23b0"
prettytable = "^2.0.0"
psaw = "^0.0.12"

View File

@@ -224,6 +224,6 @@ werkzeug==2.0.1; python_version >= "3.6" and python_full_version < "3.0.0" or py
widgetsnbextension==3.5.1
wrapt==1.12.1; python_version >= "3.6"
yarl==1.6.3; python_version >= "3.6"
yfinance==0.1.59
yfinance==0.1.63
zipp==3.4.1; python_version < "3.8" and python_version >= "3.6"
zope.interface==5.4.0; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5"

View File

@@ -203,6 +203,6 @@ websockets==9.1; python_full_version >= "3.6.1"
widgetsnbextension==3.5.1
wrapt==1.12.1; python_version >= "3.6"
yarl==1.6.3; python_version >= "3.6"
yfinance==0.1.59
yfinance==0.1.63
zipp==3.4.1; python_version < "3.8" and python_version >= "3.6"
zope.interface==5.4.0; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5"

View File

@@ -270,7 +270,7 @@ Contexts:
def call_view(self, other_args: List[str]):
"""Process view command"""
view(other_args, self.ticker, self.start, self.interval, self.stock)
view(other_args, self.ticker, self.interval, self.stock)
def call_disc(self, _):
"""Process disc command"""