Add fixed income menu

This commit is contained in:
northern-64bit
2023-01-22 09:55:09 +01:00
parent de011bd7ae
commit 0efd3355c6
10 changed files with 2198 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
""" ECB model """
__docformat__ = "numpy"
import logging
import pandas as pd
from openbb_terminal.decorators import log_start_end
logger = logging.getLogger(__name__)
@log_start_end(log=logger)
def get_series_data(
series_id: str = "EST.B.EU000A2X2A25.WT", start_date: str = "", end_date: str = ""
):
"""Get ECB data
Parameters
----------
series_id: str
ECB ID of data
start_date: Optional[str]
Start date, formatted YYYY-MM-DD
end_date: Optional[str]
End date, formatted YYYY-MM-DD
"""
start_date = start_date[0:4] + start_date[4:7] + start_date[8:9]
end_date = end_date[0:4] + end_date[4:7] + end_date[8:9]
df = pd.read_csv(
f"https://sdw.ecb.europa.eu/quickviewexport.do?trans=N&start={start_date}&end={end_date}&SERIES_KEY={series_id}&type=csv",
header=5,
usecols=[0, 1],
index_col=0,
parse_dates=True,
)
df = df.iloc[::-1]
return df

View File

@@ -0,0 +1,90 @@
""" ECB view """
__docformat__ = "numpy"
from typing import Optional, List
from itertools import cycle
import logging
import os
from matplotlib import pyplot as plt
from openbb_terminal.config_terminal import theme
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
export_data,
plot_autoscale,
is_valid_axes_count,
)
from openbb_terminal.fixedincome.ecb_model import get_series_data
logger = logging.getLogger(__name__)
ID_TO_NAME = {
"EST.B.EU000A2X2A25.WT": "Euro Short-Term Rate: Volume-Weighted Trimmed Mean Rate [Percent]",
"EST.B.EU000A2X2A25.TT": "Euro Short-Term Rate: Total Volume [Millions of EUR]",
"EST.B.EU000A2X2A25.NT": "Euro Short-Term Rate: Number of Transactions",
"EST.B.EU000A2X2A25.R75": "Euro Short-Term Rate: Rate at 75th Percentile of Volume [Percent]",
"EST.B.EU000A2X2A25.NB": "Euro Short-Term Rate: Number of Active Banks",
"EST.B.EU000A2X2A25.VL": "Euro Short-Term Rate: Share of Volume of the 5 Largest Active Banks [Percent]",
"EST.B.EU000A2X2A25.R25": "Euro Short-Term Rate: Rate at 25th Percentile of Volume [Percent]",
}
@log_start_end(log=logger)
def plot_estr(
series_id: str = "EST.B.EU000A2X2A25.WT",
start_date: Optional[str] = None,
end_date: Optional[str] = None,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plot Euro Short-Term Rate (ESTR)
Parameters
----------
series_id: str
ECB ID of ESTR data to plot, options: ['EST.B.EU000A2X2A25.WT', 'EST.B.EU000A2X2A25.TT', 'EST.B.EU000A2X2A25.NT', 'EST.B.EU000A2X2A25.R75', 'EST.B.EU000A2X2A25.NB', 'EST.B.EU000A2X2A25.VL', 'EST.B.EU000A2X2A25.R25']
start_date: Optional[str]
Start date, formatted YYYY-MM-DD
end_date: Optional[str]
End date, formatted YYYY-MM-DD
export: str
Export data to csv or excel file
external_axes: Optional[List[plt.Axes]]
External axes (1 axis is expected in the list)
"""
df = get_series_data(
series_id, start_date if start_date else "", end_date if end_date else ""
)
# This plot has 1 axis
if not external_axes:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
elif is_valid_axes_count(external_axes, 1):
(ax,) = external_axes
else:
return
colors = cycle(theme.get_colors())
ax.plot(
df.index,
df.values,
marker="o",
linestyle="dashed",
linewidth=2,
markersize=4,
color=next(colors, "#FCED00"),
)
ax.set_title(ID_TO_NAME[series_id])
theme.style_primary_axis(ax)
if external_axes is None:
theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
f"estr, {series_id}",
df,
)

View File

@@ -0,0 +1,703 @@
""" Futures Controller """
__docformat__ = "numpy"
# pylint:disable=too-many-lines
import argparse
import logging
from datetime import datetime, timedelta
from typing import List
from openbb_terminal.custom_prompt_toolkit import NestedCompleter
from openbb_terminal import feature_flags as obbff
from openbb_terminal.decorators import log_start_end
from openbb_terminal.fixedincome import ecb_view, nyfed_view
from openbb_terminal.fixedincome import fred_view
from openbb_terminal.helper_funcs import (
EXPORT_BOTH_RAW_DATA_AND_FIGURES,
valid_date,
)
from openbb_terminal.parent_classes import BaseController
from openbb_terminal.rich_config import console, MenuText
from openbb_terminal.menu import session
logger = logging.getLogger(__name__)
class FixedIncomeController(BaseController):
"""Fixed Income Controller class"""
CHOICES_COMMANDS = [
"estr",
"sofr",
"sonia",
"ameribor",
"ffer",
"fftr",
"effr",
"obfr",
"iorb",
"projection",
"oldprojection",
"dwpcr",
]
PATH = "/fixedincome/"
CHOICES_GENERATION = True
estr_parameter_to_fred_id = {
"volume_weighted_trimmed_mean_rate": "ECBESTRVOLWGTTRMDMNRT",
"total_volume": "ECBESTRTOTVOL",
"number_of_transactions": "ECBESTRNUMTRANS",
"rate_at_75th_percentile_of_volume": "ECBESTRRT75THPCTVOL",
"number_of_active_banks": "ECBESTRNUMACTBANKS",
"share_of_volume_of_the_5_largest_active_banks": "ECBESTRSHRVOL5LRGACTBNK",
"rate_at_25th_percentile_of_volume": "ECBESTRRT25THPCTVOL",
}
estr_parameter_to_ecb_id = {
"volume_weighted_trimmed_mean_rate": "EST.B.EU000A2X2A25.WT",
"total_volume": "EST.B.EU000A2X2A25.TT",
"number_of_transactions": "EST.B.EU000A2X2A25.NT",
"rate_at_75th_percentile_of_volume": "EST.B.EU000A2X2A25.R75",
"number_of_active_banks": "EST.B.EU000A2X2A25.NB",
"share_of_volume_of_the_5_largest_active_banks": "EST.B.EU000A2X2A25.VL",
"rate_at_25th_percentile_of_volume": "EST.B.EU000A2X2A25.R25",
}
sofr_parameter_to_fred_id = {
"overnight": "SOFR",
"30_day": "SOFR30DAYAVG",
"90_day": "SOFR90DAYAVG",
"180_day": "SOFR180DAYAVG",
"index": "SOFRINDEX",
}
sonia_parameter_to_fred_id = {
"rate": "IUDSOIA",
"index": "IUDZOS2",
"10th_percentile": "IUDZLS6",
"25th_percentile": "IUDZLS7",
"75th_percentile": "IUDZLS8",
"90th_percentile": "IUDZLS9",
"total_nominal_value": "IUDZLT2",
}
ameribor_parameter_to_fred_id = {
"overnight": "AMERIBOR",
"term_30": "AMBOR30T",
"term_90": "AMBOR90T",
"1_week_term_structure": "AMBOR1W",
"1_month_term_structure": "AMBOR1M",
"3_month_term_structure": "AMBOR3M",
"6_month_term_structure": "AMBOR6M",
"1_year_term_structure": "AMBOR1Y",
"2_year_term_structure": "AMBOR2Y",
"30_day_ma": "AMBOR30",
"90_day_ma": "AMBOR90",
}
ffer_parameter_to_fred_id = {
"monthly": "FEDFUNDS",
"daily": "DFF",
"weekly": "FF",
"daily_excl_weekend": "RIFSPFFNB",
"annual": "RIFSPFFNA",
"biweekly": "RIFSPFFNBWAW",
}
effr_parameter_to_fred_id = {
"rate": "EFFR",
"volume": "EFFRVOL",
"1th_percentile": "EFFR1",
"25th_percentile": "EFFR25",
"75th_percentile": "EFFR75",
"99th_percentile": "EFFR99",
}
effr_parameter_to_nyfed_id = {
"rate": "percentRate",
"volume": "volumeInBillions",
"1th_percentile": "percentPercentile1",
"25th_percentile": "percentPercentile25",
"75th_percentile": "percentPercentile75",
"99th_percentile": "percentPercentile99",
}
obfr_parameter_to_fred_id = {
"rate": "OBFR",
"volume": "OBFRVOL",
"1th_percentile": "EFFR1",
"25th_percentile": "EFFR25",
"75th_percentile": "EFFR75",
"99th_percentile": "EFFR99",
}
dwpcr_parameter_to_fred_id = {
"daily_excl_weekend": "DPCREDIT",
"monthly": "MPCREDIT",
"weekly": "WPCREDIT",
"daily": "RIFSRPF02ND",
"annual": "RIFSRPF02NA",
}
def __init__(self, queue: List[str] = None):
"""Constructor"""
super().__init__(queue)
if session and obbff.USE_PROMPT_TOOLKIT:
self.choices: dict = self.choices_default
self.completer = NestedCompleter.from_nested_dict(self.choices) # type: ignore
def print_help(self):
"""Print help"""
mt = MenuText("fixedincome/")
mt.add_info("_reference_rates_")
mt.add_cmd("estr")
mt.add_cmd("sofr")
mt.add_cmd("sonia")
mt.add_cmd("ameribor")
mt.add_raw("\n")
mt.add_info("_other_interest_rates_")
mt.add_cmd("ffer")
mt.add_cmd("fftr")
mt.add_cmd("effr")
mt.add_cmd("obfr")
mt.add_cmd("iorb")
mt.add_cmd("projection")
mt.add_cmd("oldprojection")
mt.add_cmd("dwpcr")
console.print(text=mt.menu_text, menu="Fixed Income")
@log_start_end(log=logger)
def call_estr(self, other_args: List[str]):
"""Process estr command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="estr",
description="Get Euro Short-Term Rate data",
)
parser.add_argument(
"-p",
"--parameter",
dest="parameter",
type=str,
help="Specific Euro Short-Term Rate data to retrieve",
default="volume_weighted_trimmed_mean_rate",
choices=list(self.estr_parameter_to_fred_id.keys()),
)
parser.add_argument(
"-s",
"--start",
dest="start_date",
type=valid_date,
help="Starting date (YYYY-MM-DD) of data",
default=None,
)
parser.add_argument(
"-e",
"--end",
dest="end_date",
type=valid_date,
help="Ending date (YYYY-MM-DD) of data",
default=None,
)
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
if ns_parser.source == "FRED":
fred_view.plot_estr(
self.estr_parameter_to_fred_id[ns_parser.parameter],
ns_parser.start_date,
ns_parser.end_date,
ns_parser.export,
)
elif ns_parser.source == "ECB":
ecb_view.plot_estr(
self.estr_parameter_to_ecb_id[ns_parser.parameter],
ns_parser.start_date,
ns_parser.end_date,
ns_parser.export,
)
@log_start_end(log=logger)
def call_sofr(self, other_args: List[str]):
"""Process sofr command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="sofr",
description="Get Secured Overnight Financing Rate (SOFR) data",
)
parser.add_argument(
"-p",
"--parameter",
dest="parameter",
type=str,
help="Specific SOFR data to retrieve",
default="overnight",
choices=list(self.sofr_parameter_to_fred_id.keys()),
)
parser.add_argument(
"-s",
"--start",
dest="start_date",
type=valid_date,
help="Starting date (YYYY-MM-DD) of data",
default="1980-01-01",
)
parser.add_argument(
"-e",
"--end",
dest="end_date",
type=valid_date,
help="Ending date (YYYY-MM-DD) of data",
default=None,
)
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
if ns_parser.source == "FRED":
fred_view.plot_sofr(
self.sofr_parameter_to_fred_id[ns_parser.parameter],
ns_parser.start_date,
ns_parser.end_date,
ns_parser.export,
)
elif ns_parser.source == "NYFED":
nyfed_view.plot_sofr(
ns_parser.parameter,
ns_parser.start_date,
ns_parser.end_date,
ns_parser.export,
)
@log_start_end(log=logger)
def call_sonia(self, other_args: List[str]):
"""Process sonia command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="sonia",
description="Get Sterling Overnight Index Average (SONIA) data",
)
parser.add_argument(
"-p",
"--parameter",
dest="parameter",
type=str,
help="Specific SONIA data to retrieve",
default="rate",
choices=list(self.sonia_parameter_to_fred_id.keys()),
)
parser.add_argument(
"-s",
"--start",
dest="start_date",
type=valid_date,
help="Starting date (YYYY-MM-DD) of data",
default=None,
)
parser.add_argument(
"-e",
"--end",
dest="end_date",
type=valid_date,
help="Ending date (YYYY-MM-DD) of data",
default=None,
)
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
fred_view.plot_sonia(
self.sonia_parameter_to_fred_id[ns_parser.parameter],
ns_parser.start_date,
ns_parser.end_date,
ns_parser.export,
)
@log_start_end(log=logger)
def call_ameribor(self, other_args: List[str]):
"""Process ameribor command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="ameribor",
description="Get American Interbank Offered Rate (AMERIBOR) data",
)
parser.add_argument(
"-p",
"--parameter",
dest="parameter",
type=str,
help="Specific AMERIBOR data to retrieve",
default="overnight",
choices=list(self.ameribor_parameter_to_fred_id.keys()),
)
parser.add_argument(
"-s",
"--start",
dest="start_date",
type=valid_date,
help="Starting date (YYYY-MM-DD) of data",
default=None,
)
parser.add_argument(
"-e",
"--end",
dest="end_date",
type=valid_date,
help="Ending date (YYYY-MM-DD) of data",
default=None,
)
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
fred_view.plot_ameribor(
self.ameribor_parameter_to_fred_id[ns_parser.parameter],
ns_parser.start_date,
ns_parser.end_date,
ns_parser.export,
)
@log_start_end(log=logger)
def call_ffer(self, other_args: List[str]):
"""Process ffer command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="ffer",
description="Get Federal Funds Effective Rate data",
)
parser.add_argument(
"-p",
"--parameter",
dest="parameter",
type=str,
help="Specific Federal Funds Effective Rate data to retrieve",
default="monthly",
choices=list(self.ffer_parameter_to_fred_id.keys()),
)
parser.add_argument(
"-s",
"--start",
dest="start_date",
type=valid_date,
help="Starting date (YYYY-MM-DD) of data",
default=None,
)
parser.add_argument(
"-e",
"--end",
dest="end_date",
type=valid_date,
help="Ending date (YYYY-MM-DD) of data",
default=None,
)
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
fred_view.plot_ffer(
self.ffer_parameter_to_fred_id[ns_parser.parameter],
ns_parser.start_date,
ns_parser.end_date,
ns_parser.export,
)
@log_start_end(log=logger)
def call_fftr(self, other_args: List[str]):
"""Process fftr command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="fftr",
description="Get Federal Funds Target Range data",
)
parser.add_argument(
"-s",
"--start",
dest="start_date",
type=valid_date,
help="Starting date (YYYY-MM-DD) of data",
default="1980-01-01",
)
parser.add_argument(
"-e",
"--end",
dest="end_date",
type=valid_date,
help="Ending date (YYYY-MM-DD) of data",
default=None,
)
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
if ns_parser.source == "FRED":
fred_view.plot_fftr(
ns_parser.start_date,
ns_parser.end_date,
ns_parser.export,
)
elif ns_parser.source == "NYFED":
nyfed_view.plot_fftr(
ns_parser.start_date,
ns_parser.end_date,
ns_parser.export,
)
@log_start_end(log=logger)
def call_effr(self, other_args: List[str]):
"""Process effr command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="effr",
description="Get Effective Federal Funds Rate data",
)
parser.add_argument(
"-p",
"--parameter",
dest="parameter",
type=str,
help="Specific Effective Federal Funds Rate data to retrieve",
default="rate",
choices=list(self.effr_parameter_to_fred_id.keys()),
)
parser.add_argument(
"-s",
"--start",
dest="start_date",
type=valid_date,
help="Starting date (YYYY-MM-DD) of data",
default="1980-01-01",
)
parser.add_argument(
"-e",
"--end",
dest="end_date",
type=valid_date,
help="Ending date (YYYY-MM-DD) of data",
default=None,
)
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
if ns_parser.source == "FRED":
fred_view.plot_effr(
self.effr_parameter_to_fred_id[ns_parser.parameter],
ns_parser.start_date,
ns_parser.end_date,
ns_parser.export,
)
elif ns_parser.source == "NYFED":
nyfed_view.plot_effr(
self.effr_parameter_to_nyfed_id[ns_parser.parameter],
ns_parser.start_date,
ns_parser.end_date,
ns_parser.export,
)
@log_start_end(log=logger)
def call_obfr(self, other_args: List[str]):
"""Process obfr command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="obfr",
description="Get Overnight Bank Funding Rate data",
)
parser.add_argument(
"-p",
"--parameter",
dest="parameter",
type=str,
help="Specific Overnight Bank Funding Rate data to retrieve",
default="rate",
choices=list(self.obfr_parameter_to_fred_id.keys()),
)
parser.add_argument(
"-s",
"--start",
dest="start_date",
type=valid_date,
help="Starting date (YYYY-MM-DD) of data",
default="1980-01-01",
)
parser.add_argument(
"-e",
"--end",
dest="end_date",
type=valid_date,
help="Ending date (YYYY-MM-DD) of data",
default=None,
)
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
if ns_parser.source == "FRED":
fred_view.plot_obfr(
self.obfr_parameter_to_fred_id[ns_parser.parameter],
ns_parser.start_date,
ns_parser.end_date,
ns_parser.export,
)
elif ns_parser.source == "NYFED":
nyfed_view.plot_obfr(
self.effr_parameter_to_nyfed_id[ns_parser.parameter],
ns_parser.start_date,
ns_parser.end_date,
ns_parser.export,
)
@log_start_end(log=logger)
def call_iorb(self, other_args: List[str]):
"""Process iorb command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="iorb",
description="Get Interest Rate on Reserve Balances data",
)
parser.add_argument(
"-s",
"--start",
dest="start_date",
type=valid_date,
help="Starting date (YYYY-MM-DD) of data",
default=None,
)
parser.add_argument(
"-e",
"--end",
dest="end_date",
type=valid_date,
help="Ending date (YYYY-MM-DD) of data",
default=None,
)
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
fred_view.plot_iorb(
ns_parser.start_date,
ns_parser.end_date,
ns_parser.export,
)
@log_start_end(log=logger)
def call_projection(self, other_args: List[str]):
"""Process projection command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="projection",
description="Get FOMC Summary of Economic Projections for the Fed Funds Rate",
)
parser.add_argument(
"-s",
"--start",
dest="start_date",
type=valid_date,
help="Starting date (YYYY-MM-DD) of data",
default=None,
)
parser.add_argument(
"-e",
"--end",
dest="end_date",
type=valid_date,
help="Ending date (YYYY-MM-DD) of data",
default=None,
)
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
fred_view.plot_projection(
ns_parser.start_date,
ns_parser.end_date,
ns_parser.export,
)
@log_start_end(log=logger)
def call_oldprojection(self, other_args: List[str]):
"""Process oldprojection command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="oldprojection",
description="Get Longer Run FOMC Summary of Economic Projections for the Fed Funds Rate",
)
parser.add_argument(
"-s",
"--start",
dest="start_date",
type=valid_date,
help="Starting date (YYYY-MM-DD) of data",
default=None,
)
parser.add_argument(
"-e",
"--end",
dest="end_date",
type=valid_date,
help="Ending date (YYYY-MM-DD) of data",
default=None,
)
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
fred_view.plot_oldprojection(
ns_parser.start_date,
ns_parser.end_date,
ns_parser.export,
)
@log_start_end(log=logger)
def call_dwpcr(self, other_args: List[str]):
"""Process dwpcr command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="dwpcr",
description="Get Discount Window Primary Credit Rate data",
)
parser.add_argument(
"-p",
"--parameter",
dest="parameter",
type=str,
help="Specific Discount Window Primary Credit Rate data to retrieve",
default="daily_excl_weekend",
choices=list(self.dwpcr_parameter_to_fred_id.keys()),
)
parser.add_argument(
"-s",
"--start",
dest="start_date",
type=valid_date,
help="Starting date (YYYY-MM-DD) of data",
default=None,
)
parser.add_argument(
"-e",
"--end",
dest="end_date",
type=valid_date,
help="Ending date (YYYY-MM-DD) of data",
default=None,
)
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
)
if ns_parser:
fred_view.plot_dwpcr(
self.dwpcr_parameter_to_fred_id[ns_parser.parameter],
ns_parser.start_date,
ns_parser.end_date,
ns_parser.export,
)

View File

@@ -0,0 +1,57 @@
""" FRED model """
__docformat__ = "numpy"
import os
import logging
from typing import Optional
from requests import HTTPError
import pandas as pd
from fredapi import Fred
import certifi
from openbb_terminal import config_terminal as cfg
from openbb_terminal.rich_config import console
from openbb_terminal.decorators import log_start_end, check_api_key
# pylint: disable=attribute-defined-outside-init
logger = logging.getLogger(__name__)
@log_start_end(log=logger)
@check_api_key(["API_FRED_KEY"])
def get_series_data(
series_id: str, start_date: Optional[str] = None, end_date: Optional[str] = None
) -> pd.DataFrame:
"""Get Series data. [Source: FRED]
Parameters
----------
series_id : str
Series ID to get data from
start_date : Optional[str]
Start date to get data from, format yyyy-mm-dd
end_date : Optional[str]
End data to get from, format yyyy-mm-dd
Returns
-------
pd.DataFrame
Series data
"""
df = pd.DataFrame()
try:
# Necessary for installer so that it can locate the correct certificates for
# API calls and https
# https://stackoverflow.com/questions/27835619/urllib-and-ssl-certificate-verify-failed-error/73270162#73270162
os.environ["REQUESTS_CA_BUNDLE"] = certifi.where()
os.environ["SSL_CERT_FILE"] = certifi.where()
fredapi_client = Fred(cfg.API_FRED_KEY)
df = fredapi_client.get_series(series_id, start_date, end_date)
# Series does not exist & invalid api keys
except HTTPError as e:
console.print(e)
return df

View File

@@ -0,0 +1,855 @@
""" FRED view """
__docformat__ = "numpy"
from typing import Optional, List
from itertools import cycle
import logging
import os
import pandas as pd
from matplotlib import pyplot as plt
from openbb_terminal.config_terminal import theme
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.decorators import log_start_end, check_api_key
from openbb_terminal.helper_funcs import (
export_data,
plot_autoscale,
is_valid_axes_count,
)
from openbb_terminal.fixedincome.fred_model import get_series_data
logger = logging.getLogger(__name__)
ID_TO_NAME_ESTR = {
"ECBESTRVOLWGTTRMDMNRT": "Euro Short-Term Rate: Volume-Weighted Trimmed Mean Rate [Percent]",
"ECBESTRTOTVOL": "Euro Short-Term Rate: Total Volume [Millions of EUR]",
"ECBESTRNUMTRANS": "Euro Short-Term Rate: Number of Transactions",
"ECBESTRRT75THPCTVOL": "Euro Short-Term Rate: Rate at 75th Percentile of Volume [Percent]",
"ECBESTRNUMACTBANKS": "Euro Short-Term Rate: Number of Active Banks",
"ECBESTRSHRVOL5LRGACTBNK": "Euro Short-Term Rate: Share of Volume of the 5 Largest Active Banks [Percent]",
"ECBESTRRT25THPCTVOL": "Euro Short-Term Rate: Rate at 25th Percentile of Volume [Percent]",
}
ID_TO_NAME_SOFR = {
"SOFR": "Secured Overnight Financing Rate (SOFR) [Percent]",
"SOFR30DAYAVG": "30-Day Average SOFR [Percent]",
"SOFR90DAYAVG": "90-Day Average SOFR [Percent]",
"SOFR180DAYAVG": "180-Day Average SOFR [Percent]",
"SOFRINDEX": "SOFR Index",
}
ID_TO_NAME_SONIA = {
"IUDSOIA": "Daily Sterling Overnight Index Average (SONIA) Rate [Percent]",
"IUDZOS2": "SONIA Compounded Index",
"IUDZLS6": "SONIA Rate: 10th percentile [Percent]",
"IUDZLS7": "SONIA Rate: 25th percentile [Percent]",
"IUDZLS8": "SONIA Rate: 75th percentile [Percent]",
"IUDZLS9": "SONIA Rate: 90th percentile [Percent]",
"IUDZLT2": "SONIA Rate Total Nominal Value [Millions of GBP]",
}
ID_TO_NAME_AMERIBOR = {
"AMERIBOR": "Overnight Unsecured AMERIBOR Benchmark Interest Rate [Percent]",
"AMBOR30T": "AMERIBOR Term-30 Derived Interest Rate Index [Percent]",
"AMBOR90T": "AMERIBOR Term-90 Derived Interest Rate Index [Percent]",
"AMBOR1W": "1-Week AMERIBOR Term Structure of Interest Rates",
"AMBOR1M": "1-Month AMERIBOR Term Structure of Interest Rates",
"AMBOR3M": "3-Month AMERIBOR Term Structure of Interest Rates",
"AMBOR6M": "6-Month AMERIBOR Term Structure of Interest Rates",
"AMBOR1Y": "1-Year AMERIBOR Term Structure of Interest Rates",
"AMBOR2Y": "2-Year AMERIBOR Term Structure of Interest Rates",
"AMBOR30": "30-Day Moving Average AMERIBOR Benchmark Interest Rate",
"AMBOR90": "90-Day Moving Average AMERIBOR Benchmark Interest Rate",
}
ID_TO_NAME_FFER = {
"FEDFUNDS": "Monthly",
"DFF": "Daily (incl. Weekends)",
"FF": "Weekly",
"RIFSPFFNB": "Daily (excl. Weekends)",
"RIFSPFFNA": "Annual",
"RIFSPFFNBWAW": "Biweekly",
}
ID_TO_NAME_EFFR = {
"EFFR": "Effective Federal Funds Rate [Percent]",
"EFFRVOL": "Effective Federal Funds Volume [Billions of USD]",
"EFFR1": "Effective Federal Funds Rate: 1th Percentile [Percent]",
"EFFR25": "Effective Federal Funds Rate: 25th Percentile [Percent]",
"EFFR75": "Effective Federal Funds Rate: 75th Percentile [Percent]",
"EFFR99": "Effective Federal Funds Rate: 99th Percentile [Percent]",
}
ID_TO_NAME_OBFR = {
"OBFR": "Overnight Bank Funding Rate [Percent]",
"OBFRVOL": "Overnight Bank Funding Volume [Billions of USD]",
"OBFR1": "Overnight Bank Funding Rate: 1th Percentile [Percent]",
"OBFR25": "Overnight Bank Funding Rate: 25th Percentile [Percent]",
"OBFR75": "Overnight Bank Funding Rate: 75th Percentile [Percent]",
"OBFR99": "Overnight Bank Funding Rate: 99th Percentile [Percent]",
}
ID_TO_NAME_DWPCR = {
"MPCREDIT": "Monthly",
"RIFSRPF02ND": "Daily (incl. Weekends)",
"WPCREDIT": "Weekly",
"DPCREDIT": "Daily (excl. Weekends)",
"RIFSRPF02NA": "Annual",
}
@log_start_end(log=logger)
@check_api_key(["API_FRED_KEY"])
def plot_estr(
series_id: str = "ECBESTRVOLWGTTRMDMNRT",
start_date: Optional[str] = None,
end_date: Optional[str] = None,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plot Euro Short-Term Rate (ESTR)
Parameters
----------
series_id: str
FRED ID of ESTR data to plot, options: ['ECBESTRVOLWGTTRMDMNRT', 'ECBESTRTOTVOL', 'ECBESTRNUMTRANS', 'ECBESTRRT75THPCTVOL', 'ECBESTRNUMACTBANKS', 'ECBESTRSHRVOL5LRGACTBNK', 'ECBESTRRT25THPCTVOL']
start_date: Optional[str]
Start date, formatted YYYY-MM-DD
end_date: Optional[str]
End date, formatted YYYY-MM-DD
export: str
Export data to csv or excel file
external_axes: Optional[List[plt.Axes]]
External axes (1 axis is expected in the list)
"""
df = get_series_data(series_id=series_id, start_date=start_date, end_date=end_date)
# This plot has 1 axis
if not external_axes:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
elif is_valid_axes_count(external_axes, 1):
(ax,) = external_axes
else:
return
colors = cycle(theme.get_colors())
ax.plot(
df.index,
df.values,
marker="o",
linestyle="dashed",
linewidth=2,
markersize=4,
color=next(colors, "#FCED00"),
)
ax.set_title(ID_TO_NAME_ESTR[series_id])
theme.style_primary_axis(ax)
if external_axes is None:
theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
f"estr, {series_id}",
df,
)
@log_start_end(log=logger)
@check_api_key(["API_FRED_KEY"])
def plot_sofr(
series_id: str = "SOFR",
start_date: Optional[str] = None,
end_date: Optional[str] = None,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plot Secured Overnight Financing Rate (SOFR)
Parameters
----------
series_id: str
FRED ID of SOFR data to plot, options: ['SOFR', 'SOFR30DAYAVG', 'SOFR90DAYAVG', 'SOFR180DAYAVG', 'SOFRINDEX']
start_date: Optional[str]
Start date, formatted YYYY-MM-DD
end_date: Optional[str]
End date, formatted YYYY-MM-DD
export: str
Export data to csv or excel file
external_axes: Optional[List[plt.Axes]]
External axes (1 axis is expected in the list)
"""
df = get_series_data(series_id=series_id, start_date=start_date, end_date=end_date)
# This plot has 1 axis
if not external_axes:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
elif is_valid_axes_count(external_axes, 1):
(ax,) = external_axes
else:
return
colors = cycle(theme.get_colors())
ax.plot(
df.index,
df.values,
marker="o",
linestyle="dashed",
linewidth=2,
markersize=4,
color=next(colors, "#FCED00"),
)
ax.set_title(ID_TO_NAME_SOFR[series_id])
theme.style_primary_axis(ax)
if external_axes is None:
theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
f"sofr, {series_id}",
df,
)
@log_start_end(log=logger)
@check_api_key(["API_FRED_KEY"])
def plot_sonia(
series_id: str = "IUDSOIA",
start_date: Optional[str] = None,
end_date: Optional[str] = None,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plot Sterling Overnight Index Average (SONIA)
Parameters
----------
series_id: str
FRED ID of SONIA data to plot, options: ['IUDSOIA', 'IUDZOS2', 'IUDZLS6', 'IUDZLS7', 'IUDZLS8', 'IUDZLS9', 'IUDZLT2']
start_date: Optional[str]
Start date, formatted YYYY-MM-DD
end_date: Optional[str]
End date, formatted YYYY-MM-DD
export: str
Export data to csv or excel file
external_axes: Optional[List[plt.Axes]]
External axes (1 axis is expected in the list)
"""
df = get_series_data(series_id=series_id, start_date=start_date, end_date=end_date)
# This plot has 1 axis
if not external_axes:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
elif is_valid_axes_count(external_axes, 1):
(ax,) = external_axes
else:
return
colors = cycle(theme.get_colors())
ax.plot(
df.index,
df.values,
marker="o",
linestyle="dashed",
linewidth=2,
markersize=4,
color=next(colors, "#FCED00"),
)
ax.set_title(ID_TO_NAME_SONIA[series_id])
theme.style_primary_axis(ax)
if external_axes is None:
theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
f"sonia, {series_id}",
df,
)
@log_start_end(log=logger)
@check_api_key(["API_FRED_KEY"])
def plot_ameribor(
series_id: str = "AMERIBOR",
start_date: Optional[str] = None,
end_date: Optional[str] = None,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plot American Interbank Offered Rate (AMERIBOR)
Parameters
----------
series_id: str
FRED ID of AMERIBOR data to plot, options: ['AMERIBOR', 'AMBOR30T', 'AMBOR90T', 'AMBOR1W', 'AMBOR1M', 'AMBOR3M', 'AMBOR6M', 'AMBOR1Y', 'AMBOR2Y', 'AMBOR30', 'AMBOR90']
start_date: Optional[str]
Start date, formatted YYYY-MM-DD
end_date: Optional[str]
End date, formatted YYYY-MM-DD
export: str
Export data to csv or excel file
external_axes: Optional[List[plt.Axes]]
External axes (1 axis is expected in the list)
"""
df = get_series_data(series_id=series_id, start_date=start_date, end_date=end_date)
# This plot has 1 axis
if not external_axes:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
elif is_valid_axes_count(external_axes, 1):
(ax,) = external_axes
else:
return
colors = cycle(theme.get_colors())
ax.plot(
df.index,
df.values,
marker="o",
linestyle="dashed",
linewidth=2,
markersize=4,
color=next(colors, "#FCED00"),
)
ax.set_title(ID_TO_NAME_AMERIBOR[series_id])
theme.style_primary_axis(ax)
if external_axes is None:
theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
f"ameribor, {series_id}",
df,
)
@log_start_end(log=logger)
@check_api_key(["API_FRED_KEY"])
def plot_ffer(
series_id: str = "FEDFUNDS",
start_date: Optional[str] = None,
end_date: Optional[str] = None,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plot Federal Funds Effective Rate
Parameters
----------
series_id: str
FRED ID of FFER data to plot, options: ['FEDFUNDS', 'DFF', 'FF', 'RIFSPFFNB', 'RIFSPFFNA', 'RIFSPFFNBWAW']
start_date: Optional[str]
Start date, formatted YYYY-MM-DD
end_date: Optional[str]
End date, formatted YYYY-MM-DD
export: str
Export data to csv or excel file
external_axes: Optional[List[plt.Axes]]
External axes (1 axis is expected in the list)
"""
df = get_series_data(series_id=series_id, start_date=start_date, end_date=end_date)
# This plot has 1 axis
if not external_axes:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
elif is_valid_axes_count(external_axes, 1):
(ax,) = external_axes
else:
return
colors = cycle(theme.get_colors())
ax.plot(
df.index,
df.values,
marker="o",
linestyle="dashed",
linewidth=2,
markersize=4,
color=next(colors, "#FCED00"),
)
ax.set_title(
"Federal Funds Effective Rate " + ID_TO_NAME_FFER[series_id] + " [Percent]"
)
theme.style_primary_axis(ax)
if external_axes is None:
theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
f"ffer, {series_id}",
df,
)
@log_start_end(log=logger)
@check_api_key(["API_FRED_KEY"])
def plot_fftr(
start_date: Optional[str] = None,
end_date: Optional[str] = None,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plot Federal Funds Target Range
Parameters
----------
start_date: Optional[str]
Start date, formatted YYYY-MM-DD
end_date: Optional[str]
End date, formatted YYYY-MM-DD
export: str
Export data to csv or excel file
external_axes: Optional[List[plt.Axes]]
External axes (1 axis is expected in the list)
"""
df_upper = get_series_data(
series_id="DFEDTARU", start_date=start_date, end_date=end_date
)
df_lower = get_series_data(
series_id="DFEDTARL", start_date=start_date, end_date=end_date
)
df = pd.DataFrame([df_upper, df_lower]).transpose()
# This plot has 1 axis
if not external_axes:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
elif is_valid_axes_count(external_axes, 1):
(ax,) = external_axes
else:
return
ax.plot(
df.index,
df.values,
)
ax.set_title("Federal Funds Target Range [Percent]")
ax.legend(["Upper limit", "Lower limit"])
theme.style_primary_axis(ax)
if external_axes is None:
theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"fftr",
df,
)
@log_start_end(log=logger)
@check_api_key(["API_FRED_KEY"])
def plot_effr(
series_id: str = "EFFR",
start_date: Optional[str] = None,
end_date: Optional[str] = None,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plot Effective Federal Funds Rate
Parameters
----------
series_id: str
FRED ID of EFFER data to plot, options: ['EFFR', 'EFFRVOL', 'EFFR1', 'EFFR25', 'EFFR75', 'EFFR99']
start_date: Optional[str]
Start date, formatted YYYY-MM-DD
end_date: Optional[str]
End date, formatted YYYY-MM-DD
export: str
Export data to csv or excel file
external_axes: Optional[List[plt.Axes]]
External axes (1 axis is expected in the list)
"""
df = get_series_data(series_id=series_id, start_date=start_date, end_date=end_date)
# This plot has 1 axis
if not external_axes:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
elif is_valid_axes_count(external_axes, 1):
(ax,) = external_axes
else:
return
colors = cycle(theme.get_colors())
ax.plot(
df.index,
df.values,
marker="o",
linestyle="dashed",
linewidth=2,
markersize=4,
color=next(colors, "#FCED00"),
)
ax.set_title(ID_TO_NAME_EFFR[series_id])
theme.style_primary_axis(ax)
if external_axes is None:
theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
f"effr, {series_id}",
df,
)
@log_start_end(log=logger)
@check_api_key(["API_FRED_KEY"])
def plot_obfr(
series_id: str = "OBFR",
start_date: Optional[str] = None,
end_date: Optional[str] = None,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plot Overnight Bank Funding Rate (OBFR)
Parameters
----------
series_id: str
FRED ID of OBFR data to plot, options: ['OBFR', 'OBFRVOL', 'OBFR1', 'OBFR25', 'OBFR75', 'OBFR99']
start_date: Optional[str]
Start date, formatted YYYY-MM-DD
end_date: Optional[str]
End date, formatted YYYY-MM-DD
export: str
Export data to csv or excel file
external_axes: Optional[List[plt.Axes]]
External axes (1 axis is expected in the list)
"""
df = get_series_data(series_id=series_id, start_date=start_date, end_date=end_date)
# This plot has 1 axis
if not external_axes:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
elif is_valid_axes_count(external_axes, 1):
(ax,) = external_axes
else:
return
colors = cycle(theme.get_colors())
ax.plot(
df.index,
df.values,
marker="o",
linestyle="dashed",
linewidth=2,
markersize=4,
color=next(colors, "#FCED00"),
)
ax.set_title(ID_TO_NAME_OBFR[series_id])
theme.style_primary_axis(ax)
if external_axes is None:
theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
f"obfr, {series_id}",
df,
)
@log_start_end(log=logger)
@check_api_key(["API_FRED_KEY"])
def plot_iorb(
start_date: Optional[str] = None,
end_date: Optional[str] = None,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plot Interest Rate on Reserve Balances
Parameters
----------
start_date: Optional[str]
Start date, formatted YYYY-MM-DD
end_date: Optional[str]
End date, formatted YYYY-MM-DD
export: str
Export data to csv or excel file
external_axes: Optional[List[plt.Axes]]
External axes (1 axis is expected in the list)
"""
df = get_series_data(series_id="IORB", start_date=start_date, end_date=end_date)
# This plot has 1 axis
if not external_axes:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
elif is_valid_axes_count(external_axes, 1):
(ax,) = external_axes
else:
return
colors = cycle(theme.get_colors())
ax.plot(
df.index,
df.values,
color=next(colors, "#FCED00"),
)
ax.set_title("Interest Rate on Reserve Balances [Percent]")
theme.style_primary_axis(ax)
if external_axes is None:
theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"iorb",
df,
)
@log_start_end(log=logger)
@check_api_key(["API_FRED_KEY"])
def plot_projection(
start_date: Optional[str] = None,
end_date: Optional[str] = None,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plot FOMC Summary of Economic Projections for the Fed Funds Rate
Parameters
----------
start_date: Optional[str]
Start date, formatted YYYY-MM-DD
end_date: Optional[str]
End date, formatted YYYY-MM-DD
export: str
Export data to csv or excel file
external_axes: Optional[List[plt.Axes]]
External axes (1 axis is expected in the list)
"""
df_range_high = get_series_data(
series_id="FEDTARRH", start_date=start_date, end_date=end_date
)
df_central_tendency_high = get_series_data(
series_id="FEDTARCTH", start_date=start_date, end_date=end_date
)
df_median = get_series_data(
series_id="FEDTARMD", start_date=start_date, end_date=end_date
)
df_range_midpoint = get_series_data(
series_id="FEDTARRM", start_date=start_date, end_date=end_date
)
df_central_tendency_midpoint = get_series_data(
series_id="FEDTARCTM", start_date=start_date, end_date=end_date
)
df_range_low = get_series_data(
series_id="FEDTARRL", start_date=start_date, end_date=end_date
)
df_central_tendency_low = get_series_data(
series_id="FEDTARCTL", start_date=start_date, end_date=end_date
)
df = pd.DataFrame(
[
df_range_high,
df_central_tendency_high,
df_median,
df_range_midpoint,
df_central_tendency_midpoint,
df_range_low,
df_central_tendency_low,
]
).transpose()
# This plot has 1 axis
if not external_axes:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
elif is_valid_axes_count(external_axes, 1):
(ax,) = external_axes
else:
return
ax.plot(
df.index,
df.values,
)
ax.set_title(
"FOMC Summary of Economic Projections for the Fed Funds Rate [Percent]"
)
ax.legend(
[
"Range High",
"Central tendency High",
"Median",
"Range Midpoint",
"Central tendency Midpoint",
"Range Low",
"Central tendency Low",
]
)
theme.style_primary_axis(ax)
if external_axes is None:
theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"projection",
df,
)
@log_start_end(log=logger)
@check_api_key(["API_FRED_KEY"])
def plot_oldprojection(
start_date: Optional[str] = None,
end_date: Optional[str] = None,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plot Longer Run FOMC Summary of Economic Projections for the Fed Funds Rate
Parameters
----------
start_date: Optional[str]
Start date, formatted YYYY-MM-DD
end_date: Optional[str]
End date, formatted YYYY-MM-DD
export: str
Export data to csv or excel file
external_axes: Optional[List[plt.Axes]]
External axes (1 axis is expected in the list)
"""
df_range_high = get_series_data(
series_id="FEDTARRHLR", start_date=start_date, end_date=end_date
)
df_central_tendency_high = get_series_data(
series_id="FEDTARCTHLR", start_date=start_date, end_date=end_date
)
df_median = get_series_data(
series_id="FEDTARMDLR", start_date=start_date, end_date=end_date
)
df_range_midpoint = get_series_data(
series_id="FEDTARRMLR", start_date=start_date, end_date=end_date
)
df_central_tendency_midpoint = get_series_data(
series_id="FEDTARCTMLR", start_date=start_date, end_date=end_date
)
df_range_low = get_series_data(
series_id="FEDTARRLLR", start_date=start_date, end_date=end_date
)
df_central_tendency_low = get_series_data(
series_id="FEDTARCTLLR", start_date=start_date, end_date=end_date
)
df = pd.DataFrame(
[
df_range_high,
df_central_tendency_high,
df_median,
df_range_midpoint,
df_central_tendency_midpoint,
df_range_low,
df_central_tendency_low,
]
).transpose()
# This plot has 1 axis
if not external_axes:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
elif is_valid_axes_count(external_axes, 1):
(ax,) = external_axes
else:
return
ax.plot(
df.index,
df.values,
)
ax.set_title(
"Longer Run FOMC Summary of Economic Projections for the Fed Funds Rate [Percent]"
)
ax.legend(
[
"Range High",
"Central tendency High",
"Median",
"Range Midpoint",
"Central tendency Midpoint",
"Range Low",
"Central tendency Low",
]
)
theme.style_primary_axis(ax)
if external_axes is None:
theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"oldprojection",
df,
)
@log_start_end(log=logger)
@check_api_key(["API_FRED_KEY"])
def plot_dwpcr(
series_id: str = "DPCREDIT",
start_date: Optional[str] = None,
end_date: Optional[str] = None,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plot Discount Window Primary Credit Rate
Parameters
----------
series_id: str
FRED ID of DWPCR data to plot, options: ['MPCREDIT', 'RIFSRPF02ND', 'WPCREDIT', 'DPCREDIT', 'RIFSRPF02NA']
start_date: Optional[str]
Start date, formatted YYYY-MM-DD
end_date: Optional[str]
End date, formatted YYYY-MM-DD
export: str
Export data to csv or excel file
external_axes: Optional[List[plt.Axes]]
External axes (1 axis is expected in the list)
"""
df = get_series_data(series_id=series_id, start_date=start_date, end_date=end_date)
# This plot has 1 axis
if not external_axes:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
elif is_valid_axes_count(external_axes, 1):
(ax,) = external_axes
else:
return
colors = cycle(theme.get_colors())
ax.plot(
df.index,
df.values,
marker="o",
linestyle="dashed",
linewidth=2,
markersize=4,
color=next(colors, "#FCED00"),
)
ax.set_title(
"Discount Window Primary Credit Rate "
+ ID_TO_NAME_DWPCR[series_id]
+ " [Percent]"
)
theme.style_primary_axis(ax)
if external_axes is None:
theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
f"dwpcr, {series_id}",
df,
)

View File

@@ -0,0 +1,133 @@
""" NYFED model """
__docformat__ = "numpy"
import logging
from datetime import datetime
import numpy
import pandas as pd
from requests import request
from openbb_terminal.decorators import log_start_end
logger = logging.getLogger(__name__)
@log_start_end(log=logger)
def get_sofr_data(
series: str = "overnight", start_date: str = "1980-01-01", end_date: str = ""
) -> pd.DataFrame:
"""Get Secured Overnight Financing Rate (SOFR) data
Parameters
----------
series: str
Specific data to return, options: ['overnight', '30_day', '90_day', '180_day', 'index', 'all']
start_date: str
Start date, formatted YYYY-MM-DD
end_date:
End date, formatted YYYY-MM-DD
Returns
-------
pd.DataFrame
Dataframe with SOFR data
"""
if isinstance(start_date, datetime):
start_date = datetime.strftime(start_date, "%Y-%m-%d")
if series.lower() == "overnight":
data = request(
"GET",
url=f"https://markets.newyorkfed.org/api/rates/secured/sofr/search.json?startDate={start_date}&endDate={end_date}",
).json()
df = pd.DataFrame.from_records(
data["refRates"],
index="effectiveDate",
exclude=["type", "revisionIndicator", "footnoteId"],
)
else:
data = request(
"GET",
url=f"https://markets.newyorkfed.org/api/rates/secured/sofrai/search.json?startDate={start_date}&endDate={end_date}",
).json()
df = pd.DataFrame.from_records(
data["refRates"],
index="effectiveDate",
exclude=["type", "revisionIndicator"],
)
df.index = pd.to_datetime(df.index)
df = df.replace("NA", numpy.NaN)
df = df.astype(float)
if series == "index":
df = df["index"]
elif series != "overnight" and series != "all":
df = df["average" + series.replace("_", "")]
return df
@log_start_end(log=logger)
def get_effr_data(start_date: str = "1980-01-01", end_date: str = "") -> pd.DataFrame:
"""Get Effective Federal Funds Rate (EFFR) data
Parameters
----------
start_date: str
Start date, formatted YYYY-MM-DD
end_date:
End date, formatted YYYY-MM-DD
Returns
-------
pd.DataFrame
Dataframe with EFFR data
"""
if isinstance(start_date, datetime):
start_date = datetime.strftime(start_date, "%Y-%m-%d")
data = request(
"GET",
url=f"https://markets.newyorkfed.org/api/rates/unsecured/effr/search.json?startDate={start_date}&endDate={end_date}",
).json()
df = pd.DataFrame.from_records(
data["refRates"],
index="effectiveDate",
exclude=["type", "revisionIndicator"],
)
df.index = pd.to_datetime(df.index)
df = df.replace("NA", numpy.NaN)
df = df.astype(float)
return df
@log_start_end(log=logger)
def get_obfr_data(start_date: str = "1980-01-01", end_date: str = "") -> pd.DataFrame:
"""Get Overnight Bank Funding Rate (OBFR) data
Parameters
----------
start_date: str
Start date, formatted YYYY-MM-DD
end_date:
End date, formatted YYYY-MM-DD
Returns
-------
pd.DataFrame
Dataframe with OBFR data
"""
if isinstance(start_date, datetime):
start_date = datetime.strftime(start_date, "%Y-%m-%d")
data = request(
"GET",
url=f"https://markets.newyorkfed.org/api/rates/unsecured/obfr/search.json?startDate={start_date}&endDate={end_date}",
).json()
df = pd.DataFrame.from_records(
data["refRates"],
index="effectiveDate",
exclude=["type", "revisionIndicator"],
)
df.index = pd.to_datetime(df.index)
df = df.replace("NA", numpy.NaN)
df = df.astype(float)
return df

View File

@@ -0,0 +1,283 @@
""" NYFED view """
__docformat__ = "numpy"
from typing import Optional, List
from itertools import cycle
import logging
import os
from matplotlib import pyplot as plt
from openbb_terminal.config_terminal import theme
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
export_data,
plot_autoscale,
is_valid_axes_count,
)
from openbb_terminal.fixedincome import nyfed_model
logger = logging.getLogger(__name__)
SERIES_TO_NAME_SOFR = {
"overnight": "Secured Overnight Financing Rate (SOFR) [Percent]",
"30_day": "30-Day Average SOFR [Percent]",
"90_day": "90-Day Average SOFR [Percent]",
"180_day": "180-Day Average SOFR [Percent]",
"index": "SOFR Index",
}
SERIES_TO_NAME_EFFR = {
"percentRate": "Effective Federal Funds Rate [Percent]",
"volumeInBillions": "Effective Federal Funds Volume [Billions of USD]",
"percentPercentile1": "Effective Federal Funds Rate: 1th Percentile [Percent]",
"percentPercentile25": "Effective Federal Funds Rate: 25th Percentile [Percent]",
"percentPercentile75": "Effective Federal Funds Rate: 75th Percentile [Percent]",
"percentPercentile99": "Effective Federal Funds Rate: 99th Percentile [Percent]",
}
SERIES_TO_NAME_OBFR = {
"percentRate": "Overnight Bank Funding Rate [Percent]",
"volumeInBillions": "Overnight Bank Funding Volume [Billions of USD]",
"percentPercentile1": "Overnight Bank Funding Rate: 1th Percentile [Percent]",
"percentPercentile25": "Overnight Bank Funding Rate: 25th Percentile [Percent]",
"percentPercentile75": "Overnight Bank Funding Rate: 75th Percentile [Percent]",
"percentPercentile99": "Overnight Bank Funding Rate: 99th Percentile [Percent]",
}
@log_start_end(log=logger)
def plot_sofr(
series: str = "overnight",
start_date: Optional[str] = "1980-01-01",
end_date: Optional[str] = None,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plot Secured Overnight Financing Rate (SOFR)
Parameters
----------
series: str
Specific data to plot, options: ['overnight', '30_day', '90_day', '180_day', 'index']
start_date: Optional[str]
Start date, formatted YYYY-MM-DD
end_date: Optional[str]
End date, formatted YYYY-MM-DD
export: str
Export data to csv or excel file
external_axes: Optional[List[plt.Axes]]
External axes (1 axis is expected in the list)
"""
df = nyfed_model.get_sofr_data(series, start_date, end_date if end_date else "")
if series == "overnight":
del df["volumeInBillions"]
# This plot has 1 axis
if not external_axes:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
elif is_valid_axes_count(external_axes, 1):
(ax,) = external_axes
else:
return
ax.plot(
df.index,
df.values,
marker="o",
linestyle="dashed",
linewidth=2,
markersize=4,
)
ax.set_title(SERIES_TO_NAME_SOFR[series])
theme.style_primary_axis(ax)
if series.lower() == "overnight":
ax.legend(
[
"Rate",
"1th percentile",
"25th percentile",
"75th percentile",
"99th percentile",
]
)
if external_axes is None:
theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
f"sofr, {series}",
df,
)
@log_start_end(log=logger)
def plot_fftr(
start_date: Optional[str] = "1980-01-01",
end_date: Optional[str] = None,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plot Federal Funding Target Range (upper and lower)
Parameters
----------
start_date: Optional[str]
Start date, formatted YYYY-MM-DD
end_date: Optional[str]
End date, formatted YYYY-MM-DD
export: str
Export data to csv or excel file
external_axes: Optional[List[plt.Axes]]
External axes (1 axis is expected in the list)
"""
df = nyfed_model.get_effr_data(start_date, end_date if end_date else "")
df = df[["targetRateTo", "targetRateFrom"]]
# This plot has 1 axis
if not external_axes:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
elif is_valid_axes_count(external_axes, 1):
(ax,) = external_axes
else:
return
ax.plot(
df.index,
df.values,
marker="o",
linestyle="dashed",
linewidth=2,
markersize=4,
)
ax.set_title("Federal Funds Target Range [Percent]")
ax.legend(["Upper limit", "Lower limit"])
theme.style_primary_axis(ax)
if external_axes is None:
theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
f"fftr",
df,
)
@log_start_end(log=logger)
def plot_effr(
series: str = "percentRate",
start_date: Optional[str] = "1980-01-01",
end_date: Optional[str] = None,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plot Effective Federal Funds Rate
Parameters
----------
series: str
Specific data to plot, options: ['percentRate', 'volumeInBillions', 'percentPercentile1', 'percentPercentile25', 'percentPercentile75', 'percentPercentile99']
start_date: Optional[str]
Start date, formatted YYYY-MM-DD
end_date: Optional[str]
End date, formatted YYYY-MM-DD
export: str
Export data to csv or excel file
external_axes: Optional[List[plt.Axes]]
External axes (1 axis is expected in the list)
"""
df = nyfed_model.get_effr_data(start_date, end_date if end_date else "")
df = df[series]
# This plot has 1 axis
if not external_axes:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
elif is_valid_axes_count(external_axes, 1):
(ax,) = external_axes
else:
return
colors = cycle(theme.get_colors())
ax.plot(
df.index,
df.values,
marker="o",
linestyle="dashed",
linewidth=2,
markersize=4,
color=next(colors, "#FCED00"),
)
ax.set_title(SERIES_TO_NAME_EFFR[series])
theme.style_primary_axis(ax)
if external_axes is None:
theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
f"effr, {series}",
df,
)
@log_start_end(log=logger)
def plot_obfr(
series: str = "percentRate",
start_date: Optional[str] = "1980-01-01",
end_date: Optional[str] = None,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plot Overnight Bank Funding Rate
Parameters
----------
series: str
Specific data to plot, options: ['percentRate', 'volumeInBillions', 'percentPercentile1', 'percentPercentile25', 'percentPercentile75', 'percentPercentile99']
start_date: Optional[str]
Start date, formatted YYYY-MM-DD
end_date: Optional[str]
End date, formatted YYYY-MM-DD
export: str
Export data to csv or excel file
external_axes: Optional[List[plt.Axes]]
External axes (1 axis is expected in the list)
"""
df = nyfed_model.get_obfr_data(start_date, end_date if end_date else "")
df = df[series]
# This plot has 1 axis
if not external_axes:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
elif is_valid_axes_count(external_axes, 1):
(ax,) = external_axes
else:
return
colors = cycle(theme.get_colors())
ax.plot(
df.index,
df.values,
marker="o",
linestyle="dashed",
linewidth=2,
markersize=4,
color=next(colors, "#FCED00"),
)
ax.set_title(SERIES_TO_NAME_OBFR[series])
theme.style_primary_axis(ax)
if external_axes is None:
theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
f"obfr, {series}",
df,
)

View File

@@ -504,6 +504,20 @@
"historical": ["YahooFinance"],
"curve": ["YahooFinance"]
},
"fixedincome": {
"estr": ["FRED", "ECB"],
"sofr": ["FRED", "NYFED"],
"sonia": ["FRED"],
"ameribor": ["FRED"],
"ffer": ["FRED"],
"fftr": ["FRED", "NYFED"],
"effr": ["FRED", "NYFED"],
"obfr": ["FRED", "NYFED"],
"iorb": ["FRED"],
"projection": ["FRED"],
"oldprojetion": ["FRED"],
"dwpcr": ["FRED"]
},
"alternative": {
"oss": {
"rossidx": ["RunaCapital"],

View File

@@ -771,6 +771,20 @@ en:
economy/qa/raw: print raw data
economy/qa/decompose: decomposition in cyclic-trend, season, and residuals of prices
economy/qa/cusum: detects abrupt changes using cumulative sum algorithm of prices
fixedincome/_reference_rates_: Reference rates
fixedincome/estr: euro short-term rate (estr)
fixedincome/sofr: secured overnight financing rate (sofr)
fixedincome/sonia: sterling overnight index average (sonia)
fixedincome/ameribor: american interbank offered rate (ameribor)
fixedincome/_other_interest_rates_: Other interest rates
fixedincome/ffer: federal funds effective rate
fixedincome/fftr: federal funds target range
fixedincome/effr: effective federal funds rate (effr)
fixedincome/obfr: overnight bank funding rate (obfr)
fixedincome/iorb: interest rate on reserve balances
fixedincome/projection: FOMC summary of economic projections for the fed funds rate
fixedincome/oldprojection: longer run FOMC summary of economic projections for the fed funds rate
fixedincome/dwpcr: discount window primary credit rate
forex/_ticker: Ticker
forex/_from: From
forex/_to: To

View File

@@ -103,6 +103,7 @@ class TerminalController(BaseController):
"sources",
"forecast",
"futures",
"fixedincome",
]
PATH = "/"
@@ -178,6 +179,7 @@ class TerminalController(BaseController):
mt.add_menu("economy")
mt.add_menu("forex")
mt.add_menu("futures")
mt.add_menu("fixedincome")
mt.add_menu("alternative")
mt.add_raw("\n")
mt.add_info("_others_")
@@ -465,6 +467,14 @@ class TerminalController(BaseController):
self.queue = self.load_class(FuturesController, self.queue)
def call_fixedincome(self, _):
"""Process fixedincome command."""
from openbb_terminal.fixedincome.fixedincome_controller import (
FixedIncomeController,
)
self.queue = self.load_class(FixedIncomeController, self.queue)
def call_intro(self, _):
"""Process intro command."""
console.print(panel.Panel("[purple]Welcome to the OpenBB Terminal.[/purple]"))