From 4e9b9ab8677740887a3c4291430e968c433a05bb Mon Sep 17 00:00:00 2001 From: Jeroen Bouma Date: Thu, 10 Mar 2022 13:59:11 +0100 Subject: [PATCH] Add Treasury rates for the United States --- gamestonk_terminal/economy/econdb_model.py | 101 +++++++++++++++++- gamestonk_terminal/economy/econdb_view.py | 75 ++++++++++++- .../economy/economy_controller.py | 98 +++++++++++++++-- 3 files changed, 262 insertions(+), 12 deletions(-) diff --git a/gamestonk_terminal/economy/econdb_model.py b/gamestonk_terminal/economy/econdb_model.py index c9c6db736d3..e63bfc7ee5d 100644 --- a/gamestonk_terminal/economy/econdb_model.py +++ b/gamestonk_terminal/economy/econdb_model.py @@ -2,9 +2,11 @@ __docformat__ = "numpy" import logging +from typing import Dict, Any from urllib.error import HTTPError import pandas as pd +import pandas_datareader.data as web import yfinance as yf from gamestonk_terminal.decorators import log_start_end @@ -225,9 +227,35 @@ PARAMETERS = { "POP": "Population", } +TREASURIES = { + "nominal": { + "1m": "1-month", + "3m": "3-month", + "6m": "6-month", + "1y": "1-year", + "2y": "2-year", + "3y": "3-year", + "5y": "5-year", + "7y": "7-year", + "10y": "10-year", + "20y": "20-year", + "30y": "30-year", + }, + "inflation": { + "5y": "5-year", + "7y": "7-year", + "10y": "10-year", + "20y": "20-year", + "30y": "30-year", + }, + "secondary": {"4w": "4-week", "3m": "3-month", "6m": "6-month", "1y": "1-year"}, +} + @log_start_end(log=logger) -def get_data(parameter: str, country: str, convert_currency: str = "USD") -> pd.Series: +def get_macro_data( + parameter: str, country: str, convert_currency: str = "USD" +) -> pd.Series: """Query the EconDB database to find specific macro data about a company [Source: EconDB] Parameters @@ -280,3 +308,74 @@ def get_data(parameter: str, country: str, convert_currency: str = "USD") -> pd. ) return df + + +@log_start_end(log=logger) +def get_treasuries( + types: list, maturities: list, start_date: str = None, end_date: str = None +) -> Dict[Any, Dict[Any, pd.Series]]: + """Obtain U.S. Treasury Rates [Source: EconDB] + + Parameters + ---------- + types: list + The type(s) of treasuries, nominal, inflation-adjusted or secondary market. + maturities : list + the maturities you wish to view. + start_date : str + The starting date, format "YEAR-MONTH-DAY", i.e. 2010-12-31. + end_date : str + The end date, format "YEAR-MONTH-DAY", i.e. 2020-06-05. + + Returns + ---------- + treasury_data: dict + Holds data of the selected types and maturities + """ + treasury_data: Dict[Any, Dict[Any, pd.Series]] = {} + + df = web.DataReader( + "&".join( + [ + "dataset=FRB_H15", + "v=Instrument", + "h=TIME", + f"from={start_date}", + f"to={end_date}", + "UNIT=[PERCENT:_PER_YEAR]", + ] + ), + "econdb", + ) + + for treasury in types: + if treasury not in TREASURIES: + console.print( + f"{treasury} is not an option. Please choose between: {', '.join(TREASURIES.keys())}" + ) + else: + type_string = treasury.capitalize() + treasury_data[type_string] = {} + for maturity in maturities: + if maturity not in TREASURIES[treasury]: + console.print( + f"The maturity {maturity} is not an option for {treasury}. " + f"Please choose between {', '.join(TREASURIES[treasury].keys())}" + ) + else: + maturity_string = TREASURIES[treasury][maturity] + + for column in df.columns: + # check if type inside the name and maturity inside the maturity string + if type_string in column[2] and maturity_string in column[3]: + treasury_data[type_string][maturity_string] = df[ + column + ].dropna() + break + + if maturity_string not in treasury_data[type_string]: + console.print( + f"No data found for the combination {treasury} and {maturity}." + ) + + return treasury_data diff --git a/gamestonk_terminal/economy/econdb_view.py b/gamestonk_terminal/economy/econdb_view.py index e65d7604e23..2a30f4975b2 100644 --- a/gamestonk_terminal/economy/econdb_view.py +++ b/gamestonk_terminal/economy/econdb_view.py @@ -10,14 +10,14 @@ from matplotlib import pyplot as plt from gamestonk_terminal.config_plot import PLOT_DPI from gamestonk_terminal.config_terminal import theme from gamestonk_terminal.decorators import log_start_end -from gamestonk_terminal.economy.econdb_model import get_data, PARAMETERS +from gamestonk_terminal.economy import econdb_model from gamestonk_terminal.helper_funcs import plot_autoscale, print_rich_table logger = logging.getLogger(__name__) @log_start_end(log=logger) -def show_data( +def show_macro_data( parameters: list, countries: list, start_date: int = None, @@ -62,7 +62,7 @@ def show_data( for country in countries: country_data[country] = {} for parameter in parameters: - country_data[country][parameter] = get_data( + country_data[country][parameter] = econdb_model.get_macro_data( parameter, country, convert_currency ) @@ -91,7 +91,7 @@ def show_data( for column in df_rounded.columns: country_label = column[0].replace("_", " ") - parameter_label = PARAMETERS[column[1]] + parameter_label = econdb_model.PARAMETERS[column[1]] if len(parameters) > 1 and len(countries) > 1: ax.plot(df_rounded[column], label=f"{country_label} [{parameter_label}]") ax.set_title(f"Macro data {denomination}") @@ -123,3 +123,70 @@ def show_data( if external_axes is None: theme.visualize_output() + + +@log_start_end(log=logger) +def show_treasuries( + types: list, + maturities: list, + start_date: str = None, + end_date: str = None, + raw: bool = False, + external_axes: Optional[List[plt.axes]] = None, + export: str = "", +): + """Obtain U.S. Treasury Rates [Source: EconDB] + + Parameters + ---------- + types: list + The type(s) of treasuries, nominal, inflation-adjusted or secondary market. + maturities : list + the maturities you wish to view. + start_date : str + The starting date, format "YEAR-MONTH-DAY", i.e. 2010-12-31. + end_date : str + The end date, format "YEAR-MONTH-DAY", i.e. 2020-06-05. + raw : bool + Whether to display the raw output. + external_axes: Optional[List[plt.axes]] + External axes to plot on + export : str + Export data to csv,json,xlsx or png,jpg,pdf,svg file + + Returns + ---------- + Plots the Treasury Series. + """ + if external_axes is None: + _, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) + else: + ax = external_axes[0] + + treasury_data = econdb_model.get_treasuries(types, maturities, start_date, end_date) + + for treasury, maturities_data in treasury_data.items(): + for maturity in maturities_data: + ax.plot(maturities_data[maturity], label=f"{treasury} ({maturity}]") + + ax.set_title("U.S. Treasuries") + ax.legend() + + if raw: + df = pd.DataFrame.from_dict(treasury_data, orient="index").stack().to_frame() + df = pd.DataFrame(df[0].values.tolist(), index=df.index).T + + print_rich_table( + df.iloc[-10:], + headers=list(df.columns), + show_index=True, + title="U.S. Treasuries", + ) + + if export: + print("Doing nothing!") + + theme.style_primary_axis(ax) + + if external_axes is None: + theme.visualize_output() diff --git a/gamestonk_terminal/economy/economy_controller.py b/gamestonk_terminal/economy/economy_controller.py index cb621f45ddc..d3f05c4a25b 100644 --- a/gamestonk_terminal/economy/economy_controller.py +++ b/gamestonk_terminal/economy/economy_controller.py @@ -5,7 +5,9 @@ __docformat__ = "numpy" import argparse import logging import os +from datetime import date from typing import List, Dict + import pandas as pd from prompt_toolkit.completion import NestedCompleter @@ -25,7 +27,6 @@ from gamestonk_terminal.economy import ( yfinance_model, yfinance_view, ) - from gamestonk_terminal.helper_funcs import ( EXPORT_BOTH_RAW_DATA_AND_FIGURES, EXPORT_ONLY_FIGURES_ALLOWED, @@ -50,7 +51,8 @@ class EconomyController(BaseController): "futures", "macro", "fred", - "indices", + "index", + "treasury", "valuation", "performance", "spectrum", @@ -196,7 +198,8 @@ Overview Macro Data macro collect macro data for a country or countries [src][Source: EconDB][/src] fred collect macro data from FRED based on a series ID [src][Source: FRED][/src] - indices show the most important indices worldwide [src][Source: Yahoo Finance][/src] + index find and plot any (major) index on the market [src][Source: Yahoo Finance][/src] + treasury obtain U.S. treasury rates [src][Source: EconDB][/src] Performance & Valuations rtps real-time performance sectors [src][Source: Alpha Vantage][/src] @@ -206,7 +209,7 @@ Performance & Valuations Index feargreed CNN Fear and Greed Index [src][Source: CNN][/src] - bigmac the economists Big Mac index [src][Source: NASDAQ Datalink][/src][/cmds] + bigmac The Economist Big Mac index [src][Source: NASDAQ Datalink][/src][/cmds] [menu] > pred Open the prediction menu to analyse FRED series[/menu] """ @@ -449,7 +452,7 @@ Index headers=["Country", "Currency"], ) elif ns_parser.parameters and ns_parser.countries: - econdb_view.show_data( + econdb_view.show_macro_data( parameters=ns_parser.parameters, countries=ns_parser.countries, start_date=ns_parser.start_date, @@ -465,7 +468,7 @@ Index add_help=False, formatter_class=argparse.ArgumentDefaultsHelpFormatter, prog="fred", - description="Print series notes when searching for series. [Source: FRED]", + description="Query the FRED database and plot data based on the Series ID. [Source: FRED]", ) parser.add_argument( @@ -490,7 +493,7 @@ Index action="store", dest="query", type=str, - help="Query for this series search term.", + help="Query the FRED database to obtain Series IDs given the query seaarch term.", ) parser.add_argument( @@ -675,6 +678,87 @@ Index export=ns_parser.export, ) + @log_start_end(log=logger) + def call_treasury(self, other_args: List[str]): + """Process treasury command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="treasury", + description="Obtain any set of U.S. treasuries and plot them together. These can be a range of maturities " + "for nominal, inflation-adjusted and secondary markets over a lengthy period. " + "[Source: EconDB / FED]", + ) + + parser.add_argument( + "-m", + "--maturity", + nargs="+", + type=str, + dest="maturity", + help="The preferred maturity which is dependent on the type of the treasury", + default="1y", + ) + + parser.add_argument( + "-t", + "--type", + nargs="+", + dest="type", + choices=econdb_model.TREASURIES, + help="Whether to select nominal, inflation indexed or secondary market treasury bills", + default="nominal", + ) + + parser.add_argument( + "-s", + "--start_date", + dest="start_date", + help="The start date of the data (format: YEAR-MONTH-DAY, i.e. 2010-12-31)", + default="2000-01-01", + ) + + parser.add_argument( + "-e", + "--end_date", + dest="end_date", + help="The end date of the data (format: YEAR-MONTH-DAY, i.e. 2021-06-20)", + default=date.today(), + ) + + parser.add_argument( + "-l", + "--limit", + type=str, + dest="limit", + help="Takes into account the amount of rows you wish to see for your query ('-q').", + default=10, + ) + + parser.add_argument( + "-r", + "--raw", + dest="raw", + help="Show raw data", + action="store_true", + default=False, + ) + + if other_args and "-" not in other_args[0][0]: + other_args.insert(0, "-m") + ns_parser = parse_known_args_and_warn( + parser, other_args, export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED + ) + + if ns_parser and ns_parser.maturity and ns_parser.type: + econdb_view.show_treasuries( + types=ns_parser.type, + maturities=ns_parser.maturity, + start_date=ns_parser.start_date, + end_date=ns_parser.end_date, + raw=ns_parser.raw, + ) + @log_start_end(log=logger) def call_map(self, other_args: List[str]): """Process map command"""