diff --git a/openbb_platform/core/openbb_core/api/app_loader.py b/openbb_platform/core/openbb_core/api/app_loader.py index 5bbc40d17ce..b11b0abefc8 100644 --- a/openbb_platform/core/openbb_core/api/app_loader.py +++ b/openbb_platform/core/openbb_core/api/app_loader.py @@ -6,7 +6,7 @@ from fastapi import APIRouter, FastAPI from openbb_core.api.exception_handlers import ExceptionHandlers from openbb_core.app.model.abstract.error import OpenBBError from openbb_core.app.router import RouterLoader -from openbb_core.provider.utils.errors import EmptyDataError +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError from pydantic import ValidationError @@ -40,3 +40,4 @@ class AppLoader: app.exception_handlers[ValidationError] = ExceptionHandlers.validation app.exception_handlers[OpenBBError] = ExceptionHandlers.openbb app.exception_handlers[EmptyDataError] = ExceptionHandlers.empty_data + app.exception_handlers[UnauthorizedError] = ExceptionHandlers.unauthorized diff --git a/openbb_platform/core/openbb_core/api/exception_handlers.py b/openbb_platform/core/openbb_core/api/exception_handlers.py index a3994fe3f69..9a96c5eadba 100644 --- a/openbb_platform/core/openbb_core/api/exception_handlers.py +++ b/openbb_platform/core/openbb_core/api/exception_handlers.py @@ -10,7 +10,7 @@ from fastapi import Request from fastapi.responses import JSONResponse, Response from openbb_core.app.model.abstract.error import OpenBBError from openbb_core.env import Env -from openbb_core.provider.utils.errors import EmptyDataError +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError from pydantic import ValidationError logger = logging.getLogger("uvicorn.error") @@ -55,7 +55,7 @@ class ExceptionHandlers: return await ExceptionHandlers._handle( exception=error, status_code=500, - detail="Unexpected error.", + detail=f"Unexpected Error -> {error.__class__.__name__} -> {str(error.args[0] or error.args)}", ) @staticmethod @@ -99,3 +99,12 @@ class ExceptionHandlers: async def empty_data(_: Request, error: EmptyDataError): """Exception handler for EmptyDataError.""" return Response(status_code=204) + + @staticmethod + async def unauthorized(_: Request, error: UnauthorizedError): + """Exception handler for OpenBBError.""" + return await ExceptionHandlers._handle( + exception=error, + status_code=502, + detail=str(error.original), + ) diff --git a/openbb_platform/core/openbb_core/app/router.py b/openbb_platform/core/openbb_core/app/router.py index a52b7087f30..50dac517686 100644 --- a/openbb_platform/core/openbb_core/app/router.py +++ b/openbb_platform/core/openbb_core/app/router.py @@ -293,6 +293,10 @@ class Router: "model": OpenBBErrorResponse, "description": "Internal Error", }, + 502: { + "model": OpenBBErrorResponse, + "description": "Unauthorized", + }, }, ) diff --git a/openbb_platform/core/openbb_core/app/static/utils/decorators.py b/openbb_platform/core/openbb_core/app/static/utils/decorators.py index 0b2ea4f0ddd..9afac5077d7 100644 --- a/openbb_platform/core/openbb_core/app/static/utils/decorators.py +++ b/openbb_platform/core/openbb_core/app/static/utils/decorators.py @@ -5,6 +5,7 @@ from typing import Any, Callable, Optional, TypeVar, overload from openbb_core.app.model.abstract.error import OpenBBError from openbb_core.env import Env +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError from pydantic import ValidationError, validate_call from typing_extensions import ParamSpec @@ -85,10 +86,21 @@ def exception_handler(func: Callable[P, R]) -> Callable[P, R]: raise OpenBBError(f"\n[Error] -> {error_str}").with_traceback( tb ) from None + if isinstance(e, UnauthorizedError): + raise UnauthorizedError(f"\n[Error] -> {str(e)}").with_traceback( + tb + ) from None + if isinstance(e, EmptyDataError): + raise EmptyDataError(f"\n[Empty] -> {str(e)}").with_traceback( + tb + ) from None if isinstance(e, OpenBBError): raise OpenBBError(f"\n[Error] -> {str(e)}").with_traceback(tb) from None - raise OpenBBError("\n[Error] -> Unexpected error.").with_traceback( - tb - ) from None + if isinstance(e, Exception): + raise OpenBBError( + f"\n[Unexpected Error] -> {e.__class__.__name__} -> {str(e.args[0] or e.args)}" + ).with_traceback(tb) from None + + return None return wrapper diff --git a/openbb_platform/core/openbb_core/provider/utils/errors.py b/openbb_platform/core/openbb_core/provider/utils/errors.py index cfa87f16c37..264265af341 100644 --- a/openbb_platform/core/openbb_core/provider/utils/errors.py +++ b/openbb_platform/core/openbb_core/provider/utils/errors.py @@ -1,5 +1,7 @@ """Custom exceptions for the provider.""" +from typing import Union + from openbb_core.app.model.abstract.error import OpenBBError @@ -12,3 +14,26 @@ class EmptyDataError(OpenBBError): """Initialize the exception.""" self.message = message super().__init__(self.message) + + +class UnauthorizedError(OpenBBError): + """Exception raised for an unauthorized provider request response.""" + + def __init__( + self, + message: Union[str, tuple[str]] = ( + "Unauthorized API request." + " Please check your credentials and subscription access.", + ), + provider_name: str = "", + ): + """Initialize the exception.""" + if provider_name and provider_name != "": + msg = message + if isinstance(msg, tuple): + msg = msg[0].replace("", provider_name) + elif isinstance(msg, str): + msg = msg.replace("", provider_name) + message = msg + self.message = message + super().__init__(self.message) diff --git a/openbb_platform/providers/benzinga/openbb_benzinga/models/analyst_search.py b/openbb_platform/providers/benzinga/openbb_benzinga/models/analyst_search.py index e89bcd00415..2a3307c0617 100644 --- a/openbb_platform/providers/benzinga/openbb_benzinga/models/analyst_search.py +++ b/openbb_platform/providers/benzinga/openbb_benzinga/models/analyst_search.py @@ -8,17 +8,13 @@ from datetime import ( ) from typing import Any, Dict, List, Optional +from openbb_core.app.model.abstract.error import OpenBBError from openbb_core.provider.abstract.fetcher import Fetcher from openbb_core.provider.standard_models.analyst_search import ( AnalystSearchData, AnalystSearchQueryParams, ) from openbb_core.provider.utils.errors import EmptyDataError -from openbb_core.provider.utils.helpers import ( - amake_request, - get_querystring, - safe_fromtimestamp, -) from pydantic import Field, field_validator, model_validator @@ -367,6 +363,9 @@ class BenzingaAnalystSearchData(AnalystSearchData): @classmethod def validate_date(cls, v: float) -> Optional[dateType]: """Validate last_updated.""" + # pylint: disable=import-outside-toplevel + from openbb_core.provider.utils.helpers import safe_fromtimestamp + if v: dt = safe_fromtimestamp(v, tz=timezone.utc) return dt.date() if dt.time() == dt.min.time() else dt @@ -414,15 +413,31 @@ class BenzingaAnalystSearchFetcher( **kwargs: Any, ) -> List[Dict]: """Extract the raw data.""" + # pylint: disable=import-outside-toplevel + from openbb_benzinga.utils.helpers import response_callback + from openbb_core.provider.utils.helpers import amake_request, get_querystring + token = credentials.get("benzinga_api_key") if credentials else "" - querystring = get_querystring(query.model_dump(), []) + querystring = get_querystring(query.model_dump(by_alias=True), []) url = f"https://api.benzinga.com/api/v2.1/calendar/ratings/analysts?{querystring}&token={token}" - response = await amake_request(url, **kwargs) + data = await amake_request(url, response_callback=response_callback, **kwargs) - if not response: - raise EmptyDataError() + if (isinstance(data, list) and not data) or ( + isinstance(data, dict) and not data.get("analyst_ratings_analyst") + ): + raise EmptyDataError("No ratings data returned.") - return response.get("analyst_ratings_analyst") # type: ignore + if isinstance(data, dict) and "analyst_ratings_analyst" not in data: + raise OpenBBError( + f"Unexpected data format. Expected 'analyst_ratings_analyst' key, got: {list(data.keys())}" + ) + + if not isinstance(data, dict): + raise OpenBBError( + f"Unexpected data format. Expected dict, got: {type(data).__name__}" + ) + + return data["analyst_ratings_analyst"] @staticmethod def transform_data( diff --git a/openbb_platform/providers/benzinga/openbb_benzinga/models/company_news.py b/openbb_platform/providers/benzinga/openbb_benzinga/models/company_news.py index ddeda769657..d68d14678b8 100644 --- a/openbb_platform/providers/benzinga/openbb_benzinga/models/company_news.py +++ b/openbb_platform/providers/benzinga/openbb_benzinga/models/company_news.py @@ -1,19 +1,21 @@ """Benzinga Company News Model.""" -import math +# pylint: disable=unused-argument + from datetime import ( date as dateType, datetime, ) from typing import Any, Dict, List, Literal, Optional +from openbb_core.app.model.abstract.error import OpenBBError from openbb_core.provider.abstract.fetcher import Fetcher from openbb_core.provider.standard_models.company_news import ( CompanyNewsData, CompanyNewsQueryParams, ) from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS -from openbb_core.provider.utils.helpers import amake_requests, get_querystring +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError from pydantic import Field, field_validator @@ -148,6 +150,12 @@ class BenzingaCompanyNewsFetcher( **kwargs: Any, ) -> List[Dict]: """Extract data.""" + # pylint: disable=import-outside-toplevel + import asyncio # noqa + import math + from openbb_core.provider.utils.helpers import amake_request, get_querystring + from openbb_benzinga.utils.helpers import response_callback + token = credentials.get("benzinga_api_key") if credentials else "" base_url = "https://api.benzinga.com/api/v2/news" @@ -165,11 +173,28 @@ class BenzingaCompanyNewsFetcher( for page in range(pages) ] - data = await amake_requests(urls, **kwargs) + results: list = [] - return data[: query.limit] + async def get_one(url): + """Get data for one url.""" + try: + response = await amake_request( + url, response_callback=response_callback, **kwargs + ) + if response: + results.extend(response) + except (OpenBBError, UnauthorizedError) as e: + raise e from e + + await asyncio.gather(*[get_one(url) for url in urls]) + + if not results: + raise EmptyDataError("The request was returned empty.") + + return sorted( + results, key=lambda x: x.get("created"), reverse=query.order == "desc" + )[: query.limit if query.limit else len(results)] - # pylint: disable=unused-argument @staticmethod def transform_data( query: BenzingaCompanyNewsQueryParams, diff --git a/openbb_platform/providers/benzinga/openbb_benzinga/models/price_target.py b/openbb_platform/providers/benzinga/openbb_benzinga/models/price_target.py index 5237b17c988..606ac40352c 100644 --- a/openbb_platform/providers/benzinga/openbb_benzinga/models/price_target.py +++ b/openbb_platform/providers/benzinga/openbb_benzinga/models/price_target.py @@ -10,6 +10,7 @@ from datetime import ( ) from typing import Any, Dict, List, Literal, Optional, Union +from openbb_core.app.model.abstract.error import OpenBBError from openbb_core.provider.abstract.fetcher import Fetcher from openbb_core.provider.standard_models.price_target import ( PriceTargetData, @@ -17,11 +18,6 @@ from openbb_core.provider.standard_models.price_target import ( ) from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS from openbb_core.provider.utils.errors import EmptyDataError -from openbb_core.provider.utils.helpers import ( - amake_requests, - get_querystring, - safe_fromtimestamp, -) from pydantic import Field, field_validator, model_validator COVERAGE_DICT = { @@ -58,10 +54,26 @@ class BenzingaPriceTargetQueryParams(PriceTargetQueryParams): "firm_ids": "parameters[firm_id]", } __json_schema_extra__ = { - "symbol": ["multiple_items_allowed"], - "analyst_ids": ["multiple_items_allowed"], - "firm_ids": ["multiple_items_allowed"], - "fields": ["multiple_items_allowed"], + "symbol": {"multiple_items_allowed": True}, + "analyst_ids": {"multiple_items_allowed": True}, + "firm_ids": {"multiple_items_allowed": True}, + "fields": {"multiple_items_allowed": True}, + "action": { + "multiple_items_allowed": False, + "choices": [ + "downgrades", + "maintains", + "reinstates", + "reiterates", + "upgrades", + "assumes", + "initiates", + "terminates", + "removes", + "suspends", + "firm_dissolved", + ], + }, } page: Optional[int] = Field( @@ -231,6 +243,9 @@ class BenzingaPriceTargetData(PriceTargetData): @classmethod def validate_date(cls, v: float) -> Optional[dateType]: """Convert the Unix timestamp to a datetime object.""" + # pylint: disable=import-outside-toplevel + from openbb_core.provider.utils.helpers import safe_fromtimestamp + if v: dt = safe_fromtimestamp(v, tz=timezone.utc) return dt.date() if dt.time() == dt.min.time() else dt @@ -263,18 +278,30 @@ class BenzingaPriceTargetFetcher( **kwargs: Any, ) -> List[Dict]: """Return the raw data from the Benzinga endpoint.""" + # pylint: disable=import-outside-toplevel + from openbb_benzinga.utils.helpers import response_callback + from openbb_core.provider.utils.helpers import amake_request, get_querystring + token = credentials.get("benzinga_api_key") if credentials else "" base_url = "https://api.benzinga.com/api/v2.1/calendar/ratings" querystring = get_querystring(query.model_dump(by_alias=True), []) url = f"{base_url}?{querystring}&token={token}" - data = await amake_requests(url, **kwargs) + data = await amake_request(url, response_callback=response_callback, **kwargs) - if not data: - raise EmptyDataError() + if isinstance(data, dict) and "ratings" not in data: + raise OpenBBError( + f"Unexpected data format. Expected 'ratings' key, got: {list(data.keys())}" + ) + if not isinstance(data, dict): + raise OpenBBError( + f"Unexpected data format. Expected dict, got: {type(data)}" + ) + if isinstance(data, dict) and not data.get("ratings"): + raise EmptyDataError("No ratings data returned.") - return data[0].get("ratings") + return data["ratings"] @staticmethod def transform_data( diff --git a/openbb_platform/providers/benzinga/openbb_benzinga/models/world_news.py b/openbb_platform/providers/benzinga/openbb_benzinga/models/world_news.py index 0e669771a02..5ec86333685 100644 --- a/openbb_platform/providers/benzinga/openbb_benzinga/models/world_news.py +++ b/openbb_platform/providers/benzinga/openbb_benzinga/models/world_news.py @@ -2,20 +2,20 @@ # pylint: disable=unused-argument -import math from datetime import ( date as dateType, datetime, ) from typing import Any, Dict, List, Literal, Optional +from openbb_core.app.model.abstract.error import OpenBBError from openbb_core.provider.abstract.fetcher import Fetcher from openbb_core.provider.standard_models.world_news import ( WorldNewsData, WorldNewsQueryParams, ) from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS -from openbb_core.provider.utils.helpers import amake_requests, get_querystring +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError from pydantic import Field, field_validator @@ -146,6 +146,12 @@ class BenzingaWorldNewsFetcher( **kwargs: Any, ) -> List[Dict]: """Extract the data.""" + # pylint: disable=import-outside-toplevel + import asyncio # noqa + import math + from openbb_core.provider.utils.helpers import amake_request, get_querystring + from openbb_benzinga.utils.helpers import response_callback + token = credentials.get("benzinga_api_key") if credentials else "" base_url = "https://api.benzinga.com/api/v2/news" @@ -159,9 +165,27 @@ class BenzingaWorldNewsFetcher( for page in range(pages) ] - data = await amake_requests(urls, **kwargs) + results: list = [] - return data[: query.limit] + async def get_one(url): + """Get data for one url.""" + try: + response = await amake_request( + url, response_callback=response_callback, **kwargs + ) + if response: + results.extend(response) + except (OpenBBError, UnauthorizedError) as e: + raise e from e + + await asyncio.gather(*[get_one(url) for url in urls]) + + if not results: + raise EmptyDataError("The request was returned empty.") + + return sorted( + results, key=lambda x: x.get("created"), reverse=query.order == "desc" + )[: query.limit if query.limit else len(results)] @staticmethod def transform_data( diff --git a/openbb_platform/providers/benzinga/openbb_benzinga/utils/helpers.py b/openbb_platform/providers/benzinga/openbb_benzinga/utils/helpers.py new file mode 100644 index 00000000000..fbadc77fe28 --- /dev/null +++ b/openbb_platform/providers/benzinga/openbb_benzinga/utils/helpers.py @@ -0,0 +1,24 @@ +"""Benzinga Helpers.""" + +from openbb_core.app.model.abstract.error import OpenBBError +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError + + +async def response_callback(response, _): + """Response callback.""" + # pylint: disable=import-outside-toplevel + results = await response.json() + if ( + results + and isinstance(results, list) + and len(results) == 1 + and isinstance(results[0], str) + ): + if "access denied" in results[0].lower(): + raise UnauthorizedError(f"Unauthorized Benzinga request -> {results[0]}") + raise OpenBBError(results[0]) + + if isinstance(results, list) and not results: + raise EmptyDataError("The request was returned empty.") + + return results diff --git a/openbb_platform/providers/biztoc/openbb_biztoc/models/world_news.py b/openbb_platform/providers/biztoc/openbb_biztoc/models/world_news.py index e36fc886928..f1a39b205e2 100644 --- a/openbb_platform/providers/biztoc/openbb_biztoc/models/world_news.py +++ b/openbb_platform/providers/biztoc/openbb_biztoc/models/world_news.py @@ -2,7 +2,7 @@ # pylint: disable=unused-argument -from typing import Any, Dict, List, Optional +from typing import Any, Optional, Union from warnings import warn from openbb_core.app.model.abstract.error import OpenBBError @@ -11,6 +11,7 @@ from openbb_core.provider.standard_models.world_news import ( WorldNewsData, WorldNewsQueryParams, ) +from openbb_core.provider.utils.errors import UnauthorizedError from pydantic import Field, field_validator @@ -36,10 +37,10 @@ class BiztocWorldNewsData(WorldNewsData): "images": "img", } - images: Optional[List[Dict[str, str]]] = Field( + images: Optional[list[dict[str, str]]] = Field( description="Images for the article.", default=None ) - tags: Optional[List[str]] = Field(description="Tags for the article.", default=None) + tags: Optional[list[str]] = Field(description="Tags for the article.", default=None) score: Optional[float] = Field( description="Search relevance score for the article.", default=None ) @@ -63,27 +64,38 @@ class BiztocWorldNewsData(WorldNewsData): class BiztocWorldNewsFetcher( Fetcher[ BiztocWorldNewsQueryParams, - List[BiztocWorldNewsData], + list[BiztocWorldNewsData], ] ): """Transform the query, extract and transform the data from the Biztoc endpoints.""" @staticmethod - def transform_query(params: Dict[str, Any]) -> BiztocWorldNewsQueryParams: + def transform_query(params: dict[str, Any]) -> BiztocWorldNewsQueryParams: """Transform the query.""" if params.get("start_date") or params.get("end_date"): warn("start_date and end_date are not supported for this endpoint.") return BiztocWorldNewsQueryParams(**params) @staticmethod - def extract_data( + async def aextract_data( query: BiztocWorldNewsQueryParams, - credentials: Optional[Dict[str, str]], + credentials: Optional[dict[str, str]], **kwargs: Any, - ) -> List[Dict]: + ) -> list[dict]: """Extract the data from the Biztoc endpoint.""" # pylint: disable=import-outside-toplevel - from openbb_core.provider.utils.helpers import make_request + from openbb_core.provider.utils.helpers import amake_request, make_request + + async def response_callback(response, _): + res = await response.json() + if isinstance(res, dict) and "message" in res: + if "subscribed" in res["message"].lower(): + raise UnauthorizedError( + f"Unauthorized Biztoc request -> {res['message']}" + ) + raise OpenBBError(res["message"]) + + return await response.json() api_key = credentials.get("biztoc_api_key") if credentials else "" headers = { @@ -94,11 +106,13 @@ class BiztocWorldNewsFetcher( } base_url = "https://biztoc.p.rapidapi.com/" url = "" - response: List = [] + response: Union[list, dict] = [] if query.term: query.term = query.term.replace(" ", "%20") url = base_url + f"search?q={query.term}" - response = make_request(url, headers=headers).json() + response = await amake_request( + url, headers=headers, response_callback=response_callback + ) elif query.source is not None: sources_response = make_request( "https://biztoc.p.rapidapi.com/sources", @@ -110,17 +124,23 @@ class BiztocWorldNewsFetcher( f"{query.source} not a valid source. Valid sources: {sources}" ) url = base_url + f"news/source/{query.source.lower()}" - response = make_request(url, headers=headers).json() + response = await amake_request( + url, headers=headers, response_callback=response_callback + ) else: url1 = base_url + "news/latest" url2 = base_url + "news/topics" - response = make_request(url1, headers=headers).json() - response2 = make_request(url2, headers=headers).json() + response = await amake_request( + url1, headers=headers, response_callback=response_callback + ) + response2 = await amake_request( + url2, headers=headers, response_callback=response_callback + ) if response2: for topic in response2: stories = topic.get("stories", []) if stories: - response.extend( + response.extend( # type: ignore { "text" if k == "body_preview" else k: v for k, v in story.items() @@ -128,14 +148,14 @@ class BiztocWorldNewsFetcher( for story in stories ) - return response + return response # type: ignore @staticmethod def transform_data( - query: BiztocWorldNewsQueryParams, data: List[Dict], **kwargs: Any - ) -> List[BiztocWorldNewsData]: + query: BiztocWorldNewsQueryParams, data: list[dict], **kwargs: Any + ) -> list[BiztocWorldNewsData]: """Transform the data to the standard format.""" - results: List[BiztocWorldNewsData] = [] + results: list[BiztocWorldNewsData] = [] for item in data: item.pop("id", None) item.pop("uid", None) diff --git a/openbb_platform/providers/biztoc/tests/record/http/test_biztoc_fetchers/test_biztoc_world_news_fetcher_urllib3_v2.yaml b/openbb_platform/providers/biztoc/tests/record/http/test_biztoc_fetchers/test_biztoc_world_news_fetcher_urllib3_v2.yaml index b621ba5ab62..3dce9307d3c 100644 --- a/openbb_platform/providers/biztoc/tests/record/http/test_biztoc_fetchers/test_biztoc_world_news_fetcher_urllib3_v2.yaml +++ b/openbb_platform/providers/biztoc/tests/record/http/test_biztoc_fetchers/test_biztoc_world_news_fetcher_urllib3_v2.yaml @@ -26,7 +26,7 @@ interactions: Herald","web":"https://www.bostonherald.com/business/"},{"id":"bizjournals","title":"Business Journals","web":"https://www.bizjournals.com/"},{"id":"cbc","title":"CBC","web":"https://www.cbc.ca/s"},{"id":"cbs","title":"CBS","web":"https://www.cbsnews.com"},{"id":"cnbc","title":"CNBC","web":"https://www.cnbc.com/"},{"id":"cnn","title":"CNN","web":"https://edition.cnn.com/business"},{"id":"chicago","title":"Chicago Tribune","web":"https://www.chicagotribune.com/business/"},{"id":"coindesk","title":"Coindesk","web":"https://www.coindesk.com"},{"id":"dw","title":"DW","web":"https://www.dw.com/en/business/s-1431"},{"id":"dailyupside","title":"Daily - Upside","web":"https://www.thedailyupside.com/"},{"id":"dealbreaker","title":"Dealbreaker","web":"https://dealbreaker.com/"},{"id":"entrepreneur","title":"Entrepreneur","web":"https://www.entrepreneur.com/"},{"id":"euronews","title":"Euronews","web":"https://www.euronews.com/"},{"id":"fastcompany","title":"FastCompany","web":"https://www.fastcompany.com"},{"id":"finpost","title":"Financial + Upside","web":"https://www.thedailyupside.com/"},{"id":"dealbreaker","title":"Dealbreaker","web":"https://dealbreaker.com/"},{"id":"entrepreneur","title":"Entrepreneur","web":"https://www.entrepreneur.com/"},{"id":"stocktwits","title":"EurActiv","web":"https://www.euractiv.com/"},{"id":"euronews","title":"Euronews","web":"https://www.euronews.com/"},{"id":"fastcompany","title":"FastCompany","web":"https://www.fastcompany.com"},{"id":"finpost","title":"Financial Post","web":"https://financialpost.com/"},{"id":"ft","title":"Financial Times","web":"https://www.ft.com"},{"id":"forbes","title":"Forbes","web":"https://www.forbes.com"},{"id":"fortune","title":"Fortune","web":"https://fortune.com/"},{"id":"fox","title":"Fox Business","web":"https://www.foxbusiness.com"},{"id":"globeandmail","title":"Globe And Mail","web":"https://www.theglobeandmail.com"},{"id":"google_business","title":"Google @@ -63,45 +63,47 @@ interactions: CF-Cache-Status: - DYNAMIC CF-RAY: - - 89a4a7f40c219f15-FRA + - 8d46253b4f35c990-IAD Cache-Control: - no-store, no-cache, must-revalidate, max-age=0 Connection: - keep-alive Content-Encoding: - gzip - Content-Length: - - '1800' Content-Type: - application/json Date: - - Thu, 27 Jun 2024 10:11:58 GMT + - Fri, 18 Oct 2024 05:32:01 GMT NEL: - '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}' Report-To: - - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=qqd5%2FZT%2FpjnF59niBWwAAMKoNSHaARhHE%2BCScAOamvVMXueCOGrH6Cyf6yENE0qdAIp4u8QJXurzuHxBuuFVmpVCkBu%2BqOoko4Gt%2BezOVomoB2E5UoYXIZXwGcg%3D"}],"group":"cf-nel","max_age":604800}' + - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=6AJ37sdn9g018QqveznvFOUcc06J0MlsSB7CDEFKhN7XOhnexO7oUWGOx9%2BTeTH%2BUfbmxCFfUB9dRstLZUvq6koiunLgudzqseaUyrLMRwcL9G4TTGHbblRtT88%3D"}],"group":"cf-nel","max_age":604800}' Server: - RapidAPI-1.2.8 Strict-Transport-Security: - max-age=31556926; includeSubDomains + Transfer-Encoding: + - chunked Vary: - Accept-Encoding, Cookie X-RapidAPI-Region: - - AWS - eu-central-1 + - AWS - us-east-1 + X-RapidAPI-Request-Id: + - bb52b953b619ebdbae3d20f65f30c5041993d53bfcb4bd646a484856e7ad1bad X-RapidAPI-Version: - 1.2.8 X-RateLimit-Requests-Limit: - '2000' X-RateLimit-Requests-Remaining: - - '1995' + - '1914' X-RateLimit-Requests-Reset: - - '1996936' + - '1620568' X-RateLimit-rapid-free-plans-hard-limit-Limit: - '500000' X-RateLimit-rapid-free-plans-hard-limit-Remaining: - - '499995' + - '499961' X-RateLimit-rapid-free-plans-hard-limit-Reset: - - '1996936' + - '1620568' alt-svc: - h3=":443"; ma=86400 permissions-policy: @@ -109,7 +111,7 @@ interactions: referrer-policy: - strict-origin-when-cross-origin rndr-id: - - 78f5e9bd-116f-4106 + - 96769602-78bc-4d9d x-content-type-options: - nosniff x-render-origin-server: @@ -124,8 +126,6 @@ interactions: - application/json Accept-Encoding: - gzip - Connection: - - keep-alive X-RapidAPI-Host: - biztoc.p.rapidapi.com X-RapidAPI-Key: @@ -134,171 +134,153 @@ interactions: uri: https://biztoc.p.rapidapi.com/news/source/bloomberg response: body: - string: '[{"body_preview":"","img":{"s":"https://cdn.biztoc.com/671d384ea549859a_s.webp","sq":"https://cdn.biztoc.com/671d384ea549859a_sq.webp"},"published":"Thu, - 27 Jun 2024 10:00:32 GMT","title":"The Secret to a Long Life Is in Your Garage","url":"https://www.bloomberg.com/news/newsletters/2024-06-27/biking-is-the-secret-to-longevity?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/7a092becc648f312_s.webp","sq":"https://cdn.biztoc.com/7a092becc648f312_sq.webp"},"published":"Thu, - 27 Jun 2024 10:00:32 GMT","title":"RTO Mandates Are Killing the Euphoric Work-Life - Balance Some Moms Found","url":"https://www.bloomberg.com/news/features/2024-06-27/return-to-office-is-killing-work-life-balance-dream-for-moms?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/ce50045cff5cc694_s.webp","sq":"https://cdn.biztoc.com/ce50045cff5cc694_sq.webp"},"published":"Thu, - 27 Jun 2024 10:00:29 GMT","title":"Game-Changing HIV Shot Can\u2019t Get to - High-Risk Groups Fast Enough","url":"https://www.bloomberg.com/opinion/articles/2024-06-27/gilead-hiv-shot-lenacapavir-can-t-get-to-high-risk-groups-fast-enough?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/05c5bdea66614330_s.webp","sq":"https://cdn.biztoc.com/05c5bdea66614330_sq.webp"},"published":"Thu, - 27 Jun 2024 10:00:31 GMT","title":"What to Watch in Biden and Trump\u2019s - First Presidential Debate of 2024","url":"https://www.bloomberg.com/news/articles/2024-06-27/trump-vs-biden-1st-debate-what-to-expect-polls-how-to-watch?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/e3ca73bdd000e5c0_s.webp","sq":"https://cdn.biztoc.com/e3ca73bdd000e5c0_sq.webp"},"published":"Thu, - 27 Jun 2024 09:57:49 GMT","title":"Hedge Funds Sell Tech Stocks \u2018Aggressively,\u2019 - Goldman Says","url":"https://www.bloomberg.com/news/articles/2024-06-27/hedge-funds-are-selling-tech-stocks-aggressively-goldman-says?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/2cdcc4f31a5bc8a7_s.webp","sq":"https://cdn.biztoc.com/2cdcc4f31a5bc8a7_sq.webp"},"published":"Thu, - 27 Jun 2024 09:30:01 GMT","title":"BOE Warns on \u2018Struggling\u2019 Private - Equity-Backed Firms","url":"https://www.bloomberg.com/news/articles/2024-06-27/boe-warns-on-struggling-private-equity-backed-firms?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/4c381d961d53cf72_s.webp","sq":"https://cdn.biztoc.com/4c381d961d53cf72_sq.webp"},"published":"Thu, - 27 Jun 2024 09:59:15 GMT","title":"Economic Insecurity Roils Politics From - Kenya to France","url":"https://www.bloomberg.com/news/newsletters/2024-06-27/economic-insecurity-is-agitating-politics-from-kenya-to-france?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/e3225d824ef43d63_s.webp","sq":"https://cdn.biztoc.com/e3225d824ef43d63_sq.webp"},"published":"Thu, - 27 Jun 2024 09:21:46 GMT","title":"China\u2019s Offshore Wind Power Prices - to Undercut Coal This Year","url":"https://www.bloomberg.com/news/articles/2024-06-27/china-s-offshore-wind-power-prices-to-undercut-coal-this-year?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/f273766c417f6d3c_s.webp","sq":"https://cdn.biztoc.com/f273766c417f6d3c_sq.webp"},"published":"Thu, - 27 Jun 2024 09:33:49 GMT","title":"Largest Thai Mobile Operator True Debuts - Yen Sustainability Loan","url":"https://www.bloomberg.com/news/articles/2024-06-27/largest-thai-mobile-operator-true-debuts-yen-sustainability-loan?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/e088074911846227_s.webp","sq":"https://cdn.biztoc.com/e088074911846227_sq.webp"},"published":"Thu, - 27 Jun 2024 09:41:28 GMT","title":"India Credit Seen Benefiting From Index-Related - Bond Flows","url":"https://www.bloomberg.com/news/articles/2024-06-27/india-credit-seen-benefiting-from-index-related-bond-flows?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/460acda0d69de5b1_s.webp","sq":"https://cdn.biztoc.com/460acda0d69de5b1_sq.webp"},"published":"Thu, - 27 Jun 2024 09:30:43 GMT","title":"Zambia Inflation Hits 29-Month High on - Worst Drought in Decades","url":"https://www.bloomberg.com/news/articles/2024-06-27/zambia-inflation-hits-29-month-high-on-worst-drought-in-decades?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/72e6e5767c04fe2d_s.webp","sq":"https://cdn.biztoc.com/72e6e5767c04fe2d_sq.webp"},"published":"Thu, - 27 Jun 2024 09:30:00 GMT","title":"RBA\u2019s Hauser Says Current Account - Surpluses May Not Persist","url":"https://www.bloomberg.com/news/articles/2024-06-27/rba-s-hauser-says-current-account-surpluses-may-not-persist?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/961c40ef2d2996a6_s.webp","sq":"https://cdn.biztoc.com/961c40ef2d2996a6_sq.webp"},"published":"Thu, - 27 Jun 2024 09:44:02 GMT","title":"UK Mortgage Costs Could Fall For 1.5 Million - This Year, BOE Says","url":"https://www.bloomberg.com/news/articles/2024-06-27/uk-mortgage-costs-could-fall-for-1-5-million-this-year-boe-says?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/916efa0233eddfa8_s.webp","sq":"https://cdn.biztoc.com/916efa0233eddfa8_sq.webp"},"published":"Thu, - 27 Jun 2024 07:49:43 GMT","title":"Housing Crises Take a Toll on the World\u2019s - Most Liveable Cities","url":"https://www.bloomberg.com/news/articles/2024-06-27/housing-crises-take-a-toll-on-the-world-s-most-liveable-cities?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/0c8d68a121623d42_s.webp","sq":"https://cdn.biztoc.com/0c8d68a121623d42_sq.webp"},"published":"Thu, - 27 Jun 2024 09:27:11 GMT","title":"Boeing Sees Fewer Fuselage Defects, Helping - Lift Productivity","url":"https://www.bloomberg.com/news/articles/2024-06-27/boeing-sees-lower-fuselage-defects-helping-lift-productivity?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/bbd12d7a7df1d29f_s.webp","sq":"https://cdn.biztoc.com/bbd12d7a7df1d29f_sq.webp"},"published":"Thu, - 27 Jun 2024 09:15:26 GMT","title":"Rand Resumes Losses as South Africa Cabinet - Delay Fuels Angst","url":"https://www.bloomberg.com/news/articles/2024-06-27/rand-resumes-losses-as-south-africa-cabinet-delay-fuels-angst?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/c2798367d9d8a2ea_s.webp","sq":"https://cdn.biztoc.com/c2798367d9d8a2ea_sq.webp"},"published":"Thu, - 27 Jun 2024 09:20:00 GMT","title":"Egypt\u2019s $10 Billion Wind Farm Is Poised - to Break Ground in 2026","url":"https://www.bloomberg.com/news/articles/2024-06-27/egypt-s-10-billion-wind-farm-is-poised-to-break-ground-in-2026?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/86425a91d3933c5a_s.webp","sq":"https://cdn.biztoc.com/86425a91d3933c5a_sq.webp"},"published":"Thu, - 27 Jun 2024 09:15:01 GMT","title":"Boeing Said Cleared to Resume Wide-Body - Jet Deliveries to China","url":"https://www.bloomberg.com/news/articles/2024-06-27/boeing-said-cleared-to-resume-wide-body-jet-deliveries-to-china?ref=biztoc.com"},{"body_preview":"","img":null,"published":"Thu, - 27 Jun 2024 08:48:39 GMT","title":"ECB May Only Cut Rates Once More This Year, - Kazimir Says","url":"https://www.bloomberg.com/news/articles/2024-06-27/ecb-may-only-cut-rates-once-more-this-year-kazimir-says?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/ae4962855a7a53f4_s.webp","sq":"https://cdn.biztoc.com/ae4962855a7a53f4_sq.webp"},"published":"Thu, - 27 Jun 2024 09:15:20 GMT","title":"Macron? Le Pen? A Guide to France\u2019s - Crucial Election","url":"https://www.bloomberg.com/news/articles/2024-06-27/france-election-2024-macron-le-pen-and-a-political-system-under-strain?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/86d725dd5c6e6ff1_s.webp","sq":"https://cdn.biztoc.com/86d725dd5c6e6ff1_sq.webp"},"published":"Thu, - 27 Jun 2024 09:00:31 GMT","title":"Democrats Keep Feuding in Philly, Imperiling - Biden''s Reelection","url":"https://www.bloomberg.com/news/features/2024-06-27/election-2024-to-beat-trump-biden-needs-philly-democrats-to-get-along?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/78394a8d264dc840_s.webp","sq":"https://cdn.biztoc.com/78394a8d264dc840_sq.webp"},"published":"Thu, - 27 Jun 2024 09:00:29 GMT","title":"Trump Can\u2019t Handle the Foreign Policy - Debate America Needs","url":"https://www.bloomberg.com/opinion/articles/2024-06-27/trump-can-t-handle-the-foreign-policy-debate-america-needs?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/b4b892b60b395257_s.webp","sq":"https://cdn.biztoc.com/b4b892b60b395257_sq.webp"},"published":"Thu, - 27 Jun 2024 08:56:15 GMT","title":"Crypto Exchange Bybit Grabs Global Spotlight - in Void Left by FTX","url":"https://www.bloomberg.com/news/articles/2024-06-27/crypto-exchange-bybit-grabs-global-spotlight-in-void-left-by-ftx?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/9ab810dfd969627b_s.webp","sq":"https://cdn.biztoc.com/9ab810dfd969627b_sq.webp"},"published":"Thu, - 27 Jun 2024 08:12:24 GMT","title":"Suu Kyi\u2019s Family Mansion Will Be Up - for Bidding Again in August","url":"https://www.bloomberg.com/news/articles/2024-06-27/suu-kyi-s-family-mansion-will-be-up-for-bidding-again-in-august?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/a93b0f0f54e85b83_s.webp","sq":"https://cdn.biztoc.com/a93b0f0f54e85b83_sq.webp"},"published":"Thu, - 27 Jun 2024 08:43:10 GMT","title":"Japan\u2019s Jet Fuel Crunch Hits Narita, - One of Its Biggest Airports","url":"https://www.bloomberg.com/news/articles/2024-06-27/japan-s-jet-fuel-crunch-hits-narita-one-of-its-biggest-airports?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/e2f7dbdee28becd4_s.webp","sq":"https://cdn.biztoc.com/e2f7dbdee28becd4_sq.webp"},"published":"Thu, - 27 Jun 2024 08:05:22 GMT","title":"Thai Energy Billionaire Steps Up Data Center - Push to Tap AI Boom","url":"https://www.bloomberg.com/news/articles/2024-06-27/thai-energy-billionaire-steps-up-data-center-push-to-tap-ai-boom?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/71fdba8a4bfc9639_s.webp","sq":"https://cdn.biztoc.com/71fdba8a4bfc9639_sq.webp"},"published":"Thu, - 27 Jun 2024 08:24:40 GMT","title":"ECB Will Be Agile in Deciding on Interest-Rate - Path, Lane Says","url":"https://www.bloomberg.com/news/articles/2024-06-27/ecb-will-be-agile-in-deciding-on-interest-rate-path-lane-says?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/a41d31526e60312e_s.webp","sq":"https://cdn.biztoc.com/a41d31526e60312e_sq.webp"},"published":"Thu, - 27 Jun 2024 08:25:24 GMT","title":"Activist Fund in Japan Wins Daidoh Board - Seats in Rare Victory","url":"https://www.bloomberg.com/news/articles/2024-06-27/activist-fund-in-japan-wins-daidoh-board-seats-in-rare-victory?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/2da6f0fcc289cdb1_s.webp","sq":"https://cdn.biztoc.com/2da6f0fcc289cdb1_sq.webp"},"published":"Thu, - 27 Jun 2024 08:23:15 GMT","title":"Zimbabwe Holds Key Interest Rate at 20% - With Eye on Inflation","url":"https://www.bloomberg.com/news/articles/2024-06-27/-zwg-usd-zimbabwe-leaves-benchmark-interest-rate-unchanged-at-20?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/d3aba268bc340b4b_s.webp","sq":"https://cdn.biztoc.com/d3aba268bc340b4b_sq.webp"},"published":"Thu, - 27 Jun 2024 08:00:00 GMT","title":"South Korea Asks Banks for Help When Won\u2019s - Trading Hours Extend","url":"https://www.bloomberg.com/news/articles/2024-06-27/south-korea-asks-banks-for-help-when-won-s-trading-hours-extend?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/7cdd1a163283880b_s.webp","sq":"https://cdn.biztoc.com/7cdd1a163283880b_sq.webp"},"published":"Thu, - 27 Jun 2024 08:01:09 GMT","title":"Chinese Builder Sino-Ocean Group Gets Wind-Up - Petition in HK","url":"https://www.bloomberg.com/news/articles/2024-06-27/chinese-builder-sino-ocean-group-gets-wind-up-petition-in-hk-lxwz6hu3?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/b9fab14c1ca609f1_s.webp","sq":"https://cdn.biztoc.com/b9fab14c1ca609f1_sq.webp"},"published":"Thu, - 27 Jun 2024 07:44:58 GMT","title":"Bloomberg French Poll of Polls: Le Pen\u2019s - Group Makes More Gains","url":"https://www.bloomberg.com/news/articles/2024-06-27/bloomberg-french-poll-of-polls-le-pen-s-group-makes-more-gains?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/228308de25690dd0_s.webp","sq":"https://cdn.biztoc.com/228308de25690dd0_sq.webp"},"published":"Thu, - 27 Jun 2024 07:50:58 GMT","title":"China Says Two Pandas Are Heading to US - in Show of \u2018Friendship\u2019","url":"https://www.bloomberg.com/news/articles/2024-06-27/china-says-two-pandas-are-heading-to-us-in-show-of-friendship?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/69a6870fe063ddec_s.webp","sq":"https://cdn.biztoc.com/69a6870fe063ddec_sq.webp"},"published":"Thu, - 27 Jun 2024 08:00:00 GMT","title":"South Africa Achieves First Primary Budget - Surplus in 15 Years","url":"https://www.bloomberg.com/news/articles/2024-06-27/south-africa-achieves-first-primary-budget-surplus-in-15-years?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/3be9366671dc10b4_s.webp","sq":"https://cdn.biztoc.com/3be9366671dc10b4_sq.webp"},"published":"Thu, - 27 Jun 2024 08:01:42 GMT","title":"CVC Agrees to Buy UK Infrastructure Contractor - M Group Services","url":"https://www.bloomberg.com/news/articles/2024-06-27/cvc-agrees-to-buy-uk-infrastructure-contractor-m-group-services?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/e2926786e44722b4_s.webp","sq":"https://cdn.biztoc.com/e2926786e44722b4_sq.webp"},"published":"Thu, - 27 Jun 2024 08:01:30 GMT","title":"Riksbank Signals as Many as Three More - Rate Cuts This Year","url":"https://www.bloomberg.com/news/articles/2024-06-27/riksbank-signals-as-many-as-three-more-rate-cuts-this-year?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/34fec51cafcaf87c_s.webp","sq":"https://cdn.biztoc.com/34fec51cafcaf87c_sq.webp"},"published":"Thu, - 27 Jun 2024 07:36:36 GMT","title":"UBS Creates New Wealth Unit in Khan, Karofsky - Strategy Reboot","url":"https://www.bloomberg.com/news/articles/2024-06-27/ubs-unveils-new-wealth-strategy-under-khan-karofsky?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/4ea2d73048f23c34_s.webp","sq":"https://cdn.biztoc.com/4ea2d73048f23c34_sq.webp"},"published":"Thu, - 27 Jun 2024 07:49:43 GMT","title":"Russia Has Sent Around 10,000 Immigrants - to Front in Ukraine","url":"https://www.bloomberg.com/news/articles/2024-06-27/russia-has-sent-around-10-000-immigrants-to-front-in-ukraine?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/79f4306688fef94c_s.webp","sq":"https://cdn.biztoc.com/79f4306688fef94c_sq.webp"},"published":"Thu, - 27 Jun 2024 08:00:29 GMT","title":"Bonus Clawback: The Bloomberg Close, Asia - Edition","url":"https://www.bloomberg.com/news/newsletters/2024-06-27/bonus-clawback-the-bloomberg-close-asia-edition?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/8151aef0dd4fa159_s.webp","sq":"https://cdn.biztoc.com/8151aef0dd4fa159_sq.webp"},"published":"Thu, - 27 Jun 2024 08:00:31 GMT","title":"The American Entrepreneurs Who First Opened - The Chinese Market","url":"https://www.bloomberg.com/news/articles/2024-06-27/the-american-entrepreneurs-who-first-opened-the-chinese-market?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/06997e3c080c6a47_s.webp","sq":"https://cdn.biztoc.com/06997e3c080c6a47_sq.webp"},"published":"Thu, - 27 Jun 2024 06:52:18 GMT","title":"Foreign Funds Sell Japan\u2019s Stocks, - Longest Run Since March 2023","url":"https://www.bloomberg.com/news/articles/2024-06-27/foreign-funds-sell-japan-s-stocks-longest-run-since-march-2023?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/c8d8bd948e0f19a8_s.webp","sq":"https://cdn.biztoc.com/c8d8bd948e0f19a8_sq.webp"},"published":"Thu, - 27 Jun 2024 07:12:26 GMT","title":"India Plans \u2018Historic Steps\u2019 - in Budget Under New Government","url":"https://www.bloomberg.com/news/articles/2024-06-27/india-plans-historic-steps-in-budget-under-new-government?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/a023e218ff87db3a_s.webp","sq":"https://cdn.biztoc.com/a023e218ff87db3a_sq.webp"},"published":"Thu, - 27 Jun 2024 06:47:27 GMT","title":"Quant Mutual\u2019s Clients Pull $168 Million - in Days After Probe","url":"https://www.bloomberg.com/news/articles/2024-06-27/quant-mutual-s-clients-pull-168-million-in-days-after-probe?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/6d4cac6984c2b656_s.webp","sq":"https://cdn.biztoc.com/6d4cac6984c2b656_sq.webp"},"published":"Thu, - 27 Jun 2024 05:38:33 GMT","title":"Japan Inflation Outlook Jumps, Backing - BOJ Case for Rate Hike","url":"https://www.bloomberg.com/news/articles/2024-06-27/japan-inflation-outlook-jumps-backing-boj-case-for-rate-hike?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/db178aca5d2e7f0a_s.webp","sq":"https://cdn.biztoc.com/db178aca5d2e7f0a_sq.webp"},"published":"Thu, - 27 Jun 2024 05:49:13 GMT","title":"Macquarie Foresees Risk of Wider Yuan Trading - Band in China","url":"https://www.bloomberg.com/news/articles/2024-06-27/macquarie-foresees-risk-of-wider-yuan-trading-band-in-china?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/e83fb6bce870ccf7_s.webp","sq":"https://cdn.biztoc.com/e83fb6bce870ccf7_sq.webp"},"published":"Thu, - 27 Jun 2024 04:01:31 GMT","title":"India\u2019s Busy IPO Queue for Second - Half Goes Beyond Hyundai Unit","url":"https://www.bloomberg.com/news/articles/2024-06-27/india-s-busy-ipo-queue-for-second-half-goes-beyond-hyundai-unit?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/b9dabf7b272601a8_s.webp","sq":"https://cdn.biztoc.com/b9dabf7b272601a8_sq.webp"},"published":"Thu, - 27 Jun 2024 07:17:26 GMT","title":"GSK Drops as RSV Shot Suffers Fresh Blow - With US Recommendation","url":"https://www.bloomberg.com/news/articles/2024-06-27/gsk-drops-as-rsv-shot-suffers-fresh-blow-with-us-recommendation?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/e0ab66f4e886d30a_s.webp","sq":"https://cdn.biztoc.com/e0ab66f4e886d30a_sq.webp"},"published":"Thu, - 27 Jun 2024 07:08:51 GMT","title":"North Korea\u2019s Trash Balloons Can Endanger - Airplanes, Aviation Official Warns","url":"https://www.bloomberg.com/news/articles/2024-06-27/north-korea-s-trash-balloons-can-endanger-airplanes-aviation-official-warns?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/575d48ea58ba7100_s.webp","sq":"https://cdn.biztoc.com/575d48ea58ba7100_sq.webp"},"published":"Thu, - 27 Jun 2024 07:05:19 GMT","title":"Toyota to Offload Shares in Parts Maker - Aisin in $1 Billion Deal","url":"https://www.bloomberg.com/news/articles/2024-06-27/toyota-to-offload-shares-in-parts-maker-aisin-in-1-billion-deal?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/c8a7619792ea7414_s.webp","sq":"https://cdn.biztoc.com/c8a7619792ea7414_sq.webp"},"published":"Thu, - 27 Jun 2024 07:13:52 GMT","title":"China Miscalculated With Europe in Backing - Russia, US Envoy Says","url":"https://www.bloomberg.com/news/articles/2024-06-27/china-miscalculated-with-europe-in-backing-russia-us-envoy-say?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/32227393ba658fb1_s.webp","sq":"https://cdn.biztoc.com/32227393ba658fb1_sq.webp"},"published":"Thu, - 27 Jun 2024 07:00:06 GMT","title":"Weak Yen\u2019s Sway Over Japanese Stock - Market Is Unravelling","url":"https://www.bloomberg.com/news/articles/2024-06-27/weak-yen-s-sway-over-japanese-stock-market-is-unravelling?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/b32d08a7bf5b7ca2_s.webp","sq":"https://cdn.biztoc.com/b32d08a7bf5b7ca2_sq.webp"},"published":"Thu, - 27 Jun 2024 07:01:49 GMT","title":"Philippines Keeps Key Rate Steady as Peso - Hovers Near Record Low","url":"https://www.bloomberg.com/news/articles/2024-06-27/philippines-keeps-key-rate-steady-as-peso-hovers-near-record-low?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/399ef6b97458c6de_s.webp","sq":"https://cdn.biztoc.com/399ef6b97458c6de_sq.webp"},"published":"Thu, - 27 Jun 2024 07:11:42 GMT","title":"Campari Owner Rejects Claims After Reports - of \u20ac1 Billion Unpaid Taxes","url":"https://www.bloomberg.com/news/articles/2024-06-27/campari-owner-rejects-claims-after-reports-of-1b-unpaid-taxes?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/3d1ef51d324ca86d_s.webp","sq":"https://cdn.biztoc.com/3d1ef51d324ca86d_sq.webp"},"published":"Thu, - 27 Jun 2024 05:53:50 GMT","title":"Australia\u2019s No. 2 Pension Fund Says - RBA Won\u2019t Hike in August","url":"https://www.bloomberg.com/news/articles/2024-06-27/australia-s-no-2-pension-fund-reckons-rba-won-t-cut-in-august?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/939468f0d35ff041_s.webp","sq":"https://cdn.biztoc.com/939468f0d35ff041_sq.webp"},"published":"Thu, - 27 Jun 2024 06:30:10 GMT","title":"Rahul Gandhi Shares the Stage With Modi - After Years in His Shadow","url":"https://www.bloomberg.com/news/articles/2024-06-27/rahul-gandhi-finally-shares-stage-with-india-s-modi-bjp-after-years-in-shadows?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/98e137541f0e753e_s.webp","sq":"https://cdn.biztoc.com/98e137541f0e753e_sq.webp"},"published":"Thu, - 27 Jun 2024 06:45:25 GMT","title":"Top Rolex Seller Sees Signs of Stability - in UK Watch Market","url":"https://www.bloomberg.com/news/articles/2024-06-27/top-rolex-seller-sees-signs-of-stability-in-uk-watch-market?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/f8fce111e1d36341_s.webp","sq":"https://cdn.biztoc.com/f8fce111e1d36341_sq.webp"},"published":"Thu, - 27 Jun 2024 06:24:47 GMT","title":"Le Maire Says France Pulled in Extra \u20ac3 - billion in Tax Receipts","url":"https://www.bloomberg.com/news/articles/2024-06-27/le-maire-says-france-pulled-in-extra-eu3-billion-in-tax-receipts?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/15450a902a4d0722_s.webp","sq":"https://cdn.biztoc.com/15450a902a4d0722_sq.webp"},"published":"Thu, - 27 Jun 2024 03:16:49 GMT","title":"New World Tells Investors It Will Try to - Pay Perp Bond Next Year","url":"https://www.bloomberg.com/news/articles/2024-06-27/new-world-tells-investors-it-will-try-to-pay-perp-bond-next-year?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/0dfb5779d1e86302_s.webp","sq":"https://cdn.biztoc.com/0dfb5779d1e86302_sq.webp"},"published":"Thu, - 27 Jun 2024 06:26:29 GMT","title":"H&M Profit Misses as Summer Collections - Fail to Lure Shoppers","url":"https://www.bloomberg.com/news/articles/2024-06-27/h-m-profit-misses-as-summer-collections-fail-to-lure-shoppers?ref=biztoc.com"},{"body_preview":"","img":{"s":"https://cdn.biztoc.com/6b892da2567303db_s.webp","sq":"https://cdn.biztoc.com/6b892da2567303db_sq.webp"},"published":"Thu, - 27 Jun 2024 05:34:36 GMT","title":"Australian PM\u2019s Assange Welcome Sparks - Concern Over US Relations","url":"https://www.bloomberg.com/news/articles/2024-06-27/australian-pm-s-assange-welcome-sparks-concern-over-us-relations?ref=biztoc.com"}] - - ' + string: !!binary | + H4sIAAAAAAAAA6xcbW/cOJL+fr+CMBa4L+ZEry2pgcMhduwkO3GcSzvrm707LCix1OK2RGpIyp2e + xf73Q5HqTsbKLuRtfQmSjqsfmaV6f4r/87eLUvHDX3oNTwL2F+uLi8sL0W0v1n+7MBfri8ba3qxf + vaq4/KkUv1lV/VSp7lUdhMVqVfFixTLG8uov5qc9lP3F5YX59SVSv3qxv19e9EPZCtMAv1hf3Gpx + ScKc3FeWREGUkCBdh/k6isjbu4eLywsrbAsX64vrRkj2v0MUhIUh/zWAsaRWmlwz05APwLghVpFP + LZPu4wf2VcgtsQ2Qz6JqLi4vBt1+97D7/f6nslWqK0Fv3fNK2Bv3RwvWgjav8GFoGNAwf1UhNjX0 + V4SltdK0YqahLcJSq2jfMuk+tg6W2gaoFlXznxrq//h2Jhd/v/zXNJCVcVbUeV6zMkrqOp+nganU + CzQQrKPVMw3cDFr1QK40q8C4U2ZkY0Vdk+tWdMwCuWLVrmXm3OMGB0RLB+TOlVGDQLTyQLQcgZY6 + YFbyqKhCxuMkLxK+mnfAU6n5BxyE6yh7dsDvgPFmkBY02TDB8YX+YoDcsh2Q9xykFVaAe8/fDD2Q + R9a2ZGM1gCUPmnHQZu7BM21F1cLvTr05oVPDBMf3ejBAa7YDKk7o+DEfeqB71rbUOHRqPfpS2uBp + VierAlYsKMKgLudpYyo1VxvJOinWYfBMGw9M7JkkG3YwxDkf8kVvgZONGmxDXtdaVAx1ca85aPIz + HMh9XYsKyJ16An6OJqxDpoYdDPWuZ0BkahCZMoeMelCITHdwoMoh0w6RF3M6SVwAD9I4D9KkZjO1 + MJWar4UgWAfhMy08AmttcyC3GmTVkGvV9UweyP1egjbeFzlX9F42oIVlsgJ0/uS6YXILZxnE3kPT + 2kHTmnWiRQtwfslHAQeCqhDf4DEIUD20sJg9pLBieZ5BmdVVzpN6niamUi/QRLhOn9vD1f3PZAM+ + 6j40GoB8Rp9/PViDf2sAP2aSPOwVERK/Kr0km0E/wcEZ0TmqKNWOGvCh1yI21RgGqsEa/FsD+DGT + 1O5RFRSxqXHQzoqWM4mcs1XIWJmxNK7mxuGJ1MtM4rkiNnthDNkwWVmhpCGvtyCrA/mkVQmG3Ard + GXLzxDgmQJ8HYwQjn8FYLfzPn6MHg9DUHKEpc9C0d9C0RmgKHppqB031d9BL6aGI87qM4iqtqnKV + rGZmpFOpJfTwznkJ8hlqpTvylglpyGboe6UtuRosuVZDy8kvYMktE+0l+aQwajdqv4AiGodNtcOm + W8SmxmPTcrC0Qmx6QMNhoqW9wpCN0IspIilWQZwmSRYlBY9neqap1HmKuPlyrAveagBJNo2oLfki + OXhPxSxhxtUC74TFkH2tpBk6DCBvAb0XsPYcZcBADd0iNDUITQeEdo6KWcqMqwcaYTFQVEdougV0 + XsDapZSRxMAjSCtelisWxTO901TqTGVcX5F3zJDPYttYcquqwRAlyRWTO/JZmJ0hjLyBinEg9/KS + 3HylLm0SrD07SkBV0oYZqhGa1ghNlaQlkzuqEZoyyh00fgxffdokWLtokCiykq+gDFiZJrzOs5k2 + MZF6QfYarMPnedMb1gpFblu2NaMNmFOy2h6wXpBGoFMmqiaf1B40Bm20kS+bc3TAEZfWiDsagDml + qu0BK4URl6qa9oiLARsNZFguXwojKLNVEYUrFsSrmdXcVGq+BuJ8HRfP64eGWbKRrO8xEG/UIDl5 + bwhW0fS9rFuGp3B0XB+h2s04dtULKZT8h2//MSvCbMhSM4Jj4SA5FYZiZU3FEZwaKqHaLfbir4q8 + CuM4ilZxxqq5UXki9YJjD6ZF9CPThu3J+0/35A2Ug8WqzHn6VnS9Af+647eSO6Z3GJaVtoOcXyr8 + g6bF3uFS0SvKERedi3PzHte/7ohLO4eLuazDXer4qyrM4wqKrArSrKzZvOOfSp3n/r/8TK4GIyQY + AxhZOyYkeWT6gAf/gZVq0OR1jS2O64bpzmlHGvEE5zidYUfLEyjVDpTumcbCmLYOlDIExYpNd041 + DnSps4/DLIcwCXnEyryuw3lnP5U67+w/4Ru1ZS15q1oOkvxJGEZe930rKiatIRs7VDt08x9EV/re + 0gfAn7/vz64M+hGbbh02fRKGUXbCpgax0dW3iO06Sy1iU9UvWhpEGV9VeZonNQvKcG6tPJV6kSbi + +Jkm3kuy6VkFl+SjIvcSyDWTWClocjeY3b9jdvTEWkM2lQbWnen4u8HsKJOcGoT8SrX7blphPUwN + QOfyTmarhg79Yj26KueMpWUcVkmep3xmj24i9aKexMTZvyZXWu1AknvRkk+ih1ZIIJ/aAXs/Y6du + M3B2irPXrBeWteS9xDKgYWr2S18Ds4N+VoW5hpxBAGroX4eSUQPSUiHxxPHbR7ejsPoaH4+WGthu + ObfPeZhGVR2FWREn0cw23VTqRS989DzZeavUtoXjKV/hbzj05CMAN4RJPG7Q0iUdrCUPbEsezn/v + tw6TGn+gQ08lwlEm8fy/wVGGrWs9GEst21ILrFtsbBCtwigLyzKuoiLjM0PuVOplzmbSIm1cPu/6 + PeqYw5ObFlzTBXNORpxm8lul2qOObrRmkvt/nef4ecWMpfvGZfeu9aOOGT2F8Skw+WS0VqqlhoKD + XqzsDYI8KVarOgwhWWUzlTCVOs8AHvTQ9ZfkHdNamEvyZ2hBmp04rMlHhb/V8djdhPJRtC25kdzr + aqcZeq1Hps80CIvPQBv3CPS34xNQ6R6AGj+m3Iu2pSC515DHxlxpKXWEWRrzqAo5j1lazrWJqdTL + 1PE8MFy1rNqRR6V3mPsLSa6F9Smokly5qQ55L6t2MKOJfFT4X1vAoeYnLZQW9nCOWVTC+uzT4aGT + wieie/9E2HCg4oiPxiEV/ugWcNbZj/hLqaROS17xOl7FnMc8CGYO8CdS57mpt6A7JsmVaFv0y0KD + cQHCN+Q6QC3datU5o7hWLT83PDg8Wn6H5yKE78J1gMlorVXnDKFS7WIOKViFSRpBzuswARan8457 + KjX3uON1Gq7D53yJK7ElH1U3aIbjecD8/x1rx0mxIY/CNm5WQO6fQJM7JkU/+LYAcirOKsdKsaXS + QePAHqFpw9pxTGzoXtjGzQqoegJNu++gkVexWFHGozCMeJCWaV6xFU9mpqgTqfl6iIJ1kjwvyq7u + r53XN+QOwGKQdmd/rYELSz8z95Gf2qBjsjhUUzV5L/lgrD7LCfWlqpzXN7Tz2P7wK4+tHfY4tkEn + hdjotMSIvZQmyiwJ0gyiPK+LFKqZxcJUar4mwnCd5j/SxMYyjaVwwzSQq+GATJJLcvPrgPFhs2c9 + ztG2mnWuXXqllLFjo8icrQnjsKlBbFp6bAoOmpo963GO5qDRRZUIPfaKlutN53EZFGGa52EaQj23 + RTeRepEiJlQulyt5YsU7II9uQIYjGYEDm8/Qiq1QgyE3X6HzzQEfIp5Ao6m8/9PtWeQKlyQ5bkUD + dO8mZNUITvURnMIJ3I33n2paMb2Ya8qjvIjrKirjpI5iFs3Tw1Rqrh6idRpPXdPvKHUbC9CS+8H2 + gyVMcnKtB5zRiBZnm0Li0V8raYUcAPWxaYeuPytDGkl1BoGpcsCujVEhsCuZ9QiMCnLAqAuDwMs1 + TaEMAlgFYVYlWZTObZo+l5qviChfp8+Lh5sONE7S4Vt/wngK2HWrjDvuz0wYVMEfwmMGhUHidpD8 + vJHZEZlWHhlzUUf/qhAZz1t7ZBoeUymMEDUCL2cNLEjThK1WUVgkyWxreC71Amso1lHwQ6903QhM + j3wd57gum53wI5zHRligDwLIGyElaIKxlHz85ZrctMLC+U6pctjHAg65LmbEpnuHbQVQ7rB9HJeH + igJiL6UJiLKiyjKW1hnUSTDTHKZSL/JLk1r6vayVOeD04AnQ27wdBHfELqvIBxztv5dcYFfpgWyg + skqfc/QCv+s4kymH337D+RjCU+3h6XaER2NocbwvLDW90GK5uByzpAqzLC3KgCVZOXN0P5Waf+5J + OiX4epbjZzBq0EjxvYIn0GwLJ2+Ebh8s1scVkD+skoLcjb4Ix23MkgfVo1v6jLS482ODPj4JLccn + OXknjANgsVKugK6Sgnajb8L5G0OmRY9uSuODLFZGl2Fe11XM4irI49XMzsZUan7yhJ2NeOKmRAnV + KWx/EAP5yEpD3gjkWZWDq+CQSXxJrm/unQf7CHvyDvgWXLz41/WSvbIenBraioFKVhrKv8NFQhJ3 + jkvCnjYI6SLFYhVdkFSrMCzCMCxxWjmzoptIzTeT+AdjtiumnVWommysqnaO7tUe0Eo+MIuLCQ/H + 7YTRUflqw5cRZxXWHhnfbIPIjuzVHtAqWodM7XFBwbk1OdYa3rstR0cNojznEEV5la2KcC4d9bnU + fC2ExXTEdsVa4aoGqwff6L7C7lKrqh1wUh7IB1W50WavPOHkktwJKYxn159JR2WtcEXDERs5RrT0 + 2LQ80BaxqTph026EXpRpBFXJGVtVEEIalmxmg2MqNV8RQTBtNP2uirgdtGMCb1q152ovyTuxbVrk + YxlHn0eiKhrGndKAyyPd0A5miSqi9sDUjMC0OQE79jzSVNEuOqUBl0kc8GI975yXLK6TGlarMK9n + 9jemUi+wiGgdPC/nPiptG/Kz0sB8pJachMFlEATkQSvVuzJ6nDZ8N6HAwcN5s3+JwHSHwD4wS47/ + EwQBtQ7Y7ZKMo4Zvc4k94i5WQwRRWearVVGlQVHMbfZNpeaqIFwH+XRb4U5YM5TCNAJ7S1hU4+6O + kC4x+tSI1qXzQG5xQlk1yD0if4jD/JhHnaOF7oSNvSWsq93mjnS5UH/CprXHdtYQh/kxc1pMEXFQ + Qs3yVRhCzuOZ0WEq9SKnNJn//JH134b+D/jmkQ/YQDLkNTqeIyvvS+9jsxsRMXIFLW7QkDuwWp1V + z6ndQdEOv8ZlpC0yB6gGizRsIZ/AWKUNKuev+KBjSxz3Gix0PTbOt6qtF0ubOGQsX/Eg5FGVzuXE + TKXm20aSTG1jzIWQCGy8ZjAj2iJf/t2gLYbsG5yHPQF5Ay5wGqRtf1syed33yKDBRJdJe3bN54nB + BpMjfAjaDMiaP1DwD0H5+BBI4P62bcLcQ7isl8nFUqqoCBNe1CXkRVoW9UzvNZV6gYbidfK8/vsF + TiazaQV39XaYBuQTnr6zKJxQvG5B++z2GOwfge0A+3Tn6OSA7HlqEBfDRZgGtMcD9waiJGWI67zW + Mdbvj7iLzSlSiKMyrliSVhDxeOacYiI1Xw1ptE6yf7B4uGc9TkgZ9sQrpbnLpdyQ6E5JsMipfMAE + xx0BuTpzQnFcOkRUKvEd1w7VJVJuPNSNqNSeUGm54HCCFzmkqzzLGGdxUcysr6dSLzCCcB39sClO + 3uFA2vc5XKObvNHIpL+X5A2YXljA5hTy7MhNjUTeBXLYBmfSvqHhWtyUIyQePPeQ2JBCSAoecrHm + U5kUYZ2WSRIGZRLOPPep1NxzD1z79YdlBHmr1R45e26Np1V7fLNvnkBiJHg92AZ5EbgD/VpKNUin + Hdj7SvxltUSLLr5s1XaqiC3v3VItVEqqTlSulq4YRuzFiGNhWUJYrgqep5DDzD7rVGr+qx7F6zj6 + Z0nS7X9j7xtqXw64UfTAkUWM68xm5Gz/AljRWePCwtldPu/aDa2/Yusbal8RuEm0g3b7zEcKJcaH + BsMxRoZF+3pFkMZRHnOI0yzOspnKmEq9oHQIp9Xb78roO9gynymRBy26Y0LkkiGXFR1fd6+NT1rV + wi5SR3ewZWNiZLXojlmQy4BcKnSsnb0yeo+8WAhY5VEBnBdRXUQxn8lUmkrNd0VJPN3cuVW6wx6G + ZXWNvuU1kiFYKxyH+9hGJZ8ddR6z2soCxwLCld7nKKF2wFi51TU2+dgJ+LtmKtWONy9GYCwiXOm9 + 2Ei0gCheRUUapxGrYC6heCL1Ah2s1kn6z8zBs1fxLQdjPIf4uhEt18eElTwy6TY7r4YD+QDGuAn2 + zdcetHBzVew3ncP0di/6ERy9lQOn2Fz1W24+HTpaEaZOT7AcgSbMyjrP6qIMw7JKwnwuqfK51Hyd + YJR+rpPHx5uRyYQThStoxEgj3VQgwZA3qho6kC4z3eDJm3H8YOtWfD3rKoY9jDwmHCyU35CNQ6b8 + GzI1DnmcQjjkxaq0VRJmrE7zOmRQzO23TqV+rIWHZrgkYfZNCxiyk3X6PFAgI2NjgXFxovEdl2zv + BOctkBtm7Biw37GOGXc/EmjyBphtzhn/jEMGpGaMA1P8UUfaYJK1BzOOrVVlaZgvlp+mQZ6zNORx + DHFQzs1PJ1Jzjz1aR8WUo3ENuFRQaoF+GC86Ao77bDj18ZvmnzQYM2g4rbdBJ3ACcSs0nHPo1ffA + pQPGnTYc+vg9834EPq24eWDk9S2WI2VpCkFZVDULV0mZzOxwT6Xmv/pJuA7iyZZJy8k738f7vjBm + Bl99YG70Jo2jjG16pnfkHcPi4Q107LzBJ2610cYh/644ZoZ2HpnaERnXsPSONohMuUNebPK2gqha + lRAEAdRlNjM0T6VeoIV8Onn7Xdlw2mR25Zp3+LdCoyZEB2QjMPq+7rVoyWucDmM+dXX/x3N0cSwb + vttjRmjfGkJoasVI78Yir1PSNkghqHH0U6q/Lnf5RVIHENRQxnmaRsXcyy+eS83Xxo+WPj8+CSSw + jB7JMbpvDhiMmWXEOy1vK79T28ehavFDt/l/jjKkhx/9kmN1wwEjMrOMetflDeaoNemR/e7/YiEi + CNOihjyGYlXn5czG3VRqfoiIi3W8+oF7whUH3G0zOFtw0dmtohirpKdNQtuSj+oJWl9F3ArpqE1X + 6nwHhesOuN5m6ND7kUJ5wvaDubalErF9IVF7bFqq5VxUuUqLMmYZK+p4tZo7/plKzddEEk5d1JeN + a5bSt7hxMFLtyabX7p7IW7w3zyq3Z/JB7ZGrgRO6PUh7IL8AO+caveyVq4y3Dd0i9JFpbzw0rfHS + PKtc6to6aDegc9D0gNCLBeyqrPNVhTlnEAZzm6lTqfnOKczX4fNW9sdfrq9ODSa8E8Qy7Yc5WRCM + BbYzEscHwIsNoWfa6eOLRJWx9qzcSR6qEhtMI7Qf4WRBMJbYzkYcIwBvNXTQqI9BospYu1j2lKQ1 + z9IiZEVdp1Uwk3Y/lXqBMtIf3Fc13krliEldJ7baB27cjmOScXZanEae5ckw/GU9Z9nE8U4qR0z6 + hoxnXTlk2ntkR7E82YW/q2cxk0iyMApZXadBHCV1NvNinqnUy+qI52NQdPTGh4H7usbUdby7k3wG + 1/0nt8C/TT3Xx+0T8qhZf5YSHGNsrNus4uxAudrjWih1zfCh51jeLdfizvIqZBleZsR4PPdK1YnU + CwJBuo6TaSDAe0bwpR7nz28xiZfYLCA3Xd+qAziCxqdWuQbSz7iai1LCit9AnhkJKo99ZONtT9gU + Rmx8z/tWubvBdriai1Iee7E8NYoqgKDM6yJi2ewLqSZSL3jv86n3wYsvjrOFeuzo3TFO7tjXsYen + 9Pjxn1VXCqwakEV36M14rwC5RaPwxbbn55+jHXdrxjhwqGnHOO3YV6o0/c2hU3ZCpzVO/32t7bn5 + E83837/9PwAAAP//AwCUFTALXFsAAA== headers: CF-Cache-Status: - DYNAMIC CF-RAY: - - 89a4a7f75ec918de-FRA + - 8d46253e7fd558ba-IAD Cache-Control: - no-store, no-cache, must-revalidate, max-age=0 Connection: - keep-alive Content-Encoding: - gzip - Content-Length: - - '5904' Content-Type: - application/json Date: - - Thu, 27 Jun 2024 10:11:59 GMT + - Fri, 18 Oct 2024 05:32:01 GMT NEL: - '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}' Report-To: - - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=yNZDg0%2BZ2k%2FVgkUiTSGQCmqLRboOxdmahSxGhMzK2yxlnLsMIPrriLCq5vOBmzsVz5jCzYKR0LYKlBNcIaW05p5i55ZwAAjhWP77VyyyNwQUe393E1bdGzZetho%3D"}],"group":"cf-nel","max_age":604800}' + - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=1jncDmrg1XfuP0IcLzSdFqxnDMUXcq%2FYLEq7Y47JCzrfHGKMIYKTdVDqO5wAJ1CDVG8lCorUMgO5Aw5pGQ4cBY8eGoB%2FI0iTPcN%2FHHf9%2Bz3zMUu9I%2FdQYPbfHmI%3D"}],"group":"cf-nel","max_age":604800}' Server: - RapidAPI-1.2.8 Strict-Transport-Security: - max-age=31556926; includeSubDomains + Transfer-Encoding: + - chunked Vary: - Accept-Encoding, Cookie X-RapidAPI-Region: - - AWS - eu-central-1 + - AWS - us-east-1 + X-RapidAPI-Request-Id: + - c9f0a6fb613c5c0a2361b3f48bba6dcc7bc83feaa827675cb22eb492b1669872 X-RapidAPI-Version: - 1.2.8 X-RateLimit-Requests-Limit: - '2000' X-RateLimit-Requests-Remaining: - - '1994' + - '1913' X-RateLimit-Requests-Reset: - - '1996935' + - '1620568' X-RateLimit-rapid-free-plans-hard-limit-Limit: - '500000' X-RateLimit-rapid-free-plans-hard-limit-Remaining: - - '499994' + - '499960' X-RateLimit-rapid-free-plans-hard-limit-Reset: - - '1996935' + - '1620568' alt-svc: - h3=":443"; ma=86400 permissions-policy: @@ -306,7 +288,7 @@ interactions: referrer-policy: - strict-origin-when-cross-origin rndr-id: - - 6526935a-5651-4667 + - 8911030f-1e15-4bb9 x-content-type-options: - nosniff x-render-origin-server: diff --git a/openbb_platform/providers/fmp/openbb_fmp/models/economic_calendar.py b/openbb_platform/providers/fmp/openbb_fmp/models/economic_calendar.py index ab1b5f5ba62..8fc63118de7 100644 --- a/openbb_platform/providers/fmp/openbb_fmp/models/economic_calendar.py +++ b/openbb_platform/providers/fmp/openbb_fmp/models/economic_calendar.py @@ -2,7 +2,6 @@ # pylint: disable=unused-argument -import asyncio from datetime import datetime, timedelta from typing import Any, Dict, List, Optional from warnings import warn @@ -13,7 +12,7 @@ from openbb_core.provider.standard_models.economic_calendar import ( EconomicCalendarData, EconomicCalendarQueryParams, ) -from openbb_core.provider.utils.helpers import amake_request +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError from pydantic import Field, field_validator, model_validator @@ -97,6 +96,11 @@ class FMPEconomicCalendarFetcher( **kwargs: Any, ) -> List[Dict]: """Return the data from the FMP endpoint.""" + # pylint: disable=import-outside-toplevel + import asyncio # noqa + from openbb_core.provider.utils.helpers import amake_request + from openbb_fmp.utils.helpers import response_callback + api_key = credentials.get("fmp_api_key") if credentials else "" base_url = "https://financialmodelingprep.com/api/v3/economic_calendar?" @@ -123,12 +127,12 @@ class FMPEconomicCalendarFetcher( """Get data for one URL.""" n_urls = 1 try: - result = await amake_request(url, **kwargs) + result = await amake_request(url, response_callback=response_callback) if result: - if "Error Message" in result: - raise OpenBBError(result["Error Message"]) results.extend(result) - except Exception as e: + except UnauthorizedError as e: + raise e from e + except OpenBBError as e: if len(urls) == 1 or (len(urls) > 1 and n_urls == len(urls)): raise e from e warn(f"Error in fetching part of the data from FMP -> {e}") @@ -136,6 +140,9 @@ class FMPEconomicCalendarFetcher( await asyncio.gather(*[get_one(url) for url in urls]) + if not results: + raise EmptyDataError("The request was returned empty.") + return results @staticmethod diff --git a/openbb_platform/providers/fmp/openbb_fmp/utils/helpers.py b/openbb_platform/providers/fmp/openbb_fmp/utils/helpers.py index 53d7aba1dd5..8c46bf16b8c 100644 --- a/openbb_platform/providers/fmp/openbb_fmp/utils/helpers.py +++ b/openbb_platform/providers/fmp/openbb_fmp/utils/helpers.py @@ -4,19 +4,27 @@ from datetime import date from typing import Any, List, Optional, Union from openbb_core.app.model.abstract.error import OpenBBError -from openbb_core.provider.utils.errors import EmptyDataError +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError from openbb_core.provider.utils.helpers import get_querystring async def response_callback(response, _): """Use callback for make_request.""" data = await response.json() - if isinstance(data, dict) and "Error Message" in data: - raise OpenBBError(f"FMP Error Message -> {data['Error Message']}") - if isinstance(data, dict) and "error" in data: - raise OpenBBError( - f"FMP Error Message -> {data['error']}. Status code: {response.status}" - ) + if isinstance(data, dict): + error_message = data.get("Error Message", data.get("error")) + if error_message is not None: + conditions = ( + "upgrade" in error_message.lower() + or "exclusive endpoint" in error_message.lower() + or "subscription" in error_message.lower() + or "unauthorized" in error_message.lower() + ) + if conditions: + raise UnauthorizedError(f"Unauthorized FMP request -> {error_message}") + raise OpenBBError( + f"FMP Error Message -> Status code: {response.status} -> {error_message}" + ) return data diff --git a/openbb_platform/providers/intrinio/openbb_intrinio/models/company_news.py b/openbb_platform/providers/intrinio/openbb_intrinio/models/company_news.py index 446c4d431a8..3681a9d1e9a 100644 --- a/openbb_platform/providers/intrinio/openbb_intrinio/models/company_news.py +++ b/openbb_platform/providers/intrinio/openbb_intrinio/models/company_news.py @@ -11,7 +11,7 @@ from openbb_core.provider.standard_models.company_news import ( CompanyNewsData, CompanyNewsQueryParams, ) -from openbb_core.provider.utils.errors import EmptyDataError +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError from openbb_core.provider.utils.helpers import ( amake_request, get_querystring, @@ -219,8 +219,14 @@ class IntrinioCompanyNewsFetcher( async def callback(response, session): """Response callback.""" result = await response.json() - if "error" in result: - raise OpenBBError(f"Intrinio Error Message -> {result['error']}") + + if isinstance(result, dict) and "error" in result: + if "api key" in result.get("message", "").lower(): + raise UnauthorizedError( + f"Unauthorized Intrinio request -> {result.get('message')}" + ) + raise OpenBBError(f"Error in Intrinio request -> {result}") + symbol = response.url.parts[-2] _data = result.get("news", []) data = [] diff --git a/openbb_platform/providers/intrinio/openbb_intrinio/models/forward_ebitda_estimates.py b/openbb_platform/providers/intrinio/openbb_intrinio/models/forward_ebitda_estimates.py index 574b61c9c9b..ccdb683140f 100644 --- a/openbb_platform/providers/intrinio/openbb_intrinio/models/forward_ebitda_estimates.py +++ b/openbb_platform/providers/intrinio/openbb_intrinio/models/forward_ebitda_estimates.py @@ -12,7 +12,7 @@ from openbb_core.provider.standard_models.forward_ebitda_estimates import ( ForwardEbitdaEstimatesData, ForwardEbitdaEstimatesQueryParams, ) -from openbb_core.provider.utils.errors import EmptyDataError +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError from openbb_core.provider.utils.helpers import ( amake_request, get_querystring, @@ -135,9 +135,15 @@ class IntrinioForwardEbitdaEstimatesFetcher( async def fetch_callback(response, session): """Use callback for pagination.""" data = await response.json() - messages = data.get("messages") - if messages: - raise OpenBBError(str(messages)) + error = data.get("error", None) + if error: + message = data.get("message", "") + if "api key" in message.lower(): + raise UnauthorizedError( + f"Unauthorized Intrinio request -> {message}" + ) + raise OpenBBError(f"Error: {error} -> {message}") + estimates = data.get("ebitda_consensus", []) # type: ignore if estimates and len(estimates) > 0: results.extend(estimates) diff --git a/openbb_platform/providers/intrinio/openbb_intrinio/models/forward_eps_estimates.py b/openbb_platform/providers/intrinio/openbb_intrinio/models/forward_eps_estimates.py index c466d04711b..c49033fcc6c 100644 --- a/openbb_platform/providers/intrinio/openbb_intrinio/models/forward_eps_estimates.py +++ b/openbb_platform/providers/intrinio/openbb_intrinio/models/forward_eps_estimates.py @@ -13,7 +13,7 @@ from openbb_core.provider.standard_models.forward_eps_estimates import ( ForwardEpsEstimatesData, ForwardEpsEstimatesQueryParams, ) -from openbb_core.provider.utils.errors import EmptyDataError +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError from openbb_core.provider.utils.helpers import ( amake_request, get_querystring, @@ -165,9 +165,15 @@ class IntrinioForwardEpsEstimatesFetcher( async def fetch_callback(response, session): """Use callback for pagination.""" data = await response.json() - messages = data.get("messages", None) - if messages: - raise OpenBBError(str(messages)) + error = data.get("error", None) + if error: + message = data.get("message", "") + if "api key" in message.lower(): + raise UnauthorizedError( + f"Unauthorized Intrinio request -> {message}" + ) + raise OpenBBError(f"Error: {error} -> {message}") + if data.get("estimates") and len(data.get("estimates")) > 0: # type: ignore results.extend(data.get("estimates")) # type: ignore while data.get("next_page"): # type: ignore diff --git a/openbb_platform/providers/intrinio/openbb_intrinio/models/forward_pe_estimates.py b/openbb_platform/providers/intrinio/openbb_intrinio/models/forward_pe_estimates.py index 5498703e368..d56e5c45def 100644 --- a/openbb_platform/providers/intrinio/openbb_intrinio/models/forward_pe_estimates.py +++ b/openbb_platform/providers/intrinio/openbb_intrinio/models/forward_pe_estimates.py @@ -13,7 +13,7 @@ from openbb_core.provider.standard_models.forward_pe_estimates import ( ForwardPeEstimatesData, ForwardPeEstimatesQueryParams, ) -from openbb_core.provider.utils.errors import EmptyDataError +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError from openbb_core.provider.utils.helpers import amake_request from openbb_intrinio.utils.helpers import response_callback from pydantic import Field @@ -108,7 +108,11 @@ class IntrinioForwardPeEstimatesFetcher( data = await response.json() error = data.get("error", None) if error: - message = data.get("message", None) + message = data.get("message", "") + if "api key" in message.lower(): + raise UnauthorizedError( + f"Unauthorized Intrinio request -> {message}" + ) raise OpenBBError(f"Error: {error} -> {message}") forward_pe = data.get("forward_pe") if forward_pe and len(forward_pe) > 0: # type: ignore diff --git a/openbb_platform/providers/intrinio/openbb_intrinio/models/forward_sales_estimates.py b/openbb_platform/providers/intrinio/openbb_intrinio/models/forward_sales_estimates.py index 54cac4dacc3..013dc06810c 100644 --- a/openbb_platform/providers/intrinio/openbb_intrinio/models/forward_sales_estimates.py +++ b/openbb_platform/providers/intrinio/openbb_intrinio/models/forward_sales_estimates.py @@ -13,7 +13,7 @@ from openbb_core.provider.standard_models.forward_sales_estimates import ( ForwardSalesEstimatesData, ForwardSalesEstimatesQueryParams, ) -from openbb_core.provider.utils.errors import EmptyDataError +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError from openbb_core.provider.utils.helpers import ( amake_request, get_querystring, @@ -184,9 +184,14 @@ class IntrinioForwardSalesEstimatesFetcher( async def fetch_callback(response, session): """Use callback for pagination.""" data = await response.json() - messages = data.get("messages") - if messages: - raise OpenBBError(str(messages)) + error = data.get("error", None) + if error: + message = data.get("message", "") + if "api key" in message.lower(): + raise UnauthorizedError( + f"Unauthorized Intrinio request -> {message}" + ) + raise OpenBBError(f"Error: {error} -> {message}") if data.get("estimates") and len(data.get("estimates")) > 0: # type: ignore results.extend(data.get("estimates")) # type: ignore while data.get("next_page"): # type: ignore diff --git a/openbb_platform/providers/intrinio/openbb_intrinio/models/world_news.py b/openbb_platform/providers/intrinio/openbb_intrinio/models/world_news.py index b625d91267c..e6f396e98ff 100644 --- a/openbb_platform/providers/intrinio/openbb_intrinio/models/world_news.py +++ b/openbb_platform/providers/intrinio/openbb_intrinio/models/world_news.py @@ -5,14 +5,13 @@ from datetime import datetime, timedelta from typing import Any, Dict, List, Literal, Optional, Union +from openbb_core.app.model.abstract.error import OpenBBError from openbb_core.provider.abstract.fetcher import Fetcher from openbb_core.provider.standard_models.world_news import ( WorldNewsData, WorldNewsQueryParams, ) -from openbb_core.provider.utils.errors import EmptyDataError -from openbb_core.provider.utils.helpers import amake_request, get_querystring -from openbb_intrinio.utils.helpers import get_data +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError from openbb_intrinio.utils.references import IntrinioCompany, IntrinioSecurity from pydantic import Field, field_validator @@ -185,6 +184,10 @@ class IntrinioWorldNewsFetcher( **kwargs: Any, ) -> List[Dict]: """Return the raw data from the Intrinio endpoint.""" + # pylint: disable=import-outside-toplevel + from openbb_core.provider.utils.helpers import amake_request, get_querystring + from openbb_intrinio.utils.helpers import get_data + api_key = credentials.get("intrinio_api_key") if credentials else "" base_url = "https://api-v2.intrinio.com/companies" @@ -200,6 +203,14 @@ class IntrinioWorldNewsFetcher( async def callback(response, session): """Response callback.""" result = await response.json() + + if isinstance(result, dict) and "error" in result: + if "api key" in result.get("message", "").lower(): + raise UnauthorizedError( + f"Unauthorized Intrinio request -> {result.get('message')}" + ) + raise OpenBBError(f"Error in Intrinio request -> {result}") + _data = result.get("news", []) data = [] data.extend( diff --git a/openbb_platform/providers/intrinio/openbb_intrinio/utils/helpers.py b/openbb_platform/providers/intrinio/openbb_intrinio/utils/helpers.py index b55b72543a5..d546cd13055 100644 --- a/openbb_platform/providers/intrinio/openbb_intrinio/utils/helpers.py +++ b/openbb_platform/providers/intrinio/openbb_intrinio/utils/helpers.py @@ -10,7 +10,7 @@ from io import StringIO from typing import Any, Dict, List, Optional, TypeVar, Union from openbb_core.app.model.abstract.error import OpenBBError -from openbb_core.provider.utils.errors import EmptyDataError +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError from openbb_core.provider.utils.helpers import ( ClientResponse, ClientSession, @@ -63,8 +63,10 @@ async def response_callback( """Use callback for async_request.""" data = await response.json() - if isinstance(data, dict) and response.status != 200: + if isinstance(data, dict) and (response.status != 200 or data.get("error")): if message := data.get("error", None) or data.get("message", None): + if "api key" in message.lower(): + raise UnauthorizedError(f"Unauthorized Intrinio request -> {message}") raise OpenBBError(f"Error in Intrinio request -> {message}") if error := data.get("Error Message", None): diff --git a/openbb_platform/providers/tiingo/openbb_tiingo/models/company_news.py b/openbb_platform/providers/tiingo/openbb_tiingo/models/company_news.py index 3f12de18d6a..fe11aed1ee7 100644 --- a/openbb_platform/providers/tiingo/openbb_tiingo/models/company_news.py +++ b/openbb_platform/providers/tiingo/openbb_tiingo/models/company_news.py @@ -2,7 +2,6 @@ # pylint: disable=unused-argument -import math from datetime import datetime from typing import Any, Dict, List, Optional @@ -12,7 +11,7 @@ from openbb_core.provider.standard_models.company_news import ( CompanyNewsData, CompanyNewsQueryParams, ) -from openbb_core.provider.utils.helpers import amake_requests, get_querystring +from openbb_core.provider.utils.errors import EmptyDataError from pydantic import Field, field_validator @@ -27,7 +26,10 @@ class TiingoCompanyNewsQueryParams(CompanyNewsQueryParams): "start_date": "startDate", "end_date": "endDate", } - __json_schema_extra__ = {"symbol": {"multiple_items_allowed": True}} + __json_schema_extra__ = { + "symbol": {"multiple_items_allowed": True}, + "source": {"multiple_items_allowed": True}, + } offset: Optional[int] = Field( default=0, description="Page offset, used in conjunction with limit." @@ -87,6 +89,12 @@ class TiingoCompanyNewsFetcher( **kwargs: Any, ) -> List[Dict]: """Return the raw data from the tiingo endpoint.""" + # pylint: disable=import-outside-toplevel + import asyncio # noqa + import math + from openbb_core.provider.utils.helpers import get_querystring + from openbb_tiingo.utils.helpers import get_data + api_key = credentials.get("tiingo_token") if credentials else "" base_url = "https://api.tiingo.com/tiingo/news" @@ -106,7 +114,22 @@ class TiingoCompanyNewsFetcher( else: urls = [f"{base_url}?{query_str}&token={api_key}&limit={limit}"] - return await amake_requests(urls) + results: list = [] + + async def get_one(url): + """Get data for one URL and append results to list.""" + response = await get_data(url) + if isinstance(response, list): + results.extend(response) + elif isinstance(response, dict): + results.append(response) + + await asyncio.gather(*[get_one(url) for url in urls]) + + if not results: + raise EmptyDataError() + + return results @staticmethod def transform_data( diff --git a/openbb_platform/providers/tiingo/openbb_tiingo/models/crypto_historical.py b/openbb_platform/providers/tiingo/openbb_tiingo/models/crypto_historical.py index d413ccace61..93862a0530c 100644 --- a/openbb_platform/providers/tiingo/openbb_tiingo/models/crypto_historical.py +++ b/openbb_platform/providers/tiingo/openbb_tiingo/models/crypto_historical.py @@ -3,71 +3,74 @@ # pylint: disable=unused-argument from datetime import datetime -from typing import Any, Dict, List, Literal, Optional +from typing import Any, Literal, Optional, Union from warnings import warn -from dateutil.relativedelta import relativedelta +from openbb_core.app.model.abstract.error import OpenBBError from openbb_core.provider.abstract.fetcher import Fetcher from openbb_core.provider.standard_models.crypto_historical import ( CryptoHistoricalData, CryptoHistoricalQueryParams, ) from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS -from openbb_core.provider.utils.helpers import ( - ClientResponse, - amake_requests, - get_querystring, -) -from pydantic import Field, PrivateAttr, model_validator +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError +from pydantic import Field class TiingoCryptoHistoricalQueryParams(CryptoHistoricalQueryParams): """Tiingo Crypto Historical Price Query. - Source: https://www.tiingo.com/documentation/end-of-day + Source: https://www.tiingo.com/documentation/crypto """ __alias_dict__ = { - "symbol": "tickers", "start_date": "startDate", "end_date": "endDate", - "interval": "resampleFreq", + "symbol": "tickers", } __json_schema_extra__ = { "symbol": {"multiple_items_allowed": True}, - "interval": {"choices": ["1m", "5m", "15m", "30m", "1h", "4h", "1d"]}, + "exchanges": {"multiple_items_allowed": True}, + "interval": { + "choices": [ + "1m", + "5m", + "15m", + "30m", + "90m", + "1h", + "2h", + "4h", + "1d", + "7d", + "30d", + ] + }, } - interval: Literal["1m", "5m", "15m", "30m", "1h", "4h", "1d"] = Field( - default="1d", description=QUERY_DESCRIPTIONS.get("interval", "") - ) - exchanges: Optional[List[str]] = Field( + interval: Union[ + Literal[ + "1m", + "5m", + "15m", + "30m", + "90m", + "1h", + "2h", + "4h", + "1d", + "7d", + "30d", + ], + str, + ] = Field(default="1d", description=QUERY_DESCRIPTIONS.get("interval", "")) + + exchanges: Optional[Union[list[str], str]] = Field( default=None, description=( "To limit the query to a subset of exchanges e.g. ['POLONIEX', 'GDAX']" ), ) - _frequency: Literal["daily", "weekly", "monthly", "annually"] = PrivateAttr( - default=None - ) - - # pylint: disable=protected-access - @model_validator(mode="after") # type: ignore[arg-type] - @classmethod - def set_time_params(cls, values: "TiingoCryptoHistoricalQueryParams"): - """Set the default start & end date and time params for Tiingo API.""" - frequency_dict = { - "1d": "1Day", - "1m": "1Min", - "5m": "5Min", - "15m": "15Min", - "30m": "30Min", - "1h": "1Hour", - "4h": "4Hour", - } - values._frequency = frequency_dict[values.interval] # type: ignore[assignment] - - return values class TiingoCryptoHistoricalData(CryptoHistoricalData): @@ -96,14 +99,17 @@ class TiingoCryptoHistoricalData(CryptoHistoricalData): class TiingoCryptoHistoricalFetcher( Fetcher[ TiingoCryptoHistoricalQueryParams, - List[TiingoCryptoHistoricalData], + list[TiingoCryptoHistoricalData], ] ): """Transform the query, extract and transform the data from the Tiingo endpoints.""" @staticmethod - def transform_query(params: Dict[str, Any]) -> TiingoCryptoHistoricalQueryParams: + def transform_query(params: dict[str, Any]) -> TiingoCryptoHistoricalQueryParams: """Transform the query params.""" + # pylint: disable=import-outside-toplevel + from dateutil.relativedelta import relativedelta + transformed_params = params now = datetime.now().date() @@ -115,51 +121,74 @@ class TiingoCryptoHistoricalFetcher( return TiingoCryptoHistoricalQueryParams(**transformed_params) - # pylint: disable=protected-access @staticmethod async def aextract_data( query: TiingoCryptoHistoricalQueryParams, - credentials: Optional[Dict[str, str]], + credentials: Optional[dict[str, str]], **kwargs: Optional[Any], - ) -> List[Dict]: + ) -> list[dict]: """Return the raw data from the Tiingo endpoint.""" + # pylint: disable=import-outside-toplevel + from openbb_core.provider.utils.helpers import get_querystring + from openbb_tiingo.utils.helpers import get_data + api_key = credentials.get("tiingo_token") if credentials else "" base_url = "https://api.tiingo.com/tiingo/crypto/prices" - query_str = get_querystring( - query.model_dump(by_alias=False), ["tickers", "resampleFreq"] - ) - results: List[dict] = [] + query_str = get_querystring(query.model_dump(by_alias=True), ["interval"]) + frequency = query.interval - async def callback(response: ClientResponse, _: Any) -> List[Dict]: - result = await response.json() - symbol = response.url.query.get("tickers", "") - if not result: - warn(f"No data found the the symbol: {symbol}") - return results - data = result[0].get("priceData") - if "," in query.symbol: - for d in data: - d["symbol"] = symbol.upper() if symbol else None - if len(data) > 0: - results.extend(data) - return results + if frequency.endswith("m"): + frequency = f"{frequency[:-1]}min" + elif frequency == "h": + frequency = f"{frequency[:-1]}hour" + elif frequency.endswith("d"): + frequency = f"{frequency[:-1]}day" - urls = [ - f"{base_url}?tickers={symbol}&{query_str}&resampleFreq={query._frequency}&token={api_key}" - for symbol in query.symbol.split(",") - ] + results: list = [] + url = f"{base_url}?{query_str}&resampleFreq={frequency}&token={api_key}" - return await amake_requests(urls, callback, **kwargs) + try: + results = await get_data(url) + except (EmptyDataError, OpenBBError, UnauthorizedError) as e: + raise e from e + + return results @staticmethod def transform_data( query: TiingoCryptoHistoricalQueryParams, - data: List[Dict], + data: list[dict], **kwargs: Any, - ) -> List[TiingoCryptoHistoricalData]: + ) -> list[TiingoCryptoHistoricalData]: """Return the transformed data.""" - return [ - TiingoCryptoHistoricalData.model_validate(d) - for d in sorted(data, key=lambda x: x["date"], reverse=True) - ] + # pylint: disable=import-outside-toplevel + from pandas import to_datetime + + results: list[TiingoCryptoHistoricalData] = [] + symbols = query.symbol.split(",") + returned_symbols = [item.get("ticker", "").upper() for item in data] + + for symbol in symbols: + if symbol not in returned_symbols: + warn(f"No data found for {symbol}") + + for item in data: + symbol = item.get("ticker", "").upper() + price_data = item.get("priceData", []) + + if not price_data: + warn(f"No data found for {symbol}") + continue + + for row in price_data: + if len(returned_symbols) > 1: + row["symbol"] = symbol + if query.interval.endswith("d"): + row["date"] = to_datetime(row["date"]).date() + else: + row["date"] = to_datetime(row["date"], utc=True) + + results.append(TiingoCryptoHistoricalData.model_validate(row)) + + return sorted(results, key=lambda x: x.date) diff --git a/openbb_platform/providers/tiingo/openbb_tiingo/models/currency_historical.py b/openbb_platform/providers/tiingo/openbb_tiingo/models/currency_historical.py index bcc58760ee3..372e36b3230 100644 --- a/openbb_platform/providers/tiingo/openbb_tiingo/models/currency_historical.py +++ b/openbb_platform/providers/tiingo/openbb_tiingo/models/currency_historical.py @@ -3,65 +3,65 @@ # pylint: disable=unused-argument from datetime import datetime -from typing import Any, Dict, List, Literal, Optional +from typing import Any, Literal, Optional, Union from warnings import warn -from dateutil.relativedelta import relativedelta +from openbb_core.app.model.abstract.error import OpenBBError from openbb_core.provider.abstract.fetcher import Fetcher from openbb_core.provider.standard_models.currency_historical import ( CurrencyHistoricalData, CurrencyHistoricalQueryParams, ) from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS -from openbb_core.provider.utils.helpers import ( - ClientResponse, - amake_requests, - get_querystring, -) -from pydantic import Field, PrivateAttr, model_validator +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError +from pydantic import Field class TiingoCurrencyHistoricalQueryParams(CurrencyHistoricalQueryParams): """Tiingo Currency Historical Price Query. - Source: https://www.tiingo.com/documentation/end-of-day + Source: https://www.tiingo.com/documentation/forex """ __alias_dict__ = { - "symbol": "tickers", "start_date": "startDate", "end_date": "endDate", - "interval": "resampleFreq", } __json_schema_extra__ = { "symbol": {"multiple_items_allowed": True}, - "interval": {"choices": ["1m", "5m", "15m", "30m", "1h", "4h", "1d"]}, + "interval": { + "choices": [ + "1m", + "5m", + "15m", + "30m", + "90m", + "1h", + "2h", + "4h", + "1d", + "5d", + "21d", + ] + }, } - interval: Literal["1m", "5m", "15m", "30m", "1h", "4h", "1d"] = Field( - default="1d", description=QUERY_DESCRIPTIONS.get("interval", "") - ) - _frequency: Literal["daily", "weekly", "monthly", "annually"] = PrivateAttr( - default=None - ) - - # pylint: disable=protected-access - @model_validator(mode="after") # type: ignore[arg-type] - @classmethod - def set_time_params(cls, values: "TiingoCurrencyHistoricalQueryParams"): - """Set the default start & end date and time params for Tiingo API.""" - frequency_dict = { - "1d": "1Day", - "1m": "1Min", - "5m": "5Min", - "15m": "15Min", - "30m": "30Min", - "1h": "1Hour", - "4h": "4Hour", - } - values._frequency = frequency_dict[values.interval] # type: ignore[assignment] - - return values + interval: Union[ + Literal[ + "1m", + "5m", + "15m", + "30m", + "90m", + "1h", + "2h", + "4h", + "1d", + "5d", + "21d", + ], + str, + ] = Field(default="1d", description=QUERY_DESCRIPTIONS.get("interval", "")) class TiingoCurrencyHistoricalData(CurrencyHistoricalData): @@ -73,14 +73,17 @@ class TiingoCurrencyHistoricalData(CurrencyHistoricalData): class TiingoCurrencyHistoricalFetcher( Fetcher[ TiingoCurrencyHistoricalQueryParams, - List[TiingoCurrencyHistoricalData], + list[TiingoCurrencyHistoricalData], ] ): """Transform the query, extract and transform the data from the Tiingo endpoints.""" @staticmethod - def transform_query(params: Dict[str, Any]) -> TiingoCurrencyHistoricalQueryParams: + def transform_query(params: dict[str, Any]) -> TiingoCurrencyHistoricalQueryParams: """Transform the query params.""" + # pylint: disable=import-outside-toplevel + from dateutil.relativedelta import relativedelta + transformed_params = params now = datetime.now().date() @@ -92,51 +95,92 @@ class TiingoCurrencyHistoricalFetcher( return TiingoCurrencyHistoricalQueryParams(**transformed_params) - # pylint: disable=protected-access,unused-argument @staticmethod async def aextract_data( query: TiingoCurrencyHistoricalQueryParams, - credentials: Optional[Dict[str, str]], + credentials: Optional[dict[str, str]], **kwargs: Any, - ) -> List[Dict]: + ) -> list[dict]: """Return the raw data from the Tiingo endpoint.""" + # pylint: disable=import-outside-toplevel + import asyncio # noqa + from openbb_core.provider.utils.helpers import get_querystring + from openbb_tiingo.utils.helpers import get_data + from pandas import to_datetime api_key = credentials.get("tiingo_token") if credentials else "" - - base_url = "https://api.tiingo.com/tiingo/fx/prices" + base_url = "https://api.tiingo.com/tiingo/fx" query_str = get_querystring( query.model_dump(by_alias=False), ["tickers", "resampleFreq"] ) - results: List[dict] = [] - async def callback(response: ClientResponse, _: Any) -> List[Dict]: - result = await response.json() - symbol = response.url.query.get("tickers", "") - if not result: - warn(f"No data found the the symbol: {symbol}") - return results - data = result - if len(data) > 0: - if "," not in query.symbol: - _ = [d.pop("ticker") for d in data] + query_str = get_querystring( + query.model_dump(by_alias=True), ["symbol", "interval"] + ) + frequency = query.interval + + if frequency.endswith("m"): + frequency = f"{frequency[:-1]}min" + elif frequency == "h": + frequency = f"{frequency[:-1]}hour" + elif frequency.endswith("d"): + frequency = f"{frequency[:-1]}day" + + results: list = [] + messages: list = [] + + async def get_one(symbol): + """Get data for one symbol.""" + url = f"{base_url}/{symbol}/prices?{query_str}&resampleFreq={frequency}&token={api_key}" + data = None + try: + data = await get_data(url) + except UnauthorizedError as e: + raise e from e + except OpenBBError as e: + if ( + e.original + and isinstance(e.original, str) + and "ticker" in e.original.lower() + ): + messages.append(e.original) else: - for d in data: - d["ticker"] = d["ticker"].upper() + messages.append(f"{symbol}: {e.original}") + + if isinstance(data, list): + for d in data: + if "," in query.symbol: + d["symbol"] = symbol + if query.interval.endswith("d"): + d["date"] = to_datetime(d["date"]).date() + else: + d["date"] = to_datetime(d["date"], utc=True) + results.extend(data) - return results - urls = [ - f"{base_url}?tickers={symbol}&{query_str}&resampleFreq={query._frequency}&token={api_key}" - for symbol in query.symbol.split(",") - ] + symbols = query.symbol.split(",") + await asyncio.gather(*[get_one(symbol) for symbol in symbols]) - return await amake_requests(urls, callback, **kwargs) + if not results and messages: + raise OpenBBError(f"{messages}") + + if not results and not messages: + raise EmptyDataError("The request was returned empty.") + + if results and messages: + for message in messages: + warn(message) + + return results @staticmethod def transform_data( query: TiingoCurrencyHistoricalQueryParams, - data: List[Dict], + data: list[dict], **kwargs: Any, - ) -> List[TiingoCurrencyHistoricalData]: + ) -> list[TiingoCurrencyHistoricalData]: """Return the transformed data.""" - return [TiingoCurrencyHistoricalData.model_validate(d) for d in data] + return sorted( + [TiingoCurrencyHistoricalData.model_validate(d) for d in data], + key=lambda x: x.date, + ) diff --git a/openbb_platform/providers/tiingo/openbb_tiingo/models/equity_historical.py b/openbb_platform/providers/tiingo/openbb_tiingo/models/equity_historical.py index 03558ce9078..b73c2853b31 100644 --- a/openbb_platform/providers/tiingo/openbb_tiingo/models/equity_historical.py +++ b/openbb_platform/providers/tiingo/openbb_tiingo/models/equity_historical.py @@ -3,10 +3,10 @@ # pylint: disable=unused-argument from datetime import datetime -from typing import Any, Dict, List, Literal, Optional +from typing import Any, Literal, Optional, Union from warnings import warn -from dateutil.relativedelta import relativedelta +from openbb_core.app.model.abstract.error import OpenBBError from openbb_core.provider.abstract.fetcher import Fetcher from openbb_core.provider.standard_models.equity_historical import ( EquityHistoricalData, @@ -16,12 +16,8 @@ from openbb_core.provider.utils.descriptions import ( DATA_DESCRIPTIONS, QUERY_DESCRIPTIONS, ) -from openbb_core.provider.utils.helpers import ( - ClientResponse, - amake_requests, - get_querystring, -) -from pydantic import Field, PrivateAttr, model_validator +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError +from pydantic import Field class TiingoEquityHistoricalQueryParams(EquityHistoricalQueryParams): @@ -36,31 +32,30 @@ class TiingoEquityHistoricalQueryParams(EquityHistoricalQueryParams): } __json_schema_extra__ = { "symbol": {"multiple_items_allowed": True}, - "interval": {"choices": ["1m", "5m", "15m", "30m", "1h", "4h", "1d"]}, + "interval": { + "choices": [ + "1m", + "5m", + "15m", + "30m", + "90m", + "1h", + "2h", + "4h", + "1d", + "1W", + "1M", + "1Y", + ] + }, } - interval: Literal["1d", "1W", "1M", "1Y"] = Field( - default="1d", description=QUERY_DESCRIPTIONS.get("interval", "") - ) - _frequency: Literal["daily", "weekly", "monthly", "annually"] = PrivateAttr( - default=None - ) - - # pylint: disable=protected-access - @model_validator(mode="after") # type: ignore[arg-type] - @classmethod - def set_time_params(cls, values: "TiingoEquityHistoricalQueryParams"): - """Set the default start & end date and time params for Tiingo API.""" - frequency_dict = { - "1d": "daily", - "1W": "weekly", - "1M": "monthly", - "1Y": "annually", - } - - values._frequency = frequency_dict[values.interval] # type: ignore[assignment] - - return values + interval: Union[ + Literal[ + "1m", "5m", "15m", "30m", "90m", "1h", "2h", "4h", "1d", "1W", "1M", "1Y" + ], + str, + ] = Field(default="1d", description=QUERY_DESCRIPTIONS.get("interval", "")) class TiingoEquityHistoricalData(EquityHistoricalData): @@ -109,14 +104,17 @@ class TiingoEquityHistoricalData(EquityHistoricalData): class TiingoEquityHistoricalFetcher( Fetcher[ TiingoEquityHistoricalQueryParams, - List[TiingoEquityHistoricalData], + list[TiingoEquityHistoricalData], ] ): """Transform the query, extract and transform the data from the Tiingo endpoints.""" @staticmethod - def transform_query(params: Dict[str, Any]) -> TiingoEquityHistoricalQueryParams: + def transform_query(params: dict[str, Any]) -> TiingoEquityHistoricalQueryParams: """Transform the query params.""" + # pylint: disable=import-outside-toplevel + from dateutil.relativedelta import relativedelta + transformed_params = params now = datetime.now().date() @@ -132,45 +130,108 @@ class TiingoEquityHistoricalFetcher( @staticmethod async def aextract_data( query: TiingoEquityHistoricalQueryParams, - credentials: Optional[Dict[str, str]], + credentials: Optional[dict[str, str]], **kwargs: Any, - ) -> List[Dict]: + ) -> list[dict]: """Return the raw data from the Tiingo endpoint.""" + # pylint: disable=import-outside-toplevel + import asyncio # noqa + from openbb_core.provider.utils.helpers import get_querystring + from openbb_tiingo.utils.helpers import get_data + api_key = credentials.get("tiingo_token") if credentials else "" - base_url = "https://api.tiingo.com/tiingo/daily" + base_url = ( + "https://api.tiingo.com/tiingo/daily" + if query.interval in ["1d", "1W", "1M", "1Y"] + else "https://api.tiingo.com/iex" + ) query_str = get_querystring( query.model_dump(by_alias=True), ["symbol", "interval"] ) + frequency_dict = { + "1d": "daily", + "1W": "weekly", + "1M": "monthly", + "1Y": "annually", + } + frequency = ( + frequency_dict.get(query.interval, "") + if query.interval in frequency_dict + else query.interval + ) + cols_str = "&columns=open,high,low,close,volume" - async def callback(response: ClientResponse, _: Any) -> List[Dict]: - data = await response.json() - symbol = response.url.parts[-2] - results: List[dict] = [] - if not data: - warn(f"No data found the the symbol: {symbol}") - return results + if frequency.endswith("m"): + frequency = f"{frequency[:-1]}min" + query_str = query_str + cols_str + elif frequency == "h": + frequency = f"{frequency[:-1]}hour" + query_str = query_str + cols_str - if isinstance(data, List): - results = data + results: list = [] + messages: list = [] - if "," in query.symbol: - for d in results: - d["symbol"] = symbol - return results + async def get_one(symbol): + """Get data for one symbol.""" + url = f"{base_url}/{symbol}/prices?{query_str}&resampleFreq={frequency}&token={api_key}" + data = None + try: + data = await get_data(url) + except UnauthorizedError as e: + raise e from e + except OpenBBError as e: + if ( + e.original + and isinstance(e.original, str) + and "ticker" in e.original.lower() + ): + messages.append(e.original) + else: + messages.append(f"{symbol}: {e.original}") - urls = [ - f"{base_url}/{symbol}/prices?{query_str}&resampleFreq={query._frequency}&token={api_key}" - for symbol in query.symbol.split(",") - ] + if isinstance(data, list): + if "," in query.symbol: + for d in data: + d["symbol"] = symbol + results.extend(data) - return await amake_requests(urls, callback, **kwargs) + symbols = query.symbol.split(",") + await asyncio.gather(*[get_one(symbol) for symbol in symbols]) + + if not results and messages: + raise OpenBBError(f"{messages}") + + if not results and not messages: + raise EmptyDataError("The request was returned empty.") + + if results and messages: + for message in messages: + warn(message) + + return results @staticmethod def transform_data( query: TiingoEquityHistoricalQueryParams, - data: List[Dict], + data: list[dict], **kwargs: Any, - ) -> List[TiingoEquityHistoricalData]: + ) -> list[TiingoEquityHistoricalData]: """Return the transformed data.""" - return [TiingoEquityHistoricalData.model_validate(d) for d in data] + # pylint: disable=import-outside-toplevel + from pandas import to_datetime + from pytz import timezone + + results: list[TiingoEquityHistoricalData] = [] + for item in data: + # If the data is intraday, it comes from IEX and the TZ should be localized to America/New_York + if query.interval in ["1d", "1W", "1M", "1Y"]: + item["date"] = to_datetime(item["date"]).date() + else: + item["date"] = to_datetime(item["date"], utc=True).tz_convert( + timezone("America/New_York") + ) + + results.append(TiingoEquityHistoricalData.model_validate(item)) + + return results diff --git a/openbb_platform/providers/tiingo/openbb_tiingo/models/trailing_dividend_yield.py b/openbb_platform/providers/tiingo/openbb_tiingo/models/trailing_dividend_yield.py index 9133a73b41b..4bb9b7cf7ff 100644 --- a/openbb_platform/providers/tiingo/openbb_tiingo/models/trailing_dividend_yield.py +++ b/openbb_platform/providers/tiingo/openbb_tiingo/models/trailing_dividend_yield.py @@ -39,23 +39,22 @@ class TiingoTrailingDivYieldFetcher( return TiingoTrailingDivYieldQueryParams(**transformed_params) @staticmethod - def extract_data( + async def aextract_data( query: TiingoTrailingDivYieldQueryParams, credentials: Optional[Dict[str, str]], **kwargs: Any, ) -> List[Dict]: """Return the raw data from the Tiingo endpoint.""" # pylint: disable=import-outside-toplevel - from openbb_core.provider.utils.helpers import make_request + from openbb_tiingo.utils.helpers import get_data api_key = credentials.get("tiingo_token") if credentials else "" url = ( f"https://api.tiingo.com/tiingo/corporate-actions/{query.symbol}/distribution-yield?" f"token={api_key}" ) - data = make_request(url) - return data.json() + return await get_data(url) # type: ignore @staticmethod def transform_data( diff --git a/openbb_platform/providers/tiingo/openbb_tiingo/models/world_news.py b/openbb_platform/providers/tiingo/openbb_tiingo/models/world_news.py index cdaa0331218..46b9cd1cfb5 100644 --- a/openbb_platform/providers/tiingo/openbb_tiingo/models/world_news.py +++ b/openbb_platform/providers/tiingo/openbb_tiingo/models/world_news.py @@ -2,7 +2,6 @@ # pylint: disable=unused-argument -import math from datetime import datetime from typing import Any, Dict, List, Optional @@ -12,7 +11,7 @@ from openbb_core.provider.standard_models.world_news import ( WorldNewsData, WorldNewsQueryParams, ) -from openbb_core.provider.utils.helpers import amake_requests, get_querystring +from openbb_core.provider.utils.errors import EmptyDataError from pydantic import Field, field_validator @@ -26,6 +25,8 @@ class TiingoWorldNewsQueryParams(WorldNewsQueryParams): "start_date": "startDate", "end_date": "endDate", } + __json_schema_extra__ = {"source": {"multiple_items_allowed": True}} + offset: Optional[int] = Field( default=0, description="Page offset, used in conjunction with limit." ) @@ -90,6 +91,12 @@ class TiingoWorldNewsFetcher( **kwargs: Any, ) -> List[Dict]: """Return the raw data from the tiingo endpoint.""" + # pylint: disable=import-outside-toplevel + import asyncio # noqa + import math + from openbb_core.provider.utils.helpers import get_querystring + from openbb_tiingo.utils.helpers import get_data + api_key = credentials.get("tiingo_token") if credentials else "" base_url = "https://api.tiingo.com/tiingo/news" @@ -110,7 +117,22 @@ class TiingoWorldNewsFetcher( else: urls = [f"{base_url}?{query_str}&token={api_key}&limit={limit}"] - return await amake_requests(urls) + results: list = [] + + async def get_one(url): + """Get data for one URL and append results to list.""" + response = await get_data(url) + if isinstance(response, list): + results.extend(response) + elif isinstance(response, dict): + results.append(response) + + await asyncio.gather(*[get_one(url) for url in urls]) + + if not results: + raise EmptyDataError() + + return results @staticmethod def transform_data( diff --git a/openbb_platform/providers/tiingo/openbb_tiingo/utils/helpers.py b/openbb_platform/providers/tiingo/openbb_tiingo/utils/helpers.py index 13f7b4093d7..dd493f8a523 100644 --- a/openbb_platform/providers/tiingo/openbb_tiingo/utils/helpers.py +++ b/openbb_platform/providers/tiingo/openbb_tiingo/utils/helpers.py @@ -1,109 +1,41 @@ """Tiingo Helpers Module.""" -import json -from io import StringIO -from typing import Any, List, Optional, TypeVar, Union - -import requests -from openbb_core.app.model.abstract.error import OpenBBError -from openbb_core.provider import helpers -from openbb_core.provider.utils.errors import EmptyDataError -from pydantic import BaseModel -from requests.exceptions import SSLError - -T = TypeVar("T", bound=BaseModel) +from typing import Optional, Union -class BasicResponse: - """Basic Response class.""" - - def __init__(self, response: StringIO): - """Initialize the BasicResponse class.""" - # Find a way to get the status code - self.status_code = 200 - response.seek(0) - self.text = response.read() - - def json(self) -> dict: - """Return the response as a dictionary.""" - return json.loads(self.text) - - -def request(url: str) -> BasicResponse: - """ - Request function for PyScript. Pass in Method and make sure to await. - - Parameters: - ----------- - url: str - URL to make request to - - Return: - ------- - response: BasicRequest - BasicRequest object with status_code and text attributes - """ +async def get_data(url: str) -> Union[dict, list]: + """Get data from Tiingo endpoint and parse the JSON response.""" # pylint: disable=import-outside-toplevel - from pyodide.http import open_url # type: ignore + from json import JSONDecodeError # noqa + from openbb_core.app.model.abstract.error import OpenBBError + from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError + from openbb_core.provider.utils.helpers import amake_request - response = open_url(url) - return BasicResponse(response) + response: Optional[Union[dict, list]] = None - -def get_data(url: str, **kwargs: Any) -> Union[list, dict]: - """Get data from Tiingo endpoint.""" try: - r: Union[requests.Response, BasicResponse] = helpers.make_request(url, **kwargs) - except SSLError: - r = request(url) - if r.status_code == 404: - raise OpenBBError("Tiingo endpoint doesn't exist.") + response = await amake_request(url) + if ( + response + and isinstance(response, dict) + and len(list(response.keys())) == 1 + and response.get("detail") + ): + if ( + "token" in response["detail"] + or "access" in response["detail"] + or "permission" in response["detail"] + or "authorized" in response["detail"] + ): + raise UnauthorizedError( + f"Unauthorized Tiingo request -> {response['detail']}" + ) + raise OpenBBError(response["detail"]) - data = r.json() - if r.status_code != 200: - error = data.get("detail") - raise OpenBBError(f"Error in Tiingo request -> {error}") + if not response: + raise EmptyDataError("The response is empty") - if len(data) == 0: - raise EmptyDataError() + return response - return data - - -def get_data_many( - url: str, sub_dict: Optional[str] = None, **kwargs: Any -) -> List[dict]: - """Get data from Tiingo endpoint and convert to list of schemas. - - Parameters: - ----------- - url: str - The URL to get the data from. - sub_dict: Optional[str] - The sub-dictionary to use. - - Returns: - -------- - List[dict] - Dictionary of data. - """ - data = get_data(url, **kwargs) - if sub_dict and isinstance(data, dict): - data = data.get(sub_dict, []) - if isinstance(data, dict): - raise ValueError("Expected list of dicts, got dict") - return data - - -def get_data_one(url: str, **kwargs: Any) -> dict: - """Get data from Tiingo endpoint and convert to schema.""" - data = get_data(url, **kwargs) - if isinstance(data, list): - if len(data) == 0: - raise ValueError("Expected dict, got empty list") - try: - data = {i: data[i] for i in range(len(data))} if len(data) > 1 else data[0] - except TypeError as e: - raise ValueError("Expected dict, got list of dicts") from e - - return data + except JSONDecodeError as e: + raise OpenBBError(f"Failed to parse JSON response -> {e}") from e diff --git a/openbb_platform/providers/tiingo/tests/record/http/test_tiingo_fetchers/test_tiingo_crypto_historical_fetcher_urllib3_v1.yaml b/openbb_platform/providers/tiingo/tests/record/http/test_tiingo_fetchers/test_tiingo_crypto_historical_fetcher_urllib3_v1.yaml index 53657fbb4cf..378f9d37ef3 100644 --- a/openbb_platform/providers/tiingo/tests/record/http/test_tiingo_fetchers/test_tiingo_crypto_historical_fetcher_urllib3_v1.yaml +++ b/openbb_platform/providers/tiingo/tests/record/http/test_tiingo_fetchers/test_tiingo_crypto_historical_fetcher_urllib3_v1.yaml @@ -9,7 +9,7 @@ interactions: Connection: - keep-alive method: GET - uri: https://api.tiingo.com/tiingo/crypto/prices?endDate=2023-06-06&resampleFreq=1Day&startDate=2023-01-01&tickers=BTCUSD&token=MOCK_TOKEN + uri: https://api.tiingo.com/tiingo/crypto/prices?endDate=2023-06-06&resampleFreq=1day&startDate=2023-01-01&tickers=BTCUSD&token=MOCK_TOKEN response: body: string: '[{"ticker":"btcusd","baseCurrency":"btc","quoteCurrency":"usd","priceData":[{"date":"2023-01-01T00:00:00+00:00","open":16534.758508538427,"high":16622.870558446135,"low":16492.287893194825,"close":16610.40117718445,"volume":110346.5693071621,"volumeNotional":1832900784.7179508,"tradesDone":2812901.0},{"date":"2023-01-02T00:00:00+00:00","open":16610.892883605946,"high":16792.022463375222,"low":16542.456230097472,"close":16666.42070337159,"volume":139190.34028523602,"volumeNotional":2319804769.039194,"tradesDone":3586445.0},{"date":"2023-01-03T00:00:00+00:00","open":16666.425770956354,"high":16772.008176728094,"low":16600.462687819214,"close":16670.2239959582,"volume":182632.56007866,"volumeNotional":3044525685.4665556,"tradesDone":4392043.0},{"date":"2023-01-04T00:00:00+00:00","open":16670.492558854425,"high":16985.44143125503,"low":16647.613841053073,"close":16845.3620428872,"volume":254928.102217694,"volumeNotional":4294356176.7632103,"tradesDone":5662266.0},{"date":"2023-01-05T00:00:00+00:00","open":16845.34346331706,"high":16874.57078229087,"low":16748.352864565408,"close":16825.22744905322,"volume":182315.91906806597,"volumeNotional":3067506805.903389,"tradesDone":4181793.0},{"date":"2023-01-06T00:00:00+00:00","open":16825.356660535454,"high":17033.021856610823,"low":16672.387166794186,"close":16943.062497969404,"volume":239812.614435073,"volumeNotional":4063160114.1748815,"tradesDone":4719899.0},{"date":"2023-01-07T00:00:00+00:00","open":16942.30531964883,"high":16974.006096954814,"low":16900.429739245064,"close":16935.606463508877,"volume":111958.584354078,"volumeNotional":1896086524.8322272,"tradesDone":2704933.0},{"date":"2023-01-08T00:00:00+00:00","open":16935.99943944265,"high":17168.020164038557,"low":16903.27274222517,"close":17121.282112787987,"volume":148123.123651652,"volumeNotional":2536057787.4673123,"tradesDone":3456234.0},{"date":"2023-01-09T00:00:00+00:00","open":17121.57061012745,"high":17390.76578282186,"low":17097.311813958935,"close":17172.208908019893,"volume":310183.262251941,"volumeNotional":5326531779.161452,"tradesDone":5881651.0},{"date":"2023-01-10T00:00:00+00:00","open":17172.797115007168,"high":17493.595691785365,"low":17139.96726397043,"close":17436.2637252567,"volume":255246.05909687202,"volumeNotional":4450537601.245518,"tradesDone":5000575.0},{"date":"2023-01-11T00:00:00+00:00","open":17436.280208162683,"high":17994.80360990724,"low":17309.4444175157,"close":17936.958420493294,"volume":301326.40384703095,"volumeNotional":5404879176.800964,"tradesDone":5156459.0},{"date":"2023-01-12T00:00:00+00:00","open":17937.23178217057,"high":19111.686238683895,"low":17887.70292419522,"close":18843.615393985634,"volume":546194.156613748,"volumeNotional":10292272617.671824,"tradesDone":8515248.0},{"date":"2023-01-13T00:00:00+00:00","open":18843.702644737696,"high":19996.242779748394,"low":18710.313626706644,"close":19925.507116903274,"volume":445054.043296865,"volumeNotional":8867927507.118261,"tradesDone":7738164.0},{"date":"2023-01-14T00:00:00+00:00","open":19925.46402800475,"high":21260.3129558461,"low":19885.518587547882,"close":20946.42909671108,"volume":475917.1693841831,"volumeNotional":9968765244.413227,"tradesDone":8814695.0},{"date":"2023-01-15T00:00:00+00:00","open":20944.38103412309,"high":21040.41314056405,"low":20542.15697053462,"close":20860.213701599645,"volume":213663.78927575698,"volumeNotional":4457072304.585845,"tradesDone":5169848.0},{"date":"2023-01-16T00:00:00+00:00","open":20861.34285941691,"high":21461.509652455217,"low":20603.222622679405,"close":21178.20240975164,"volume":344480.687747793,"volumeNotional":7295481731.373212,"tradesDone":6682521.0},{"date":"2023-01-17T00:00:00+00:00","open":21177.07334134622,"high":21628.41751210442,"low":20832.822616861344,"close":21125.716720343295,"volume":317891.67411837686,"volumeNotional":6715689455.180516,"tradesDone":6108968.0},{"date":"2023-01-18T00:00:00+00:00","open":21123.508789269184,"high":21639.834325639462,"low":20394.387947494208,"close":20669.66398713652,"volume":399287.363072815,"volumeNotional":8253135629.024868,"tradesDone":7306519.0},{"date":"2023-01-19T00:00:00+00:00","open":20669.667255804423,"high":21186.72047920568,"low":20650.451074363024,"close":21067.169977846763,"volume":280914.929889477,"volumeNotional":5918082577.296517,"tradesDone":5390518.0},{"date":"2023-01-20T00:00:00+00:00","open":21067.318845244237,"high":22747.54274303515,"low":20854.487051634573,"close":22659.49889848295,"volume":383260.33795678604,"volumeNotional":8684487205.763996,"tradesDone":6964724.0},{"date":"2023-01-21T00:00:00+00:00","open":22658.741683860597,"high":23365.612176433126,"low":22415.414658865433,"close":22777.866458104367,"volume":393591.21135730395,"volumeNotional":8965168051.3802,"tradesDone":7340650.0},{"date":"2023-01-22T00:00:00+00:00","open":22777.786814010415,"high":23070.80216753831,"low":22291.02015218942,"close":22706.6567041434,"volume":287904.65037854103,"volumeNotional":6537352059.67196,"tradesDone":6152631.0},{"date":"2023-01-23T00:00:00+00:00","open":22705.023761257806,"high":23177.64120280451,"low":22495.040780156975,"close":22914.806544240204,"volume":334985.914643084,"volumeNotional":7676137429.091631,"tradesDone":6689264.0},{"date":"2023-01-24T00:00:00+00:00","open":22916.213812975722,"high":23160.337734320918,"low":22458.873414989514,"close":22631.297007531946,"volume":341607.57040865096,"volumeNotional":7731022385.939561,"tradesDone":6912892.0},{"date":"2023-01-25T00:00:00+00:00","open":22630.35882328906,"high":23815.402364488167,"low":22299.05184661137,"close":23058.887712962543,"volume":398687.62187728495,"volumeNotional":9193293105.416382,"tradesDone":7487613.0},{"date":"2023-01-26T00:00:00+00:00","open":23058.54405024964,"high":23280.685861431793,"low":22848.58534793659,"close":23009.407018044218,"volume":323698.13523062505,"volumeNotional":7448102144.50337,"tradesDone":6453592.0},{"date":"2023-01-27T00:00:00+00:00","open":23007.85085501095,"high":23498.853019121838,"low":22578.236382525603,"close":23074.906999829804,"volume":284459.814003024,"volumeNotional":6563883753.308663,"tradesDone":5859985.0},{"date":"2023-01-28T00:00:00+00:00","open":23074.56872156852,"high":23189.26405811895,"low":22876.64747411179,"close":23027.41455681704,"volume":145082.87347243898,"volumeNotional":3340883472.544086,"tradesDone":3461693.0},{"date":"2023-01-29T00:00:00+00:00","open":23022.479105202696,"high":23965.235948533962,"low":22966.640963715956,"close":23747.019042121985,"volume":296682.5813472069,"volumeNotional":7045326908.718027,"tradesDone":6033555.0},{"date":"2023-01-30T00:00:00+00:00","open":23747.74358095152,"high":23804.554993231297,"low":22504.088155533067,"close":22833.288374006806,"volume":318186.1375034659,"volumeNotional":7265235834.22802,"tradesDone":6866289.0},{"date":"2023-01-31T00:00:00+00:00","open":22834.34868719895,"high":23323.165558785888,"low":22717.46523452395,"close":23129.71238462947,"volume":294786.55345481803,"volumeNotional":6818328196.266142,"tradesDone":6291240.0},{"date":"2023-02-01T00:00:00+00:00","open":23129.60734979065,"high":23822.940259567993,"low":22775.455317329255,"close":23748.088923078056,"volume":341733.46495692,"volumeNotional":8115516713.788515,"tradesDone":7150155.0},{"date":"2023-02-02T00:00:00+00:00","open":23747.0872030901,"high":24262.102952024463,"low":23367.25434031797,"close":23491.2274576747,"volume":394680.288277346,"volumeNotional":9271524424.983757,"tradesDone":8218546.0},{"date":"2023-02-03T00:00:00+00:00","open":23491.928051755865,"high":23747.077662050582,"low":23211.68416433434,"close":23436.420261583615,"volume":355423.665510659,"volumeNotional":8329858395.820326,"tradesDone":7051300.0},{"date":"2023-02-04T00:00:00+00:00","open":23436.514729027833,"high":23598.81510929699,"low":23254.097741367463,"close":23353.810507945356,"volume":174061.56393647002,"volumeNotional":4065000780.888936,"tradesDone":4282100.0},{"date":"2023-02-05T00:00:00+00:00","open":23354.211922806222,"high":23498.76637636073,"low":22750.479134986206,"close":22955.052298862247,"volume":222521.450994416,"volumeNotional":5107991545.195532,"tradesDone":5260451.0},{"date":"2023-02-06T00:00:00+00:00","open":22954.81271990142,"high":23158.324821368344,"low":22634.657513798375,"close":22766.908081381862,"volume":284031.2601124471,"volumeNotional":6466513591.219145,"tradesDone":6061109.0},{"date":"2023-02-07T00:00:00+00:00","open":22766.946866931554,"high":23349.111314865186,"low":22751.77838080674,"close":23244.890157805403,"volume":326719.584936721,"volumeNotional":7594560864.257853,"tradesDone":7332769.0},{"date":"2023-02-08T00:00:00+00:00","open":23243.04282353539,"high":23456.15056067334,"low":22666.32378169172,"close":22967.39589438958,"volume":296785.900615876,"volumeNotional":6816399275.317785,"tradesDone":6863165.0},{"date":"2023-02-09T00:00:00+00:00","open":22966.23326482415,"high":23015.73874123728,"low":21692.99680676366,"close":21806.785634220563,"volume":437322.539375191,"volumeNotional":9536598869.16777,"tradesDone":8646010.0},{"date":"2023-02-10T00:00:00+00:00","open":21808.339830547367,"high":21956.961142582437,"low":21458.412880304477,"close":21629.589423115016,"volume":361572.229258134,"volumeNotional":7820658865.653852,"tradesDone":6343721.0},{"date":"2023-02-11T00:00:00+00:00","open":21629.56994239977,"high":21912.57758626528,"low":21606.285495750766,"close":21868.469120508347,"volume":185398.990533929,"volumeNotional":4054392099.464646,"tradesDone":3717975.0},{"date":"2023-02-12T00:00:00+00:00","open":21868.92047543776,"high":22094.33927435566,"low":21635.239865646385,"close":21785.92248542488,"volume":215986.308771281,"volumeNotional":4705460980.804172,"tradesDone":4028782.0},{"date":"2023-02-13T00:00:00+00:00","open":21784.961342118844,"high":21901.667037425694,"low":21364.02496161614,"close":21789.100791446246,"volume":321054.7047442801,"volumeNotional":6995493321.241134,"tradesDone":5795945.0},{"date":"2023-02-14T00:00:00+00:00","open":21789.813889905905,"high":22334.904152432726,"low":21548.09009000796,"close":22200.10689875198,"volume":388077.974555726,"volumeNotional":8615372520.188267,"tradesDone":6677024.0},{"date":"2023-02-15T00:00:00+00:00","open":22200.25645853632,"high":24384.62829397166,"low":22053.983193218235,"close":24331.147433807317,"volume":414707.982965513,"volumeNotional":10090321075.51075,"tradesDone":7527313.0},{"date":"2023-02-16T00:00:00+00:00","open":24330.07392682627,"high":25231.587838856147,"low":23494.70937538958,"close":23506.73478761036,"volume":494987.637211754,"volumeNotional":11635543111.082594,"tradesDone":10017567.0},{"date":"2023-02-17T00:00:00+00:00","open":23506.500363758303,"high":25023.454206492523,"low":23333.031972129258,"close":24579.63020419649,"volume":535465.0397492789,"volumeNotional":13161532664.312649,"tradesDone":9876808.0},{"date":"2023-02-18T00:00:00+00:00","open":24578.04586250838,"high":24884.206935482573,"low":24431.85754839516,"close":24636.835983572786,"volume":226346.40309056902,"volumeNotional":5576459208.414001,"tradesDone":5587301.0},{"date":"2023-02-19T00:00:00+00:00","open":24636.960781383248,"high":25192.516211187314,"low":24197.513424917393,"close":24279.314507001585,"volume":319962.408439316,"volumeNotional":7768467944.915851,"tradesDone":6819798.0},{"date":"2023-02-20T00:00:00+00:00","open":24279.82212524917,"high":25121.10976908513,"low":23847.92533372801,"close":24844.512855441255,"volume":370089.7517008561,"volumeNotional":9194699593.79898,"tradesDone":8912465.0},{"date":"2023-02-21T00:00:00+00:00","open":24845.961542510562,"high":25253.691856111283,"low":24153.678570217904,"close":24456.85051691342,"volume":408337.32267434703,"volumeNotional":9986644861.123146,"tradesDone":9645034.0},{"date":"2023-02-22T00:00:00+00:00","open":24455.532273815614,"high":24487.54482763843,"low":23579.58845207356,"close":24190.23629090606,"volume":412202.607884278,"volumeNotional":9971278484.448383,"tradesDone":10006318.0},{"date":"2023-02-23T00:00:00+00:00","open":24189.261865227578,"high":24603.99633281332,"low":23612.852511785713,"close":23942.64086692768,"volume":429154.11443397193,"volumeNotional":10275082838.456974,"tradesDone":9578353.0},{"date":"2023-02-24T00:00:00+00:00","open":23942.8014480139,"high":24131.65220176608,"low":22821.76108661926,"close":23187.7594074938,"volume":378410.5775526979,"volumeNotional":8774493429.542732,"tradesDone":8872408.0},{"date":"2023-02-25T00:00:00+00:00","open":23186.532860926316,"high":23223.65221829308,"low":22727.54442118508,"close":23161.79691640286,"volume":203126.375823149,"volumeNotional":4704771865.1807,"tradesDone":5788856.0},{"date":"2023-02-26T00:00:00+00:00","open":23161.794958186474,"high":23698.716825376534,"low":23059.296256018395,"close":23557.24304450421,"volume":214691.089723741,"volumeNotional":5057530180.111627,"tradesDone":6187090.0},{"date":"2023-02-27T00:00:00+00:00","open":23557.238213359717,"high":23899.96014698971,"low":23102.92724625777,"close":23491.09651011545,"volume":306302.1805658,"volumeNotional":7195374084.9300165,"tradesDone":8383090.0},{"date":"2023-02-28T00:00:00+00:00","open":23492.04498127966,"high":23600.002394182917,"low":23021.69308328172,"close":23143.86643650886,"volume":280682.00044089096,"volumeNotional":6496066729.336101,"tradesDone":7350756.0},{"date":"2023-03-01T00:00:00+00:00","open":23144.27814122816,"high":23999.76013244346,"low":23020.584899482204,"close":23633.620866618927,"volume":337141.683397634,"volumeNotional":7967878723.753355,"tradesDone":8204359.0},{"date":"2023-03-02T00:00:00+00:00","open":23634.45572366933,"high":23803.56478707363,"low":23193.889885658158,"close":23465.50232382252,"volume":256409.812836994,"volumeNotional":6016785058.97738,"tradesDone":6713059.0},{"date":"2023-03-03T00:00:00+00:00","open":23465.668271156672,"high":23479.360293301717,"low":21980.487424792944,"close":22355.051813818725,"volume":354871.338496905,"volumeNotional":7933167159.337515,"tradesDone":7529497.0},{"date":"2023-03-04T00:00:00+00:00","open":22354.712279160834,"high":22413.38098047793,"low":22162.598529893046,"close":22348.10163881476,"volume":126410.68585299602,"volumeNotional":2825038855.675038,"tradesDone":3669199.0},{"date":"2023-03-05T00:00:00+00:00","open":22348.557517145302,"high":22663.786358985504,"low":22189.803438091967,"close":22433.141901199633,"volume":164977.92274369,"volumeNotional":3700973151.474348,"tradesDone":4365140.0},{"date":"2023-03-06T00:00:00+00:00","open":22432.42079890968,"high":22604.158075918673,"low":22260.755639498268,"close":22407.856206357712,"volume":220051.03349124696,"volumeNotional":4930871916.532267,"tradesDone":5579208.0},{"date":"2023-03-07T00:00:00+00:00","open":22407.78544494383,"high":22557.75346609151,"low":21925.38651659266,"close":22196.01333077293,"volume":312923.36840575404,"volumeNotional":6945651256.644485,"tradesDone":6805051.0},{"date":"2023-03-08T00:00:00+00:00","open":22196.516231385245,"high":22286.67148021186,"low":21576.22476428865,"close":21701.066618080036,"volume":324288.55411497195,"volumeNotional":7037407516.329859,"tradesDone":7199547.0},{"date":"2023-03-09T00:00:00+00:00","open":21700.130678069694,"high":21828.4485783622,"low":20033.532707329286,"close":20358.80594538473,"volume":469177.988154495,"volumeNotional":9551903614.68338,"tradesDone":9012340.0},{"date":"2023-03-10T00:00:00+00:00","open":20359.015298201055,"high":20364.28409489808,"low":19550.79323447636,"close":20217.025364156147,"volume":607665.151521093,"volumeNotional":12285181781.215725,"tradesDone":10043791.0},{"date":"2023-03-11T00:00:00+00:00","open":20216.013994410965,"high":20885.787417853026,"low":19887.294073306668,"close":20608.31095556546,"volume":433044.25016966,"volumeNotional":8924310565.016033,"tradesDone":8816837.0},{"date":"2023-03-12T00:00:00+00:00","open":20607.832859580714,"high":22336.149681645147,"low":20431.527006945962,"close":22192.69281286857,"volume":473717.985748779,"volumeNotional":10513077737.653503,"tradesDone":8901607.0},{"date":"2023-03-13T00:00:00+00:00","open":22193.987921282795,"high":24623.733257081625,"low":21885.82323429922,"close":24187.655049850575,"volume":755439.36759096,"volumeNotional":18272306834.36741,"tradesDone":13707875.0},{"date":"2023-03-14T00:00:00+00:00","open":24186.731084713705,"high":26498.513239674518,"low":24039.102900934104,"close":24734.138121488864,"volume":778704.6162816129,"volumeNotional":19260587534.9504,"tradesDone":14163547.0},{"date":"2023-03-15T00:00:00+00:00","open":24733.515542517143,"high":25311.99304916627,"low":23932.543907568026,"close":24382.07161143555,"volume":637435.3612997518,"volumeNotional":15541994626.871841,"tradesDone":11908088.0},{"date":"2023-03-16T00:00:00+00:00","open":24382.048799054122,"high":25208.935406751192,"low":24203.02849180725,"close":25030.48921556089,"volume":480833.26540094096,"volumeNotional":12035491864.101181,"tradesDone":9792622.0},{"date":"2023-03-17T00:00:00+00:00","open":25030.814468696008,"high":27830.562262254385,"low":24910.982306554783,"close":27446.279838770355,"volume":696402.6093887371,"volumeNotional":19113660897.733162,"tradesDone":12506946.0},{"date":"2023-03-18T00:00:00+00:00","open":27446.866546782778,"high":27781.46442110656,"low":26653.825538874808,"close":26982.051577725462,"volume":405178.53545737796,"volumeNotional":10932548141.898237,"tradesDone":9478941.0},{"date":"2023-03-19T00:00:00+00:00","open":26981.87986819447,"high":28478.71097386288,"low":26891.905934720326,"close":28050.330386850223,"volume":407187.529512644,"volumeNotional":11421744732.23499,"tradesDone":9220811.0},{"date":"2023-03-20T00:00:00+00:00","open":28051.118058643577,"high":28568.40049592391,"low":27216.594834584925,"close":27798.536291386794,"volume":525578.2631171329,"volumeNotional":14610306421.225657,"tradesDone":11461901.0},{"date":"2023-03-21T00:00:00+00:00","open":27798.3081589649,"high":28517.532566468268,"low":27403.888624347812,"close":28197.93305049566,"volume":452952.937069486,"volumeNotional":12772336594.51074,"tradesDone":11028812.0},{"date":"2023-03-22T00:00:00+00:00","open":28198.416014978484,"high":28891.57656419918,"low":26670.92195447159,"close":27314.896197671238,"volume":285080.68233111,"volumeNotional":7786949245.835559,"tradesDone":3962082.0},{"date":"2023-03-23T00:00:00+00:00","open":27314.60316990628,"high":28785.648117353863,"low":27185.628461519915,"close":28352.68633491559,"volume":178047.573365239,"volumeNotional":5048127000.3174925,"tradesDone":2708870.0},{"date":"2023-03-24T00:00:00+00:00","open":28353.33311100366,"high":28430.37142628591,"low":27049.98379295986,"close":27492.777830911058,"volume":113222.070595023,"volumeNotional":3112789232.424695,"tradesDone":1906189.0},{"date":"2023-03-25T00:00:00+00:00","open":27493.125286740007,"high":27851.600766038853,"low":27186.682682331964,"close":27492.53961942098,"volume":69834.353792928,"volumeNotional":1919923738.4487348,"tradesDone":1389686.0},{"date":"2023-03-26T00:00:00+00:00","open":27491.960826601942,"high":28227.84618347879,"low":27448.148946565314,"close":27995.420380192507,"volume":70316.739717935,"volumeNotional":1968546688.1681693,"tradesDone":1388686.0},{"date":"2023-03-27T00:00:00+00:00","open":27995.87566058183,"high":28049.44273343421,"low":26527.468611635708,"close":27146.81184455866,"volume":122776.79240064991,"volumeNotional":3332998482.1788826,"tradesDone":1954887.0},{"date":"2023-03-28T00:00:00+00:00","open":27146.892507791785,"high":27534.93745888457,"low":26664.19516746953,"close":27281.456202201356,"volume":106381.114770002,"volumeNotional":2902231723.339165,"tradesDone":2018099.0},{"date":"2023-03-29T00:00:00+00:00","open":27281.696342306175,"high":28656.79795532486,"low":27256.464858025658,"close":28359.403692552256,"volume":125638.37105392481,"volumeNotional":3563029283.9929256,"tradesDone":2278145.0},{"date":"2023-03-30T00:00:00+00:00","open":28359.58817500611,"high":29189.82244560705,"low":27708.593117492306,"close":28043.67866711094,"volume":142451.4687043699,"volumeNotional":3994863214.0033603,"tradesDone":2467444.0},{"date":"2023-03-31T00:00:00+00:00","open":28043.621161111594,"high":28660.65978578988,"low":27523.643876505976,"close":28477.839146521797,"volume":112214.00252795599,"volumeNotional":3195612313.978521,"tradesDone":1981453.0},{"date":"2023-04-01T00:00:00+00:00","open":28477.905325187417,"high":28826.764796371815,"low":28233.755997156444,"close":28467.52709041305,"volume":43822.84443634101,"volumeNotional":1247528011.1704943,"tradesDone":1087709.0},{"date":"2023-04-02T00:00:00+00:00","open":28467.092297308955,"high":28543.025888069165,"low":27870.760616689717,"close":28189.1954953179,"volume":51730.560743851995,"volumeNotional":1458242889.8908617,"tradesDone":1150207.0},{"date":"2023-04-03T00:00:00+00:00","open":28189.388861355168,"high":28514.89738857829,"low":27236.953917904593,"close":27813.068652742673,"volume":114956.22506374688,"volumeNotional":3197285379.75813,"tradesDone":2029381.0},{"date":"2023-04-04T00:00:00+00:00","open":27812.232569697495,"high":28447.977603275915,"low":27666.683963937794,"close":28179.550977743347,"volume":75262.597812757,"volumeNotional":2120866211.7819808,"tradesDone":1448132.0},{"date":"2023-04-05T00:00:00+00:00","open":28178.620174199867,"high":28790.93640051994,"low":27826.742800553253,"close":28182.40014485109,"volume":89303.4162063269,"volumeNotional":2516784609.8288846,"tradesDone":1600226.0},{"date":"2023-04-06T00:00:00+00:00","open":28181.226809797674,"high":28197.726297182675,"low":27722.80454397576,"close":28050.389287798567,"volume":60027.9693645,"volumeNotional":1683807908.8302715,"tradesDone":1254152.0},{"date":"2023-04-07T00:00:00+00:00","open":28049.129848845587,"high":28119.83006175765,"low":27779.958930234556,"close":27922.12348951081,"volume":36082.033404931,"volumeNotional":1007486992.4851375,"tradesDone":935208.0},{"date":"2023-04-08T00:00:00+00:00","open":27925.471526652775,"high":28172.54241430878,"low":27876.380087775582,"close":27956.293725887004,"volume":26598.338776819997,"volumeNotional":743590971.4654299,"tradesDone":804911.0},{"date":"2023-04-09T00:00:00+00:00","open":27956.573935229786,"high":28548.688569693295,"low":27817.042769722506,"close":28342.495064276176,"volume":44545.56860263101,"volumeNotional":1262532558.255445,"tradesDone":945568.0},{"date":"2023-04-10T00:00:00+00:00","open":28342.43055809878,"high":29779.67080827219,"low":28179.520213701635,"close":29656.61244743198,"volume":97128.765063421,"volumeNotional":2880510142.9835477,"tradesDone":1573253.0},{"date":"2023-04-11T00:00:00+00:00","open":29654.745199677203,"high":30557.198540379464,"low":29607.81561929335,"close":30225.469359186805,"volume":102481.52329064399,"volumeNotional":3097552142.104149,"tradesDone":1764534.0},{"date":"2023-04-12T00:00:00+00:00","open":30225.72508003706,"high":30504.601472108952,"low":29665.183850285972,"close":29911.02891865836,"volume":88613.49615458502,"volumeNotional":2650520846.0632143,"tradesDone":1596619.0},{"date":"2023-04-13T00:00:00+00:00","open":29911.141658694414,"high":30624.794090043593,"low":29875.267309562558,"close":30404.18681745729,"volume":75353.70665377901,"volumeNotional":2291068174.4893713,"tradesDone":1428219.0},{"date":"2023-04-14T00:00:00+00:00","open":30405.125538135544,"high":31034.785606224243,"low":29995.595089877344,"close":30495.442509464345,"volume":111628.49694776098,"volumeNotional":3404160411.0883613,"tradesDone":1952515.0},{"date":"2023-04-15T00:00:00+00:00","open":30495.835509853812,"high":30617.760587500758,"low":30232.21078718001,"close":30324.025972602365,"volume":36559.415698781995,"volumeNotional":1108628671.1930318,"tradesDone":1014796.0},{"date":"2023-04-16T00:00:00+00:00","open":30323.057441695695,"high":30577.531689790554,"low":30154.372637969736,"close":30328.186035822226,"volume":39591.095855641004,"volumeNotional":1200726120.4719508,"tradesDone":931312.0},{"date":"2023-04-17T00:00:00+00:00","open":30328.46552367096,"high":30346.16421998582,"low":29259.615981469815,"close":29448.489131984712,"volume":80986.505868898,"volumeNotional":2384930237.917659,"tradesDone":1381824.0},{"date":"2023-04-18T00:00:00+00:00","open":29448.619649516146,"high":30500.077279004283,"low":29116.796212942845,"close":30395.098257947626,"volume":87379.820628146,"volumeNotional":2655918233.7543364,"tradesDone":1438908.0},{"date":"2023-04-19T00:00:00+00:00","open":30395.16846215601,"high":30432.61094176216,"low":28567.995115067748,"close":28837.519850419303,"volume":124291.059136961,"volumeNotional":3584245885.0917525,"tradesDone":2064860.0},{"date":"2023-04-20T00:00:00+00:00","open":28838.508789484225,"high":29108.99807458294,"low":28005.488361156542,"close":28265.954795955946,"volume":106434.8614682109,"volumeNotional":3008482982.9742827,"tradesDone":1743454.0},{"date":"2023-04-21T00:00:00+00:00","open":28262.11974001594,"high":28380.135302684113,"low":27522.026597208638,"close":27715.097450066816,"volume":69773.45753696091,"volumeNotional":1933778175.0649705,"tradesDone":1185713.0},{"date":"2023-04-22T00:00:00+00:00","open":27263.391881269803,"high":27897.267786210876,"low":27141.596883538572,"close":27824.698633288474,"volume":12400.066247519999,"volumeNotional":345028106.3700562,"tradesDone":347581.0},{"date":"2023-04-23T00:00:00+00:00","open":27826.59679673722,"high":27826.602068722957,"low":27340.997971129862,"close":27599.502225204586,"volume":13307.54968058,"volumeNotional":367281747.02118826,"tradesDone":346658.0},{"date":"2023-04-24T00:00:00+00:00","open":27599.621634474883,"high":28005.278188531087,"low":26969.491026015952,"close":27525.23964615514,"volume":23992.601999789997,"volumeNotional":660402119.7790407,"tradesDone":480639.0},{"date":"2023-04-25T00:00:00+00:00","open":27523.69657396147,"high":28411.067894674634,"low":27199.679087188597,"close":28310.70962548191,"volume":22104.650063540004,"volumeNotional":625798329.3217714,"tradesDone":508476.0},{"date":"2023-04-26T00:00:00+00:00","open":28310.715696425294,"high":30046.94055832169,"low":27241.41319681689,"close":28430.996052002098,"volume":54794.776898359996,"volumeNotional":1557870085.6676087,"tradesDone":834063.0},{"date":"2023-04-27T00:00:00+00:00","open":28434.628926772093,"high":29902.782139278817,"low":28393.613034007954,"close":29487.236634049434,"volume":44510.0519411,"volumeNotional":1312478434.181047,"tradesDone":759196.0},{"date":"2023-04-28T00:00:00+00:00","open":29486.731825257353,"high":29608.814453889314,"low":28906.43362397016,"close":29341.341111277394,"volume":23478.47756923,"volumeNotional":688890019.1322523,"tradesDone":521039.0},{"date":"2023-04-29T00:00:00+00:00","open":29340.749529400142,"high":29473.660631063864,"low":29062.075256318374,"close":29252.946894678757,"volume":8090.212709180001,"volumeNotional":236662562.74829772,"tradesDone":282658.0},{"date":"2023-04-30T00:00:00+00:00","open":29253.783344011357,"high":29974.598381346354,"low":29107.38104905114,"close":29253.429147353683,"volume":14291.112259460002,"volumeNotional":418064039.9189908,"tradesDone":352101.0},{"date":"2023-05-01T00:00:00+00:00","open":29247.47953069144,"high":29352.1852811805,"low":27671.833637914755,"close":28087.66078391997,"volume":30373.589957109998,"volumeNotional":853123091.5051839,"tradesDone":609569.0},{"date":"2023-05-02T00:00:00+00:00","open":28087.902753940016,"high":28909.88961857747,"low":27890.097757422976,"close":28701.565610101043,"volume":22091.20594578,"volumeNotional":634052196.8590589,"tradesDone":560143.0},{"date":"2023-05-03T00:00:00+00:00","open":28704.26371631166,"high":29283.411816217427,"low":28137.263985393343,"close":29048.476020954815,"volume":27598.15038133,"volumeNotional":801684209.5747695,"tradesDone":621582.0},{"date":"2023-05-04T00:00:00+00:00","open":29048.255579948236,"high":29393.889437573434,"low":28685.527053446334,"close":28875.94775363128,"volume":18918.530587769998,"volumeNotional":546290500.8279217,"tradesDone":477635.0},{"date":"2023-05-05T00:00:00+00:00","open":28873.201416660264,"high":29717.353487988858,"low":28814.370750031427,"close":29552.746275608606,"volume":24331.01272661,"volumeNotional":719048245.7381092,"tradesDone":543637.0},{"date":"2023-05-06T00:00:00+00:00","open":29555.801043590734,"high":29867.763769028694,"low":28421.402957684157,"close":28970.22784016688,"volume":15712.83635088,"volumeNotional":455204449.10024995,"tradesDone":404158.0},{"date":"2023-05-07T00:00:00+00:00","open":28965.276678162198,"high":29243.84742076087,"low":28565.865042788984,"close":28696.722203602185,"volume":9987.49573574,"volumeNotional":286608390.6381922,"tradesDone":310619.0},{"date":"2023-05-08T00:00:00+00:00","open":28472.541377523143,"high":28675.263918379515,"low":27282.739121348808,"close":27695.29097613682,"volume":19715.42092036,"volumeNotional":546024319.1063855,"tradesDone":454006.0},{"date":"2023-05-09T00:00:00+00:00","open":27693.557653515818,"high":27837.148489330437,"low":27367.338185714238,"close":27647.14135749171,"volume":11886.394124100001,"volumeNotional":328624818.57985157,"tradesDone":326762.0},{"date":"2023-05-10T00:00:00+00:00","open":27647.929683865335,"high":28335.057311092238,"low":26803.82655311878,"close":27623.148526039015,"volume":23298.802386069998,"volumeNotional":643586278.7892437,"tradesDone":403650.0},{"date":"2023-05-11T00:00:00+00:00","open":27621.319171040424,"high":27651.261883478175,"low":26713.825715273088,"close":26989.29358627093,"volume":17071.37896,"volumeNotional":460744458.67392844,"tradesDone":363044.0},{"date":"2023-05-12T00:00:00+00:00","open":26987.750999734784,"high":27101.05092687869,"low":25816.344886340754,"close":26808.83648070762,"volume":23175.62035248,"volumeNotional":621311416.3685958,"tradesDone":442896.0},{"date":"2023-05-13T00:00:00+00:00","open":26808.573459713167,"high":27065.32502367204,"low":26700.990076284368,"close":26788.95717195767,"volume":5978.35866155,"volumeNotional":160153994.14286512,"tradesDone":222213.0},{"date":"2023-05-14T00:00:00+00:00","open":26787.70541614048,"high":27217.80454267041,"low":26584.98549063506,"close":26929.750351193816,"volume":5325.23155407,"volumeNotional":143407156.31340498,"tradesDone":216690.0},{"date":"2023-05-15T00:00:00+00:00","open":26929.856052445924,"high":27678.363087021284,"low":26739.767346563985,"close":27172.140952780337,"volume":14778.894882440001,"volumeNotional":401574214.8719837,"tradesDone":340076.0},{"date":"2023-05-16T00:00:00+00:00","open":27167.37180420204,"high":27304.486816110348,"low":26861.79601276833,"close":27038.70675406801,"volume":13401.24438209,"volumeNotional":362352316.9869329,"tradesDone":306961.0},{"date":"2023-05-17T00:00:00+00:00","open":27040.01868472971,"high":27516.069168144164,"low":26552.424937236,"close":27409.062924636062,"volume":17194.46485198,"volumeNotional":471284169.0833629,"tradesDone":328612.0},{"date":"2023-05-18T00:00:00+00:00","open":27409.553499459897,"high":27488.153460471985,"low":26365.38242974328,"close":26824.636480646677,"volume":16108.27923974,"volumeNotional":432098734.93477315,"tradesDone":327274.0},{"date":"2023-05-19T00:00:00+00:00","open":26820.999682086232,"high":27188.324159971864,"low":26634.591305349826,"close":26890.761192095222,"volume":9119.23955382,"volumeNotional":245223293.0952826,"tradesDone":266717.0},{"date":"2023-05-20T00:00:00+00:00","open":26890.796718191526,"high":27174.697399748005,"low":26837.657549591877,"close":27113.860537351844,"volume":3976.86769966,"volumeNotional":107828236.18408048,"tradesDone":168960.0},{"date":"2023-05-21T00:00:00+00:00","open":27114.704406744604,"high":27286.46917984799,"low":26670.045070663025,"close":26753.03816675353,"volume":6930.686227840001,"volumeNotional":185416913.1751966,"tradesDone":190327.0},{"date":"2023-05-22T00:00:00+00:00","open":26751.422279237282,"high":27105.811537252463,"low":26535.979585871653,"close":26855.41485048113,"volume":10058.69892581,"volumeNotional":270130532.50871646,"tradesDone":255036.0},{"date":"2023-05-23T00:00:00+00:00","open":26854.944218919427,"high":27502.248011734497,"low":26804.574850073415,"close":27224.00254892539,"volume":13529.55216089,"volumeNotional":368328562.51388836,"tradesDone":306007.0},{"date":"2023-05-24T00:00:00+00:00","open":27223.47150621644,"high":27225.56663765902,"low":26069.99356361116,"close":26323.143527303786,"volume":20340.303927930003,"volumeNotional":535420739.6838824,"tradesDone":361731.0},{"date":"2023-05-25T00:00:00+00:00","open":26323.16013830477,"high":26624.593469542837,"low":25866.18001135021,"close":26479.757462389596,"volume":14245.59330562,"volumeNotional":377219855.64065844,"tradesDone":310426.0},{"date":"2023-05-26T00:00:00+00:00","open":26480.37889292411,"high":26948.061915079623,"low":26336.790891938206,"close":26717.25710800466,"volume":12383.845352429998,"volumeNotional":330862380.26664084,"tradesDone":278847.0},{"date":"2023-05-27T00:00:00+00:00","open":26713.903175083964,"high":26934.43250818705,"low":26560.75062578429,"close":26869.686068549425,"volume":4345.55878206,"volumeNotional":116763800.26638019,"tradesDone":166510.0},{"date":"2023-05-28T00:00:00+00:00","open":26872.62671434272,"high":28274.59197224525,"low":26784.175033765834,"close":28075.96264143509,"volume":13205.203105560002,"volumeNotional":370748789.06426525,"tradesDone":257003.0},{"date":"2023-05-29T00:00:00+00:00","open":28074.02273842439,"high":28471.035133920494,"low":27537.401911366873,"close":27746.122340239403,"volume":13667.199090490001,"volumeNotional":379211778.01314425,"tradesDone":281796.0},{"date":"2023-05-30T00:00:00+00:00","open":27745.4370434407,"high":28056.471343790403,"low":27557.275664111574,"close":27700.88977281828,"volume":14133.71955223,"volumeNotional":391516607.3962498,"tradesDone":312104.0},{"date":"2023-05-31T00:00:00+00:00","open":27701.991855086773,"high":27844.222073245546,"low":26843.812147761822,"close":27222.163647614194,"volume":18281.035789470003,"volumeNotional":497649347.90884435,"tradesDone":355318.0},{"date":"2023-06-01T00:00:00+00:00","open":27221.91634087899,"high":27358.634040967616,"low":26614.083702803593,"close":26827.381582501104,"volume":14371.844910249998,"volumeNotional":385558967.451803,"tradesDone":350869.0},{"date":"2023-06-02T00:00:00+00:00","open":26826.88998267247,"high":27307.312997414876,"low":26507.710424894784,"close":27251.151462640217,"volume":14637.30025375,"volumeNotional":398883286.2190833,"tradesDone":342946.0},{"date":"2023-06-03T00:00:00+00:00","open":27252.733037080354,"high":27341.05910613207,"low":26924.580105079418,"close":27076.886752617964,"volume":4702.83227989,"volumeNotional":127338057.05913767,"tradesDone":186200.0},{"date":"2023-06-04T00:00:00+00:00","open":27077.725008848007,"high":27468.432085113214,"low":26960.673160533373,"close":27122.291618814626,"volume":5188.868145299999,"volumeNotional":140733995.00840434,"tradesDone":194052.0},{"date":"2023-06-05T00:00:00+00:00","open":27122.018337875525,"high":27135.91269814294,"low":25395.269396851225,"close":25737.608234366533,"volume":23068.073136000003,"volumeNotional":593717029.096083,"tradesDone":508512.0},{"date":"2023-06-06T00:00:00+00:00","open":25739.44609922973,"high":27367.30342715931,"low":25352.44191369581,"close":27242.45212263633,"volume":23623.905409249997,"volumeNotional":643573112.0611824,"tradesDone":492875.0}]}]' @@ -21,7 +21,7 @@ interactions: Content-Type: - application/json Date: - - Thu, 29 Feb 2024 04:25:59 GMT + - Thu, 17 Oct 2024 21:28:47 GMT Server: - nginx/1.18.0 (Ubuntu) Vary: diff --git a/openbb_platform/providers/tiingo/tests/record/http/test_tiingo_fetchers/test_tiingo_crypto_historical_fetcher_urllib3_v2.yaml b/openbb_platform/providers/tiingo/tests/record/http/test_tiingo_fetchers/test_tiingo_crypto_historical_fetcher_urllib3_v2.yaml index 9c4c386a585..1228f57f828 100644 --- a/openbb_platform/providers/tiingo/tests/record/http/test_tiingo_fetchers/test_tiingo_crypto_historical_fetcher_urllib3_v2.yaml +++ b/openbb_platform/providers/tiingo/tests/record/http/test_tiingo_fetchers/test_tiingo_crypto_historical_fetcher_urllib3_v2.yaml @@ -9,7 +9,7 @@ interactions: Connection: - keep-alive method: GET - uri: https://api.tiingo.com/tiingo/crypto/prices?endDate=2023-06-06&resampleFreq=1Day&startDate=2023-01-01&tickers=BTCUSD&token=MOCK_TOKEN + uri: https://api.tiingo.com/tiingo/crypto/prices?endDate=2023-06-06&resampleFreq=1day&startDate=2023-01-01&tickers=BTCUSD&token=MOCK_TOKEN response: body: string: '[{"ticker":"btcusd","baseCurrency":"btc","quoteCurrency":"usd","priceData":[{"date":"2023-01-01T00:00:00+00:00","open":16534.758508538427,"high":16622.870558446135,"low":16492.287893194825,"close":16610.40117718445,"volume":110346.5693071621,"volumeNotional":1832900784.7179508,"tradesDone":2812901.0},{"date":"2023-01-02T00:00:00+00:00","open":16610.892883605946,"high":16792.022463375222,"low":16542.456230097472,"close":16666.42070337159,"volume":139190.34028523602,"volumeNotional":2319804769.039194,"tradesDone":3586445.0},{"date":"2023-01-03T00:00:00+00:00","open":16666.425770956354,"high":16772.008176728094,"low":16600.462687819214,"close":16670.2239959582,"volume":182632.56007866,"volumeNotional":3044525685.4665556,"tradesDone":4392043.0},{"date":"2023-01-04T00:00:00+00:00","open":16670.492558854425,"high":16985.44143125503,"low":16647.613841053073,"close":16845.3620428872,"volume":254928.102217694,"volumeNotional":4294356176.7632103,"tradesDone":5662266.0},{"date":"2023-01-05T00:00:00+00:00","open":16845.34346331706,"high":16874.57078229087,"low":16748.352864565408,"close":16825.22744905322,"volume":182315.91906806597,"volumeNotional":3067506805.903389,"tradesDone":4181793.0},{"date":"2023-01-06T00:00:00+00:00","open":16825.356660535454,"high":17033.021856610823,"low":16672.387166794186,"close":16943.062497969404,"volume":239812.614435073,"volumeNotional":4063160114.1748815,"tradesDone":4719899.0},{"date":"2023-01-07T00:00:00+00:00","open":16942.30531964883,"high":16974.006096954814,"low":16900.429739245064,"close":16935.606463508877,"volume":111958.584354078,"volumeNotional":1896086524.8322272,"tradesDone":2704933.0},{"date":"2023-01-08T00:00:00+00:00","open":16935.99943944265,"high":17168.020164038557,"low":16903.27274222517,"close":17121.282112787987,"volume":148123.123651652,"volumeNotional":2536057787.4673123,"tradesDone":3456234.0},{"date":"2023-01-09T00:00:00+00:00","open":17121.57061012745,"high":17390.76578282186,"low":17097.311813958935,"close":17172.208908019893,"volume":310183.262251941,"volumeNotional":5326531779.161452,"tradesDone":5881651.0},{"date":"2023-01-10T00:00:00+00:00","open":17172.797115007168,"high":17493.595691785365,"low":17139.96726397043,"close":17436.2637252567,"volume":255246.05909687202,"volumeNotional":4450537601.245518,"tradesDone":5000575.0},{"date":"2023-01-11T00:00:00+00:00","open":17436.280208162683,"high":17994.80360990724,"low":17309.4444175157,"close":17936.958420493294,"volume":301326.40384703095,"volumeNotional":5404879176.800964,"tradesDone":5156459.0},{"date":"2023-01-12T00:00:00+00:00","open":17937.23178217057,"high":19111.686238683895,"low":17887.70292419522,"close":18843.615393985634,"volume":546194.156613748,"volumeNotional":10292272617.671824,"tradesDone":8515248.0},{"date":"2023-01-13T00:00:00+00:00","open":18843.702644737696,"high":19996.242779748394,"low":18710.313626706644,"close":19925.507116903274,"volume":445054.043296865,"volumeNotional":8867927507.118261,"tradesDone":7738164.0},{"date":"2023-01-14T00:00:00+00:00","open":19925.46402800475,"high":21260.3129558461,"low":19885.518587547882,"close":20946.42909671108,"volume":475917.1693841831,"volumeNotional":9968765244.413227,"tradesDone":8814695.0},{"date":"2023-01-15T00:00:00+00:00","open":20944.38103412309,"high":21040.41314056405,"low":20542.15697053462,"close":20860.213701599645,"volume":213663.78927575698,"volumeNotional":4457072304.585845,"tradesDone":5169848.0},{"date":"2023-01-16T00:00:00+00:00","open":20861.34285941691,"high":21461.509652455217,"low":20603.222622679405,"close":21178.20240975164,"volume":344480.687747793,"volumeNotional":7295481731.373212,"tradesDone":6682521.0},{"date":"2023-01-17T00:00:00+00:00","open":21177.07334134622,"high":21628.41751210442,"low":20832.822616861344,"close":21125.716720343295,"volume":317891.67411837686,"volumeNotional":6715689455.180516,"tradesDone":6108968.0},{"date":"2023-01-18T00:00:00+00:00","open":21123.508789269184,"high":21639.834325639462,"low":20394.387947494208,"close":20669.66398713652,"volume":399287.363072815,"volumeNotional":8253135629.024868,"tradesDone":7306519.0},{"date":"2023-01-19T00:00:00+00:00","open":20669.667255804423,"high":21186.72047920568,"low":20650.451074363024,"close":21067.169977846763,"volume":280914.929889477,"volumeNotional":5918082577.296517,"tradesDone":5390518.0},{"date":"2023-01-20T00:00:00+00:00","open":21067.318845244237,"high":22747.54274303515,"low":20854.487051634573,"close":22659.49889848295,"volume":383260.33795678604,"volumeNotional":8684487205.763996,"tradesDone":6964724.0},{"date":"2023-01-21T00:00:00+00:00","open":22658.741683860597,"high":23365.612176433126,"low":22415.414658865433,"close":22777.866458104367,"volume":393591.21135730395,"volumeNotional":8965168051.3802,"tradesDone":7340650.0},{"date":"2023-01-22T00:00:00+00:00","open":22777.786814010415,"high":23070.80216753831,"low":22291.02015218942,"close":22706.6567041434,"volume":287904.65037854103,"volumeNotional":6537352059.67196,"tradesDone":6152631.0},{"date":"2023-01-23T00:00:00+00:00","open":22705.023761257806,"high":23177.64120280451,"low":22495.040780156975,"close":22914.806544240204,"volume":334985.914643084,"volumeNotional":7676137429.091631,"tradesDone":6689264.0},{"date":"2023-01-24T00:00:00+00:00","open":22916.213812975722,"high":23160.337734320918,"low":22458.873414989514,"close":22631.297007531946,"volume":341607.57040865096,"volumeNotional":7731022385.939561,"tradesDone":6912892.0},{"date":"2023-01-25T00:00:00+00:00","open":22630.35882328906,"high":23815.402364488167,"low":22299.05184661137,"close":23058.887712962543,"volume":398687.62187728495,"volumeNotional":9193293105.416382,"tradesDone":7487613.0},{"date":"2023-01-26T00:00:00+00:00","open":23058.54405024964,"high":23280.685861431793,"low":22848.58534793659,"close":23009.407018044218,"volume":323698.13523062505,"volumeNotional":7448102144.50337,"tradesDone":6453592.0},{"date":"2023-01-27T00:00:00+00:00","open":23007.85085501095,"high":23498.853019121838,"low":22578.236382525603,"close":23074.906999829804,"volume":284459.814003024,"volumeNotional":6563883753.308663,"tradesDone":5859985.0},{"date":"2023-01-28T00:00:00+00:00","open":23074.56872156852,"high":23189.26405811895,"low":22876.64747411179,"close":23027.41455681704,"volume":145082.87347243898,"volumeNotional":3340883472.544086,"tradesDone":3461693.0},{"date":"2023-01-29T00:00:00+00:00","open":23022.479105202696,"high":23965.235948533962,"low":22966.640963715956,"close":23747.019042121985,"volume":296682.5813472069,"volumeNotional":7045326908.718027,"tradesDone":6033555.0},{"date":"2023-01-30T00:00:00+00:00","open":23747.74358095152,"high":23804.554993231297,"low":22504.088155533067,"close":22833.288374006806,"volume":318186.1375034659,"volumeNotional":7265235834.22802,"tradesDone":6866289.0},{"date":"2023-01-31T00:00:00+00:00","open":22834.34868719895,"high":23323.165558785888,"low":22717.46523452395,"close":23129.71238462947,"volume":294786.55345481803,"volumeNotional":6818328196.266142,"tradesDone":6291240.0},{"date":"2023-02-01T00:00:00+00:00","open":23129.60734979065,"high":23822.940259567993,"low":22775.455317329255,"close":23748.088923078056,"volume":341733.46495692,"volumeNotional":8115516713.788515,"tradesDone":7150155.0},{"date":"2023-02-02T00:00:00+00:00","open":23747.0872030901,"high":24262.102952024463,"low":23367.25434031797,"close":23491.2274576747,"volume":394680.288277346,"volumeNotional":9271524424.983757,"tradesDone":8218546.0},{"date":"2023-02-03T00:00:00+00:00","open":23491.928051755865,"high":23747.077662050582,"low":23211.68416433434,"close":23436.420261583615,"volume":355423.665510659,"volumeNotional":8329858395.820326,"tradesDone":7051300.0},{"date":"2023-02-04T00:00:00+00:00","open":23436.514729027833,"high":23598.81510929699,"low":23254.097741367463,"close":23353.810507945356,"volume":174061.56393647002,"volumeNotional":4065000780.888936,"tradesDone":4282100.0},{"date":"2023-02-05T00:00:00+00:00","open":23354.211922806222,"high":23498.76637636073,"low":22750.479134986206,"close":22955.052298862247,"volume":222521.450994416,"volumeNotional":5107991545.195532,"tradesDone":5260451.0},{"date":"2023-02-06T00:00:00+00:00","open":22954.81271990142,"high":23158.324821368344,"low":22634.657513798375,"close":22766.908081381862,"volume":284031.2601124471,"volumeNotional":6466513591.219145,"tradesDone":6061109.0},{"date":"2023-02-07T00:00:00+00:00","open":22766.946866931554,"high":23349.111314865186,"low":22751.77838080674,"close":23244.890157805403,"volume":326719.584936721,"volumeNotional":7594560864.257853,"tradesDone":7332769.0},{"date":"2023-02-08T00:00:00+00:00","open":23243.04282353539,"high":23456.15056067334,"low":22666.32378169172,"close":22967.39589438958,"volume":296785.900615876,"volumeNotional":6816399275.317785,"tradesDone":6863165.0},{"date":"2023-02-09T00:00:00+00:00","open":22966.23326482415,"high":23015.73874123728,"low":21692.99680676366,"close":21806.785634220563,"volume":437322.539375191,"volumeNotional":9536598869.16777,"tradesDone":8646010.0},{"date":"2023-02-10T00:00:00+00:00","open":21808.339830547367,"high":21956.961142582437,"low":21458.412880304477,"close":21629.589423115016,"volume":361572.229258134,"volumeNotional":7820658865.653852,"tradesDone":6343721.0},{"date":"2023-02-11T00:00:00+00:00","open":21629.56994239977,"high":21912.57758626528,"low":21606.285495750766,"close":21868.469120508347,"volume":185398.990533929,"volumeNotional":4054392099.464646,"tradesDone":3717975.0},{"date":"2023-02-12T00:00:00+00:00","open":21868.92047543776,"high":22094.33927435566,"low":21635.239865646385,"close":21785.92248542488,"volume":215986.308771281,"volumeNotional":4705460980.804172,"tradesDone":4028782.0},{"date":"2023-02-13T00:00:00+00:00","open":21784.961342118844,"high":21901.667037425694,"low":21364.02496161614,"close":21789.100791446246,"volume":321054.7047442801,"volumeNotional":6995493321.241134,"tradesDone":5795945.0},{"date":"2023-02-14T00:00:00+00:00","open":21789.813889905905,"high":22334.904152432726,"low":21548.09009000796,"close":22200.10689875198,"volume":388077.974555726,"volumeNotional":8615372520.188267,"tradesDone":6677024.0},{"date":"2023-02-15T00:00:00+00:00","open":22200.25645853632,"high":24384.62829397166,"low":22053.983193218235,"close":24331.147433807317,"volume":414707.982965513,"volumeNotional":10090321075.51075,"tradesDone":7527313.0},{"date":"2023-02-16T00:00:00+00:00","open":24330.07392682627,"high":25231.587838856147,"low":23494.70937538958,"close":23506.73478761036,"volume":494987.637211754,"volumeNotional":11635543111.082594,"tradesDone":10017567.0},{"date":"2023-02-17T00:00:00+00:00","open":23506.500363758303,"high":25023.454206492523,"low":23333.031972129258,"close":24579.63020419649,"volume":535465.0397492789,"volumeNotional":13161532664.312649,"tradesDone":9876808.0},{"date":"2023-02-18T00:00:00+00:00","open":24578.04586250838,"high":24884.206935482573,"low":24431.85754839516,"close":24636.835983572786,"volume":226346.40309056902,"volumeNotional":5576459208.414001,"tradesDone":5587301.0},{"date":"2023-02-19T00:00:00+00:00","open":24636.960781383248,"high":25192.516211187314,"low":24197.513424917393,"close":24279.314507001585,"volume":319962.408439316,"volumeNotional":7768467944.915851,"tradesDone":6819798.0},{"date":"2023-02-20T00:00:00+00:00","open":24279.82212524917,"high":25121.10976908513,"low":23847.92533372801,"close":24844.512855441255,"volume":370089.7517008561,"volumeNotional":9194699593.79898,"tradesDone":8912465.0},{"date":"2023-02-21T00:00:00+00:00","open":24845.961542510562,"high":25253.691856111283,"low":24153.678570217904,"close":24456.85051691342,"volume":408337.32267434703,"volumeNotional":9986644861.123146,"tradesDone":9645034.0},{"date":"2023-02-22T00:00:00+00:00","open":24455.532273815614,"high":24487.54482763843,"low":23579.58845207356,"close":24190.23629090606,"volume":412202.607884278,"volumeNotional":9971278484.448383,"tradesDone":10006318.0},{"date":"2023-02-23T00:00:00+00:00","open":24189.261865227578,"high":24603.99633281332,"low":23612.852511785713,"close":23942.64086692768,"volume":429154.11443397193,"volumeNotional":10275082838.456974,"tradesDone":9578353.0},{"date":"2023-02-24T00:00:00+00:00","open":23942.8014480139,"high":24131.65220176608,"low":22821.76108661926,"close":23187.7594074938,"volume":378410.5775526979,"volumeNotional":8774493429.542732,"tradesDone":8872408.0},{"date":"2023-02-25T00:00:00+00:00","open":23186.532860926316,"high":23223.65221829308,"low":22727.54442118508,"close":23161.79691640286,"volume":203126.375823149,"volumeNotional":4704771865.1807,"tradesDone":5788856.0},{"date":"2023-02-26T00:00:00+00:00","open":23161.794958186474,"high":23698.716825376534,"low":23059.296256018395,"close":23557.24304450421,"volume":214691.089723741,"volumeNotional":5057530180.111627,"tradesDone":6187090.0},{"date":"2023-02-27T00:00:00+00:00","open":23557.238213359717,"high":23899.96014698971,"low":23102.92724625777,"close":23491.09651011545,"volume":306302.1805658,"volumeNotional":7195374084.9300165,"tradesDone":8383090.0},{"date":"2023-02-28T00:00:00+00:00","open":23492.04498127966,"high":23600.002394182917,"low":23021.69308328172,"close":23143.86643650886,"volume":280682.00044089096,"volumeNotional":6496066729.336101,"tradesDone":7350756.0},{"date":"2023-03-01T00:00:00+00:00","open":23144.27814122816,"high":23999.76013244346,"low":23020.584899482204,"close":23633.620866618927,"volume":337141.683397634,"volumeNotional":7967878723.753355,"tradesDone":8204359.0},{"date":"2023-03-02T00:00:00+00:00","open":23634.45572366933,"high":23803.56478707363,"low":23193.889885658158,"close":23465.50232382252,"volume":256409.812836994,"volumeNotional":6016785058.97738,"tradesDone":6713059.0},{"date":"2023-03-03T00:00:00+00:00","open":23465.668271156672,"high":23479.360293301717,"low":21980.487424792944,"close":22355.051813818725,"volume":354871.338496905,"volumeNotional":7933167159.337515,"tradesDone":7529497.0},{"date":"2023-03-04T00:00:00+00:00","open":22354.712279160834,"high":22413.38098047793,"low":22162.598529893046,"close":22348.10163881476,"volume":126410.68585299602,"volumeNotional":2825038855.675038,"tradesDone":3669199.0},{"date":"2023-03-05T00:00:00+00:00","open":22348.557517145302,"high":22663.786358985504,"low":22189.803438091967,"close":22433.141901199633,"volume":164977.92274369,"volumeNotional":3700973151.474348,"tradesDone":4365140.0},{"date":"2023-03-06T00:00:00+00:00","open":22432.42079890968,"high":22604.158075918673,"low":22260.755639498268,"close":22407.856206357712,"volume":220051.03349124696,"volumeNotional":4930871916.532267,"tradesDone":5579208.0},{"date":"2023-03-07T00:00:00+00:00","open":22407.78544494383,"high":22557.75346609151,"low":21925.38651659266,"close":22196.01333077293,"volume":312923.36840575404,"volumeNotional":6945651256.644485,"tradesDone":6805051.0},{"date":"2023-03-08T00:00:00+00:00","open":22196.516231385245,"high":22286.67148021186,"low":21576.22476428865,"close":21701.066618080036,"volume":324288.55411497195,"volumeNotional":7037407516.329859,"tradesDone":7199547.0},{"date":"2023-03-09T00:00:00+00:00","open":21700.130678069694,"high":21828.4485783622,"low":20033.532707329286,"close":20358.80594538473,"volume":469177.988154495,"volumeNotional":9551903614.68338,"tradesDone":9012340.0},{"date":"2023-03-10T00:00:00+00:00","open":20359.015298201055,"high":20364.28409489808,"low":19550.79323447636,"close":20217.025364156147,"volume":607665.151521093,"volumeNotional":12285181781.215725,"tradesDone":10043791.0},{"date":"2023-03-11T00:00:00+00:00","open":20216.013994410965,"high":20885.787417853026,"low":19887.294073306668,"close":20608.31095556546,"volume":433044.25016966,"volumeNotional":8924310565.016033,"tradesDone":8816837.0},{"date":"2023-03-12T00:00:00+00:00","open":20607.832859580714,"high":22336.149681645147,"low":20431.527006945962,"close":22192.69281286857,"volume":473717.985748779,"volumeNotional":10513077737.653503,"tradesDone":8901607.0},{"date":"2023-03-13T00:00:00+00:00","open":22193.987921282795,"high":24623.733257081625,"low":21885.82323429922,"close":24187.655049850575,"volume":755439.36759096,"volumeNotional":18272306834.36741,"tradesDone":13707875.0},{"date":"2023-03-14T00:00:00+00:00","open":24186.731084713705,"high":26498.513239674518,"low":24039.102900934104,"close":24734.138121488864,"volume":778704.6162816129,"volumeNotional":19260587534.9504,"tradesDone":14163547.0},{"date":"2023-03-15T00:00:00+00:00","open":24733.515542517143,"high":25311.99304916627,"low":23932.543907568026,"close":24382.07161143555,"volume":637435.3612997518,"volumeNotional":15541994626.871841,"tradesDone":11908088.0},{"date":"2023-03-16T00:00:00+00:00","open":24382.048799054122,"high":25208.935406751192,"low":24203.02849180725,"close":25030.48921556089,"volume":480833.26540094096,"volumeNotional":12035491864.101181,"tradesDone":9792622.0},{"date":"2023-03-17T00:00:00+00:00","open":25030.814468696008,"high":27830.562262254385,"low":24910.982306554783,"close":27446.279838770355,"volume":696402.6093887371,"volumeNotional":19113660897.733162,"tradesDone":12506946.0},{"date":"2023-03-18T00:00:00+00:00","open":27446.866546782778,"high":27781.46442110656,"low":26653.825538874808,"close":26982.051577725462,"volume":405178.53545737796,"volumeNotional":10932548141.898237,"tradesDone":9478941.0},{"date":"2023-03-19T00:00:00+00:00","open":26981.87986819447,"high":28478.71097386288,"low":26891.905934720326,"close":28050.330386850223,"volume":407187.529512644,"volumeNotional":11421744732.23499,"tradesDone":9220811.0},{"date":"2023-03-20T00:00:00+00:00","open":28051.118058643577,"high":28568.40049592391,"low":27216.594834584925,"close":27798.536291386794,"volume":525578.2631171329,"volumeNotional":14610306421.225657,"tradesDone":11461901.0},{"date":"2023-03-21T00:00:00+00:00","open":27798.3081589649,"high":28517.532566468268,"low":27403.888624347812,"close":28197.93305049566,"volume":452952.937069486,"volumeNotional":12772336594.51074,"tradesDone":11028812.0},{"date":"2023-03-22T00:00:00+00:00","open":28198.416014978484,"high":28891.57656419918,"low":26670.92195447159,"close":27314.896197671238,"volume":285080.68233111,"volumeNotional":7786949245.835559,"tradesDone":3962082.0},{"date":"2023-03-23T00:00:00+00:00","open":27314.60316990628,"high":28785.648117353863,"low":27185.628461519915,"close":28352.68633491559,"volume":178047.573365239,"volumeNotional":5048127000.3174925,"tradesDone":2708870.0},{"date":"2023-03-24T00:00:00+00:00","open":28353.33311100366,"high":28430.37142628591,"low":27049.98379295986,"close":27492.777830911058,"volume":113222.070595023,"volumeNotional":3112789232.424695,"tradesDone":1906189.0},{"date":"2023-03-25T00:00:00+00:00","open":27493.125286740007,"high":27851.600766038853,"low":27186.682682331964,"close":27492.53961942098,"volume":69834.353792928,"volumeNotional":1919923738.4487348,"tradesDone":1389686.0},{"date":"2023-03-26T00:00:00+00:00","open":27491.960826601942,"high":28227.84618347879,"low":27448.148946565314,"close":27995.420380192507,"volume":70316.739717935,"volumeNotional":1968546688.1681693,"tradesDone":1388686.0},{"date":"2023-03-27T00:00:00+00:00","open":27995.87566058183,"high":28049.44273343421,"low":26527.468611635708,"close":27146.81184455866,"volume":122776.79240064991,"volumeNotional":3332998482.1788826,"tradesDone":1954887.0},{"date":"2023-03-28T00:00:00+00:00","open":27146.892507791785,"high":27534.93745888457,"low":26664.19516746953,"close":27281.456202201356,"volume":106381.114770002,"volumeNotional":2902231723.339165,"tradesDone":2018099.0},{"date":"2023-03-29T00:00:00+00:00","open":27281.696342306175,"high":28656.79795532486,"low":27256.464858025658,"close":28359.403692552256,"volume":125638.37105392481,"volumeNotional":3563029283.9929256,"tradesDone":2278145.0},{"date":"2023-03-30T00:00:00+00:00","open":28359.58817500611,"high":29189.82244560705,"low":27708.593117492306,"close":28043.67866711094,"volume":142451.4687043699,"volumeNotional":3994863214.0033603,"tradesDone":2467444.0},{"date":"2023-03-31T00:00:00+00:00","open":28043.621161111594,"high":28660.65978578988,"low":27523.643876505976,"close":28477.839146521797,"volume":112214.00252795599,"volumeNotional":3195612313.978521,"tradesDone":1981453.0},{"date":"2023-04-01T00:00:00+00:00","open":28477.905325187417,"high":28826.764796371815,"low":28233.755997156444,"close":28467.52709041305,"volume":43822.84443634101,"volumeNotional":1247528011.1704943,"tradesDone":1087709.0},{"date":"2023-04-02T00:00:00+00:00","open":28467.092297308955,"high":28543.025888069165,"low":27870.760616689717,"close":28189.1954953179,"volume":51730.560743851995,"volumeNotional":1458242889.8908617,"tradesDone":1150207.0},{"date":"2023-04-03T00:00:00+00:00","open":28189.388861355168,"high":28514.89738857829,"low":27236.953917904593,"close":27813.068652742673,"volume":114956.22506374688,"volumeNotional":3197285379.75813,"tradesDone":2029381.0},{"date":"2023-04-04T00:00:00+00:00","open":27812.232569697495,"high":28447.977603275915,"low":27666.683963937794,"close":28179.550977743347,"volume":75262.597812757,"volumeNotional":2120866211.7819808,"tradesDone":1448132.0},{"date":"2023-04-05T00:00:00+00:00","open":28178.620174199867,"high":28790.93640051994,"low":27826.742800553253,"close":28182.40014485109,"volume":89303.4162063269,"volumeNotional":2516784609.8288846,"tradesDone":1600226.0},{"date":"2023-04-06T00:00:00+00:00","open":28181.226809797674,"high":28197.726297182675,"low":27722.80454397576,"close":28050.389287798567,"volume":60027.9693645,"volumeNotional":1683807908.8302715,"tradesDone":1254152.0},{"date":"2023-04-07T00:00:00+00:00","open":28049.129848845587,"high":28119.83006175765,"low":27779.958930234556,"close":27922.12348951081,"volume":36082.033404931,"volumeNotional":1007486992.4851375,"tradesDone":935208.0},{"date":"2023-04-08T00:00:00+00:00","open":27925.471526652775,"high":28172.54241430878,"low":27876.380087775582,"close":27956.293725887004,"volume":26598.338776819997,"volumeNotional":743590971.4654299,"tradesDone":804911.0},{"date":"2023-04-09T00:00:00+00:00","open":27956.573935229786,"high":28548.688569693295,"low":27817.042769722506,"close":28342.495064276176,"volume":44545.56860263101,"volumeNotional":1262532558.255445,"tradesDone":945568.0},{"date":"2023-04-10T00:00:00+00:00","open":28342.43055809878,"high":29779.67080827219,"low":28179.520213701635,"close":29656.61244743198,"volume":97128.765063421,"volumeNotional":2880510142.9835477,"tradesDone":1573253.0},{"date":"2023-04-11T00:00:00+00:00","open":29654.745199677203,"high":30557.198540379464,"low":29607.81561929335,"close":30225.469359186805,"volume":102481.52329064399,"volumeNotional":3097552142.104149,"tradesDone":1764534.0},{"date":"2023-04-12T00:00:00+00:00","open":30225.72508003706,"high":30504.601472108952,"low":29665.183850285972,"close":29911.02891865836,"volume":88613.49615458502,"volumeNotional":2650520846.0632143,"tradesDone":1596619.0},{"date":"2023-04-13T00:00:00+00:00","open":29911.141658694414,"high":30624.794090043593,"low":29875.267309562558,"close":30404.18681745729,"volume":75353.70665377901,"volumeNotional":2291068174.4893713,"tradesDone":1428219.0},{"date":"2023-04-14T00:00:00+00:00","open":30405.125538135544,"high":31034.785606224243,"low":29995.595089877344,"close":30495.442509464345,"volume":111628.49694776098,"volumeNotional":3404160411.0883613,"tradesDone":1952515.0},{"date":"2023-04-15T00:00:00+00:00","open":30495.835509853812,"high":30617.760587500758,"low":30232.21078718001,"close":30324.025972602365,"volume":36559.415698781995,"volumeNotional":1108628671.1930318,"tradesDone":1014796.0},{"date":"2023-04-16T00:00:00+00:00","open":30323.057441695695,"high":30577.531689790554,"low":30154.372637969736,"close":30328.186035822226,"volume":39591.095855641004,"volumeNotional":1200726120.4719508,"tradesDone":931312.0},{"date":"2023-04-17T00:00:00+00:00","open":30328.46552367096,"high":30346.16421998582,"low":29259.615981469815,"close":29448.489131984712,"volume":80986.505868898,"volumeNotional":2384930237.917659,"tradesDone":1381824.0},{"date":"2023-04-18T00:00:00+00:00","open":29448.619649516146,"high":30500.077279004283,"low":29116.796212942845,"close":30395.098257947626,"volume":87379.820628146,"volumeNotional":2655918233.7543364,"tradesDone":1438908.0},{"date":"2023-04-19T00:00:00+00:00","open":30395.16846215601,"high":30432.61094176216,"low":28567.995115067748,"close":28837.519850419303,"volume":124291.059136961,"volumeNotional":3584245885.0917525,"tradesDone":2064860.0},{"date":"2023-04-20T00:00:00+00:00","open":28838.508789484225,"high":29108.99807458294,"low":28005.488361156542,"close":28265.954795955946,"volume":106434.8614682109,"volumeNotional":3008482982.9742827,"tradesDone":1743454.0},{"date":"2023-04-21T00:00:00+00:00","open":28262.11974001594,"high":28380.135302684113,"low":27522.026597208638,"close":27715.097450066816,"volume":69773.45753696091,"volumeNotional":1933778175.0649705,"tradesDone":1185713.0},{"date":"2023-04-22T00:00:00+00:00","open":27263.391881269803,"high":27897.267786210876,"low":27141.596883538572,"close":27824.698633288474,"volume":12400.066247519999,"volumeNotional":345028106.3700562,"tradesDone":347581.0},{"date":"2023-04-23T00:00:00+00:00","open":27826.59679673722,"high":27826.602068722957,"low":27340.997971129862,"close":27599.502225204586,"volume":13307.54968058,"volumeNotional":367281747.02118826,"tradesDone":346658.0},{"date":"2023-04-24T00:00:00+00:00","open":27599.621634474883,"high":28005.278188531087,"low":26969.491026015952,"close":27525.23964615514,"volume":23992.601999789997,"volumeNotional":660402119.7790407,"tradesDone":480639.0},{"date":"2023-04-25T00:00:00+00:00","open":27523.69657396147,"high":28411.067894674634,"low":27199.679087188597,"close":28310.70962548191,"volume":22104.650063540004,"volumeNotional":625798329.3217714,"tradesDone":508476.0},{"date":"2023-04-26T00:00:00+00:00","open":28310.715696425294,"high":30046.94055832169,"low":27241.41319681689,"close":28430.996052002098,"volume":54794.776898359996,"volumeNotional":1557870085.6676087,"tradesDone":834063.0},{"date":"2023-04-27T00:00:00+00:00","open":28434.628926772093,"high":29902.782139278817,"low":28393.613034007954,"close":29487.236634049434,"volume":44510.0519411,"volumeNotional":1312478434.181047,"tradesDone":759196.0},{"date":"2023-04-28T00:00:00+00:00","open":29486.731825257353,"high":29608.814453889314,"low":28906.43362397016,"close":29341.341111277394,"volume":23478.47756923,"volumeNotional":688890019.1322523,"tradesDone":521039.0},{"date":"2023-04-29T00:00:00+00:00","open":29340.749529400142,"high":29473.660631063864,"low":29062.075256318374,"close":29252.946894678757,"volume":8090.212709180001,"volumeNotional":236662562.74829772,"tradesDone":282658.0},{"date":"2023-04-30T00:00:00+00:00","open":29253.783344011357,"high":29974.598381346354,"low":29107.38104905114,"close":29253.429147353683,"volume":14291.112259460002,"volumeNotional":418064039.9189908,"tradesDone":352101.0},{"date":"2023-05-01T00:00:00+00:00","open":29247.47953069144,"high":29352.1852811805,"low":27671.833637914755,"close":28087.66078391997,"volume":30373.589957109998,"volumeNotional":853123091.5051839,"tradesDone":609569.0},{"date":"2023-05-02T00:00:00+00:00","open":28087.902753940016,"high":28909.88961857747,"low":27890.097757422976,"close":28701.565610101043,"volume":22091.20594578,"volumeNotional":634052196.8590589,"tradesDone":560143.0},{"date":"2023-05-03T00:00:00+00:00","open":28704.26371631166,"high":29283.411816217427,"low":28137.263985393343,"close":29048.476020954815,"volume":27598.15038133,"volumeNotional":801684209.5747695,"tradesDone":621582.0},{"date":"2023-05-04T00:00:00+00:00","open":29048.255579948236,"high":29393.889437573434,"low":28685.527053446334,"close":28875.94775363128,"volume":18918.530587769998,"volumeNotional":546290500.8279217,"tradesDone":477635.0},{"date":"2023-05-05T00:00:00+00:00","open":28873.201416660264,"high":29717.353487988858,"low":28814.370750031427,"close":29552.746275608606,"volume":24331.01272661,"volumeNotional":719048245.7381092,"tradesDone":543637.0},{"date":"2023-05-06T00:00:00+00:00","open":29555.801043590734,"high":29867.763769028694,"low":28421.402957684157,"close":28970.22784016688,"volume":15712.83635088,"volumeNotional":455204449.10024995,"tradesDone":404158.0},{"date":"2023-05-07T00:00:00+00:00","open":28965.276678162198,"high":29243.84742076087,"low":28565.865042788984,"close":28696.722203602185,"volume":9987.49573574,"volumeNotional":286608390.6381922,"tradesDone":310619.0},{"date":"2023-05-08T00:00:00+00:00","open":28472.541377523143,"high":28675.263918379515,"low":27282.739121348808,"close":27695.29097613682,"volume":19715.42092036,"volumeNotional":546024319.1063855,"tradesDone":454006.0},{"date":"2023-05-09T00:00:00+00:00","open":27693.557653515818,"high":27837.148489330437,"low":27367.338185714238,"close":27647.14135749171,"volume":11886.394124100001,"volumeNotional":328624818.57985157,"tradesDone":326762.0},{"date":"2023-05-10T00:00:00+00:00","open":27647.929683865335,"high":28335.057311092238,"low":26803.82655311878,"close":27623.148526039015,"volume":23298.802386069998,"volumeNotional":643586278.7892437,"tradesDone":403650.0},{"date":"2023-05-11T00:00:00+00:00","open":27621.319171040424,"high":27651.261883478175,"low":26713.825715273088,"close":26989.29358627093,"volume":17071.37896,"volumeNotional":460744458.67392844,"tradesDone":363044.0},{"date":"2023-05-12T00:00:00+00:00","open":26987.750999734784,"high":27101.05092687869,"low":25816.344886340754,"close":26808.83648070762,"volume":23175.62035248,"volumeNotional":621311416.3685958,"tradesDone":442896.0},{"date":"2023-05-13T00:00:00+00:00","open":26808.573459713167,"high":27065.32502367204,"low":26700.990076284368,"close":26788.95717195767,"volume":5978.35866155,"volumeNotional":160153994.14286512,"tradesDone":222213.0},{"date":"2023-05-14T00:00:00+00:00","open":26787.70541614048,"high":27217.80454267041,"low":26584.98549063506,"close":26929.750351193816,"volume":5325.23155407,"volumeNotional":143407156.31340498,"tradesDone":216690.0},{"date":"2023-05-15T00:00:00+00:00","open":26929.856052445924,"high":27678.363087021284,"low":26739.767346563985,"close":27172.140952780337,"volume":14778.894882440001,"volumeNotional":401574214.8719837,"tradesDone":340076.0},{"date":"2023-05-16T00:00:00+00:00","open":27167.37180420204,"high":27304.486816110348,"low":26861.79601276833,"close":27038.70675406801,"volume":13401.24438209,"volumeNotional":362352316.9869329,"tradesDone":306961.0},{"date":"2023-05-17T00:00:00+00:00","open":27040.01868472971,"high":27516.069168144164,"low":26552.424937236,"close":27409.062924636062,"volume":17194.46485198,"volumeNotional":471284169.0833629,"tradesDone":328612.0},{"date":"2023-05-18T00:00:00+00:00","open":27409.553499459897,"high":27488.153460471985,"low":26365.38242974328,"close":26824.636480646677,"volume":16108.27923974,"volumeNotional":432098734.93477315,"tradesDone":327274.0},{"date":"2023-05-19T00:00:00+00:00","open":26820.999682086232,"high":27188.324159971864,"low":26634.591305349826,"close":26890.761192095222,"volume":9119.23955382,"volumeNotional":245223293.0952826,"tradesDone":266717.0},{"date":"2023-05-20T00:00:00+00:00","open":26890.796718191526,"high":27174.697399748005,"low":26837.657549591877,"close":27113.860537351844,"volume":3976.86769966,"volumeNotional":107828236.18408048,"tradesDone":168960.0},{"date":"2023-05-21T00:00:00+00:00","open":27114.704406744604,"high":27286.46917984799,"low":26670.045070663025,"close":26753.03816675353,"volume":6930.686227840001,"volumeNotional":185416913.1751966,"tradesDone":190327.0},{"date":"2023-05-22T00:00:00+00:00","open":26751.422279237282,"high":27105.811537252463,"low":26535.979585871653,"close":26855.41485048113,"volume":10058.69892581,"volumeNotional":270130532.50871646,"tradesDone":255036.0},{"date":"2023-05-23T00:00:00+00:00","open":26854.944218919427,"high":27502.248011734497,"low":26804.574850073415,"close":27224.00254892539,"volume":13529.55216089,"volumeNotional":368328562.51388836,"tradesDone":306007.0},{"date":"2023-05-24T00:00:00+00:00","open":27223.47150621644,"high":27225.56663765902,"low":26069.99356361116,"close":26323.143527303786,"volume":20340.303927930003,"volumeNotional":535420739.6838824,"tradesDone":361731.0},{"date":"2023-05-25T00:00:00+00:00","open":26323.16013830477,"high":26624.593469542837,"low":25866.18001135021,"close":26479.757462389596,"volume":14245.59330562,"volumeNotional":377219855.64065844,"tradesDone":310426.0},{"date":"2023-05-26T00:00:00+00:00","open":26480.37889292411,"high":26948.061915079623,"low":26336.790891938206,"close":26717.25710800466,"volume":12383.845352429998,"volumeNotional":330862380.26664084,"tradesDone":278847.0},{"date":"2023-05-27T00:00:00+00:00","open":26713.903175083964,"high":26934.43250818705,"low":26560.75062578429,"close":26869.686068549425,"volume":4345.55878206,"volumeNotional":116763800.26638019,"tradesDone":166510.0},{"date":"2023-05-28T00:00:00+00:00","open":26872.62671434272,"high":28274.59197224525,"low":26784.175033765834,"close":28075.96264143509,"volume":13205.203105560002,"volumeNotional":370748789.06426525,"tradesDone":257003.0},{"date":"2023-05-29T00:00:00+00:00","open":28074.02273842439,"high":28471.035133920494,"low":27537.401911366873,"close":27746.122340239403,"volume":13667.199090490001,"volumeNotional":379211778.01314425,"tradesDone":281796.0},{"date":"2023-05-30T00:00:00+00:00","open":27745.4370434407,"high":28056.471343790403,"low":27557.275664111574,"close":27700.88977281828,"volume":14133.71955223,"volumeNotional":391516607.3962498,"tradesDone":312104.0},{"date":"2023-05-31T00:00:00+00:00","open":27701.991855086773,"high":27844.222073245546,"low":26843.812147761822,"close":27222.163647614194,"volume":18281.035789470003,"volumeNotional":497649347.90884435,"tradesDone":355318.0},{"date":"2023-06-01T00:00:00+00:00","open":27221.91634087899,"high":27358.634040967616,"low":26614.083702803593,"close":26827.381582501104,"volume":14371.844910249998,"volumeNotional":385558967.451803,"tradesDone":350869.0},{"date":"2023-06-02T00:00:00+00:00","open":26826.88998267247,"high":27307.312997414876,"low":26507.710424894784,"close":27251.151462640217,"volume":14637.30025375,"volumeNotional":398883286.2190833,"tradesDone":342946.0},{"date":"2023-06-03T00:00:00+00:00","open":27252.733037080354,"high":27341.05910613207,"low":26924.580105079418,"close":27076.886752617964,"volume":4702.83227989,"volumeNotional":127338057.05913767,"tradesDone":186200.0},{"date":"2023-06-04T00:00:00+00:00","open":27077.725008848007,"high":27468.432085113214,"low":26960.673160533373,"close":27122.291618814626,"volume":5188.868145299999,"volumeNotional":140733995.00840434,"tradesDone":194052.0},{"date":"2023-06-05T00:00:00+00:00","open":27122.018337875525,"high":27135.91269814294,"low":25395.269396851225,"close":25737.608234366533,"volume":23068.073136000003,"volumeNotional":593717029.096083,"tradesDone":508512.0},{"date":"2023-06-06T00:00:00+00:00","open":25739.44609922973,"high":27367.30342715931,"low":25352.44191369581,"close":27242.45212263633,"volume":23623.905409249997,"volumeNotional":643573112.0611824,"tradesDone":492875.0}]}]' @@ -21,7 +21,7 @@ interactions: Content-Type: - application/json Date: - - Thu, 27 Jun 2024 10:15:29 GMT + - Thu, 17 Oct 2024 21:23:04 GMT Server: - nginx/1.18.0 (Ubuntu) Vary: diff --git a/openbb_platform/providers/tiingo/tests/record/http/test_tiingo_fetchers/test_tiingo_currency_historical_fetcher_urllib3_v1.yaml b/openbb_platform/providers/tiingo/tests/record/http/test_tiingo_fetchers/test_tiingo_currency_historical_fetcher_urllib3_v1.yaml index c52c5778263..417529e8df7 100644 --- a/openbb_platform/providers/tiingo/tests/record/http/test_tiingo_fetchers/test_tiingo_currency_historical_fetcher_urllib3_v1.yaml +++ b/openbb_platform/providers/tiingo/tests/record/http/test_tiingo_fetchers/test_tiingo_currency_historical_fetcher_urllib3_v1.yaml @@ -9,7 +9,7 @@ interactions: Connection: - keep-alive method: GET - uri: https://api.tiingo.com/tiingo/fx/prices?endDate=2023-06-06&resampleFreq=1Day&startDate=2023-01-01&tickers=EURUSD&token=MOCK_TOKEN + uri: https://api.tiingo.com/tiingo/fx/EURUSD/prices?endDate=2023-06-06&resampleFreq=1day&startDate=2023-01-01&token=MOCK_TOKEN response: body: string: '[{"date":"2023-01-01T00:00:00.000Z","ticker":"eurusd","open":1.070235,"high":1.070235,"low":1.070235,"close":1.070235},{"date":"2023-01-02T00:00:00.000Z","ticker":"eurusd","open":1.070595,"high":1.07094,"low":1.065015,"close":1.067685},{"date":"2023-01-03T00:00:00.000Z","ticker":"eurusd","open":1.06768,"high":1.06804,"low":1.051965,"close":1.05457},{"date":"2023-01-04T00:00:00.000Z","ticker":"eurusd","open":1.054575,"high":1.063555,"low":1.054555,"close":1.06063},{"date":"2023-01-05T00:00:00.000Z","ticker":"eurusd","open":1.060635,"high":1.063155,"low":1.051515,"close":1.052105},{"date":"2023-01-06T00:00:00.000Z","ticker":"eurusd","open":1.05211,"high":1.06483,"low":1.04827,"close":1.06439},{"date":"2023-01-08T00:00:00.000Z","ticker":"eurusd","open":1.064195,"high":1.0663,"low":1.063835,"close":1.066285},{"date":"2023-01-09T00:00:00.000Z","ticker":"eurusd","open":1.06629,"high":1.076065,"low":1.065175,"close":1.073295},{"date":"2023-01-10T00:00:00.000Z","ticker":"eurusd","open":1.07329,"high":1.075935,"low":1.071225,"close":1.07387},{"date":"2023-01-11T00:00:00.000Z","ticker":"eurusd","open":1.073865,"high":1.077655,"low":1.07257,"close":1.076555},{"date":"2023-01-12T00:00:00.000Z","ticker":"eurusd","open":1.07656,"high":1.086705,"low":1.073125,"close":1.085985},{"date":"2023-01-13T00:00:00.000Z","ticker":"eurusd","open":1.086005,"high":1.086805,"low":1.078055,"close":1.08336},{"date":"2023-01-15T00:00:00.000Z","ticker":"eurusd","open":1.083365,"high":1.0834,"low":1.082035,"close":1.082285},{"date":"2023-01-16T00:00:00.000Z","ticker":"eurusd","open":1.08229,"high":1.087435,"low":1.080165,"close":1.082985},{"date":"2023-01-17T00:00:00.000Z","ticker":"eurusd","open":1.08298,"high":1.086955,"low":1.07748,"close":1.078955},{"date":"2023-01-18T00:00:00.000Z","ticker":"eurusd","open":1.07896,"high":1.088755,"low":1.07662,"close":1.079755},{"date":"2023-01-19T00:00:00.000Z","ticker":"eurusd","open":1.079765,"high":1.084015,"low":1.07824,"close":1.083365},{"date":"2023-01-20T00:00:00.000Z","ticker":"eurusd","open":1.08337,"high":1.085905,"low":1.080245,"close":1.085645},{"date":"2023-01-22T00:00:00.000Z","ticker":"eurusd","open":1.0864,"high":1.086985,"low":1.08615,"close":1.086435},{"date":"2023-01-23T00:00:00.000Z","ticker":"eurusd","open":1.08643,"high":1.092705,"low":1.084635,"close":1.08715},{"date":"2023-01-24T00:00:00.000Z","ticker":"eurusd","open":1.08716,"high":1.08982,"low":1.08352,"close":1.089005},{"date":"2023-01-25T00:00:00.000Z","ticker":"eurusd","open":1.089015,"high":1.09238,"low":1.085735,"close":1.09209},{"date":"2023-01-26T00:00:00.000Z","ticker":"eurusd","open":1.092085,"high":1.092945,"low":1.085055,"close":1.08933},{"date":"2023-01-27T00:00:00.000Z","ticker":"eurusd","open":1.089335,"high":1.090045,"low":1.08378,"close":1.086915},{"date":"2023-01-29T00:00:00.000Z","ticker":"eurusd","open":1.08622,"high":1.087295,"low":1.08614,"close":1.087205},{"date":"2023-01-30T00:00:00.000Z","ticker":"eurusd","open":1.087195,"high":1.091395,"low":1.083925,"close":1.085005},{"date":"2023-01-31T00:00:00.000Z","ticker":"eurusd","open":1.08501,"high":1.087505,"low":1.08021,"close":1.086085},{"date":"2023-02-01T00:00:00.000Z","ticker":"eurusd","open":1.086075,"high":1.103335,"low":1.08524,"close":1.101285},{"date":"2023-02-02T00:00:00.000Z","ticker":"eurusd","open":1.10129,"high":1.10269,"low":1.088555,"close":1.09048},{"date":"2023-02-03T00:00:00.000Z","ticker":"eurusd","open":1.090475,"high":1.094015,"low":1.079275,"close":1.07941},{"date":"2023-02-05T00:00:00.000Z","ticker":"eurusd","open":1.079055,"high":1.07985,"low":1.078555,"close":1.078955},{"date":"2023-02-06T00:00:00.000Z","ticker":"eurusd","open":1.07894,"high":1.079895,"low":1.07094,"close":1.072915},{"date":"2023-02-07T00:00:00.000Z","ticker":"eurusd","open":1.07291,"high":1.076665,"low":1.066925,"close":1.073045},{"date":"2023-02-08T00:00:00.000Z","ticker":"eurusd","open":1.07305,"high":1.076085,"low":1.070955,"close":1.071555},{"date":"2023-02-09T00:00:00.000Z","ticker":"eurusd","open":1.071545,"high":1.07909,"low":1.070965,"close":1.073925},{"date":"2023-02-10T00:00:00.000Z","ticker":"eurusd","open":1.07393,"high":1.075285,"low":1.06664,"close":1.067705},{"date":"2023-02-12T00:00:00.000Z","ticker":"eurusd","open":1.06812,"high":1.06826,"low":1.06713,"close":1.067735},{"date":"2023-02-13T00:00:00.000Z","ticker":"eurusd","open":1.06774,"high":1.073245,"low":1.065565,"close":1.073115},{"date":"2023-02-14T00:00:00.000Z","ticker":"eurusd","open":1.073105,"high":1.08031,"low":1.070685,"close":1.073545},{"date":"2023-02-15T00:00:00.000Z","ticker":"eurusd","open":1.07354,"high":1.074465,"low":1.066065,"close":1.069155},{"date":"2023-02-16T00:00:00.000Z","ticker":"eurusd","open":1.069175,"high":1.072245,"low":1.065465,"close":1.066555},{"date":"2023-02-17T00:00:00.000Z","ticker":"eurusd","open":1.06656,"high":1.069845,"low":1.061285,"close":1.069415},{"date":"2023-02-19T00:00:00.000Z","ticker":"eurusd","open":1.068945,"high":1.06934,"low":1.068265,"close":1.068425},{"date":"2023-02-20T00:00:00.000Z","ticker":"eurusd","open":1.06843,"high":1.070475,"low":1.067045,"close":1.068245},{"date":"2023-02-21T00:00:00.000Z","ticker":"eurusd","open":1.06824,"high":1.069825,"low":1.06375,"close":1.065145},{"date":"2023-02-22T00:00:00.000Z","ticker":"eurusd","open":1.06514,"high":1.066415,"low":1.059925,"close":1.060555},{"date":"2023-02-23T00:00:00.000Z","ticker":"eurusd","open":1.060565,"high":1.062795,"low":1.05772,"close":1.05978},{"date":"2023-02-24T00:00:00.000Z","ticker":"eurusd","open":1.059775,"high":1.061445,"low":1.05362,"close":1.054585},{"date":"2023-02-26T00:00:00.000Z","ticker":"eurusd","open":1.05471,"high":1.055545,"low":1.05469,"close":1.055355},{"date":"2023-02-27T00:00:00.000Z","ticker":"eurusd","open":1.05535,"high":1.061995,"low":1.053315,"close":1.060975},{"date":"2023-02-28T00:00:00.000Z","ticker":"eurusd","open":1.060965,"high":1.06453,"low":1.057425,"close":1.057695},{"date":"2023-03-01T00:00:00.000Z","ticker":"eurusd","open":1.057705,"high":1.069165,"low":1.056545,"close":1.06688},{"date":"2023-03-02T00:00:00.000Z","ticker":"eurusd","open":1.066875,"high":1.067295,"low":1.057655,"close":1.059855},{"date":"2023-03-03T00:00:00.000Z","ticker":"eurusd","open":1.05985,"high":1.06387,"low":1.058855,"close":1.063405},{"date":"2023-03-05T00:00:00.000Z","ticker":"eurusd","open":1.06283,"high":1.06294,"low":1.062365,"close":1.062585},{"date":"2023-03-06T00:00:00.000Z","ticker":"eurusd","open":1.06259,"high":1.069445,"low":1.062235,"close":1.068565},{"date":"2023-03-07T00:00:00.000Z","ticker":"eurusd","open":1.06856,"high":1.069455,"low":1.054615,"close":1.05485},{"date":"2023-03-08T00:00:00.000Z","ticker":"eurusd","open":1.054855,"high":1.0574,"low":1.052455,"close":1.054915},{"date":"2023-03-09T00:00:00.000Z","ticker":"eurusd","open":1.05492,"high":1.059125,"low":1.053815,"close":1.058565},{"date":"2023-03-10T00:00:00.000Z","ticker":"eurusd","open":1.05857,"high":1.070065,"low":1.0574,"close":1.06399},{"date":"2023-03-12T00:00:00.000Z","ticker":"eurusd","open":1.068065,"high":1.07037,"low":1.06779,"close":1.06812},{"date":"2023-03-13T00:00:00.000Z","ticker":"eurusd","open":1.068125,"high":1.074865,"low":1.065045,"close":1.072305},{"date":"2023-03-14T00:00:00.000Z","ticker":"eurusd","open":1.07231,"high":1.074965,"low":1.067895,"close":1.072705},{"date":"2023-03-15T00:00:00.000Z","ticker":"eurusd","open":1.07271,"high":1.075995,"low":1.051625,"close":1.058185},{"date":"2023-03-16T00:00:00.000Z","ticker":"eurusd","open":1.05819,"high":1.063565,"low":1.055145,"close":1.06137},{"date":"2023-03-17T00:00:00.000Z","ticker":"eurusd","open":1.061375,"high":1.06853,"low":1.061175,"close":1.066485},{"date":"2023-03-19T00:00:00.000Z","ticker":"eurusd","open":1.068485,"high":1.06886,"low":1.06665,"close":1.068085},{"date":"2023-03-20T00:00:00.000Z","ticker":"eurusd","open":1.068095,"high":1.07309,"low":1.063135,"close":1.071875},{"date":"2023-03-21T00:00:00.000Z","ticker":"eurusd","open":1.07189,"high":1.078845,"low":1.070415,"close":1.07728},{"date":"2023-03-22T00:00:00.000Z","ticker":"eurusd","open":1.077275,"high":1.091255,"low":1.075915,"close":1.08691},{"date":"2023-03-23T00:00:00.000Z","ticker":"eurusd","open":1.086935,"high":1.092975,"low":1.082445,"close":1.08347},{"date":"2023-03-24T00:00:00.000Z","ticker":"eurusd","open":1.083475,"high":1.083725,"low":1.07137,"close":1.07587},{"date":"2023-03-26T00:00:00.000Z","ticker":"eurusd","open":1.077265,"high":1.07799,"low":1.07658,"close":1.077775},{"date":"2023-03-27T00:00:00.000Z","ticker":"eurusd","open":1.07776,"high":1.08079,"low":1.07451,"close":1.080645},{"date":"2023-03-28T00:00:00.000Z","ticker":"eurusd","open":1.080635,"high":1.084865,"low":1.08037,"close":1.08391},{"date":"2023-03-29T00:00:00.000Z","ticker":"eurusd","open":1.083925,"high":1.087125,"low":1.081835,"close":1.08428},{"date":"2023-03-30T00:00:00.000Z","ticker":"eurusd","open":1.084285,"high":1.09263,"low":1.08237,"close":1.090425},{"date":"2023-03-31T00:00:00.000Z","ticker":"eurusd","open":1.090415,"high":1.092585,"low":1.083705,"close":1.084245},{"date":"2023-04-02T00:00:00.000Z","ticker":"eurusd","open":1.084275,"high":1.08453,"low":1.080145,"close":1.080265},{"date":"2023-04-03T00:00:00.000Z","ticker":"eurusd","open":1.080295,"high":1.091665,"low":1.07883,"close":1.090695},{"date":"2023-04-04T00:00:00.000Z","ticker":"eurusd","open":1.090705,"high":1.097335,"low":1.08831,"close":1.095775},{"date":"2023-04-05T00:00:00.000Z","ticker":"eurusd","open":1.09579,"high":1.096965,"low":1.08911,"close":1.090315},{"date":"2023-04-06T00:00:00.000Z","ticker":"eurusd","open":1.09033,"high":1.09377,"low":1.08848,"close":1.091985},{"date":"2023-04-07T00:00:00.000Z","ticker":"eurusd","open":1.091995,"high":1.09241,"low":1.08764,"close":1.09031},{"date":"2023-04-09T00:00:00.000Z","ticker":"eurusd","open":1.090365,"high":1.091365,"low":1.090145,"close":1.09132},{"date":"2023-04-10T00:00:00.000Z","ticker":"eurusd","open":1.09134,"high":1.091725,"low":1.083145,"close":1.0869},{"date":"2023-04-11T00:00:00.000Z","ticker":"eurusd","open":1.086895,"high":1.0928,"low":1.086725,"close":1.09164},{"date":"2023-04-12T00:00:00.000Z","ticker":"eurusd","open":1.09165,"high":1.100035,"low":1.091485,"close":1.0997},{"date":"2023-04-13T00:00:00.000Z","ticker":"eurusd","open":1.099705,"high":1.106775,"low":1.097705,"close":1.10518},{"date":"2023-04-14T00:00:00.000Z","ticker":"eurusd","open":1.105195,"high":1.10758,"low":1.09725,"close":1.099455},{"date":"2023-04-16T00:00:00.000Z","ticker":"eurusd","open":1.09929,"high":1.09962,"low":1.098345,"close":1.098465},{"date":"2023-04-17T00:00:00.000Z","ticker":"eurusd","open":1.098455,"high":1.099975,"low":1.090925,"close":1.092465},{"date":"2023-04-18T00:00:00.000Z","ticker":"eurusd","open":1.092475,"high":1.0983,"low":1.092245,"close":1.097505},{"date":"2023-04-19T00:00:00.000Z","ticker":"eurusd","open":1.09751,"high":1.098415,"low":1.091745,"close":1.09519},{"date":"2023-04-20T00:00:00.000Z","ticker":"eurusd","open":1.095195,"high":1.098965,"low":1.093355,"close":1.09678},{"date":"2023-04-21T00:00:00.000Z","ticker":"eurusd","open":1.096755,"high":1.09938,"low":1.093815,"close":1.09895},{"date":"2023-04-24T00:00:00.000Z","ticker":"eurusd","open":1.102605,"high":1.105725,"low":1.102055,"close":1.105725},{"date":"2023-04-25T00:00:00.000Z","ticker":"eurusd","open":1.10572,"high":1.106715,"low":1.096435,"close":1.097815},{"date":"2023-04-26T00:00:00.000Z","ticker":"eurusd","open":1.09781,"high":1.109545,"low":1.096855,"close":1.104535},{"date":"2023-04-27T00:00:00.000Z","ticker":"eurusd","open":1.104525,"high":1.106355,"low":1.09922,"close":1.103175},{"date":"2023-04-28T00:00:00.000Z","ticker":"eurusd","open":1.103185,"high":1.104505,"low":1.096265,"close":1.10168},{"date":"2023-04-30T00:00:00.000Z","ticker":"eurusd","open":1.10229,"high":1.10231,"low":1.101015,"close":1.101075},{"date":"2023-05-01T00:00:00.000Z","ticker":"eurusd","open":1.101095,"high":1.10356,"low":1.09645,"close":1.096875},{"date":"2023-05-02T00:00:00.000Z","ticker":"eurusd","open":1.096885,"high":1.101395,"low":1.094225,"close":1.10109},{"date":"2023-05-03T00:00:00.000Z","ticker":"eurusd","open":1.101085,"high":1.10914,"low":1.1005,"close":1.106865},{"date":"2023-05-04T00:00:00.000Z","ticker":"eurusd","open":1.106875,"high":1.10916,"low":1.098625,"close":1.102305},{"date":"2023-05-05T00:00:00.000Z","ticker":"eurusd","open":1.102315,"high":1.104795,"low":1.096685,"close":1.10188},{"date":"2023-05-07T00:00:00.000Z","ticker":"eurusd","open":1.102015,"high":1.102385,"low":1.101445,"close":1.101835},{"date":"2023-05-08T00:00:00.000Z","ticker":"eurusd","open":1.10185,"high":1.105375,"low":1.099545,"close":1.099665},{"date":"2023-05-09T00:00:00.000Z","ticker":"eurusd","open":1.099645,"high":1.100085,"low":1.094125,"close":1.096475},{"date":"2023-05-10T00:00:00.000Z","ticker":"eurusd","open":1.09648,"high":1.100695,"low":1.094165,"close":1.098285},{"date":"2023-05-11T00:00:00.000Z","ticker":"eurusd","open":1.09828,"high":1.09982,"low":1.090025,"close":1.091255},{"date":"2023-05-12T00:00:00.000Z","ticker":"eurusd","open":1.091245,"high":1.09356,"low":1.084805,"close":1.084995},{"date":"2023-05-14T00:00:00.000Z","ticker":"eurusd","open":1.085515,"high":1.08559,"low":1.08424,"close":1.085295},{"date":"2023-05-15T00:00:00.000Z","ticker":"eurusd","open":1.085305,"high":1.08909,"low":1.08483,"close":1.087375},{"date":"2023-05-16T00:00:00.000Z","ticker":"eurusd","open":1.08738,"high":1.090465,"low":1.085515,"close":1.086555},{"date":"2023-05-17T00:00:00.000Z","ticker":"eurusd","open":1.08655,"high":1.087365,"low":1.081045,"close":1.083805},{"date":"2023-05-18T00:00:00.000Z","ticker":"eurusd","open":1.083795,"high":1.08481,"low":1.076265,"close":1.077515},{"date":"2023-05-19T00:00:00.000Z","ticker":"eurusd","open":1.077525,"high":1.082885,"low":1.076015,"close":1.08059},{"date":"2023-05-21T00:00:00.000Z","ticker":"eurusd","open":1.080745,"high":1.08243,"low":1.080695,"close":1.08221},{"date":"2023-05-22T00:00:00.000Z","ticker":"eurusd","open":1.082215,"high":1.083135,"low":1.07957,"close":1.081065},{"date":"2023-05-23T00:00:00.000Z","ticker":"eurusd","open":1.081085,"high":1.082065,"low":1.076045,"close":1.07694},{"date":"2023-05-24T00:00:00.000Z","ticker":"eurusd","open":1.076925,"high":1.080125,"low":1.074235,"close":1.075575},{"date":"2023-05-25T00:00:00.000Z","ticker":"eurusd","open":1.07558,"high":1.07558,"low":1.070745,"close":1.072365},{"date":"2023-05-26T00:00:00.000Z","ticker":"eurusd","open":1.072355,"high":1.075875,"low":1.070185,"close":1.072565},{"date":"2023-05-28T00:00:00.000Z","ticker":"eurusd","open":1.07239,"high":1.07294,"low":1.071845,"close":1.072175},{"date":"2023-05-29T00:00:00.000Z","ticker":"eurusd","open":1.072145,"high":1.074355,"low":1.070575,"close":1.070695},{"date":"2023-05-30T00:00:00.000Z","ticker":"eurusd","open":1.070665,"high":1.074665,"low":1.067265,"close":1.073185},{"date":"2023-05-31T00:00:00.000Z","ticker":"eurusd","open":1.073175,"high":1.073575,"low":1.063525,"close":1.069355},{"date":"2023-06-01T00:00:00.000Z","ticker":"eurusd","open":1.069365,"high":1.076855,"low":1.066195,"close":1.076065},{"date":"2023-06-02T00:00:00.000Z","ticker":"eurusd","open":1.07607,"high":1.077905,"low":1.070535,"close":1.07075},{"date":"2023-06-04T00:00:00.000Z","ticker":"eurusd","open":1.07093,"high":1.07103,"low":1.069395,"close":1.069705},{"date":"2023-06-05T00:00:00.000Z","ticker":"eurusd","open":1.069695,"high":1.07226,"low":1.067465,"close":1.071145},{"date":"2023-06-06T00:00:00.000Z","ticker":"eurusd","open":1.07115,"high":1.073295,"low":1.066715,"close":1.069875}]' @@ -21,7 +21,7 @@ interactions: Content-Type: - application/json Date: - - Thu, 29 Feb 2024 04:26:42 GMT + - Thu, 17 Oct 2024 21:28:31 GMT Server: - nginx/1.18.0 (Ubuntu) Vary: diff --git a/openbb_platform/providers/tiingo/tests/record/http/test_tiingo_fetchers/test_tiingo_currency_historical_fetcher_urllib3_v2.yaml b/openbb_platform/providers/tiingo/tests/record/http/test_tiingo_fetchers/test_tiingo_currency_historical_fetcher_urllib3_v2.yaml index 769df016c3b..4b837ef80ed 100644 --- a/openbb_platform/providers/tiingo/tests/record/http/test_tiingo_fetchers/test_tiingo_currency_historical_fetcher_urllib3_v2.yaml +++ b/openbb_platform/providers/tiingo/tests/record/http/test_tiingo_fetchers/test_tiingo_currency_historical_fetcher_urllib3_v2.yaml @@ -9,7 +9,7 @@ interactions: Connection: - keep-alive method: GET - uri: https://api.tiingo.com/tiingo/fx/prices?endDate=2023-06-06&resampleFreq=1Day&startDate=2023-01-01&tickers=EURUSD&token=MOCK_TOKEN + uri: https://api.tiingo.com/tiingo/fx/EURUSD/prices?endDate=2023-06-06&resampleFreq=1day&startDate=2023-01-01&token=MOCK_TOKEN response: body: string: '[{"date":"2023-01-01T00:00:00.000Z","ticker":"eurusd","open":1.070235,"high":1.070235,"low":1.070235,"close":1.070235},{"date":"2023-01-02T00:00:00.000Z","ticker":"eurusd","open":1.070595,"high":1.07094,"low":1.065015,"close":1.067685},{"date":"2023-01-03T00:00:00.000Z","ticker":"eurusd","open":1.06768,"high":1.06804,"low":1.051965,"close":1.05457},{"date":"2023-01-04T00:00:00.000Z","ticker":"eurusd","open":1.054575,"high":1.063555,"low":1.054555,"close":1.06063},{"date":"2023-01-05T00:00:00.000Z","ticker":"eurusd","open":1.060635,"high":1.063155,"low":1.051515,"close":1.052105},{"date":"2023-01-06T00:00:00.000Z","ticker":"eurusd","open":1.05211,"high":1.06483,"low":1.04827,"close":1.06439},{"date":"2023-01-08T00:00:00.000Z","ticker":"eurusd","open":1.064195,"high":1.0663,"low":1.063835,"close":1.066285},{"date":"2023-01-09T00:00:00.000Z","ticker":"eurusd","open":1.06629,"high":1.076065,"low":1.065175,"close":1.073295},{"date":"2023-01-10T00:00:00.000Z","ticker":"eurusd","open":1.07329,"high":1.075935,"low":1.071225,"close":1.07387},{"date":"2023-01-11T00:00:00.000Z","ticker":"eurusd","open":1.073865,"high":1.077655,"low":1.07257,"close":1.076555},{"date":"2023-01-12T00:00:00.000Z","ticker":"eurusd","open":1.07656,"high":1.086705,"low":1.073125,"close":1.085985},{"date":"2023-01-13T00:00:00.000Z","ticker":"eurusd","open":1.086005,"high":1.086805,"low":1.078055,"close":1.08336},{"date":"2023-01-15T00:00:00.000Z","ticker":"eurusd","open":1.083365,"high":1.0834,"low":1.082035,"close":1.082285},{"date":"2023-01-16T00:00:00.000Z","ticker":"eurusd","open":1.08229,"high":1.087435,"low":1.080165,"close":1.082985},{"date":"2023-01-17T00:00:00.000Z","ticker":"eurusd","open":1.08298,"high":1.086955,"low":1.07748,"close":1.078955},{"date":"2023-01-18T00:00:00.000Z","ticker":"eurusd","open":1.07896,"high":1.088755,"low":1.07662,"close":1.079755},{"date":"2023-01-19T00:00:00.000Z","ticker":"eurusd","open":1.079765,"high":1.084015,"low":1.07824,"close":1.083365},{"date":"2023-01-20T00:00:00.000Z","ticker":"eurusd","open":1.08337,"high":1.085905,"low":1.080245,"close":1.085645},{"date":"2023-01-22T00:00:00.000Z","ticker":"eurusd","open":1.0864,"high":1.086985,"low":1.08615,"close":1.086435},{"date":"2023-01-23T00:00:00.000Z","ticker":"eurusd","open":1.08643,"high":1.092705,"low":1.084635,"close":1.08715},{"date":"2023-01-24T00:00:00.000Z","ticker":"eurusd","open":1.08716,"high":1.08982,"low":1.08352,"close":1.089005},{"date":"2023-01-25T00:00:00.000Z","ticker":"eurusd","open":1.089015,"high":1.09238,"low":1.085735,"close":1.09209},{"date":"2023-01-26T00:00:00.000Z","ticker":"eurusd","open":1.092085,"high":1.092945,"low":1.085055,"close":1.08933},{"date":"2023-01-27T00:00:00.000Z","ticker":"eurusd","open":1.089335,"high":1.090045,"low":1.08378,"close":1.086915},{"date":"2023-01-29T00:00:00.000Z","ticker":"eurusd","open":1.08622,"high":1.087295,"low":1.08614,"close":1.087205},{"date":"2023-01-30T00:00:00.000Z","ticker":"eurusd","open":1.087195,"high":1.091395,"low":1.083925,"close":1.085005},{"date":"2023-01-31T00:00:00.000Z","ticker":"eurusd","open":1.08501,"high":1.087505,"low":1.08021,"close":1.086085},{"date":"2023-02-01T00:00:00.000Z","ticker":"eurusd","open":1.086075,"high":1.103335,"low":1.08524,"close":1.101285},{"date":"2023-02-02T00:00:00.000Z","ticker":"eurusd","open":1.10129,"high":1.10269,"low":1.088555,"close":1.09048},{"date":"2023-02-03T00:00:00.000Z","ticker":"eurusd","open":1.090475,"high":1.094015,"low":1.079275,"close":1.07941},{"date":"2023-02-05T00:00:00.000Z","ticker":"eurusd","open":1.079055,"high":1.07985,"low":1.078555,"close":1.078955},{"date":"2023-02-06T00:00:00.000Z","ticker":"eurusd","open":1.07894,"high":1.079895,"low":1.07094,"close":1.072915},{"date":"2023-02-07T00:00:00.000Z","ticker":"eurusd","open":1.07291,"high":1.076665,"low":1.066925,"close":1.073045},{"date":"2023-02-08T00:00:00.000Z","ticker":"eurusd","open":1.07305,"high":1.076085,"low":1.070955,"close":1.071555},{"date":"2023-02-09T00:00:00.000Z","ticker":"eurusd","open":1.071545,"high":1.07909,"low":1.070965,"close":1.073925},{"date":"2023-02-10T00:00:00.000Z","ticker":"eurusd","open":1.07393,"high":1.075285,"low":1.06664,"close":1.067705},{"date":"2023-02-12T00:00:00.000Z","ticker":"eurusd","open":1.06812,"high":1.06826,"low":1.06713,"close":1.067735},{"date":"2023-02-13T00:00:00.000Z","ticker":"eurusd","open":1.06774,"high":1.073245,"low":1.065565,"close":1.073115},{"date":"2023-02-14T00:00:00.000Z","ticker":"eurusd","open":1.073105,"high":1.08031,"low":1.070685,"close":1.073545},{"date":"2023-02-15T00:00:00.000Z","ticker":"eurusd","open":1.07354,"high":1.074465,"low":1.066065,"close":1.069155},{"date":"2023-02-16T00:00:00.000Z","ticker":"eurusd","open":1.069175,"high":1.072245,"low":1.065465,"close":1.066555},{"date":"2023-02-17T00:00:00.000Z","ticker":"eurusd","open":1.06656,"high":1.069845,"low":1.061285,"close":1.069415},{"date":"2023-02-19T00:00:00.000Z","ticker":"eurusd","open":1.068945,"high":1.06934,"low":1.068265,"close":1.068425},{"date":"2023-02-20T00:00:00.000Z","ticker":"eurusd","open":1.06843,"high":1.070475,"low":1.067045,"close":1.068245},{"date":"2023-02-21T00:00:00.000Z","ticker":"eurusd","open":1.06824,"high":1.069825,"low":1.06375,"close":1.065145},{"date":"2023-02-22T00:00:00.000Z","ticker":"eurusd","open":1.06514,"high":1.066415,"low":1.059925,"close":1.060555},{"date":"2023-02-23T00:00:00.000Z","ticker":"eurusd","open":1.060565,"high":1.062795,"low":1.05772,"close":1.05978},{"date":"2023-02-24T00:00:00.000Z","ticker":"eurusd","open":1.059775,"high":1.061445,"low":1.05362,"close":1.054585},{"date":"2023-02-26T00:00:00.000Z","ticker":"eurusd","open":1.05471,"high":1.055545,"low":1.05469,"close":1.055355},{"date":"2023-02-27T00:00:00.000Z","ticker":"eurusd","open":1.05535,"high":1.061995,"low":1.053315,"close":1.060975},{"date":"2023-02-28T00:00:00.000Z","ticker":"eurusd","open":1.060965,"high":1.06453,"low":1.057425,"close":1.057695},{"date":"2023-03-01T00:00:00.000Z","ticker":"eurusd","open":1.057705,"high":1.069165,"low":1.056545,"close":1.06688},{"date":"2023-03-02T00:00:00.000Z","ticker":"eurusd","open":1.066875,"high":1.067295,"low":1.057655,"close":1.059855},{"date":"2023-03-03T00:00:00.000Z","ticker":"eurusd","open":1.05985,"high":1.06387,"low":1.058855,"close":1.063405},{"date":"2023-03-05T00:00:00.000Z","ticker":"eurusd","open":1.06283,"high":1.06294,"low":1.062365,"close":1.062585},{"date":"2023-03-06T00:00:00.000Z","ticker":"eurusd","open":1.06259,"high":1.069445,"low":1.062235,"close":1.068565},{"date":"2023-03-07T00:00:00.000Z","ticker":"eurusd","open":1.06856,"high":1.069455,"low":1.054615,"close":1.05485},{"date":"2023-03-08T00:00:00.000Z","ticker":"eurusd","open":1.054855,"high":1.0574,"low":1.052455,"close":1.054915},{"date":"2023-03-09T00:00:00.000Z","ticker":"eurusd","open":1.05492,"high":1.059125,"low":1.053815,"close":1.058565},{"date":"2023-03-10T00:00:00.000Z","ticker":"eurusd","open":1.05857,"high":1.070065,"low":1.0574,"close":1.06399},{"date":"2023-03-12T00:00:00.000Z","ticker":"eurusd","open":1.068065,"high":1.07037,"low":1.06779,"close":1.06812},{"date":"2023-03-13T00:00:00.000Z","ticker":"eurusd","open":1.068125,"high":1.074865,"low":1.065045,"close":1.072305},{"date":"2023-03-14T00:00:00.000Z","ticker":"eurusd","open":1.07231,"high":1.074965,"low":1.067895,"close":1.072705},{"date":"2023-03-15T00:00:00.000Z","ticker":"eurusd","open":1.07271,"high":1.075995,"low":1.051625,"close":1.058185},{"date":"2023-03-16T00:00:00.000Z","ticker":"eurusd","open":1.05819,"high":1.063565,"low":1.055145,"close":1.06137},{"date":"2023-03-17T00:00:00.000Z","ticker":"eurusd","open":1.061375,"high":1.06853,"low":1.061175,"close":1.066485},{"date":"2023-03-19T00:00:00.000Z","ticker":"eurusd","open":1.068485,"high":1.06886,"low":1.06665,"close":1.068085},{"date":"2023-03-20T00:00:00.000Z","ticker":"eurusd","open":1.068095,"high":1.07309,"low":1.063135,"close":1.071875},{"date":"2023-03-21T00:00:00.000Z","ticker":"eurusd","open":1.07189,"high":1.078845,"low":1.070415,"close":1.07728},{"date":"2023-03-22T00:00:00.000Z","ticker":"eurusd","open":1.077275,"high":1.091255,"low":1.075915,"close":1.08691},{"date":"2023-03-23T00:00:00.000Z","ticker":"eurusd","open":1.086935,"high":1.092975,"low":1.082445,"close":1.08347},{"date":"2023-03-24T00:00:00.000Z","ticker":"eurusd","open":1.083475,"high":1.083725,"low":1.07137,"close":1.07587},{"date":"2023-03-26T00:00:00.000Z","ticker":"eurusd","open":1.077265,"high":1.07799,"low":1.07658,"close":1.077775},{"date":"2023-03-27T00:00:00.000Z","ticker":"eurusd","open":1.07776,"high":1.08079,"low":1.07451,"close":1.080645},{"date":"2023-03-28T00:00:00.000Z","ticker":"eurusd","open":1.080635,"high":1.084865,"low":1.08037,"close":1.08391},{"date":"2023-03-29T00:00:00.000Z","ticker":"eurusd","open":1.083925,"high":1.087125,"low":1.081835,"close":1.08428},{"date":"2023-03-30T00:00:00.000Z","ticker":"eurusd","open":1.084285,"high":1.09263,"low":1.08237,"close":1.090425},{"date":"2023-03-31T00:00:00.000Z","ticker":"eurusd","open":1.090415,"high":1.092585,"low":1.083705,"close":1.084245},{"date":"2023-04-02T00:00:00.000Z","ticker":"eurusd","open":1.084275,"high":1.08453,"low":1.080145,"close":1.080265},{"date":"2023-04-03T00:00:00.000Z","ticker":"eurusd","open":1.080295,"high":1.091665,"low":1.07883,"close":1.090695},{"date":"2023-04-04T00:00:00.000Z","ticker":"eurusd","open":1.090705,"high":1.097335,"low":1.08831,"close":1.095775},{"date":"2023-04-05T00:00:00.000Z","ticker":"eurusd","open":1.09579,"high":1.096965,"low":1.08911,"close":1.090315},{"date":"2023-04-06T00:00:00.000Z","ticker":"eurusd","open":1.09033,"high":1.09377,"low":1.08848,"close":1.091985},{"date":"2023-04-07T00:00:00.000Z","ticker":"eurusd","open":1.091995,"high":1.09241,"low":1.08764,"close":1.09031},{"date":"2023-04-09T00:00:00.000Z","ticker":"eurusd","open":1.090365,"high":1.091365,"low":1.090145,"close":1.09132},{"date":"2023-04-10T00:00:00.000Z","ticker":"eurusd","open":1.09134,"high":1.091725,"low":1.083145,"close":1.0869},{"date":"2023-04-11T00:00:00.000Z","ticker":"eurusd","open":1.086895,"high":1.0928,"low":1.086725,"close":1.09164},{"date":"2023-04-12T00:00:00.000Z","ticker":"eurusd","open":1.09165,"high":1.100035,"low":1.091485,"close":1.0997},{"date":"2023-04-13T00:00:00.000Z","ticker":"eurusd","open":1.099705,"high":1.106775,"low":1.097705,"close":1.10518},{"date":"2023-04-14T00:00:00.000Z","ticker":"eurusd","open":1.105195,"high":1.10758,"low":1.09725,"close":1.099455},{"date":"2023-04-16T00:00:00.000Z","ticker":"eurusd","open":1.09929,"high":1.09962,"low":1.098345,"close":1.098465},{"date":"2023-04-17T00:00:00.000Z","ticker":"eurusd","open":1.098455,"high":1.099975,"low":1.090925,"close":1.092465},{"date":"2023-04-18T00:00:00.000Z","ticker":"eurusd","open":1.092475,"high":1.0983,"low":1.092245,"close":1.097505},{"date":"2023-04-19T00:00:00.000Z","ticker":"eurusd","open":1.09751,"high":1.098415,"low":1.091745,"close":1.09519},{"date":"2023-04-20T00:00:00.000Z","ticker":"eurusd","open":1.095195,"high":1.098965,"low":1.093355,"close":1.09678},{"date":"2023-04-21T00:00:00.000Z","ticker":"eurusd","open":1.096755,"high":1.09938,"low":1.093815,"close":1.09895},{"date":"2023-04-24T00:00:00.000Z","ticker":"eurusd","open":1.102605,"high":1.105725,"low":1.102055,"close":1.105725},{"date":"2023-04-25T00:00:00.000Z","ticker":"eurusd","open":1.10572,"high":1.106715,"low":1.096435,"close":1.097815},{"date":"2023-04-26T00:00:00.000Z","ticker":"eurusd","open":1.09781,"high":1.109545,"low":1.096855,"close":1.104535},{"date":"2023-04-27T00:00:00.000Z","ticker":"eurusd","open":1.104525,"high":1.106355,"low":1.09922,"close":1.103175},{"date":"2023-04-28T00:00:00.000Z","ticker":"eurusd","open":1.103185,"high":1.104505,"low":1.096265,"close":1.10168},{"date":"2023-04-30T00:00:00.000Z","ticker":"eurusd","open":1.10229,"high":1.10231,"low":1.101015,"close":1.101075},{"date":"2023-05-01T00:00:00.000Z","ticker":"eurusd","open":1.101095,"high":1.10356,"low":1.09645,"close":1.096875},{"date":"2023-05-02T00:00:00.000Z","ticker":"eurusd","open":1.096885,"high":1.101395,"low":1.094225,"close":1.10109},{"date":"2023-05-03T00:00:00.000Z","ticker":"eurusd","open":1.101085,"high":1.10914,"low":1.1005,"close":1.106865},{"date":"2023-05-04T00:00:00.000Z","ticker":"eurusd","open":1.106875,"high":1.10916,"low":1.098625,"close":1.102305},{"date":"2023-05-05T00:00:00.000Z","ticker":"eurusd","open":1.102315,"high":1.104795,"low":1.096685,"close":1.10188},{"date":"2023-05-07T00:00:00.000Z","ticker":"eurusd","open":1.102015,"high":1.102385,"low":1.101445,"close":1.101835},{"date":"2023-05-08T00:00:00.000Z","ticker":"eurusd","open":1.10185,"high":1.105375,"low":1.099545,"close":1.099665},{"date":"2023-05-09T00:00:00.000Z","ticker":"eurusd","open":1.099645,"high":1.100085,"low":1.094125,"close":1.096475},{"date":"2023-05-10T00:00:00.000Z","ticker":"eurusd","open":1.09648,"high":1.100695,"low":1.094165,"close":1.098285},{"date":"2023-05-11T00:00:00.000Z","ticker":"eurusd","open":1.09828,"high":1.09982,"low":1.090025,"close":1.091255},{"date":"2023-05-12T00:00:00.000Z","ticker":"eurusd","open":1.091245,"high":1.09356,"low":1.084805,"close":1.084995},{"date":"2023-05-14T00:00:00.000Z","ticker":"eurusd","open":1.085515,"high":1.08559,"low":1.08424,"close":1.085295},{"date":"2023-05-15T00:00:00.000Z","ticker":"eurusd","open":1.085305,"high":1.08909,"low":1.08483,"close":1.087375},{"date":"2023-05-16T00:00:00.000Z","ticker":"eurusd","open":1.08738,"high":1.090465,"low":1.085515,"close":1.086555},{"date":"2023-05-17T00:00:00.000Z","ticker":"eurusd","open":1.08655,"high":1.087365,"low":1.081045,"close":1.083805},{"date":"2023-05-18T00:00:00.000Z","ticker":"eurusd","open":1.083795,"high":1.08481,"low":1.076265,"close":1.077515},{"date":"2023-05-19T00:00:00.000Z","ticker":"eurusd","open":1.077525,"high":1.082885,"low":1.076015,"close":1.08059},{"date":"2023-05-21T00:00:00.000Z","ticker":"eurusd","open":1.080745,"high":1.08243,"low":1.080695,"close":1.08221},{"date":"2023-05-22T00:00:00.000Z","ticker":"eurusd","open":1.082215,"high":1.083135,"low":1.07957,"close":1.081065},{"date":"2023-05-23T00:00:00.000Z","ticker":"eurusd","open":1.081085,"high":1.082065,"low":1.076045,"close":1.07694},{"date":"2023-05-24T00:00:00.000Z","ticker":"eurusd","open":1.076925,"high":1.080125,"low":1.074235,"close":1.075575},{"date":"2023-05-25T00:00:00.000Z","ticker":"eurusd","open":1.07558,"high":1.07558,"low":1.070745,"close":1.072365},{"date":"2023-05-26T00:00:00.000Z","ticker":"eurusd","open":1.072355,"high":1.075875,"low":1.070185,"close":1.072565},{"date":"2023-05-28T00:00:00.000Z","ticker":"eurusd","open":1.07239,"high":1.07294,"low":1.071845,"close":1.072175},{"date":"2023-05-29T00:00:00.000Z","ticker":"eurusd","open":1.072145,"high":1.074355,"low":1.070575,"close":1.070695},{"date":"2023-05-30T00:00:00.000Z","ticker":"eurusd","open":1.070665,"high":1.074665,"low":1.067265,"close":1.073185},{"date":"2023-05-31T00:00:00.000Z","ticker":"eurusd","open":1.073175,"high":1.073575,"low":1.063525,"close":1.069355},{"date":"2023-06-01T00:00:00.000Z","ticker":"eurusd","open":1.069365,"high":1.076855,"low":1.066195,"close":1.076065},{"date":"2023-06-02T00:00:00.000Z","ticker":"eurusd","open":1.07607,"high":1.077905,"low":1.070535,"close":1.07075},{"date":"2023-06-04T00:00:00.000Z","ticker":"eurusd","open":1.07093,"high":1.07103,"low":1.069395,"close":1.069705},{"date":"2023-06-05T00:00:00.000Z","ticker":"eurusd","open":1.069695,"high":1.07226,"low":1.067465,"close":1.071145},{"date":"2023-06-06T00:00:00.000Z","ticker":"eurusd","open":1.07115,"high":1.073295,"low":1.066715,"close":1.069875}]' @@ -21,7 +21,7 @@ interactions: Content-Type: - application/json Date: - - Thu, 27 Jun 2024 10:15:30 GMT + - Thu, 17 Oct 2024 21:24:05 GMT Server: - nginx/1.18.0 (Ubuntu) Vary: diff --git a/openbb_platform/providers/tradingeconomics/openbb_tradingeconomics/models/economic_calendar.py b/openbb_platform/providers/tradingeconomics/openbb_tradingeconomics/models/economic_calendar.py index 79a7bd88d06..bb96f129836 100644 --- a/openbb_platform/providers/tradingeconomics/openbb_tradingeconomics/models/economic_calendar.py +++ b/openbb_platform/providers/tradingeconomics/openbb_tradingeconomics/models/economic_calendar.py @@ -6,7 +6,7 @@ from datetime import ( date as dateType, datetime, ) -from typing import Any, Dict, List, Literal, Optional, Union +from typing import Any, Literal, Optional, Union from warnings import warn from openbb_core.app.model.abstract.error import OpenBBError @@ -104,7 +104,7 @@ class TEEconomicCalendarQueryParams(EconomicCalendarQueryParams): # pylint: disable=import-outside-toplevel from openbb_core.provider.utils.helpers import check_item - result: List = [] + result: list = [] values = c.replace(" ", "_").split(",") for v in values: check_item(v.lower(), COUNTRIES) @@ -200,7 +200,7 @@ class TEEconomicCalendarData(EconomicCalendarData): @field_validator("reference_date", mode="before", check_fields=False) @classmethod - def validate_date(cls, v: str) -> dateType: + def validate_date(cls, v): """Validate the date.""" # pylint: disable=import-outside-toplevel from pandas import to_datetime @@ -224,51 +224,47 @@ class TEEconomicCalendarData(EconomicCalendarData): class TEEconomicCalendarFetcher( Fetcher[ TEEconomicCalendarQueryParams, - List[TEEconomicCalendarData], + list[TEEconomicCalendarData], ] ): """Transform the query, extract and transform the data from the Trading Economics endpoints.""" @staticmethod - def transform_query(params: Dict[str, Any]) -> TEEconomicCalendarQueryParams: + def transform_query(params: dict[str, Any]) -> TEEconomicCalendarQueryParams: """Transform the query params.""" return TEEconomicCalendarQueryParams(**params) @staticmethod async def aextract_data( query: TEEconomicCalendarQueryParams, - credentials: Optional[Dict[str, str]], + credentials: Optional[dict[str, str]], **kwargs: Any, - ) -> Union[dict, List[dict]]: + ) -> Union[dict, list[dict]]: """Return the raw data from the TE endpoint.""" # pylint: disable=import-outside-toplevel - from openbb_core.provider.utils.helpers import ClientResponse, amake_request + from openbb_core.provider.utils.helpers import amake_request from openbb_tradingeconomics.utils import url_generator + from openbb_tradingeconomics.utils.helpers import response_callback api_key = credentials.get("tradingeconomics_api_key") if credentials else "" + if query.group is not None: query.group = query.group.replace("_", " ") # type: ignore + url = url_generator.generate_url(query) + if not url: raise OpenBBError( "No url generated. Check combination of input parameters." ) + url = f"{url}{api_key}" - async def callback(response: ClientResponse, _: Any) -> Union[dict, List[dict]]: - """Return the response.""" - if response.status != 200: - raise OpenBBError( - f"Error in TE request: \n{await response.text()}" - f"\nInfo -> TE API tend to fail if the number of countries is above {TE_COUNTRY_LIMIT}." - ) - return await response.json() - - return await amake_request(url, response_callback=callback, **kwargs) + return await amake_request(url, response_callback=response_callback, **kwargs) @staticmethod def transform_data( - query: TEEconomicCalendarQueryParams, data: List[Dict], **kwargs: Any - ) -> List[TEEconomicCalendarData]: + query: TEEconomicCalendarQueryParams, data: list[dict], **kwargs: Any + ) -> list[TEEconomicCalendarData]: """Return the transformed data.""" return [TEEconomicCalendarData.model_validate(d) for d in data] diff --git a/openbb_platform/providers/tradingeconomics/openbb_tradingeconomics/utils/helpers.py b/openbb_platform/providers/tradingeconomics/openbb_tradingeconomics/utils/helpers.py new file mode 100644 index 00000000000..95a19123f62 --- /dev/null +++ b/openbb_platform/providers/tradingeconomics/openbb_tradingeconomics/utils/helpers.py @@ -0,0 +1,26 @@ +"""TradingEconomics Helpers.""" + +from typing import Union + +from openbb_core.app.model.abstract.error import OpenBBError +from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError + + +async def response_callback(response, _) -> Union[dict, list[dict]]: + """Return the response.""" + if response.status != 200: + message = await response.text() + + if "credentials" in message or "unauthorized" in message.lower(): + raise UnauthorizedError( + f"Unauthorized TradingEconomics request -> {message}" + ) + + raise OpenBBError(f"{response.status} -> {message}") + + results = await response.json() + + if not results: + raise EmptyDataError("The request was returned empty.") + + return results