Bug fixing (#3680)

* ycrv bug

* fred search multiple, test fix

* ba/interest to allow multiple words

* Fixes #3642

* Date logic

* debug
This commit is contained in:
James Maslek
2022-12-02 14:34:40 -05:00
committed by GitHub
parent 18da2e1bda
commit f47d15088f
6 changed files with 217 additions and 330 deletions

View File

@@ -229,42 +229,41 @@ class DueDiligenceController(CryptoBaseController):
def call_nonzero(self, other_args: List[str]):
"""Process nonzero command"""
if self.symbol.upper() in glassnode_model.GLASSNODE_SUPPORTED_ASSETS:
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="nonzero",
description="""
Display addresses with nonzero assets in a certain blockchain
[Source: https://glassnode.org]
Note that free api keys only allow fetching data with a 1y lag
""",
)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="nonzero",
description="""
Display addresses with nonzero assets in a certain blockchain
[Source: https://glassnode.org]
Note that free api keys only allow fetching data with a 1y lag
""",
)
parser.add_argument(
"-s",
"--since",
dest="since",
type=valid_date,
help="Initial date. Default: 2 years ago",
default=(datetime.now() - timedelta(days=365 * 2)).strftime("%Y-%m-%d"),
)
parser.add_argument(
"-s",
"--since",
dest="since",
type=valid_date,
help="Initial date. Default: 2 years ago",
default=(datetime.now() - timedelta(days=365 * 2)).strftime("%Y-%m-%d"),
)
parser.add_argument(
"-u",
"--until",
dest="until",
type=valid_date,
help="Final date. Default: 1 year ago",
default=(datetime.now() - timedelta(days=367)).strftime("%Y-%m-%d"),
)
parser.add_argument(
"-u",
"--until",
dest="until",
type=valid_date,
help="Final date. Default: 1 year ago",
default=(datetime.now() - timedelta(days=367)).strftime("%Y-%m-%d"),
)
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
if self.symbol.upper() in glassnode_model.GLASSNODE_SUPPORTED_ASSETS:
glassnode_view.display_non_zero_addresses(
symbol=self.symbol.upper(),
start_date=ns_parser.since.strftime("%Y-%m-%d"),
@@ -272,8 +271,8 @@ class DueDiligenceController(CryptoBaseController):
export=ns_parser.export,
)
else:
console.print("Glassnode source does not support this symbol\n")
else:
console.print(f"[red]{self.symbol} not supported on Glassnode.[/red]")
@log_start_end(log=logger)
def call_stats(self, other_args):
@@ -308,52 +307,50 @@ class DueDiligenceController(CryptoBaseController):
@log_start_end(log=logger)
def call_active(self, other_args: List[str]):
"""Process active command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="active",
description="""
Display active blockchain addresses over time
[Source: https://glassnode.org]
""",
)
if self.symbol.upper() in glassnode_model.GLASSNODE_SUPPORTED_ASSETS:
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="active",
description="""
Display active blockchain addresses over time
[Source: https://glassnode.org]
""",
)
parser.add_argument(
"-i",
"--interval",
dest="interval",
type=str,
help="Frequency interval. Default: 24h",
default="24h",
choices=glassnode_model.INTERVALS_ACTIVE_ADDRESSES,
)
parser.add_argument(
"-i",
"--interval",
dest="interval",
type=str,
help="Frequency interval. Default: 24h",
default="24h",
choices=glassnode_model.INTERVALS_ACTIVE_ADDRESSES,
)
parser.add_argument(
"-s",
"--since",
dest="since",
type=valid_date,
help="Initial date. Default: 1 year ago",
default=(datetime.now() - timedelta(days=365)).strftime("%Y-%m-%d"),
)
parser.add_argument(
"-s",
"--since",
dest="since",
type=valid_date,
help="Initial date. Default: 1 year ago",
default=(datetime.now() - timedelta(days=365)).strftime("%Y-%m-%d"),
)
parser.add_argument(
"-u",
"--until",
dest="until",
type=valid_date,
help="Final date. Default: Today",
default=(datetime.now()).strftime("%Y-%m-%d"),
)
parser.add_argument(
"-u",
"--until",
dest="until",
type=valid_date,
help="Final date. Default: Today",
default=(datetime.now()).strftime("%Y-%m-%d"),
)
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
if self.symbol.upper() in glassnode_model.GLASSNODE_SUPPORTED_ASSETS:
glassnode_view.display_active_addresses(
symbol=self.symbol.upper(),
interval=ns_parser.interval,
@@ -361,64 +358,61 @@ class DueDiligenceController(CryptoBaseController):
end_date=ns_parser.until.strftime("%Y-%m-%d"),
export=ns_parser.export,
)
else:
console.print("Glassnode source does not support this symbol\n")
else:
console.print(f"[red]{self.symbol} not supported on Glassnode.[/red]")
@log_start_end(log=logger)
def call_change(self, other_args: List[str]):
"""Process change command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="change",
description="""
Display active blockchain addresses over time
[Source: https://glassnode.org]
Note that free api keys only allow fetching data with a 1y lag
""",
)
if self.symbol.upper() in glassnode_model.GLASSNODE_SUPPORTED_ASSETS:
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="change",
description="""
Display active blockchain addresses over time
[Source: https://glassnode.org]
Note that free api keys only allow fetching data with a 1y lag
""",
)
parser.add_argument(
"-e",
"--exchange",
dest="exchange",
type=str,
help="Exchange to check change. Default: aggregated",
default="aggregated",
choices=glassnode_model.GLASSNODE_SUPPORTED_EXCHANGES,
)
parser.add_argument(
"-e",
"--exchange",
dest="exchange",
type=str,
help="Exchange to check change. Default: aggregated",
default="aggregated",
choices=glassnode_model.GLASSNODE_SUPPORTED_EXCHANGES,
)
parser.add_argument(
"-s",
"--since",
dest="since",
type=valid_date,
help="Initial date. Default: 2 years ago",
default=(datetime.now() - timedelta(days=365 * 2)).strftime("%Y-%m-%d"),
)
parser.add_argument(
"-s",
"--since",
dest="since",
type=valid_date,
help="Initial date. Default: 2 years ago",
default=(datetime.now() - timedelta(days=365 * 2)).strftime("%Y-%m-%d"),
)
parser.add_argument(
"-u",
"--until",
dest="until",
type=valid_date,
help="Final date. Default: 1 year ago",
default=(datetime.now() - timedelta(days=367)).strftime("%Y-%m-%d"),
)
parser.add_argument(
"-u",
"--until",
dest="until",
type=valid_date,
help="Final date. Default: 1 year ago",
default=(datetime.now() - timedelta(days=367)).strftime("%Y-%m-%d"),
)
if other_args:
if not other_args[0][0] == "-":
other_args.insert(0, "-e")
if other_args:
if not other_args[0][0] == "-":
other_args.insert(0, "-e")
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
if self.symbol.upper() in glassnode_model.GLASSNODE_SUPPORTED_ASSETS:
glassnode_view.display_exchange_net_position_change(
symbol=self.symbol.upper(),
exchange=ns_parser.exchange,
@@ -426,71 +420,70 @@ class DueDiligenceController(CryptoBaseController):
end_date=ns_parser.until.strftime("%Y-%m-%d"),
export=ns_parser.export,
)
else:
console.print("Glassnode source does not support this symbol\n")
else:
console.print(f"[red]{self.symbol} not supported on Glassnode.[/red]")
@log_start_end(log=logger)
def call_eb(self, other_args: List[str]):
"""Process eb command"""
if self.symbol.upper() in glassnode_model.GLASSNODE_SUPPORTED_ASSETS:
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="eb",
description="""
Display active blockchain addresses over time
[Source: https://glassnode.org]
Note that free api keys only allow fetching data with a 1y lag
""",
)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="eb",
description="""
Display active blockchain addresses over time
[Source: https://glassnode.org]
Note that free api keys only allow fetching data with a 1y lag
""",
)
parser.add_argument(
"-p",
"--pct",
dest="percentage",
action="store_true",
help="Show percentage instead of stacked value. Default: False",
default=False,
)
parser.add_argument(
"-p",
"--pct",
dest="percentage",
action="store_true",
help="Show percentage instead of stacked value. Default: False",
default=False,
)
parser.add_argument(
"-e",
"--exchange",
dest="exchange",
type=str,
help="Exchange to check change. Default: aggregated",
default="aggregated",
choices=glassnode_model.GLASSNODE_SUPPORTED_EXCHANGES,
)
parser.add_argument(
"-e",
"--exchange",
dest="exchange",
type=str,
help="Exchange to check change. Default: aggregated",
default="aggregated",
choices=glassnode_model.GLASSNODE_SUPPORTED_EXCHANGES,
)
parser.add_argument(
"-s",
"--since",
dest="since",
type=valid_date,
help="Initial date. Default: 2 years ago",
default=(datetime.now() - timedelta(days=365 * 2)).strftime("%Y-%m-%d"),
)
parser.add_argument(
"-s",
"--since",
dest="since",
type=valid_date,
help="Initial date. Default: 2 years ago",
default=(datetime.now() - timedelta(days=365 * 2)).strftime("%Y-%m-%d"),
)
parser.add_argument(
"-u",
"--until",
dest="until",
type=valid_date,
help="Final date. Default: 1 year ago",
default=(datetime.now() - timedelta(days=367)).strftime("%Y-%m-%d"),
)
parser.add_argument(
"-u",
"--until",
dest="until",
type=valid_date,
help="Final date. Default: 1 year ago",
default=(datetime.now() - timedelta(days=367)).strftime("%Y-%m-%d"),
)
if other_args and not other_args[0][0] == "-":
other_args.insert(0, "-e")
if other_args and not other_args[0][0] == "-":
other_args.insert(0, "-e")
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
if self.symbol.upper() in glassnode_model.GLASSNODE_SUPPORTED_ASSETS:
glassnode_view.display_exchange_balances(
symbol=self.symbol.upper(),
exchange=ns_parser.exchange,
@@ -499,9 +492,8 @@ class DueDiligenceController(CryptoBaseController):
percentage=ns_parser.percentage,
export=ns_parser.export,
)
else:
console.print("Glassnode source does not support this symbol\n")
else:
console.print(f"[red]{self.symbol} not supported on Glassnode.[/red]")
@log_start_end(log=logger)
def call_oi(self, other_args):

View File

@@ -31,7 +31,6 @@ from openbb_terminal.economy import (
yfinance_model,
yfinance_view,
investingcom_model,
investingcom_view,
plot_view,
commodity_view,
)
@@ -661,6 +660,7 @@ class EconomyController(BaseController):
"--query",
type=str,
action="store",
nargs="+",
dest="query",
help="Query the FRED database to obtain Series IDs given the query search term.",
)
@@ -675,9 +675,8 @@ class EconomyController(BaseController):
)
if ns_parser:
parameters = list_from_str(ns_parser.parameter.upper())
if ns_parser.query:
query = ns_parser.query.replace(",", " ")
query = " ".join(ns_parser.query)
df_search = fred_model.get_series_notes(search_query=query)
if not df_search.empty:
@@ -1005,16 +1004,6 @@ class EconomyController(BaseController):
description="Generate country yield curve. The yield curve shows the bond rates"
" at different maturities.",
)
parser.add_argument(
"-c",
"--country",
action="store",
dest="country",
default="united_states",
choices=investingcom_model.BOND_COUNTRIES,
help="Yield curve for a country. Ex: united_states",
)
parser.add_argument(
"-d",
"--date",
@@ -1030,105 +1019,15 @@ class EconomyController(BaseController):
raw=True,
)
if ns_parser:
country = ns_parser.country.lower().replace("_", " ")
if country == "united states":
fred_view.display_yield_curve(
date=ns_parser.date.strftime("%Y-%m-%d")
if ns_parser.date
else None,
raw=ns_parser.raw,
export=ns_parser.export,
)
else:
console.print("Source FRED is only available for united states.\n")
fred_view.display_yield_curve(
date=ns_parser.date.strftime("%Y-%m-%d") if ns_parser.date else "",
raw=ns_parser.raw,
export=ns_parser.export,
)
# TODO: Add `Investing` to sources again when `investpy` is fixed
@log_start_end(log=logger)
def call_spread(self, other_args: List[str]):
"""Process spread command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="spread",
description="Generate bond spread matrix.",
)
parser.add_argument(
"-g",
"--group",
action="store",
dest="group",
choices=investingcom_model.MATRIX_CHOICES,
default="G7",
help="Show bond spread matrix for group of countries.",
)
parser.add_argument(
"-c",
"--countries",
action="store",
dest="countries",
type=str,
help="Show bond spread matrix for explicit list of countries.",
)
parser.add_argument(
"-m",
"--maturity",
action="store",
dest="maturity",
type=str,
default="10Y",
help="Specify maturity to compare rates.",
)
parser.add_argument(
"--change",
action="store",
dest="change",
type=bool,
default=False,
help="Get matrix of 1 day change in rates or spreads.",
)
parser.add_argument(
"--color",
action="store",
dest="color",
type=str,
choices=investingcom_view.COLORS,
default="openbb",
help="Set color palette on heatmap.",
)
ns_parser = self.parse_known_args_and_warn(
parser,
other_args,
export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED,
raw=True,
)
if ns_parser:
if ns_parser.countries:
countries_string = ns_parser.countries.replace("_", " ")
countries_list = investingcom_model.countries_string_to_list(
countries_string
)
investingcom_view.display_spread_matrix(
countries=countries_list,
maturity=ns_parser.maturity.upper(),
change=ns_parser.change,
color=ns_parser.color,
raw=ns_parser.raw,
export=ns_parser.export,
)
elif ns_parser.group:
investingcom_view.display_spread_matrix(
countries=ns_parser.group,
maturity=ns_parser.maturity.upper(),
change=ns_parser.change,
color=ns_parser.color,
raw=ns_parser.raw,
export=ns_parser.export,
)
@log_start_end(log=logger)
def call_events(self, other_args: List[str]):
"""Process events command"""

View File

@@ -256,14 +256,16 @@ def get_aggregated_series_data(
@log_start_end(log=logger)
@check_api_key(["API_FRED_KEY"])
def get_yield_curve(
date: str = None,
date: str = "", return_date: bool = False
) -> Tuple[pd.DataFrame, str]:
"""Gets yield curve data from FRED
Parameters
----------
date: str
Date to get curve for. If None, gets most recent date (format yyyy-mm-dd)
Date to get curve for. If empty, gets most recent date (format yyyy-mm-dd)
return_date: bool
If True, returns date of yield curve
Returns
-------
@@ -275,6 +277,9 @@ def get_yield_curve(
--------
>>> from openbb_terminal.sdk import openbb
>>> ycrv_df = openbb.economy.ycrv()
Since there is a delay with the data, the most recent date is returned and can be accessed with return_date=True
>>> ycrv_df, ycrv_date = openbb.economy.ycrv(return_date=True)
"""
# Necessary for installer so that it can locate the correct certificates for
@@ -298,9 +303,20 @@ def get_yield_curve(
"30Year": "DGS30",
}
df = pd.DataFrame()
# Check that the date is in the past
today = datetime.now().strftime("%Y-%m-%d")
if date and date >= today:
console.print("[red]Date cannot be today or in the future[/red]")
if return_date:
return pd.DataFrame(), date
return pd.DataFrame()
if date is None:
# Add in logic that will get the most recent date.
get_last = False
if not date:
date = (datetime.now() - timedelta(days=7)).strftime("%Y-%m-%d")
get_last = True
for key, s_id in fred_series.items():
df = pd.concat(
@@ -310,10 +326,18 @@ def get_yield_curve(
],
axis=1,
)
if df.empty:
if return_date:
return pd.DataFrame(), date
return pd.DataFrame()
# Drop rows with NaN -- corresponding to weekends typically
df = df.dropna()
if date is None:
date_of_yield = df.index[-1]
rates = pd.DataFrame(df.iloc[-1, :].values, columns=["Rate"])
if date not in df.index or get_last:
# If the get_last flag is true, we want the first date, otherwise we want the last date.
idx = -1 if get_last else 0
date_of_yield = df.index[idx].strftime("%Y-%m-%d")
rates = pd.DataFrame(df.iloc[idx, :].values, columns=["Rate"])
else:
date_of_yield = date
series = df[df.index == date]
@@ -326,5 +350,6 @@ def get_yield_curve(
"Maturity",
[1 / 12, 0.25, 0.5, 1, 2, 3, 5, 7, 10, 20, 30],
)
return rates, date_of_yield
if return_date:
return rates, date_of_yield
return rates

View File

@@ -185,7 +185,7 @@ def format_data_to_plot(data: pd.DataFrame, detail: dict) -> Tuple[pd.DataFrame,
@log_start_end(log=logger)
@check_api_key(["API_FRED_KEY"])
def display_yield_curve(
date: str = None,
date: str = "",
external_axes: Optional[List[plt.Axes]] = None,
raw: bool = False,
export: str = "",
@@ -203,7 +203,7 @@ def display_yield_curve(
export : str
Export data to csv,json,xlsx or png,jpg,pdf,svg file
"""
rates, date_of_yield = fred_model.get_yield_curve(date)
rates, date_of_yield = fred_model.get_yield_curve(date, True)
if rates.empty:
console.print(f"[red]Yield data not found for {date_of_yield}.[/red]\n")
return

View File

@@ -637,7 +637,8 @@ class BehaviouralAnalysisController(StockBaseController):
"--words",
help="Select multiple sentences/words separated by commas. E.g. COVID,WW3,NFT",
dest="words",
type=lambda s: [str(item) for item in s.split(",")],
nargs="+",
type=str,
default=None,
)
if other_args and "-" not in other_args[0][0]:
@@ -648,6 +649,7 @@ class BehaviouralAnalysisController(StockBaseController):
if ns_parser:
if self.ticker:
if ns_parser.words:
words = " ".join(ns_parser.words).split(",")
df_stock = yf.download(
self.ticker,
start=ns_parser.start.strftime("%Y-%m-%d"),
@@ -658,7 +660,7 @@ class BehaviouralAnalysisController(StockBaseController):
google_view.display_correlation_interest(
symbol=self.ticker,
data=df_stock,
words=ns_parser.words,
words=words,
export=ns_parser.export,
)
else:

View File

@@ -572,37 +572,6 @@ def test_call_func_expect_queue(expected_queue, func, queue):
# [],
# dict(country="portugal", export="csv", raw=False),
# ),
(
"call_spread",
[
"--countries=United states, United Kingdom, France",
"--export=csv",
],
"investingcom_view.display_spread_matrix",
[],
dict(
countries=["united states", "united kingdom", "france"],
maturity="10Y",
change=False,
color="openbb",
raw=False,
export="csv",
),
),
(
"call_spread",
["--group=EZ", "--color=binary", "--maturity=5Y", "--change=True"],
"investingcom_view.display_spread_matrix",
[],
dict(
countries="EZ",
maturity="5Y",
change=True,
color="binary",
raw=False,
export="",
),
),
(
"call_events",
[