Feature/improving to plotly (#5238)

* introducing singleton abstract class

* changing charting manager to be a singleton and introducing the to_plotly_json methon on the charting manager level: which should be a proxy for the actual implementation on the charting extension module level

* exposing to_plotly_json method on a module level for the openbb_charint extension

* changing the logging manager to be a singleton

* forcing both managers (logging and charting) to update on each run

* expanding the to_plotly_json functionality on the CommandOutput level

* fix readme typo

* fix indicators anchored to left

* ruff

* removing unnecesary change

* improved docstrings

* black

* ruff
This commit is contained in:
Henrique Joaquim
2023-07-24 17:19:19 +01:00
committed by GitHub
parent 91532c9988
commit beefeed8ce
9 changed files with 294 additions and 54 deletions

View File

@@ -3,3 +3,4 @@ from openbb_charting.core.backend import (
create_backend,
get_backend,
)
from openbb_charting.core.to_plotly_json import to_plotly_json

View File

@@ -171,7 +171,7 @@ class PlotlyTA(PltTA):
self.indicators = indicators
self.intraday = df_stock.index[-2].time() != df_stock.index[-1].time()
self.df_stock = df_stock
self.df_stock = df_stock.sort_index(ascending=True)
self.close_column = check_columns(self.df_stock)
self.params = self.indicators.get_params()
@@ -434,7 +434,6 @@ class PlotlyTA(PltTA):
fig : OpenBBFigure
Plotly figure with candlestick/line chart and volume bar chart (if enabled)
"""
self.df_ta = self.calculate_indicators()
symbol = (

View File

@@ -0,0 +1,61 @@
from typing import Any, Dict, Optional, Union
import pandas as pd
from openbb_charting.core.plotly_ta.data_classes import ChartIndicators
from openbb_charting.core.plotly_ta.ta_class import PlotlyTA
from openbb_core.app.model.charts.charting_settings import ChartingSettings
def to_plotly_json(
charting_settings: ChartingSettings,
data: Union[pd.DataFrame, pd.Series],
indicators: Optional[Union[ChartIndicators, Dict[str, Dict[str, Any]]]] = None,
symbol: str = "",
candles: bool = True,
volume: bool = True,
prepost: bool = False,
volume_ticks_x: int = 7,
) -> str:
"""
Returns the plotly json representation of the chart.
This function is used so it can be called at the module level and used out of the box,
which allows some more flexibility, ease of use and doesn't require the user to know
about the PlotlyTA class.
Parameters
----------
charting_settings : ChartingSettings
Charting settings.
data : Union[pd.DataFrame, pd.Series]
Data to be plotted.
indicators : Optional[Union[ChartIndicators, Dict[str, Dict[str, Any]]]], optional
Indicators to be plotted, by default None
symbol : str, optional
Symbol to be plotted, by default ""
candles : bool, optional
If True, candles will be plotted, by default True
volume : bool, optional
If True, volume will be plotted, by default True
prepost : bool, optional
If True, prepost will be plotted, by default False
volume_ticks_x : int, optional
Volume ticks, by default 7
Returns
-------
str
Plotly json representation of the chart.
"""
ta = PlotlyTA(charting_settings=charting_settings)
fig = ta.plot(
df_stock=data,
indicators=indicators,
symbol=symbol,
candles=candles,
volume=volume,
prepost=prepost,
volume_ticks_x=volume_ticks_x,
)
return fig.show(external=True).to_plotly_json()

View File

@@ -1,12 +1,14 @@
from importlib import import_module
from typing import Callable, Generic, Optional, TypeVar
from typing import Callable, Generic, Optional, Tuple, TypeVar
import pkg_resources
from openbb_core.app.model.abstract.singleton import SingletonMeta
from openbb_core.app.model.charts.chart import Chart, ChartFormat
from openbb_core.app.model.charts.charting_settings import ChartingSettings
from openbb_core.app.model.system_settings import SystemSettings
from openbb_core.app.model.user_settings import UserSettings
from openbb_core.app.service.system_service import SystemService
from openbb_core.app.service.user_service import UserService
T = TypeVar("T")
@@ -18,7 +20,7 @@ class ChartingManagerError(Exception):
pass
class ChartingManager:
class ChartingManager(metaclass=SingletonMeta):
"""
Charting manager class.
It is responsible for retrieving and executing the charting function, corresponding
@@ -42,14 +44,31 @@ class ChartingManager:
def __init__(
self,
user_settings: Optional[UserSettings] = None,
system_settings: Optional[SystemSettings] = None,
) -> None:
user_settings = user_settings or UserService().read_default_user_settings()
self._system_settings = (
system_settings or SystemService().read_default_system_settings()
)
self._charting_settings = ChartingSettings(user_settings, system_settings)
self._charting_extension = user_settings.preferences.charting_extension
self._charting_extension_installed = self.check_charting_extension_installed(
self._charting_extension
)
@property
def charting_settings(self) -> ChartingSettings:
return self._charting_settings
@charting_settings.setter
def charting_settings(self, value: Tuple[SystemSettings, UserSettings]):
system_settings, user_settings = value
self._charting_settings = ChartingSettings(
user_settings=user_settings,
system_settings=system_settings,
)
@staticmethod
def check_charting_extension_installed(
charting_extension: str, plugin: str = POETRY_PLUGIN
@@ -116,7 +135,6 @@ class ChartingManager:
charting_settings : ChartingSettings
Charting settings.
"""
# Dynamically import the backend module
backend_module = import_module(charting_extension)
@@ -126,6 +144,25 @@ class ChartingManager:
create_backend_func(charting_settings=charting_settings)
get_backend_func().start(debug=charting_settings.debug_mode)
def to_plotly_json(self, **kwargs) -> str:
"""
Returns the plotly json representation of the chart.
"""
if not self._charting_extension_installed:
raise ChartingManagerError(
f"Charting extension `{self._charting_extension}` is not installed"
)
self.handle_backend(self._charting_extension, self._charting_settings)
# Dynamically import the charting module
backend_module = import_module(self._charting_extension)
# Get the plotly json function from the charting module
to_plotly_json_func = getattr(backend_module, "to_plotly_json")
# Add the charting settings to the kwargs
kwargs["charting_settings"] = self._charting_settings
return to_plotly_json_func(**kwargs)
def chart(
self,
user_settings: UserSettings,
@@ -158,8 +195,7 @@ class ChartingManager:
Chart
Chart object.
"""
charting_settings = ChartingSettings(user_settings, system_settings)
self._charting_settings = ChartingSettings(user_settings, system_settings)
self._charting_extension = user_settings.preferences.charting_extension
self._charting_extension_installed = self.check_charting_extension_installed(
self._charting_extension
@@ -170,10 +206,10 @@ class ChartingManager:
f"Charting extension `{self._charting_extension}` is not installed"
)
self.handle_backend(self._charting_extension, charting_settings)
self.handle_backend(self._charting_extension, self._charting_settings)
kwargs["command_output_item"] = command_output_item
kwargs["charting_settings"] = charting_settings
kwargs["charting_settings"] = self._charting_settings
return Chart(
content=self.get_chart_function(self._charting_extension, route)(**kwargs),

View File

@@ -355,6 +355,13 @@ class StaticCommandRunner:
return command_output
@classmethod
def __update_managers_settings(
cls, system_settings: SystemSettings, user_settings: UserSettings
):
cls.logging_manager.logging_settings = (system_settings, user_settings)
cls.charting_manager.charting_settings = (system_settings, user_settings)
@classmethod
def run(
cls,
@@ -371,6 +378,10 @@ class StaticCommandRunner:
route = execution_context.route
journal_service = execution_context.journal_service
cls.__update_managers_settings(
execution_context.system_settings, execution_context.user_settings
)
func = command_map.get_command(route=route)
if func:

View File

@@ -2,13 +2,14 @@
import json
import logging
from enum import Enum
from typing import Any, Callable, Dict, Optional
from typing import Any, Callable, Dict, Optional, Tuple
from openbb_core.app.logs.formatters.formatter_with_exceptions import (
FormatterWithExceptions,
)
from openbb_core.app.logs.handlers_manager import HandlersManager
from openbb_core.app.logs.models.logging_settings import LoggingSettings
from openbb_core.app.model.abstract.singleton import SingletonMeta
from openbb_core.app.model.command_output import CommandOutput
from openbb_core.app.model.system_settings import SystemSettings
from openbb_core.app.model.user_settings import UserSettings
@@ -21,12 +22,58 @@ from openbb_core.app.service.user_service import UserService
from pydantic.json import pydantic_encoder
class LoggingManager:
class LoggingManager(metaclass=SingletonMeta):
"""
Logging Manager class responsible for managing logging settings and handling logs.
Attributes
----------
_user_settings : Optional[UserSettings]
User Settings object.
_system_settings : Optional[SystemSettings]
System Settings object.
_logging_settings : LoggingSettings
LoggingSettings object containing the current logging settings.
_handlers_manager : HandlersManager
HandlersManager object managing logging handlers.
Methods
-------
__init__(system_settings, user_settings)
Logging Manager Constructor.
log(user_settings, system_settings, command_output, route, func, kwargs)
Log command output and relevant information.
logging_settings
Property to access the current logging settings.
logging_settings.setter
Setter method to update the logging settings.
_setup_handlers()
Setup Logging Handlers.
_log_startup()
Log startup information.
"""
def __init__(
self,
system_settings: Optional[SystemSettings] = None,
user_settings: Optional[UserSettings] = None,
) -> None:
"""
Logging Manager Constructor
Sets up the logging settings and handlers and then logs the startup information.
Parameters
----------
system_settings : Optional[SystemSettings], optional
System Settings, by default None
user_settings : Optional[UserSettings], optional
User Settings, by default None
"""
self._user_settings = (
user_settings or UserService().read_default_user_settings()
)
@@ -40,8 +87,43 @@ class LoggingManager:
self._handlers_manager = self._setup_handlers()
self._log_startup()
@property
def logging_settings(self) -> LoggingSettings:
"""
Current logging settings.
Returns
-------
LoggingSettings
LoggingSettings object containing the current logging settings.
"""
return self._logging_settings
@logging_settings.setter
def logging_settings(self, value: Tuple[SystemSettings, UserSettings]):
"""
Setter for updating the logging settings.
Parameters
----------
value : Tuple[SystemSettings, UserSettings]
Tuple containing updated SystemSettings and UserSettings.
"""
system_settings, user_settings = value
self._logging_settings = LoggingSettings(
user_settings=user_settings,
system_settings=system_settings,
)
def _setup_handlers(self) -> HandlersManager:
"""Setup Logging"""
"""
Setup Logging Handlers.
Returns
-------
HandlersManager
Handlers Manager object.
"""
logger = logging.getLogger(__name__)
logging.basicConfig(
level=self._logging_settings.verbosity,
@@ -63,6 +145,10 @@ class LoggingManager:
return handlers_manager
def _log_startup(self) -> None:
"""
Log startup information.
"""
def check_credentials_defined(credentials: Dict[str, Any]):
class CredentialsDefinition(Enum):
defined = "defined"
@@ -101,6 +187,24 @@ class LoggingManager:
func: Callable,
kwargs: Dict[str, Any],
):
"""
Log command output and relevant information.
Parameters
----------
user_settings : UserSettings
User Settings object.
system_settings : SystemSettings
System Settings object.
command_output : CommandOutput
CommandOutput object containing command output and error information.
route : str
Route for the command.
func : Callable
Callable representing the executed function.
kwargs : Dict[str, Any]
Keyword arguments passed to the function.
"""
self._user_settings = user_settings
self._system_settings = system_settings
self._logging_settings = LoggingSettings(

View File

@@ -0,0 +1,9 @@
class SingletonMeta(type):
# TODO : check if we want to update this to be thread safe
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
instance = super().__call__(*args, **kwargs)
cls._instances[cls] = instance
return cls._instances[cls]

View File

@@ -4,10 +4,11 @@ import pandas as pd
from pydantic import Field
from pydantic.generics import GenericModel
from openbb_core.app.charting_manager import ChartingManager
from openbb_core.app.model.abstract.error import Error
from openbb_core.app.model.abstract.tagged import Tagged
from openbb_core.app.model.abstract.warning import Warning_
from openbb_core.app.model.charts.chart import Chart
from openbb_core.app.model.charts.chart import Chart, ChartFormat
from openbb_core.app.provider_interface import get_provider_interface
T = TypeVar("T")
@@ -85,20 +86,38 @@ class CommandOutput(GenericModel, Generic[T], Tagged):
return results
def to_plotly_json(self) -> Optional[Dict[str, Any]]:
def to_plotly_json(
self, create_chart: bool = True, **kwargs
) -> Optional[Dict[str, Any]]:
"""
Outputs the plotly json.
It is a proxy to the `chart.content` attribute that contains it already.
Returns
-------
Optional[Dict[str, Any]]
Plotly json.
Returns the plotly json representation of the chart.
If the chart was already computed it return the plotly json representation of the chart.
Otherwise it computes the chart based on the available data and provided kwargs.
Parameters
----------
create_chart : bool, optional
If True, it creates the chart object and populates the respective field on the object, by default True.
**kwargs
Keyword arguments to be passed to the charting extension.
This implies that the user has to know the charting extension API; this is the case
because the charting extension may vary on user settings.
"""
if not self.chart:
raise OpenBBError("Chart not found.")
if not self.chart.format == "plotly":
raise OpenBBError("Chart is not in plotly format.")
return self.chart.content
if self.chart and not kwargs:
plotly_json = self.chart.content
else:
cm = ChartingManager()
kwargs["data"] = self.to_dataframe()
plotly_json = cm.to_plotly_json(**kwargs)
if create_chart:
try:
self.chart = Chart(content=plotly_json, format=ChartFormat.plotly)
except Exception as e:
self.chart = Chart(error=Error(message=str(e)))
return plotly_json
def show(self):
"""Displays chart."""

View File

@@ -19,7 +19,7 @@ class CLASS_economy(Container):
def corecpi(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""CORECPI."""
inputs = filter_inputs(
@@ -248,7 +248,7 @@ class CLASS_economy(Container):
def cpi_options(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""Get the options for v3 cpi(options=True)"""
inputs = filter_inputs(
@@ -448,7 +448,7 @@ class CLASS_economy(Container):
def macro(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""Query EconDB for macro data."""
inputs = filter_inputs(
@@ -470,7 +470,7 @@ class CLASS_economy(Container):
def macro_countries(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""MACRO_COUNTRIES."""
inputs = filter_inputs(
@@ -492,7 +492,7 @@ class CLASS_economy(Container):
def macro_parameters(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""MACRO_PARAMETERS."""
inputs = filter_inputs(
@@ -514,7 +514,7 @@ class CLASS_economy(Container):
def balance(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""BALANCE."""
inputs = filter_inputs(
@@ -536,7 +536,7 @@ class CLASS_economy(Container):
def bigmac(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""BIGMAC."""
inputs = filter_inputs(
@@ -558,7 +558,7 @@ class CLASS_economy(Container):
def country_codes(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""COUNTRY_CODES."""
inputs = filter_inputs(
@@ -580,7 +580,7 @@ class CLASS_economy(Container):
def currencies(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""CURRENCIES."""
inputs = filter_inputs(
@@ -602,7 +602,7 @@ class CLASS_economy(Container):
def debt(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""DEBT."""
inputs = filter_inputs(
@@ -624,7 +624,7 @@ class CLASS_economy(Container):
def events(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""EVENTS."""
inputs = filter_inputs(
@@ -646,7 +646,7 @@ class CLASS_economy(Container):
def fgdp(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""FGDP."""
inputs = filter_inputs(
@@ -668,7 +668,7 @@ class CLASS_economy(Container):
def fred(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""FRED."""
inputs = filter_inputs(
@@ -690,7 +690,7 @@ class CLASS_economy(Container):
def fred_search(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""FRED Search (was fred_notes)."""
inputs = filter_inputs(
@@ -712,7 +712,7 @@ class CLASS_economy(Container):
def futures(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""FUTURES. 2 sources"""
inputs = filter_inputs(
@@ -734,7 +734,7 @@ class CLASS_economy(Container):
def gdp(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""GDP."""
inputs = filter_inputs(
@@ -756,7 +756,7 @@ class CLASS_economy(Container):
def glbonds(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""GLBONDS."""
inputs = filter_inputs(
@@ -778,7 +778,7 @@ class CLASS_economy(Container):
def indices(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""INDICES."""
inputs = filter_inputs(
@@ -800,7 +800,7 @@ class CLASS_economy(Container):
def overview(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""OVERVIEW."""
inputs = filter_inputs(
@@ -822,7 +822,7 @@ class CLASS_economy(Container):
def perfmap(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""PERFMAP."""
inputs = filter_inputs(
@@ -844,7 +844,7 @@ class CLASS_economy(Container):
def performance(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""PERFORMANCE."""
inputs = filter_inputs(
@@ -866,7 +866,7 @@ class CLASS_economy(Container):
def revenue(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""REVENUE."""
inputs = filter_inputs(
@@ -888,7 +888,7 @@ class CLASS_economy(Container):
def rgdp(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""RGDP."""
inputs = filter_inputs(
@@ -910,7 +910,7 @@ class CLASS_economy(Container):
def rtps(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""RTPS."""
inputs = filter_inputs(
@@ -932,7 +932,7 @@ class CLASS_economy(Container):
def search_index(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""SEARCH_INDEX."""
inputs = filter_inputs(
@@ -954,7 +954,7 @@ class CLASS_economy(Container):
def spending(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""SPENDING."""
inputs = filter_inputs(
@@ -976,7 +976,7 @@ class CLASS_economy(Container):
def trust(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""TRUST."""
inputs = filter_inputs(
@@ -998,7 +998,7 @@ class CLASS_economy(Container):
def usbonds(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""USBONDS."""
inputs = filter_inputs(
@@ -1020,7 +1020,7 @@ class CLASS_economy(Container):
def valuation(
self,
chart: bool = False,
provider: Optional[Literal["fmp", "fred", "benzinga", "polygon"]] = None,
provider: Optional[Literal["fmp", "fred", "polygon", "benzinga"]] = None,
) -> CommandOutput[openbb_core.app.model.results.empty.Empty]:
"""VALUATION."""
inputs = filter_inputs(