mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 12:40:35 +00:00
Update view plot (#541)
This commit is contained in:
@@ -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.
|
||||

|
||||
|
||||

|
||||
|
||||
Line plot color is configurable in config_plot.py
|
||||
|
||||
```
|
||||
quote -t S_TICKER
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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("")
|
||||
|
||||
@@ -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
10
poetry.lock
generated
@@ -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"},
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"""
|
||||
|
||||
Reference in New Issue
Block a user