mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 12:40:35 +00:00
General bug fixes (#862)
* Bug fixes * make all yfinance data non tz aware * Get rid of namespace input * candle -> display_candle * Didier I hope you read this. pycharm would not have let me miss committing this file Co-authored-by: James Maslek <james@Jamess-MacBook-Pro.local>
This commit is contained in:
@@ -500,7 +500,7 @@ def display_unitroot(
|
||||
|
||||
|
||||
def display_raw(
|
||||
df: pd.DataFrame, export: str, sort: str, des: bool, num: int = 20
|
||||
df: pd.DataFrame, sort: str = "", des: bool = False, num: int = 20, export: str = ""
|
||||
) -> None:
|
||||
"""Return raw stock data
|
||||
|
||||
@@ -508,14 +508,14 @@ def display_raw(
|
||||
----------
|
||||
df : DataFrame
|
||||
DataFrame with historical information
|
||||
export : str
|
||||
Export data as CSV, JSON, XLSX
|
||||
sort : str
|
||||
The column to sort by
|
||||
des : bool
|
||||
Whether to sort descending
|
||||
num : int
|
||||
Number of rows to show
|
||||
export : str
|
||||
Export data as CSV, JSON, XLSX
|
||||
"""
|
||||
|
||||
export_data(
|
||||
@@ -525,13 +525,16 @@ def display_raw(
|
||||
df,
|
||||
)
|
||||
|
||||
if isinstance(df, pd.Series):
|
||||
df = pd.DataFrame(df)
|
||||
|
||||
if sort:
|
||||
df = df.sort_values(by=sort, ascending=des)
|
||||
|
||||
if gtff.USE_TABULATE_DF:
|
||||
print(
|
||||
tabulate(
|
||||
df.head(num),
|
||||
df.tail(num),
|
||||
headers=[x.title() if x != "" else "Date" for x in df.columns],
|
||||
tablefmt="fancy_grid",
|
||||
showindex=True,
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
"""Technical Analysis Trendline Module"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
from typing import Union
|
||||
from datetime import datetime
|
||||
|
||||
import yfinance as yf
|
||||
from pandas.core.frame import DataFrame
|
||||
from scipy.stats import linregress
|
||||
|
||||
|
||||
def load_ticker(ticker: str, start_date: str) -> DataFrame:
|
||||
def load_ticker(ticker: str, start_date: Union[str, datetime]) -> DataFrame:
|
||||
"""Loads a ticker data from Yahoo Finance, adds a data index column data_id and Open-Close High/Low columns.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
The stock ticker.
|
||||
start_date : str
|
||||
start_date : Union[str,datetime]
|
||||
Start date to load stock ticker data formatted YYYY-MM-DD.
|
||||
|
||||
Returns
|
||||
|
||||
@@ -18,10 +18,12 @@ from gamestonk_terminal.common.quantitative_analysis import (
|
||||
from gamestonk_terminal import feature_flags as gtff
|
||||
from gamestonk_terminal.stocks.stocks_helper import load
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
EXPORT_ONLY_RAW_DATA_ALLOWED,
|
||||
get_flair,
|
||||
check_positive,
|
||||
check_proportion_range,
|
||||
parse_known_args_and_warn,
|
||||
try_except,
|
||||
)
|
||||
from gamestonk_terminal.menu import session
|
||||
from gamestonk_terminal.stocks.quantitative_analysis.factors_view import capm_view
|
||||
@@ -31,7 +33,7 @@ class QaController:
|
||||
"""Quantitative Analysis Controller class"""
|
||||
|
||||
# Command choices
|
||||
CHOICES = ["?", "cls", "help", "q", "quit", "load", "pick"]
|
||||
CHOICES = ["?", "cls", "help", "q", "quit", "load", "pick", "raw"]
|
||||
|
||||
CHOICES_COMMANDS = [
|
||||
"summary",
|
||||
@@ -118,6 +120,7 @@ Rolling Metrics:
|
||||
skew rolling skewness of distribution of prices
|
||||
kurtosis rolling kurtosis of distribution of prices
|
||||
Other:
|
||||
raw print raw data
|
||||
decompose decomposition in cyclic-trend, season, and residuals of prices
|
||||
cusum detects abrupt changes using cumulative sum algorithm of prices
|
||||
capm capital asset pricing model
|
||||
@@ -216,6 +219,46 @@ Other:
|
||||
except Exception as e:
|
||||
print(e, "\n")
|
||||
|
||||
@try_except
|
||||
def call_raw(self, other_args: List[str]):
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
add_help=False,
|
||||
prog="raw",
|
||||
description="""
|
||||
Print raw data to console
|
||||
""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--num",
|
||||
help="Number to show",
|
||||
type=check_positive,
|
||||
default=20,
|
||||
dest="num",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-d",
|
||||
"--descend",
|
||||
action="store_true",
|
||||
default=False,
|
||||
dest="descend",
|
||||
help="Sort in descending order",
|
||||
)
|
||||
|
||||
ns_parser = parse_known_args_and_warn(
|
||||
parser, other_args, export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED
|
||||
)
|
||||
if not ns_parser:
|
||||
return
|
||||
qa_view.display_raw(
|
||||
self.stock[self.target],
|
||||
num=ns_parser.num,
|
||||
sort="",
|
||||
des=ns_parser.descend,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
def call_summary(self, other_args: List[str]):
|
||||
"""Process summary command"""
|
||||
parser = argparse.ArgumentParser(
|
||||
|
||||
@@ -30,7 +30,7 @@ from gamestonk_terminal.stocks.government import gov_controller
|
||||
from gamestonk_terminal.stocks.insider import insider_controller
|
||||
from gamestonk_terminal.stocks.research import res_controller
|
||||
from gamestonk_terminal.stocks.screener import screener_controller
|
||||
from gamestonk_terminal.stocks.stocks_helper import candle, load, quote
|
||||
from gamestonk_terminal.stocks.stocks_helper import display_candle, load, quote
|
||||
from gamestonk_terminal.stocks.technical_analysis import ta_controller
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
valid_date,
|
||||
@@ -220,9 +220,24 @@ Market {('CLOSED', 'OPEN')[b_is_stock_market_open()]}
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
prog="data",
|
||||
prog="candle",
|
||||
description="Shows historic data for a stock",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-s",
|
||||
"--start_date",
|
||||
dest="s_start",
|
||||
type=valid_date,
|
||||
default=(datetime.now() - timedelta(days=366)).strftime("%Y-%m-%d"),
|
||||
help="Start date for candle data",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--plotly",
|
||||
dest="plotly",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Flag to show interactive plot using plotly.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--export",
|
||||
choices=["csv", "json", "xlsx"],
|
||||
@@ -232,7 +247,6 @@ Market {('CLOSED', 'OPEN')[b_is_stock_market_open()]}
|
||||
help="Export dataframe data to csv,json,xlsx file",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-s",
|
||||
"--sort",
|
||||
choices=[
|
||||
"AdjClose",
|
||||
@@ -264,24 +278,39 @@ Market {('CLOSED', 'OPEN')[b_is_stock_market_open()]}
|
||||
default=False,
|
||||
help="Shows raw data instead of chart",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--num",
|
||||
type=check_positive,
|
||||
help="Number to show if raw selected",
|
||||
dest="num",
|
||||
default=20,
|
||||
)
|
||||
|
||||
try:
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
if not self.ticker:
|
||||
print("No ticker loaded. First use `load {ticker}`\n")
|
||||
return
|
||||
|
||||
if ns_parser.raw:
|
||||
qa_view.display_raw(
|
||||
self.stock,
|
||||
ns_parser.export,
|
||||
ns_parser.sort,
|
||||
ns_parser.descending,
|
||||
df=self.stock,
|
||||
export=ns_parser.export,
|
||||
sort=ns_parser.sort,
|
||||
des=ns_parser.descending,
|
||||
num=ns_parser.num,
|
||||
)
|
||||
|
||||
else:
|
||||
candle(
|
||||
self.ticker + "." + self.suffix if self.suffix else self.ticker,
|
||||
other_args,
|
||||
display_candle(
|
||||
s_ticker=self.ticker + "." + self.suffix
|
||||
if self.suffix
|
||||
else self.ticker,
|
||||
s_start=ns_parser.s_start,
|
||||
plotly=ns_parser.plotly,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
||||
@@ -203,6 +203,8 @@ def load(
|
||||
print("")
|
||||
return [s_ticker, s_start, s_interval, df_stock]
|
||||
|
||||
df_stock_candidate.index = df_stock_candidate.index.tz_localize(None)
|
||||
|
||||
# pylint: disable=no-member
|
||||
df_stock_candidate.sort_index(ascending=True, inplace=True)
|
||||
|
||||
@@ -329,6 +331,8 @@ def load(
|
||||
print("")
|
||||
return [s_ticker, s_start, s_interval, df_stock]
|
||||
|
||||
df_stock_candidate.index = df_stock_candidate.index.tz_localize(None)
|
||||
|
||||
if s_start_dt > ns_parser.s_start_date:
|
||||
s_start = pytz.utc.localize(s_start_dt)
|
||||
else:
|
||||
@@ -403,215 +407,184 @@ def load(
|
||||
return [s_ticker, s_start, s_interval, df_stock]
|
||||
|
||||
|
||||
def candle(s_ticker: str, other_args: List[str]):
|
||||
def display_candle(s_ticker: str, s_start: datetime, plotly: bool):
|
||||
"""Shows candle plot of loaded ticker
|
||||
|
||||
Parameters
|
||||
----------
|
||||
s_ticker: str
|
||||
Ticker to display
|
||||
other_args: str
|
||||
Argparse arguments
|
||||
s_start: datetime
|
||||
Starting date for candle
|
||||
plotly: bool
|
||||
Flag to show interactive plotly chart
|
||||
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
prog="candle",
|
||||
description="Displays candle chart of loaded ticker",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-s",
|
||||
"--start_date",
|
||||
dest="s_start",
|
||||
type=valid_date,
|
||||
default=(datetime.now() - timedelta(days=366)).strftime("%Y-%m-%d"),
|
||||
help="Start date for candle data",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--plotly",
|
||||
dest="plotly",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Flag to show interactive plot using plotly.",
|
||||
)
|
||||
# TODO: Add option to customize plot even further
|
||||
print(type(s_start))
|
||||
df_stock = trend.load_ticker(s_ticker, s_start)
|
||||
df_stock["ma20"] = df_stock["Close"].rolling(20).mean().fillna(method="bfill")
|
||||
df_stock["ma50"] = df_stock["Close"].rolling(50).mean().fillna(method="bfill")
|
||||
|
||||
try:
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
if not s_ticker:
|
||||
print("No ticker loaded. First use `load {ticker}`", "\n")
|
||||
return
|
||||
df_stock = trend.find_trendline(df_stock, "OC_High", "high")
|
||||
df_stock = trend.find_trendline(df_stock, "OC_Low", "low")
|
||||
if not plotly:
|
||||
mc = mpf.make_marketcolors(
|
||||
up="green",
|
||||
down="red",
|
||||
edge="black",
|
||||
wick="black",
|
||||
volume="in",
|
||||
ohlc="i",
|
||||
)
|
||||
|
||||
df_stock = trend.load_ticker(s_ticker, ns_parser.s_start)
|
||||
df_stock["ma20"] = df_stock["Close"].rolling(20).mean().fillna(method="bfill")
|
||||
df_stock["ma50"] = df_stock["Close"].rolling(50).mean().fillna(method="bfill")
|
||||
s = mpf.make_mpf_style(marketcolors=mc, gridstyle=":", y_on_right=True)
|
||||
|
||||
df_stock = trend.find_trendline(df_stock, "OC_High", "high")
|
||||
df_stock = trend.find_trendline(df_stock, "OC_Low", "low")
|
||||
if not ns_parser.plotly:
|
||||
mc = mpf.make_marketcolors(
|
||||
up="green",
|
||||
down="red",
|
||||
edge="black",
|
||||
wick="black",
|
||||
volume="in",
|
||||
ohlc="i",
|
||||
ap0 = []
|
||||
|
||||
if "OC_High_trend" in df_stock.columns:
|
||||
ap0.append(
|
||||
mpf.make_addplot(df_stock["OC_High_trend"], color="g"),
|
||||
)
|
||||
|
||||
s = mpf.make_mpf_style(marketcolors=mc, gridstyle=":", y_on_right=True)
|
||||
|
||||
ap0 = []
|
||||
|
||||
if "OC_High_trend" in df_stock.columns:
|
||||
ap0.append(
|
||||
mpf.make_addplot(df_stock["OC_High_trend"], color="g"),
|
||||
)
|
||||
|
||||
if "OC_Low_trend" in df_stock.columns:
|
||||
ap0.append(
|
||||
mpf.make_addplot(df_stock["OC_Low_trend"], color="b"),
|
||||
)
|
||||
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
|
||||
mpf.plot(
|
||||
df_stock,
|
||||
type="candle",
|
||||
mav=(20, 50),
|
||||
volume=True,
|
||||
title=f"\n{s_ticker} - Starting {ns_parser.s_start.strftime('%Y-%m-%d')}",
|
||||
addplot=ap0,
|
||||
xrotation=10,
|
||||
style=s,
|
||||
figratio=(10, 7),
|
||||
figscale=1.10,
|
||||
figsize=(plot_autoscale()),
|
||||
update_width_config=dict(
|
||||
candle_linewidth=1.0, candle_width=0.8, volume_linewidth=1.0
|
||||
),
|
||||
)
|
||||
else:
|
||||
fig = make_subplots(
|
||||
rows=2,
|
||||
cols=1,
|
||||
shared_xaxes=True,
|
||||
vertical_spacing=0.06,
|
||||
subplot_titles=(f"{s_ticker}", "Volume"),
|
||||
row_width=[0.2, 0.7],
|
||||
)
|
||||
fig.add_trace(
|
||||
go.Candlestick(
|
||||
x=df_stock.index,
|
||||
open=df_stock.Open,
|
||||
high=df_stock.High,
|
||||
low=df_stock.Low,
|
||||
close=df_stock.Close,
|
||||
name="OHLC",
|
||||
),
|
||||
row=1,
|
||||
col=1,
|
||||
if "OC_Low_trend" in df_stock.columns:
|
||||
ap0.append(
|
||||
mpf.make_addplot(df_stock["OC_Low_trend"], color="b"),
|
||||
)
|
||||
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
|
||||
mpf.plot(
|
||||
df_stock,
|
||||
type="candle",
|
||||
mav=(20, 50),
|
||||
volume=True,
|
||||
title=f"\n{s_ticker} - Starting {s_start.strftime('%Y-%m-%d')}",
|
||||
addplot=ap0,
|
||||
xrotation=10,
|
||||
style=s,
|
||||
figratio=(10, 7),
|
||||
figscale=1.10,
|
||||
figsize=(plot_autoscale()),
|
||||
update_width_config=dict(
|
||||
candle_linewidth=1.0, candle_width=0.8, volume_linewidth=1.0
|
||||
),
|
||||
)
|
||||
else:
|
||||
fig = make_subplots(
|
||||
rows=2,
|
||||
cols=1,
|
||||
shared_xaxes=True,
|
||||
vertical_spacing=0.06,
|
||||
subplot_titles=(f"{s_ticker}", "Volume"),
|
||||
row_width=[0.2, 0.7],
|
||||
)
|
||||
fig.add_trace(
|
||||
go.Candlestick(
|
||||
x=df_stock.index,
|
||||
open=df_stock.Open,
|
||||
high=df_stock.High,
|
||||
low=df_stock.Low,
|
||||
close=df_stock.Close,
|
||||
name="OHLC",
|
||||
),
|
||||
row=1,
|
||||
col=1,
|
||||
)
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=df_stock.index,
|
||||
y=df_stock["ma20"],
|
||||
name="MA20",
|
||||
mode="lines",
|
||||
line=go.scatter.Line(color="royalblue"),
|
||||
),
|
||||
row=1,
|
||||
col=1,
|
||||
)
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=df_stock.index,
|
||||
y=df_stock["ma50"],
|
||||
name="MA50",
|
||||
mode="lines",
|
||||
line=go.scatter.Line(color="black"),
|
||||
),
|
||||
row=1,
|
||||
col=1,
|
||||
)
|
||||
|
||||
if "OC_High_trend" in df_stock.columns:
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=df_stock.index,
|
||||
y=df_stock["ma20"],
|
||||
name="MA20",
|
||||
y=df_stock["OC_High_trend"],
|
||||
name="High Trend",
|
||||
mode="lines",
|
||||
line=go.scatter.Line(color="royalblue"),
|
||||
line=go.scatter.Line(color="red"),
|
||||
),
|
||||
row=1,
|
||||
col=1,
|
||||
)
|
||||
if "OC_Low_trend" in df_stock.columns:
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=df_stock.index,
|
||||
y=df_stock["ma50"],
|
||||
name="MA50",
|
||||
y=df_stock["OC_Low_trend"],
|
||||
name="Low Trend",
|
||||
mode="lines",
|
||||
line=go.scatter.Line(color="black"),
|
||||
line=go.scatter.Line(color="green"),
|
||||
),
|
||||
row=1,
|
||||
col=1,
|
||||
)
|
||||
|
||||
if "OC_High_trend" in df_stock.columns:
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=df_stock.index,
|
||||
y=df_stock["OC_High_trend"],
|
||||
name="High Trend",
|
||||
mode="lines",
|
||||
line=go.scatter.Line(color="red"),
|
||||
),
|
||||
row=1,
|
||||
col=1,
|
||||
)
|
||||
if "OC_Low_trend" in df_stock.columns:
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=df_stock.index,
|
||||
y=df_stock["OC_Low_trend"],
|
||||
name="Low Trend",
|
||||
mode="lines",
|
||||
line=go.scatter.Line(color="green"),
|
||||
),
|
||||
row=1,
|
||||
col=1,
|
||||
)
|
||||
fig.add_trace(
|
||||
go.Bar(
|
||||
x=df_stock.index,
|
||||
y=df_stock.Volume,
|
||||
name="Volume",
|
||||
marker_color="black",
|
||||
fig.add_trace(
|
||||
go.Bar(
|
||||
x=df_stock.index,
|
||||
y=df_stock.Volume,
|
||||
name="Volume",
|
||||
marker_color="black",
|
||||
),
|
||||
row=2,
|
||||
col=1,
|
||||
)
|
||||
fig.update_layout(
|
||||
yaxis_title="Stock Price ($)",
|
||||
xaxis=dict(
|
||||
rangeselector=dict(
|
||||
buttons=list(
|
||||
[
|
||||
dict(
|
||||
count=1,
|
||||
label="1m",
|
||||
step="month",
|
||||
stepmode="backward",
|
||||
),
|
||||
dict(
|
||||
count=3,
|
||||
label="3m",
|
||||
step="month",
|
||||
stepmode="backward",
|
||||
),
|
||||
dict(count=1, label="YTD", step="year", stepmode="todate"),
|
||||
dict(
|
||||
count=1,
|
||||
label="1y",
|
||||
step="year",
|
||||
stepmode="backward",
|
||||
),
|
||||
dict(step="all"),
|
||||
]
|
||||
)
|
||||
),
|
||||
row=2,
|
||||
col=1,
|
||||
)
|
||||
fig.update_layout(
|
||||
yaxis_title="Stock Price ($)",
|
||||
xaxis=dict(
|
||||
rangeselector=dict(
|
||||
buttons=list(
|
||||
[
|
||||
dict(
|
||||
count=1,
|
||||
label="1m",
|
||||
step="month",
|
||||
stepmode="backward",
|
||||
),
|
||||
dict(
|
||||
count=3,
|
||||
label="3m",
|
||||
step="month",
|
||||
stepmode="backward",
|
||||
),
|
||||
dict(
|
||||
count=1, label="YTD", step="year", stepmode="todate"
|
||||
),
|
||||
dict(
|
||||
count=1,
|
||||
label="1y",
|
||||
step="year",
|
||||
stepmode="backward",
|
||||
),
|
||||
dict(step="all"),
|
||||
]
|
||||
)
|
||||
),
|
||||
rangeslider=dict(visible=False),
|
||||
type="date",
|
||||
),
|
||||
)
|
||||
rangeslider=dict(visible=False),
|
||||
type="date",
|
||||
),
|
||||
)
|
||||
|
||||
fig.show()
|
||||
print("")
|
||||
|
||||
except Exception as e:
|
||||
print(e, "\n")
|
||||
fig.show()
|
||||
print("")
|
||||
|
||||
|
||||
def quote(other_args: List[str], s_ticker: str):
|
||||
|
||||
Reference in New Issue
Block a user