feature/commodities-lbma-fixing: Adds Commodity Extension and LBMA Gold/Silver daily fixing levels (#5760)

* add commodity extension and add lbma fixing endpoint

* dev_install.py

* readme url

* renovate the standard model

* makes a query_params model for nasdaq data link

* literal not optional

* unused imports

* missing test params

* test cassette

* DataLink query param description

* test file import

* actually fix import

* from openbb_core.provider.....

* ruff

* another import statement

* black

* async router

* move query_params

* update version

* version numbers

* extension_map

* satisfy pylint?

* pylint

* Update pyproject.toml

* black

* poetry lock

* Update extension_map.json

* Update __extensions__.py

* Update module_map.json

* clean descriptions

---------

Co-authored-by: Pratyush Shukla <ps4534@nyu.edu>
This commit is contained in:
Danglewood
2024-02-05 01:22:08 -08:00
committed by GitHub
parent 3de1bddc2d
commit b4649b375e
25 changed files with 8498 additions and 1608 deletions

View File

@@ -0,0 +1,87 @@
"""LBMA Fixing Standard Model."""
from datetime import (
date as dateType,
datetime,
)
from typing import Literal, Optional
from pydantic import Field, field_validator
from openbb_core.provider.abstract.data import Data
from openbb_core.provider.abstract.query_params import QueryParams
from openbb_core.provider.utils.descriptions import (
DATA_DESCRIPTIONS,
QUERY_DESCRIPTIONS,
)
class LbmaFixingQueryParams(QueryParams):
"""
LBMA Fixing Query.
Source: https://www.lbma.org.uk/prices-and-data/precious-metal-prices#/table
"""
asset: Literal["gold", "silver"] = Field(
description="The metal to get price fixing rates for.",
default="gold",
)
start_date: Optional[dateType] = Field(
default=None,
description=QUERY_DESCRIPTIONS.get("start_date", ""),
)
end_date: Optional[dateType] = Field(
default=None,
description=QUERY_DESCRIPTIONS.get("end_date", ""),
)
class LbmaFixingData(Data):
"""LBMA Fixing Data. Historical fixing prices in USD, GBP and EUR."""
date: dateType = Field(description=DATA_DESCRIPTIONS.get("date", ""))
usd_am: Optional[float] = Field(
default=None,
description="AM fixing price in USD.",
)
usd_pm: Optional[float] = Field(
default=None,
description="PM fixing price in USD.",
)
gbp_am: Optional[float] = Field(
default=None,
description="AM fixing price in GBP.",
)
gbp_pm: Optional[float] = Field(
default=None,
description="PM fixing price in GBP.",
)
euro_am: Optional[float] = Field(
default=None,
description="AM fixing price in EUR.",
)
euro_pm: Optional[float] = Field(
default=None,
description="PM fixing price in EUR.",
)
usd: Optional[float] = Field(
default=None,
description="Daily fixing price in USD.",
)
gbp: Optional[float] = Field(
default=None,
description="Daily fixing price in GBP.",
)
eur: Optional[float] = Field(
default=None,
description="Daily fixing price in EUR.",
)
@field_validator("date", mode="before", check_fields=False)
@classmethod
def validate_date(cls, v) -> dateType:
"""Validate date."""
if isinstance(v, datetime):
return v.date()
return datetime.strptime(v, "%Y-%m-%d").date()

View File

@@ -29,6 +29,7 @@ openbb-tiingo = { path = "./providers/tiingo", develop = true }
openbb-tradingeconomics = { path = "./providers/tradingeconomics", develop = true }
openbb-yfinance = { path = "./providers/yfinance", develop = true }
openbb-commodity = { path = "./extensions/commodity", develop = true }
openbb-crypto = { path = "./extensions/crypto", develop = true }
openbb-currency = { path = "./extensions/currency", develop = true }
openbb-derivatives = { path = "./extensions/derivatives", develop = true }

View File

@@ -0,0 +1,15 @@
# Commodity Extension for OpenBB Platform
This extension provides a set of commands for commodity-related data.
## Installation
To install the extension, run the following command in this folder:
```bash
pip install openbb-commodity
```
For development please check [Contribution Guidelines](https://github.com/OpenBB-finance/OpenBBTerminal/blob/develop/openbb_platform/CONTRIBUTING.md).
Documentation available [here](https://docs.openbb.co/platform).

View File

@@ -0,0 +1,55 @@
"""Test Commodity API endpoints."""
import base64
import pytest
import requests
from openbb_core.env import Env
from openbb_core.provider.utils.helpers import get_querystring
# pylint: disable=redefined-outer-name
@pytest.fixture(scope="session")
def headers():
userpass = f"{Env().API_USERNAME}:{Env().API_PASSWORD}"
userpass_bytes = userpass.encode("ascii")
base64_bytes = base64.b64encode(userpass_bytes)
return {"Authorization": f"Basic {base64_bytes.decode('ascii')}"}
@pytest.mark.parametrize(
"params",
[
(
{
"asset": "gold",
"start_date": None,
"end_date": None,
"collapse": None,
"transform": None,
"provider": "nasdaq",
}
),
(
{
"asset": "silver",
"start_date": "1990-01-01",
"end_date": "2023-01-01",
"collapse": "monthly",
"transform": "diff",
"provider": "nasdaq",
}
),
],
)
@pytest.mark.integration
def test_commodity_lbma_fixing(params, headers):
params = {p: v for p, v in params.items() if v}
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/commodity/lbma_fixing?{query_str}"
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200

View File

@@ -0,0 +1,50 @@
"""Test Commodity extension."""
import pytest
from openbb_core.app.model.obbject import OBBject
# pylint: disable=redefined-outer-name
@pytest.fixture(scope="session")
def obb(pytestconfig): # pylint: disable=inconsistent-return-statements
"""Fixture to setup obb."""
if pytestconfig.getoption("markexpr") != "not integration":
import openbb # pylint: disable=import-outside-toplevel
return openbb.obb
@pytest.mark.parametrize(
"params",
[
(
{
"asset": "gold",
"start_date": None,
"end_date": None,
"collapse": None,
"transform": None,
"provider": "nasdaq",
}
),
(
{
"asset": "silver",
"start_date": "1990-01-01",
"end_date": "2023-01-01",
"collapse": "monthly",
"transform": "diff",
"provider": "nasdaq",
}
),
],
)
@pytest.mark.integration
def test_commodity_lbma_fixing(params, obb):
params = {p: v for p, v in params.items() if v}
result = obb.commodity.lbma_fixing(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0

View File

@@ -0,0 +1,26 @@
"""The Commodity router."""
from openbb_core.app.model.command_context import CommandContext
from openbb_core.app.model.obbject import OBBject
from openbb_core.app.provider_interface import (
ExtraParams,
ProviderChoices,
StandardParams,
)
from openbb_core.app.query import Query
from openbb_core.app.router import Router
from pydantic import BaseModel
router = Router(prefix="")
# pylint: disable=unused-argument
@router.command(model="LbmaFixing")
async def lbma_fixing(
cc: CommandContext,
provider_choices: ProviderChoices,
standard_params: StandardParams,
extra_params: ExtraParams,
) -> OBBject[BaseModel]:
"""Daily LBMA Fixing Prices in USD/EUR/GBP."""
return await OBBject.from_query(Query(**locals()))

1412
openbb_platform/extensions/commodity/poetry.lock generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
[tool.poetry]
name = "openbb-commodity"
version = "1.0.0"
description = "Commodity extension for OpenBB"
authors = ["OpenBB Team <hello@openbb.co>"]
readme = "README.md"
packages = [{ include = "openbb_commodity" }]
[tool.poetry.dependencies]
python = "^3.8"
openbb-core = "^1.1.1"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.poetry.plugins."openbb_core_extension"]
commodity = "openbb_commodity.commodity_router:router"

View File

@@ -156,6 +156,7 @@ def test_regulators_cftc_cot_search(params, headers):
"start_date": "2023-01-01",
"end_date": "2023-06-06",
"transform": "diff",
"collapse": "weekly",
"provider": "nasdaq",
}
),

View File

@@ -137,6 +137,7 @@ def test_regulators_cftc_cot_search(params, obb):
"start_date": "2023-01-01",
"end_date": "2023-06-06",
"transform": "diff",
"collapse": "weekly",
"provider": "nasdaq",
}
),

View File

@@ -8,6 +8,7 @@ class Extensions(Container):
# fmt: off
"""
Routers:
/commodity
/crypto
/currency
/derivatives
@@ -20,6 +21,7 @@ Routers:
/regulators
Extensions:
- commodity@1.0.0
- crypto@1.1.1
- currency@1.1.1
- derivatives@1.1.1
@@ -48,8 +50,13 @@ Extensions:
return self.__doc__ or ""
@property
def crypto(self):
# pylint: disable=import-outside-toplevel
def commodity(self): # route = "/commodity"
from . import commodity
return commodity.ROUTER_commodity(command_runner=self._command_runner)
@property
def crypto(self): # route = "/crypto"
from . import crypto
return crypto.ROUTER_crypto(command_runner=self._command_runner)
@@ -69,8 +76,13 @@ Extensions:
return derivatives.ROUTER_derivatives(command_runner=self._command_runner)
@property
def economy(self):
# pylint: disable=import-outside-toplevel
def econometrics(self): # route = "/econometrics"
from . import econometrics
return econometrics.ROUTER_econometrics(command_runner=self._command_runner)
@property
def economy(self): # route = "/economy"
from . import economy
return economy.ROUTER_economy(command_runner=self._command_runner)
@@ -111,8 +123,19 @@ Extensions:
return news.ROUTER_news(command_runner=self._command_runner)
@property
def regulators(self):
# pylint: disable=import-outside-toplevel
def quantitative(self): # route = "/quantitative"
from . import quantitative
return quantitative.ROUTER_quantitative(command_runner=self._command_runner)
@property
def regulators(self): # route = "/regulators"
from . import regulators
return regulators.ROUTER_regulators(command_runner=self._command_runner)
@property
def technical(self): # route = "/technical"
from . import technical
return technical.ROUTER_technical(command_runner=self._command_runner)

View File

@@ -1,5 +1,6 @@
{
"openbb_core_extension": [
"commodity@1.0.0",
"crypto@1.1.1",
"currency@1.1.1",
"derivatives@1.1.1",
@@ -24,4 +25,4 @@
"tradingeconomics@1.1.1",
"yfinance@1.1.1"
]
}
}

View File

@@ -1,5 +1,6 @@
{
"__extensions__": "",
"commodity": "/commodity",
"crypto": "/crypto",
"crypto_price": "/crypto/price",
"crypto_price_historical": "/crypto/price/historical",
@@ -144,4 +145,4 @@
"regulators_sec_schema_files": "/regulators/sec/schema_files",
"regulators_sec_sic_search": "/regulators/sec/sic_search",
"regulators_sec_symbol_map": "/regulators/sec/symbol_map"
}
}

780
openbb_platform/poetry.lock generated vendored

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,7 @@ from openbb_nasdaq.models.cot import NasdaqCotFetcher
from openbb_nasdaq.models.cot_search import NasdaqCotSearchFetcher
from openbb_nasdaq.models.economic_calendar import NasdaqEconomicCalendarFetcher
from openbb_nasdaq.models.equity_search import NasdaqEquitySearchFetcher
from openbb_nasdaq.models.lbma_fixing import NasdaqLbmaFixingFetcher
from openbb_nasdaq.models.sp500_multiples import NasdaqSP500MultiplesFetcher
from openbb_nasdaq.models.top_retail import NasdaqTopRetailFetcher
@@ -26,6 +27,7 @@ unmatched technology, insights and markets expertise.""",
"COTSearch": NasdaqCotSearchFetcher,
"EconomicCalendar": NasdaqEconomicCalendarFetcher,
"EquitySearch": NasdaqEquitySearchFetcher,
"LbmaFixing": NasdaqLbmaFixingFetcher,
"SP500Multiples": NasdaqSP500MultiplesFetcher,
"TopRetail": NasdaqTopRetailFetcher,
},

View File

@@ -1,7 +1,8 @@
"""Nasdaq CFTC Commitment of Traders Reports Model."""
# pylint: disable=unused-argument
from datetime import (
date as dateType,
datetime,
)
from typing import Any, Dict, List, Literal, Optional
@@ -11,11 +12,12 @@ import pandas as pd
from openbb_core.provider.abstract.fetcher import Fetcher
from openbb_core.provider.standard_models.cot import COTData, COTQueryParams
from openbb_core.provider.utils.helpers import to_snake_case
from openbb_nasdaq.utils.query_params import DataLinkQueryParams
from openbb_nasdaq.utils.series_ids import CFTC
from pydantic import Field, field_validator
class NasdaqCotQueryParams(COTQueryParams):
class NasdaqCotQueryParams(COTQueryParams, DataLinkQueryParams):
"""Get CFTC Commitment of Traders Report.
Source: https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports/documentation
@@ -76,17 +78,6 @@ class NasdaqCotQueryParams(COTQueryParams):
""",
default=None,
)
start_date: Optional[dateType] = Field(
description="The start date of the time series. Defaults to all.", default=None
)
end_date: Optional[dateType] = Field(
description="The end date of the time series. Defaults to the most recent data.",
default=None,
)
transform: Optional[Literal["diff", "rdiff", "cumul", "normalize"]] = Field(
description="Transform the data as w/w difference, percent change, cumulative, or normalize.",
default=None,
)
class NasdaqCotData(COTData):
@@ -175,7 +166,7 @@ class NasdaqCotFetcher(Fetcher[NasdaqCotQueryParams, List[NasdaqCotData]]):
return data.to_dict("records")
except Exception as e:
raise RuntimeError(e)
raise RuntimeError(e) from e
@staticmethod
def transform_data(

View File

@@ -0,0 +1,80 @@
"""Nasdaq LBMA Fixing Model."""
# pylint: disable=unused-argument
from typing import Any, Dict, List, Optional
import nasdaqdatalink
from openbb_core.provider.abstract.fetcher import Fetcher
from openbb_core.provider.standard_models.lbma_fixing import (
LbmaFixingData,
LbmaFixingQueryParams,
)
from openbb_nasdaq.utils.query_params import DataLinkQueryParams
class NasdaqLbmaFixingQueryParams(LbmaFixingQueryParams, DataLinkQueryParams):
"""Nasdaq Data Link LBMA Fixing Query.
Source: https://data.nasdaq.com/data/LBMA-london-bullion-market-association/documentation
"""
class NasdaqLbmaFixingData(LbmaFixingData):
"""Nasdaq Data Link LBMA Fixing Data."""
__alias_dict__ = {
"date": "Date",
"usd_am": "USD (AM)",
"usd_pm": "USD (PM)",
"gbp_am": "GBP (AM)",
"gbp_pm": "GBP (PM)",
"eur_am": "EURO (AM)",
"eur_pm": "EURO (PM)",
"usd": "USD",
"gbp": "GBP",
"eur": "EURO",
}
class NasdaqLbmaFixingFetcher(
Fetcher[NasdaqLbmaFixingQueryParams, List[NasdaqLbmaFixingData]]
):
"""Transform the query, extract and transform the data from the Nasdaq endpoints."""
@staticmethod
def transform_query(params: Dict[str, Any]) -> NasdaqLbmaFixingQueryParams:
"""Transform the query params."""
return NasdaqLbmaFixingQueryParams(**params)
@staticmethod
def extract_data(
query: NasdaqLbmaFixingQueryParams,
credentials: Optional[Dict[str, str]],
**kwargs: Any,
) -> List[Dict]:
"""Extract the data from Nasdaq Data Link."""
api_key = credentials.get("nasdaq_api_key") if credentials else ""
dataset_dict = {
"gold": "LBMA/GOLD",
"silver": "LBMA/SILVER",
}
results = nasdaqdatalink.get(
dataset_dict[query.asset], # type: ignore
start_date=query.start_date,
end_date=query.end_date,
collapse=query.collapse,
transform=query.transform,
api_key=api_key,
)
return results.fillna(0).replace(0, None).reset_index().to_dict("records")
@staticmethod
def transform_data(
query: NasdaqLbmaFixingQueryParams,
data: List[Dict],
**kwargs: Any,
) -> List[NasdaqLbmaFixingData]:
"""Transform the data."""
return [NasdaqLbmaFixingData.model_validate(d) for d in data]

View File

@@ -1,6 +1,6 @@
"""Nasdaq SP500 Multiples Model."""
from typing import Any, Dict, List, Literal, Optional
from typing import Any, Dict, List, Optional
import nasdaqdatalink
from openbb_core.provider.abstract.fetcher import Fetcher
@@ -8,24 +8,13 @@ from openbb_core.provider.standard_models.sp500_multiples import (
SP500MultiplesData,
SP500MultiplesQueryParams,
)
from openbb_nasdaq.utils.query_params import DataLinkQueryParams
from openbb_nasdaq.utils.series_ids import SP500MULTIPLES
from pydantic import Field
class NasdaqSP500MultiplesQueryParams(SP500MultiplesQueryParams):
class NasdaqSP500MultiplesQueryParams(SP500MultiplesQueryParams, DataLinkQueryParams):
"""Nasdaq SP500 Multiples Query."""
collapse: Optional[Literal["daily", "weekly", "monthly", "quarterly", "annual"]] = (
Field(
description="Collapse the frequency of the time series.",
default="monthly",
)
)
transform: Optional[Literal["diff", "rdiff", "cumul", "normalize"]] = Field(
description="The transformation of the time series.",
default=None,
)
class NasdaqSP500MultiplesData(SP500MultiplesData):
"""Nasdaq SP500 Multiples Data."""

View File

@@ -0,0 +1,30 @@
"""Nasdaq Data Link Standard Query Params."""
from datetime import date as dateType
from typing import Literal, Optional
from openbb_core.provider.abstract.query_params import QueryParams
from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS
from pydantic import Field
class DataLinkQueryParams(QueryParams):
"""Standard Nasdaq Data Link Query Params"""
start_date: Optional[dateType] = Field(
description=QUERY_DESCRIPTIONS.get("start_date", ""), default=None
)
end_date: Optional[dateType] = Field(
description=QUERY_DESCRIPTIONS.get("start_date", ""),
default=None,
)
transform: Literal["diff", "rdiff", "cumul", "normalize", None] = Field(
description="Transform the data as difference, percent change, cumulative, or normalize.",
default=None,
)
collapse: Literal["daily", "weekly", "monthly", "quarterly", "annual", None] = (
Field(
description="Collapse the frequency of the time series.",
default=None,
)
)

View File

@@ -15,212 +15,255 @@ interactions:
x-api-token:
- MOCK_API_KEY
method: GET
uri: https://data.nasdaq.com/api/v3/datasets/MULTPL/SP500_PE_RATIO_MONTH/data?collapse=monthly&order=asc
uri: https://data.nasdaq.com/api/v3/datasets/MULTPL/SP500_PE_RATIO_MONTH/data?order=asc
response:
body:
string: !!binary |
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
fP755fHr1/8AAAD//wMAhzl4a6GVAAA=
H4sIAAAAAAAAA2Wd34ovOZKk3+VcVyX5PzPqep9hb5pmKLrPsAPV1bNV1bDDMO++n4WbmSu74cAB
wxXSJ3dJLoV+Gf/97a8///Hz79//+Df9/+2n//72y3/87T/++PbTr//45Zcfvv3x28+//v7vf//t
bxH+8vdf/vG3X//tP3796/f/90/arz//7fvv337607f/9fMf37/98O1///zLP75/+/MP337/4+ff
7ud///bTt6fPj6cfH/UPk++//jX68+Pzy49P1v/9t+//9x/ff/3Lf1Hgb3//9Y//88t/YT0t/NOf
vjzj6enh6c8/RHu+n4v2/LbiS8S35xVfI34elm8jPj88HeJ7xMdD/Gjx45mfEa/PrejqM6s9Pcbw
dQ3NTtvf17A8baWUNujDloi2fH5oK1FM/vzwclia/Pnh/WWLl/wttVO85C+HaPLnh+eQY2lyat9H
Gvzp4WMNl/z9quWSv6U7nn98KvpHLEXzL92OuJ306mci1unveSZKnf4aVyIa/enhNYGEaHSC66i9
Tn86LOv0x6N2sz8+PK1o9uvheUsb/fPhM75gEAzP9fAeOzV7wHlgDBEN/vjweogGf3x4DjiWBn+s
fxCG+3r4SBPRBhvNHYk00F+kQUaKYzEb4uvhc4sWuMH7mhF+PVzb5AK3rJoW4MYzYoEbe4gFfotT
EQsc96HZ0Y8PjT0UOxox3YVoRz9uKxHr6PoPsUH+spUfwzsefAs4w/ugTJAz4cQJak/G93v6F9Ho
Lw8NM0Sjvzw8Z4AiGh3Lo7jZnx86mrA0+/PDFaehmJ3i6TrEju/PECF2Zosr338M+vPD2xpmfCNu
Mxe9LVLNRXcAov3rRIDY4f0USMQ6vbM/Yr1+GA74tSMeu+EmqNMXCMZmgG1zOrQ7yX8Um+kihIgN
4cY6YkO4I16VJNgTg2g1fEvliI31j3Qv4sb6UbzYbSaWdjjNPCwHnMB8OcQN9sQ1SoO90+fngf6c
eEHsPN2BilhHdg7TAwed2oOJWMu3hBbiujxNQjQ7xdMhiGZnJY3PEcveNRex7E0NEMveBQGRf5NZ
vG87N9rrjqvsLw9PiSREEzHU3PhP5QDzTCyNKXEHukNJYgf6ozElmv2507/EshtdWtHP0kXPOiHL
RT+aWfR95E5x2/IjgTE4T1ynXykt6gFnNnJnfqK0izLHSFzwPBOxM1xmTVka/OUhq41Ek782oZNo
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
headers:
Allow:
- GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH
Cache-Control:
- no-store
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Length:
- '11041'
Content-Security-Policy:
- frame-ancestors 'self';
Content-Type:
- application/json; charset=utf-8
Date:
- Wed, 22 Nov 2023 06:16:57 GMT
ETag:
- W/"e6f4f7599579ae53f00c5086dde6ad8d"
Pragma:
- no-cache
Referrer-Policy:
- origin-when-cross-origin
Server:
- openresty
Set-Cookie:
- visid_incap_2170999=HgjuKto1SmKB4vfbqI7+pcRnsGUAAAAAQUIPAAAAAABu45kWEJrsHCG9VFchWKvQ;
expires=Wed, 22 Jan 2025 07:14:42 GMT; HttpOnly; path=/; Domain=.nasdaq.com
- nlbi_2170999=EIibFAUacy3eGZt+iMYI0AAAAABbCxmeVJi0AHDi5sBZzKtE; path=/; Domain=.nasdaq.com
- incap_ses_2106_2170999=uO+HJmlk3QMvG/SeVwQ6HcZnsGUAAAAAAD7qCbElCE3iREo9NMgiBg==;
- visid_incap_2170999=CBFfsC9zTmW4yuC4aTcUz9icXWUAAAAAQUIPAAAAAADuOaWuvNp1J+On9HnwWQhx;
expires=Thu, 21 Nov 2024 04:35:21 GMT; HttpOnly; path=/; Domain=.nasdaq.com
- nlbi_2170999=zRFbdt5npGBEe9fyKj7S7QAAAACu/+cxK1ONaf36T6Z4CRDb; path=/; Domain=.nasdaq.com
- incap_ses_2106_2170999=t6RLIYKgu38CFSqhUAQ6HdicXWUAAAAAkC15RzDqCqjdyQ+YIs1lcw==;
path=/; Domain=.nasdaq.com
Strict-Transport-Security:
- max-age=31536000; includeSubDomains; preload
X-CDN:
- Imperva
X-Iinfo:
- 17-47632248-47632253 NNYN CT(92 84 0) RT(1706059717490 57) q(0 0 2 0) r(10
11) U2
allow:
- GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH
cache-control:
- no-store
content-security-policy:
- frame-ancestors 'self';
content-type:
- application/json; charset=utf-8
date:
- Wed, 24 Jan 2024 01:28:39 GMT
etag:
- W/"47f0f57d7b77b879807ae916b057bf94"
pragma:
- no-cache
referrer-policy:
- origin-when-cross-origin
server:
- istio-envoy
strict-transport-security:
- max-age=31536000; includeSubDomains; preload
transfer-encoding:
- chunked
x-content-type-options:
X-Content-Type-Options:
- nosniff
x-envoy-upstream-service-time:
- '785'
x-frame-options:
X-Frame-Options:
- SAMEORIGIN
x-ratelimit-limit:
X-Iinfo:
- 13-12615933-12615934 NNNN CT(73 74 0) RT(1700633816153 63) q(0 0 1 -1) r(4
4) U2
X-RateLimit-Limit:
- '50000'
x-ratelimit-remaining:
- '49998'
x-request-id:
- 6ab79496-831c-96b2-8604-990b997d1a5f
x-runtime:
- '0.770136'
x-xss-protection:
X-RateLimit-Remaining:
- '49967'
X-Request-Id:
- 59a3c986-a54a-4617-aa89-6cb8d811277d
X-Runtime:
- '0.162567'
X-XSS-Protection:
- 1; mode=block
status:
code: 200

View File

@@ -9,6 +9,7 @@ from openbb_nasdaq.models.cot import NasdaqCotFetcher
from openbb_nasdaq.models.cot_search import NasdaqCotSearchFetcher
from openbb_nasdaq.models.economic_calendar import NasdaqEconomicCalendarFetcher
from openbb_nasdaq.models.equity_search import NasdaqEquitySearchFetcher
from openbb_nasdaq.models.lbma_fixing import NasdaqLbmaFixingFetcher
from openbb_nasdaq.models.sp500_multiples import NasdaqSP500MultiplesFetcher
from openbb_nasdaq.models.top_retail import NasdaqTopRetailFetcher
@@ -123,3 +124,12 @@ def test_nasdaq_calendar_earnings_fetcher(credentials=test_credentials):
fetcher = NasdaqCalendarEarningsFetcher()
result = fetcher.test(params, credentials)
assert result is None
@pytest.mark.record_http
def test_nasdaq_lbma_fixing_fetcher(credentials=test_credentials):
params = {"asset": "gold"}
fetcher = NasdaqLbmaFixingFetcher()
result = fetcher.test(params, credentials)
assert result is None

View File

@@ -22,6 +22,7 @@ openbb-tiingo = "^1.1.1"
openbb-tradingeconomics = "^1.1.1"
openbb-yfinance = "^1.1.1"
openbb-commodity = "^1.0.0"
openbb-crypto = "^1.1.1"
openbb-currency = "^1.1.1"
openbb-derivatives = "^1.1.1"