[Enhancement] openbb-cftc: Improve CFTC Endpoints and Make a Standalone Workspace App For COT Data (#7449)

* improve cftc endpoints and make a standalone workspace app

* mypy

* forgot  couple of files to commit

* test params

* integration test param name

* fix sec-sic-search

* fill some contracts missing category and subcategory, add a workspace workchoices endpoint

* linter

* integration test for cot_choices
This commit is contained in:
Danglewood
2026-04-20 15:36:41 -07:00
committed by GitHub
parent a14208947e
commit 9eca7b9f23
25 changed files with 2917 additions and 385 deletions

View File

@@ -8,17 +8,15 @@ from openbb_core.provider.utils.descriptions import (
DATA_DESCRIPTIONS, DATA_DESCRIPTIONS,
QUERY_DESCRIPTIONS, QUERY_DESCRIPTIONS,
) )
from pydantic import Field from pydantic import AliasChoices, Field
class COTQueryParams(QueryParams): class COTQueryParams(QueryParams):
"""Commitment of Traders Reports Query.""" """Commitment of Traders Reports Query."""
id: str = Field( code: str = Field(
description="A string with the CFTC market code or other identifying string," description="A string with the market code.",
+ " such as the contract market name, commodity name, or commodity group - i.e, 'gold' or 'japanese yen'." validation_alias=AliasChoices("code", "id"),
+ "Default report is Fed Funds Futures. Use the 'cftc_market_code' for an exact match.",
default="045601",
) )
start_date: dateType | None = Field( start_date: dateType | None = Field(
default=None, default=None,

View File

@@ -9,13 +9,28 @@ from pydantic import Field
class CotSearchQueryParams(QueryParams): class CotSearchQueryParams(QueryParams):
"""Commitment of Traders Reports Search Query.""" """Commitment of Traders Reports Search Query."""
code: str | None = Field(
default=None,
description="A string with the market contract code (can be partial).",
)
query: str = Field(description="Search query.", default="") query: str = Field(description="Search query.", default="")
class CotSearchData(Data): class CotSearchData(Data):
"""Commitment of Traders Reports Search Data.""" """Commitment of Traders Reports Search Data."""
code: str = Field(description="CFTC market contract code of the report.") code: str = Field(
description="CFTC market contract code of the report.",
json_schema_extra={
"x-widget_config": {
"renderFn": "cellOnClick",
"renderFnParams": {
"actionType": "groupBy",
"groupByParamName": "code",
},
},
},
)
name: str = Field(description="Name of the underlying asset.") name: str = Field(description="Name of the underlying asset.")
category: str | None = Field( category: str | None = Field(
default=None, description="Category of the underlying asset." default=None, description="Category of the underlying asset."

View File

@@ -136,51 +136,6 @@ def test_regulators_sec_sic_search(params, headers):
assert result.status_code == 200 assert result.status_code == 200
@pytest.mark.parametrize(
"params",
[
({"query": "grain", "provider": "cftc"}),
],
)
@pytest.mark.integration
def test_regulators_cftc_cot_search(params, headers):
"""Test the CFTC COT search endpoint."""
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/regulators/cftc/cot_search?{query_str}"
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
[
(
{
"id": "045601",
"report_type": "legacy",
"start_date": "2023-01-01",
"end_date": "2023-06-06",
"futures_only": False,
"provider": "cftc",
}
),
],
)
@pytest.mark.integration
def test_regulators_cftc_cot(params, headers):
"""Test the CFTC COT endpoint."""
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/regulators/cftc/cot?{query_str}"
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize( @pytest.mark.parametrize(
"params", "params",
[ [

View File

@@ -117,45 +117,6 @@ def test_regulators_sec_sic_search(params, obb):
assert len(result.results) > 0 assert len(result.results) > 0
@pytest.mark.parametrize(
"params",
[
({"query": "grain", "provider": "cftc"}),
],
)
@pytest.mark.integration
def test_regulators_cftc_cot_search(params, obb):
"""Test the CFTC COT search endpoint."""
result = obb.regulators.cftc.cot_search(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params",
[
(
{
"id": "045601",
"report_type": "legacy",
"start_date": "2023-01-01",
"end_date": "2023-06-06",
"futures_only": False,
"provider": "cftc",
}
),
],
)
@pytest.mark.integration
def test_regulators_cftc_cot(params, obb):
"""Test the CFTC COT endpoint."""
result = obb.regulators.cftc.cot(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize( @pytest.mark.parametrize(
"params", "params",
[ [

View File

@@ -1 +0,0 @@
"""Commodity Futures Trading Commission (CFTC)."""

View File

@@ -1,67 +0,0 @@
# pylint: disable=W0613:unused-argument
"""Commodity Futures Trading Commission (CFTC) Router."""
from openbb_core.app.model.command_context import CommandContext
from openbb_core.app.model.example import APIEx
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
router = Router(prefix="/cftc")
@router.command(
model="COTSearch",
examples=[
APIEx(parameters={"provider": "cftc"}),
APIEx(parameters={"query": "gold", "provider": "cftc"}),
],
)
async def cot_search(
cc: CommandContext,
provider_choices: ProviderChoices,
standard_params: StandardParams,
extra_params: ExtraParams,
) -> OBBject:
"""Get the current Commitment of Traders Reports.
Search a list of the current Commitment of Traders Reports series information.
"""
return await OBBject.from_query(Query(**locals()))
@router.command(
model="COT",
examples=[
APIEx(parameters={"provider": "ctfc"}),
APIEx(
description="Get the latest report for all items classified as, GOLD.",
parameters={"id": "gold", "provider": "cftc"},
),
APIEx(
description="Enter the entire history for a single CFTC Market Contract Code.",
parameters={"id": "088691", "provider": "cftc"},
),
APIEx(
description="Get the report for futures only.",
parameters={"id": "088691", "futures_only": True, "provider": "cftc"},
),
APIEx(
description="Get the most recent Commodity Index Traders Supplemental Report.",
parameters={"id": "all", "report_type": "supplemental", "provider": "cftc"},
),
],
)
async def cot(
cc: CommandContext,
provider_choices: ProviderChoices,
standard_params: StandardParams,
extra_params: ExtraParams,
) -> OBBject:
"""Get Commitment of Traders Reports."""
return await OBBject.from_query(Query(**locals()))

View File

@@ -5,11 +5,7 @@
from openbb_core.app.router import Router from openbb_core.app.router import Router
from .cftc.cftc_router import (
router as cftc_router,
)
from .sec.sec_router import router as sec_router from .sec.sec_router import router as sec_router
router = Router(prefix="", description="Financial market regulators data.") router = Router(prefix="", description="Financial market regulators data.")
router.include_router(sec_router) router.include_router(sec_router)
router.include_router(cftc_router)

View File

@@ -1,17 +1,20 @@
# CFTC Provider Extension # CFTC Provider Extension
This package provides full access to the CFTC Commitment of Traders database.
Reports are fetched by CFTC Code (e.g. `13874+`) and returns the full history of the contract.
## Installation ## Installation
Install from PyPI with: Install into a Python environment (3.10 - 3.14) from PyPI with:
```sh ```sh
pip install openbb-cftc pip install openbb-cftc
``` ```
Install this extension locally with: Then build the Python static assets:
```sh ```sh
pip install -e . openbb-build
``` ```
## Credentials ## Credentials
@@ -28,3 +31,84 @@ Then, generate the app_token by signing in with the credentials here: https://pu
If adding a token, use `cftc_app_token` as the key in the `user_settings.json` file. The value expected value is the app_token and not the `secret` or `api_key`. If adding a token, use `cftc_app_token` as the key in the `user_settings.json` file. The value expected value is the app_token and not the `secret` or `api_key`.
The token can be set as an environment variable:
```env
CFTC_APP_TOKEN
```
## Coverage
This extension provides a dedicated router module with two endpoints, and one OpenBB Workspace application.
- `obb.cftc.cot`
- `obb.cftc.cot_search`
## Usage
The package can be used as a Python module, or a REST API.
### REST API
Start the server over localhost with:
```sh
openbb-api
```
### Python
```python
from openbb import obb
search_results = obb.cftc.cot_search(query="gold")
print(search_results.to_df())
```
| code | name | category | subcategory | commodity_name | contract_units |
|:------------|:-------------------|:------------------|:----------------|:-----------------|:-------------------------------|
| CFTC_088691 | GOLD | NATURAL RESOURCES | PRECIOUS METALS | GOLD | (CONTRACTS OF 100 TROY OUNCES) |
| CFTC_088LM1 | GOLD -1 TROY OUNCE | NATURAL RESOURCES | PRECIOUS METALS | GOLD | (1 troy ounce x $2,300) |
| CFTC_088695 | MICRO GOLD | NATURAL RESOURCES | PRECIOUS METALS | GOLD | (CONTRACTS OF 10 TROY OUNCES) |
```python
report = obb.cftc.cot(code="CFTC_088695", measure="percent_of_oi", limit=4)
print(report.to_df().T)
```
| | 2026-03-03 | 2026-03-10 | 2026-03-17 | 2026-03-24 |
|:--------------------------------------------|-------------:|-------------:|-------------:|-------------:|
| open_interest_all | 60933 | 58119 | 64124 | 71998 |
| open_interest_pct_all | 1 | 1 | 1 | 1 |
| open_interest_pct_non_commercial_long_all | 0.186 | 0.18 | 0.168 | 0.285 |
| open_interest_pct_non_commercial_short_all | 0.527 | 0.546 | 0.555 | 0.515 |
| open_interest_pct_non_commercial_spread | 0.058 | 0.06 | 0.078 | 0.124 |
| open_interest_pct_commercial_long_all | 0.088 | 0.095 | 0.091 | 0.083 |
| open_interest_pct_commercial_short_all | 0 | 0 | 0 | 0 |
| open_interest_pct_total_reportable_long_all | 0.333 | 0.335 | 0.336 | 0.492 |
| open_interest_pct_total_reportable_short | 0.585 | 0.606 | 0.632 | 0.64 |
| open_interest_pct_non_reportable_long_all | 0.667 | 0.665 | 0.664 | 0.508 |
| open_interest_pct_non_reportable_short_all | 0.415 | 0.394 | 0.368 | 0.36 |
## Report Types
Reports can be filtered by measure, or include all reported fields. Report types come as 'Futures Only', or 'Combined' (futures and options combined positions), selectable by setting the `futures_only` boolean parameter.
### Legacy
The Legacy report is broken down by exchange with reported open interest further broken down into three trader classifications: commercial, non-commercial and non-reportable.
### Disaggregated
The Disaggregated reports are broken down by Agriculture and Natural Resource contracts. The Disaggregated reports break down reportable open interest positions into four classifications: Producer/Merchant, Swap Dealers, Managed Money and Other Reportables.
### Financial
The Traders in Financial Futures (TFF) report includes financial contracts. The TFF report breaks down the reported open interest into five classifications: Dealer, Asset Manager, Leveraged Money, Other Reportables and Non-Reportables.
### Supplemental
The Supplemental report includes 13 select agricultural commodity contracts for combined futures and options positions. Supplemental reports break down the reportable open interest positions into three trader classifications: non-commercial, commercial, and index traders.
Visit the CFTC [website](https://www.cftc.gov/MarketReports/CommitmentsofTraders/index.htm) for detailed descriptions of reports and classification methodology.

View File

@@ -0,0 +1,93 @@
"""Integration tests for the regulators API."""
# pylint: disable=redefined-outer-name
import base64
import pytest
import requests
from openbb_core.env import Env
from openbb_core.provider.utils.helpers import get_querystring
@pytest.fixture(scope="session")
def headers():
"""Get the headers for the API request."""
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",
[
(
{
"query": "grain",
"report_type": "legacy",
"futures_only": False,
"category": None,
"subcategory": None,
"code": None,
"provider": "cftc",
}
),
],
)
@pytest.mark.integration
def test_cftc_cot_search(params, headers):
"""Test the CFTC COT search endpoint."""
params = {p: v for p, v in params.items() if v}
query_str = get_querystring(params, [])
url = f"http://localhost:8000/api/v1/cftc/cot_search?{query_str}"
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
[
(
{
"code": "045601",
"report_type": "legacy",
"start_date": None,
"end_date": None,
"limit": 1,
"futures_only": False,
"measure": "all",
"provider": "cftc",
}
),
],
)
@pytest.mark.integration
def test_cftc_cot(params, headers):
"""Test the CFTC COT endpoint."""
params = {p: v for p, v in params.items() if v}
query_str = get_querystring(params, [])
url = f"http://localhost:8000/api/v1/cftc/cot?{query_str}"
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@pytest.mark.parametrize(
"params",
[
({}),
],
)
@pytest.mark.integration
def test_cftc_get_cot_choices(params, headers):
"""Test the CFTC get_cot_choices endpoint."""
query_str = get_querystring(params, [])
url = f"http://localhost:8000/api/v1/cftc/get_cot_choices?{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,84 @@
"""Test Regulators extension."""
# pylint: disable=redefined-outer-name
import pytest
from openbb_core.app.model.obbject import OBBject
# pylint: disable=inconsistent-return-statements
@pytest.fixture(scope="session")
def obb(pytestconfig):
"""Fixture to setup obb."""
if pytestconfig.getoption("markexpr") != "not integration":
import openbb # pylint: disable=import-outside-toplevel
return openbb.obb
@pytest.mark.parametrize(
"params",
[
(
{
"query": "grain",
"report_type": "legacy",
"futures_only": False,
"category": None,
"subcategory": None,
"code": None,
"provider": "cftc",
}
),
],
)
@pytest.mark.integration
def test_cftc_cot_search(params, obb):
"""Test the CFTC COT search endpoint."""
result = obb.cftc.cot_search(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params",
[
(
{
"code": "045601",
"report_type": "legacy",
"start_date": None,
"end_date": None,
"limit": 1,
"futures_only": False,
"measure": "all",
"provider": "cftc",
}
),
],
)
@pytest.mark.integration
def test_cftc_cot(params, obb):
"""Test the CFTC COT endpoint."""
result = obb.cftc.cot(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@pytest.mark.parametrize(
"params",
[
({}),
],
)
@pytest.mark.integration
@pytest.mark.skip(reason="This is not included in the Python interface.")
def test_cftc_get_cot_choices(params, obb):
"""Test the CFTC get_cot_choices endpoint."""
result = obb.cftc.get_cot_choices(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0

View File

@@ -0,0 +1,107 @@
[
{
"name": "CFTC Commitment of Traders",
"img": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Commodity_Futures_Trading_Commission_seal.svg/1920px-Commodity_Futures_Trading_Commission_seal.svg.png",
"img_dark": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Commodity_Futures_Trading_Commission_seal.svg/1920px-Commodity_Futures_Trading_Commission_seal.svg.png",
"img_light": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Commodity_Futures_Trading_Commission_seal.svg/1920px-Commodity_Futures_Trading_Commission_seal.svg.png",
"description": "Search and query the full historical database of reports for contracts covering commodity and financial futures.",
"allowCustomization": true,
"tabs": {
"": {
"id": "",
"name": "",
"layout": [
{
"i": "cftc_cot_cftc_obb",
"x": 0,
"y": 15,
"w": 40,
"h": 22,
"state": {
"params": {
"code": "CFTC_13874+",
"measure": "changes",
"futures_only": "true",
"limit": "52"
},
"chartView": {
"enabled": false,
"chartType": "line"
},
"columnState": {
"default": {
"columnPinning": {
"leftColIds": [
"date"
],
"rightColIds": []
},
"columnOrder": {
"orderedColIds": [
"date",
"open_interest_all",
"change_in_open_interest_all",
"change_in_non_commercial_long_all",
"change_in_non_commercial_short_all",
"change_in_non_commercial_spread_all",
"change_in_commercial_long_all",
"change_in_commercial_short_all",
"change_in_total_reportable_long_all",
"change_in_total_reportable_short",
"change_in_non_reportable_long_all",
"change_in_non_reportable_short_all"
]
}
}
}
},
"groups": [
"Group 1"
]
},
{
"i": "cftc_cot_search_cftc_obb",
"x": 0,
"y": 0,
"w": 40,
"h": 15,
"state": {
"params": {
"subcategory": "stock_indices"
},
"chartView": {
"enabled": false,
"chartType": "line"
},
"columnState": {
"default": {
"columnOrder": {
"orderedColIds": [
"code",
"name",
"category",
"subcategory",
"commodity_name",
"contract_units"
]
}
}
}
},
"groups": [
"Group 1"
]
}
]
}
},
"groups": [
{
"name": "Group 1",
"type": "param",
"paramName": "code",
"defaultValue": "CFTC_13874+"
}
]
}
]

View File

@@ -1 +0,0 @@
"""CFTC Provider Module Static Assets."""

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,159 @@
"""Commodity Futures Trading Commission (CFTC) Router."""
# pylint: disable=W0212,W0613
from typing import Any
from openbb_core.app.model.command_context import CommandContext
from openbb_core.app.model.example import APIEx
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
router = Router(prefix="")
COT_CHOICES: list[dict[str, str | dict[str, str | None]]] = []
async def build_choices():
"""Build the choices for Workspace."""
# pylint: disable=import-outside-toplevel
from openbb_cftc.models.cot_search import CftcCotSearchFetcher
contracts = await CftcCotSearchFetcher.fetch_data({}, {})
choices: list[dict[str, str | dict[str, str | None]]] = []
for d in contracts:
choice: dict[str, str | dict[str, str | None]] = {
"label": d.name.strip(), # type: ignore
"value": d.code.strip(), # type: ignore
"extraInfo": {"description": f"{d.subcategory.strip()} | {d.code.strip()}", "rightOfDescription": ""}, # type: ignore
}
choices.append(choice)
global COT_CHOICES # noqa: PLW0603 # pylint: disable=W0603
COT_CHOICES = choices
router.api_router.add_event_handler("startup", build_choices)
async def get_cot_choices() -> list[dict[str, str | dict[str, str | None]]]:
"""Get the choices for the COT command in Workspace."""
return COT_CHOICES
router._api_router.add_api_route(
path="/get_cot_choices",
endpoint=get_cot_choices,
methods=["GET"],
include_in_schema=False,
)
@router.command(
model="COTSearch",
examples=[
APIEx(parameters={"provider": "cftc"}),
APIEx(parameters={"query": "gold", "provider": "cftc"}),
],
widget_config={
"name": "Commitment of Traders Search",
"description": "Search for CFTC Commitment of Traders (COT) report series.",
"category": "CFTC",
"subCategory": "COT",
"refetchInterval": False,
},
)
async def cot_search(
cc: CommandContext,
provider_choices: ProviderChoices,
standard_params: StandardParams,
extra_params: ExtraParams,
) -> OBBject:
"""Search current Commitment of Traders Reports."""
return await OBBject.from_query(Query(**locals()))
@router.command(
model="COT",
examples=[
APIEx(parameters={"provider": "ctfc"}),
APIEx(
description="Get the latest report for all items classified as, GOLD.",
parameters={"code": "CFTC_088691", "limit": 1, "provider": "cftc"},
),
APIEx(
description="Get the report for futures only.",
parameters={
"code": "CFTC_088691",
"futures_only": True,
"limit": 1,
"provider": "cftc",
},
),
APIEx(
description="Filter the report down to a specific section.",
parameters={
"code": "CFTC_088691",
"futures_only": True,
"measure": "changes",
"limit": 1,
"provider": "cftc",
},
),
],
widget_config={
"name": "Commitment of Traders",
"description": "CFTC Commitment of Traders (COT) reports.",
"category": "CFTC",
"subCategory": "COT",
"refetchInterval": False,
},
)
async def cot(
cc: CommandContext,
provider_choices: ProviderChoices,
standard_params: StandardParams,
extra_params: ExtraParams,
) -> OBBject:
"""Get Commitment of Traders Reports."""
return await OBBject.from_query(Query(**locals()))
async def get_cftc_apps_json() -> list[dict[str, Any]]:
"""Get the IMF apps.json file.
This endpoint serves the apps.json file containing OpenBB Workspace app configurations.
It is automatically merged with any existing apps.json files in the Workspace and API.
Returns
-------
list[dict[str, Any]]
A list of OpenBB Workspace app configurations.
"""
# pylint: disable=import-outside-toplevel
import json
from pathlib import Path
apps_file = Path(__file__).parent / "apps.json"
try:
with apps_file.open("r", encoding="utf-8") as f:
apps_json = json.load(f)
return apps_json
except Exception:
return []
router._api_router.add_api_route(
path="/apps.json",
endpoint=get_cftc_apps_json,
methods=["GET"],
include_in_schema=False,
)

File diff suppressed because it is too large Load Diff

View File

@@ -2,13 +2,15 @@
# pylint: disable=unused-argument # pylint: disable=unused-argument
from typing import Any from typing import Any, Literal
from openbb_core.app.model.abstract.error import OpenBBError
from openbb_core.provider.abstract.fetcher import Fetcher from openbb_core.provider.abstract.fetcher import Fetcher
from openbb_core.provider.standard_models.cot_search import ( from openbb_core.provider.standard_models.cot_search import (
CotSearchData, CotSearchData,
CotSearchQueryParams, CotSearchQueryParams,
) )
from openbb_core.provider.utils.errors import EmptyDataError
from pydantic import Field from pydantic import Field
@@ -18,6 +20,74 @@ class CftcCotSearchQueryParams(CotSearchQueryParams):
Source: https://publicreporting.cftc.gov/stories/s/r4w3-av2u Source: https://publicreporting.cftc.gov/stories/s/r4w3-av2u
""" """
__json_schema_extra__ = {
"report_type": {
"multiple_items_allowed": False,
"choices": ["legacy", "disaggregated", "financial", "supplemental"],
},
"category": {
"multiple_items_allowed": False,
"choices": [
"agriculture",
"financial_instruments",
"natural_resources",
],
},
"subcategory": {
"multiple_items_allowed": False,
"choices": [
"base_metals",
"chemicals",
"currency",
"currency_non_major",
"dairy_products",
"digital_asset",
"digital_asset_non_major",
"electricity_and_sources",
"emissions",
"fertilizer",
"fiber",
"foodstuffs_softs",
"grains",
"interest_rate_swaps",
"interest_rates_non_us_treasury",
"interest_rates_us_treasury",
"livestock_meat_products",
"natural_gas_and_products",
"oilseed_and_products",
"other_agricultural",
"other_financial_instruments",
"petroleum_and_products",
"precious_metals",
"stock_indices",
"weather",
"wood_products",
"yield_insurance",
],
},
}
report_type: Literal["legacy", "disaggregated", "financial", "supplemental"] = (
Field(
default="legacy",
description="The report type to search within.",
)
)
futures_only: bool = Field(
default=False,
description="Search the futures-only report. Default is False, for the combined report.",
)
category: str | None = Field(
default=None,
description="Filter by commodity group name."
" Underscores are replaced with spaces. E.g, 'natural_resources' -> 'NATURAL RESOURCES'.",
)
subcategory: str | None = Field(
default=None,
description="Filter by commodity subgroup name."
" Underscores are replaced with spaces. E.g, 'precious_metals' -> 'PRECIOUS METALS'.",
)
class CftcCotSearchData(CotSearchData): class CftcCotSearchData(CotSearchData):
"""CFTC Commitment of Traders Reports Search Data.""" """CFTC Commitment of Traders Reports Search Data."""
@@ -43,48 +113,132 @@ class CftcCotSearchFetcher(Fetcher[CftcCotSearchQueryParams, list[CftcCotSearchD
return CftcCotSearchQueryParams(**params) return CftcCotSearchQueryParams(**params)
@staticmethod @staticmethod
def extract_data( async def aextract_data(
query: CftcCotSearchQueryParams, query: CftcCotSearchQueryParams,
credentials: dict[str, str] | None, credentials: dict[str, str] | None,
**kwargs: Any, **kwargs: Any,
) -> list[dict]: ) -> list[dict]:
"""Search a curated list of CFTC Commitment of Traders Reports.""" """Search CFTC Commitment of Traders Reports via the live API."""
# pylint: disable=import-outside-toplevel # pylint: disable=import-outside-toplevel
from importlib.resources import files # noqa from urllib.parse import quote
from pathlib import Path
from pandas import read_json
assets_path = Path(str(files("openbb_cftc").joinpath("assets"))) from openbb_cftc.utils import reports_dict
from openbb_core.provider.utils.helpers import amake_request
with open(assets_path.joinpath("cot_ids.json"), encoding="utf-8") as f: app_token = credentials.get("cftc_app_token") if credentials else ""
available_cot = read_json(f)
query_string = query.query # noqa report_type = query.report_type.replace("financial", "tff")
return ( if query.futures_only is True and report_type != "supplemental":
available_cot[ report_type += "_futures_only"
available_cot["contract_market_name"].str.contains( elif query.futures_only is False and report_type != "supplemental":
query_string, case=False report_type += "_combined"
)
| available_cot["cftc_contract_market_code"].str.contains( dataset_id = reports_dict[report_type]
query_string, case=False select_cols = (
) "cftc_contract_market_code,"
| available_cot["commodity_name"].str.contains(query_string, case=False) "contract_market_name,"
| available_cot["commodity_group_name"].str.contains( "commodity_name,"
query_string, case=False "commodity_group_name,"
) "commodity_subgroup_name,"
| available_cot["commodity_subgroup_name"].str.contains( "contract_units"
query_string, case=False
)
]
.reset_index(drop=True)
.to_dict("records")
) )
base_url = (
f"https://publicreporting.cftc.gov/resource/{dataset_id}.json"
f"?$select={select_cols}"
f"&$group={select_cols}"
"&$limit=50000"
"&$order=commodity_group_name,commodity_subgroup_name,contract_market_name"
)
search_term = query.query
where_parts: list[str] = []
from datetime import datetime, timedelta
cutoff = (datetime.now() - timedelta(weeks=52)).strftime("%Y-%m-%d")
where_parts.append(f"Report_Date_as_YYYY_MM_DD > '{cutoff}'")
if search_term:
escaped = search_term.replace("'", "''")
where_parts.append(
f"(UPPER(contract_market_name) like UPPER('%{escaped}%')"
f" OR UPPER(cftc_contract_market_code) like UPPER('%{escaped}%')"
f" OR UPPER(commodity_name) like UPPER('%{escaped}%')"
f" OR UPPER(commodity_group_name) like UPPER('%{escaped}%')"
f" OR UPPER(commodity_subgroup_name) like UPPER('%{escaped}%'))"
)
if query.category:
cat = query.category.replace("_", " ").upper()
where_parts.append(f"UPPER(commodity_group_name) = '{cat}'")
if query.subcategory:
subcategory_map = {
"currency_non_major": "CURRENCY(NON-MAJOR)",
"digital_asset_non_major": "DIGITAL ASSET (NON-MAJOR)",
"foodstuffs_softs": "FOODSTUFFS/SOFTS",
"interest_rates_non_us_treasury": "INTEREST RATES - NON U.S. TREASURY",
"interest_rates_us_treasury": "INTEREST RATES - U.S. TREASURY",
"livestock_meat_products": "LIVESTOCK/MEAT PRODUCTS",
"oilseed_and_products": "OILSEED AND PRODUCTS",
}
sub = subcategory_map.get(
query.subcategory,
query.subcategory.replace("_", " ").upper(),
)
where_parts.append(f"UPPER(commodity_subgroup_name) = '{sub}'")
if where_parts:
base_url += "&$where=" + quote(" AND ".join(where_parts))
url = f"{base_url}&$$app_token={app_token}" if app_token else base_url
try:
response = await amake_request(url, **kwargs)
except OpenBBError as error:
raise error from error
if not response:
raise EmptyDataError(
f"No results found for '{search_term}'."
if search_term
else "No results returned from the CFTC API."
)
return response # type: ignore
@staticmethod @staticmethod
def transform_data( def transform_data(
query: CotSearchQueryParams, query: CftcCotSearchQueryParams,
data: list[dict], data: list[dict],
**kwargs: Any, **kwargs: Any,
) -> list[CftcCotSearchData]: ) -> list[CftcCotSearchData]:
"""Transform the data.""" """Transform the data."""
return [CftcCotSearchData.model_validate(d) for d in data] results: list[CftcCotSearchData] = []
seen: set[str] = set()
for d in data:
code = d.get("cftc_contract_market_code", "")
if code and code not in seen:
seen.add(code)
name = d.get("commodity_name", "")
if "commodity_group_name" not in list(
d
) and name.strip().upper().endswith("INDICES"):
category = "FINANCIAL INSTRUMENTS"
subcategory = "STOCK INDICES"
d["commodity_group_name"] = category
d["commodity_subgroup_name"] = subcategory
elif (
"commodity_group_name" not in list(d)
and "CRYPTO" in name.strip().upper()
):
category = "FINANCIAL INSTRUMENTS"
subcategory = "DIGITAL ASSET (NON-MAJOR)"
d["commodity_group_name"] = category
d["commodity_subgroup_name"] = subcategory
d["cftc_contract_market_code"] = f"CFTC_{code}"
results.append(CftcCotSearchData.model_validate(d))
return results

View File

@@ -1 +1,11 @@
"""CFTC provider extension utilities.""" """CFTC provider extension utilities."""
reports_dict = {
"legacy_futures_only": "6dca-aqww",
"legacy_combined": "jun7-fc8e",
"disaggregated_futures_only": "72hh-3qpy",
"disaggregated_combined": "kh3c-gbw2",
"tff_futures_only": "gpe5-46if",
"tff_combined": "yw9f-hn96",
"supplemental": "4zgm-a668",
}

View File

@@ -419,6 +419,30 @@ files = [
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
] ]
[[package]]
name = "deepdiff"
version = "9.0.0"
description = "Deep Difference and Search of any Python object/data. Recreate objects by adding adding deltas to each other."
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
{file = "deepdiff-9.0.0-py3-none-any.whl", hash = "sha256:b1ae0dd86290d86a03de5fbee728fde43095c1472ae4974bdab23ab4656305bd"},
{file = "deepdiff-9.0.0.tar.gz", hash = "sha256:4872005306237b5b50829803feff58a1dfd20b2b357a55de22e7ded65b2008a7"},
]
[package.dependencies]
orderly-set = ">=5.5.0,<6"
[package.extras]
cli = ["click (>=8.3.1,<8.4.0)", "pyyaml (>=6.0.3,<6.1.0)"]
coverage = ["coverage (>=7.13.5,<7.14.0)"]
dev = ["bump2version (>=1.0.1,<1.1.0)", "flit-core (==3.12.0)", "ipdb (>=0.13.13,<0.14.0)", "jsonpickle (>=4.1.1,<4.2.0)", "nox (==2026.2.9)", "numpy (>=2.2.0,<2.3.0) ; python_version < \"3.14\"", "numpy (>=2.4.3,<2.5.0) ; python_version >= \"3.14\"", "orjson (>=3.11.7,<3.12.0)", "pandas (>=2.2.0,<2.3.0) ; python_version < \"3.11\"", "pandas (>=3.0.1,<3.1.0) ; python_version >= \"3.11\"", "polars (>=1.39.3,<1.40.0)", "python-dateutil (>=2.9.0.post0,<2.10.0)", "pytz", "tomli (>=2.4.0,<2.5.0)", "tomli-w (>=1.2.0,<1.3.0)", "uuid6 (==2025.0.1)"]
docs = ["Sphinx (>=8.1.3,<8.2.0)", "furo (>=2024.8.6)", "sphinx-sitemap (>=2.9.0,<2.10.0)", "sphinxemoji (>=0.3.2,<0.4.0)"]
optimize = ["orjson"]
static = ["flake8 (>=7.3.0,<7.4.0)", "flake8-pyproject (>=1.2.4,<1.3.0)", "pydantic (>=2.12.5,<2.13.0)"]
test = ["pytest (>=9.0.2,<9.1.0)", "pytest-benchmark (>=5.2.3,<5.3.0)", "pytest-cov (>=7.1.0,<7.2.0)", "python-dotenv (>=1.2.2,<1.3.0)"]
[[package]] [[package]]
name = "exceptiongroup" name = "exceptiongroup"
version = "1.3.1" version = "1.3.1"
@@ -1011,6 +1035,41 @@ uuid7 = ">=0.1.0,<0.2.0"
uvicorn = ">=0.40.0,<0.41.0" uvicorn = ">=0.40.0,<0.41.0"
websockets = ">=15.0" websockets = ">=15.0"
[[package]]
name = "openbb-platform-api"
version = "1.3.5"
description = "OpenBB Platform API: Launch script and widgets builder for the Open Data Platform REST API and Workspace Backend Connector."
optional = false
python-versions = "<4,>=3.10"
groups = ["main"]
files = [
{file = "openbb_platform_api-1.3.5-py3-none-any.whl", hash = "sha256:dfa0175006aede9e09906b81832105075747d836b135e945e73af51060731066"},
{file = "openbb_platform_api-1.3.5.tar.gz", hash = "sha256:40816bb6ffe18481d7e023a5c36304761e5334d18098c72af7bd6d44f4235932"},
]
[package.dependencies]
deepdiff = ">=8.6.2"
openbb-core = ">=1.6.4,<2.0.0"
[[package]]
name = "orderly-set"
version = "5.5.0"
description = "Orderly set"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "orderly_set-5.5.0-py3-none-any.whl", hash = "sha256:46f0b801948e98f427b412fcabb831677194c05c3b699b80de260374baa0b1e7"},
{file = "orderly_set-5.5.0.tar.gz", hash = "sha256:e87185c8e4d8afa64e7f8160ee2c542a475b738bc891dc3f58102e654125e6ce"},
]
[package.extras]
coverage = ["coverage (>=7.6.0,<7.7.0)"]
dev = ["bump2version (>=1.0.0,<1.1.0)", "ipdb (>=0.13.0,<0.14.0)"]
optimize = ["orjson"]
static = ["flake8 (>=7.1.0,<7.2.0)", "flake8-pyproject (>=1.2.3,<1.3.0)"]
test = ["pytest (>=8.3.0,<8.4.0)", "pytest-benchmark (>=5.1.0,<5.2.0)", "pytest-cov (>=6.0.0,<6.1.0)", "python-dotenv (>=1.0.0,<1.1.0)"]
[[package]] [[package]]
name = "pandas" name = "pandas"
version = "2.3.3" version = "2.3.3"
@@ -1335,19 +1394,19 @@ files = [
[[package]] [[package]]
name = "pydantic" name = "pydantic"
version = "2.13.2" version = "2.13.3"
description = "Data validation using Python type hints" description = "Data validation using Python type hints"
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "pydantic-2.13.2-py3-none-any.whl", hash = "sha256:a525087f4c03d7e7456a3de89b64cd693d2229933bb1068b9af6befd5563694e"}, {file = "pydantic-2.13.3-py3-none-any.whl", hash = "sha256:6db14ac8dfc9a1e57f87ea2c0de670c251240f43cb0c30a5130e9720dc612927"},
{file = "pydantic-2.13.2.tar.gz", hash = "sha256:b418196607e61081c3226dcd4f0672f2a194828abb9109e9cfb84026564df2d1"}, {file = "pydantic-2.13.3.tar.gz", hash = "sha256:af09e9d1d09f4e7fe37145c1f577e1d61ceb9a41924bf0094a36506285d0a84d"},
] ]
[package.dependencies] [package.dependencies]
annotated-types = ">=0.6.0" annotated-types = ">=0.6.0"
pydantic-core = "2.46.2" pydantic-core = "2.46.3"
typing-extensions = ">=4.14.1" typing-extensions = ">=4.14.1"
typing-inspection = ">=0.4.2" typing-inspection = ">=0.4.2"
@@ -1357,132 +1416,132 @@ timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows
[[package]] [[package]]
name = "pydantic-core" name = "pydantic-core"
version = "2.46.2" version = "2.46.3"
description = "Core functionality for Pydantic validation and serialization" description = "Core functionality for Pydantic validation and serialization"
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "pydantic_core-2.46.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:160ef93541f4f84e3e5068e6c1f64d8fd6f57586e5853d609b467d3333f8146a"}, {file = "pydantic_core-2.46.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:1da3786b8018e60349680720158cc19161cc3b4bdd815beb0a321cd5ce1ad5b1"},
{file = "pydantic_core-2.46.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a9124b63f4f40a12a0666df57450b4c24b98407ff74349221b869ec085a5d8e"}, {file = "pydantic_core-2.46.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cc0988cb29d21bf4a9d5cf2ef970b5c0e38d8d8e107a493278c05dc6c1dda69f"},
{file = "pydantic_core-2.46.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de12004a7da7f1eb67ece37439a5a23a915636085dd042176fda362e006e6940"}, {file = "pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27f9067c3bfadd04c55484b89c0d267981b2f3512850f6f66e1e74204a4e4ce3"},
{file = "pydantic_core-2.46.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a070c7769fec277409ad0b3d55b2f0a3703a6f00cf5031fe93090f155bf56382"}, {file = "pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a642ac886ecf6402d9882d10c405dcf4b902abeb2972cd5fb4a48c83cd59279a"},
{file = "pydantic_core-2.46.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41d701bb34f81f0b11c724cc544b9a10b26a28f4d0d1197f2037c91225708706"}, {file = "pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79f561438481f28681584b89e2effb22855e2179880314bcddbf5968e935e807"},
{file = "pydantic_core-2.46.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19631e7350b7a574fb6b6db222f4b17e8bd31803074b3307d07df62379d2b2e4"}, {file = "pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57a973eae4665352a47cf1a99b4ee864620f2fe663a217d7a8da68a1f3a5bfda"},
{file = "pydantic_core-2.46.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48b1059e4f2a6ec3e41983148eb1eec5ef9fa3a80bbc4ac0893ac76b115fe039"}, {file = "pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83d002b97072a53ea150d63e0a3adfae5670cef5aa8a6e490240e482d3b22e57"},
{file = "pydantic_core-2.46.2-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:df73724fce8ad53c670358c905b37930bd7b9d92e57db640a65c53b2706eee00"}, {file = "pydantic_core-2.46.3-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:b40ddd51e7c44b28cfaef746c9d3c506d658885e0a46f9eeef2ee815cbf8e045"},
{file = "pydantic_core-2.46.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a0891a9be0def16fb320af21a198ece052eed72bf44d73d8ff43f702bd26fd6b"}, {file = "pydantic_core-2.46.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ac5ec7fb9b87f04ee839af2d53bcadea57ded7d229719f56c0ed895bff987943"},
{file = "pydantic_core-2.46.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2ca790779aa1cba1329b8dc42ccebada441d9ac1d932de980183d544682c646d"}, {file = "pydantic_core-2.46.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a3b11c812f61b3129c4905781a2601dfdfdea5fe1e6c1cfb696b55d14e9c054f"},
{file = "pydantic_core-2.46.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:6b865eb702c3af71cf7331919a787563ce2413f7a54ef49ec6709a01b4f22ce6"}, {file = "pydantic_core-2.46.3-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:1108da631e602e5b3c38d6d04fe5bb3bfa54349e6918e3ca6cf570b2e2b2f9d4"},
{file = "pydantic_core-2.46.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:631bec5f951a30a4b332b4a57d0cdd5a2c8187eb71301f966425f2e54a697855"}, {file = "pydantic_core-2.46.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:de885175515bcfa98ae618c1df7a072f13d179f81376c8007112af20567fd08a"},
{file = "pydantic_core-2.46.2-cp310-cp310-win32.whl", hash = "sha256:8cbd9d67357f3a925f2af1d44db3e8ef1ce1a293ea0add98081b072d4a12e3b4"}, {file = "pydantic_core-2.46.3-cp310-cp310-win32.whl", hash = "sha256:d11058e3201527d41bc6b545c79187c9e4bf85e15a236a6007f0e991518882b7"},
{file = "pydantic_core-2.46.2-cp310-cp310-win_amd64.whl", hash = "sha256:dd51dd16182b4bfdcefd27b39b856aa4a57b77f15b231a2d10c45391b0a02028"}, {file = "pydantic_core-2.46.3-cp310-cp310-win_amd64.whl", hash = "sha256:3612edf65c8ea67ac13616c4d23af12faef1ae435a8a93e5934c2a0cbbdd1fd6"},
{file = "pydantic_core-2.46.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d8060f42db3cd204871db0afd51fef54a13fa544c4dd48cdcae2e174ef40c8ba"}, {file = "pydantic_core-2.46.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ab124d49d0459b2373ecf54118a45c28a1e6d4192a533fbc915e70f556feb8e5"},
{file = "pydantic_core-2.46.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:73a9d2809bd8d4a7cda4d336dc996a565eb4feaaa39932f9d85a65fa18382f28"}, {file = "pydantic_core-2.46.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cca67d52a5c7a16aed2b3999e719c4bcf644074eac304a5d3d62dd70ae7d4b2c"},
{file = "pydantic_core-2.46.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b0a2dee92dfaabcfb93629188c3e9cf74fdfc0f22e7c369cb444a98814a1e50"}, {file = "pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c024e08c0ba23e6fd68c771a521e9d6a792f2ebb0fa734296b36394dc30390e"},
{file = "pydantic_core-2.46.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3098446ba8cf774f61cb8d4008c1dba14a30426a15169cd95ac3392a461193b1"}, {file = "pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6645ce7eec4928e29a1e3b3d5c946621d105d3e79f0c9cddf07c2a9770949287"},
{file = "pydantic_core-2.46.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57c584af6c375ea3f826d8131a94cb212b3d9926eaff67117e3711bbff3a83a5"}, {file = "pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a712c7118e6c5ea96562f7b488435172abb94a3c53c22c9efc1412264a45cbbe"},
{file = "pydantic_core-2.46.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:547381cca999be88b4715a0ed7afa11f07fc7e53cb1883687b190d25a92c56cf"}, {file = "pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:69a868ef3ff206343579021c40faf3b1edc64b1cc508ff243a28b0a514ccb050"},
{file = "pydantic_core-2.46.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:caeed15dcb1233a5a94bc6ff37ef5393cf5b33a45e4bdfb2d6042f3d24e1cb27"}, {file = "pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc7e8c32db809aa0f6ea1d6869ebc8518a65d5150fdfad8bcae6a49ae32a22e2"},
{file = "pydantic_core-2.46.2-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:c05f53362568c75476b5c96659377a5dfd982cfbe5a5c07de5106d08a04efc4f"}, {file = "pydantic_core-2.46.3-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:3481bd1341dc85779ee506bc8e1196a277ace359d89d28588a9468c3ecbe63fa"},
{file = "pydantic_core-2.46.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2643ac7eae296200dbd48762a1c852cf2cad5f5e3eba34e652053cebf03becf8"}, {file = "pydantic_core-2.46.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8690eba565c6d68ffd3a8655525cbdd5246510b44a637ee2c6c03a7ebfe64d3c"},
{file = "pydantic_core-2.46.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dc4620a47c6fe6a39f89392c00833a82fc050ce90169798f78a25a8d4df03b6e"}, {file = "pydantic_core-2.46.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4de88889d7e88d50d40ee5b39d5dac0bcaef9ba91f7e536ac064e6b2834ecccf"},
{file = "pydantic_core-2.46.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:78cb0d2453b50bf2035f85fd0d9cfabdb98c47f9c53ddb7c23873cd83da9560b"}, {file = "pydantic_core-2.46.3-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:e480080975c1ef7f780b8f99ed72337e7cc5efea2e518a20a692e8e7b278eb8b"},
{file = "pydantic_core-2.46.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f0c1cbb7d6112932cc188c6be007a5e2867005a069e47f42fe67bf5f122b0908"}, {file = "pydantic_core-2.46.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:de3a5c376f8cd94da9a1b8fd3dd1c16c7a7b216ed31dc8ce9fd7a22bf13b836e"},
{file = "pydantic_core-2.46.2-cp311-cp311-win32.whl", hash = "sha256:c1ce5b2366f85cfdbf7f0907755043707f86d09a5b1b1acebbb7bf1600d75c64"}, {file = "pydantic_core-2.46.3-cp311-cp311-win32.whl", hash = "sha256:fc331a5314ffddd5385b9ee9d0d2fee0b13c27e0e02dad71b1ae5d6561f51eeb"},
{file = "pydantic_core-2.46.2-cp311-cp311-win_amd64.whl", hash = "sha256:f1a6197eadff5bd0bb932f12bb038d403cb75db5b0b391e70e816a647745ddaf"}, {file = "pydantic_core-2.46.3-cp311-cp311-win_amd64.whl", hash = "sha256:b5b9c6cf08a8a5e502698f5e153056d12c34b8fb30317e0c5fd06f45162a6346"},
{file = "pydantic_core-2.46.2-cp311-cp311-win_arm64.whl", hash = "sha256:15e42885b283f87846ee79e161002c5c496ef747a73f6e47054f45a13d9035bc"}, {file = "pydantic_core-2.46.3-cp311-cp311-win_arm64.whl", hash = "sha256:5dfd51cf457482f04ec49491811a2b8fd5b843b64b11eecd2d7a1ee596ea78a6"},
{file = "pydantic_core-2.46.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ea1ad8c89da31512fe2d249cf0638fb666925bda341901541bc5f3311c6fcc9e"}, {file = "pydantic_core-2.46.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b11b59b3eee90a80a36701ddb4576d9ae31f93f05cb9e277ceaa09e6bf074a67"},
{file = "pydantic_core-2.46.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b308da17b92481e0587244631c5529e5d91d04cb2b08194825627b1eca28e21e"}, {file = "pydantic_core-2.46.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:af8653713055ea18a3abc1537fe2ebc42f5b0bbb768d1eb79fd74eb47c0ac089"},
{file = "pydantic_core-2.46.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d333a50bdd814a917d8d6a7ee35ba2395d53ddaa882613bc24e54a9d8b129095"}, {file = "pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:75a519dab6d63c514f3a81053e5266c549679e4aa88f6ec57f2b7b854aceb1b0"},
{file = "pydantic_core-2.46.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1d00b99590c5bd1fabbc5d28b170923e32c1b1071b1f1de1851a4d14d89eb192"}, {file = "pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a6cd87cb1575b1ad05ba98894c5b5c96411ef678fa2f6ed2576607095b8d9789"},
{file = "pydantic_core-2.46.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f0e686960ffe9e65066395af856ac2d52c159043144433602c50c221d81c1ba"}, {file = "pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f80a55484b8d843c8ada81ebf70a682f3f00a3d40e378c06cf17ecb44d280d7d"},
{file = "pydantic_core-2.46.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d1128da41c9cb474e0a4701f9c363ec645c9d1a02229904c76bf4e0a194fde2"}, {file = "pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3861f1731b90c50a3266316b9044f5c9b405eecb8e299b0a7120596334e4fe9c"},
{file = "pydantic_core-2.46.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48649cf2d8c358d79586e9fb2f8235902fcaa2d969ec1c5301f2d1873b2f8321"}, {file = "pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb528e295ed31570ac3dcc9bfdd6e0150bc11ce6168ac87a8082055cf1a67395"},
{file = "pydantic_core-2.46.2-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:b902f0fc7c2cf503865a05718b68147c6cd5d0a3867af38c527be574a9fa6e9d"}, {file = "pydantic_core-2.46.3-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:367508faa4973b992b271ba1494acaab36eb7e8739d1e47be5035fb1ea225396"},
{file = "pydantic_core-2.46.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e80011f808b03d1d87a8f1e76ae3da19a18eb706c823e17981dcf1fae43744fc"}, {file = "pydantic_core-2.46.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ad3c826fe523e4becf4fe39baa44286cff85ef137c729a2c5e269afbfd0905d"},
{file = "pydantic_core-2.46.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b839d5c802e31348b949b6473f8190cddbf7d47475856d8ac995a373ee16ec59"}, {file = "pydantic_core-2.46.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ec638c5d194ef8af27db69f16c954a09797c0dc25015ad6123eb2c73a4d271ca"},
{file = "pydantic_core-2.46.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:c6b1064f3f9cf9072e1d59dd2936f9f3b668bec1c37039708c9222db703c0d5b"}, {file = "pydantic_core-2.46.3-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:28ed528c45446062ee66edb1d33df5d88828ae167de76e773a3c7f64bd14e976"},
{file = "pydantic_core-2.46.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:37a68e6f2ac95578ce3c0564802404b27b24988649616e556c07e77111ed3f1d"}, {file = "pydantic_core-2.46.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aed19d0c783886d5bd86d80ae5030006b45e28464218747dcf83dabfdd092c7b"},
{file = "pydantic_core-2.46.2-cp312-cp312-win32.whl", hash = "sha256:d9ffa75a7ef4b97d6e5e205fabd4304ef01fec09e6f1bdde04b9ad1b07d20289"}, {file = "pydantic_core-2.46.3-cp312-cp312-win32.whl", hash = "sha256:06d5d8820cbbdb4147578c1fe7ffcd5b83f34508cb9f9ab76e807be7db6ff0a4"},
{file = "pydantic_core-2.46.2-cp312-cp312-win_amd64.whl", hash = "sha256:0551f2d2ddb68af5a00e26497f8025c538f73ef3cb698f8e5a487042cd2792a8"}, {file = "pydantic_core-2.46.3-cp312-cp312-win_amd64.whl", hash = "sha256:c3212fda0ee959c1dd04c60b601ec31097aaa893573a3a1abd0a47bcac2968c1"},
{file = "pydantic_core-2.46.2-cp312-cp312-win_arm64.whl", hash = "sha256:83aef30f106edcc21a6a4cc44b82d3169a1dbe255508db788e778f3c804d3583"}, {file = "pydantic_core-2.46.3-cp312-cp312-win_arm64.whl", hash = "sha256:f1f8338dd7a7f31761f1f1a3c47503a9a3b34eea3c8b01fa6ee96408affb5e72"},
{file = "pydantic_core-2.46.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:d26e9eea3715008a09a74585fe9becd0c67fbb145dc4df9756d597d7230a652c"}, {file = "pydantic_core-2.46.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:12bc98de041458b80c86c56b24df1d23832f3e166cbaff011f25d187f5c62c37"},
{file = "pydantic_core-2.46.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:48b36e3235140510dc7861f0cd58b714b1cdd3d48f75e10ce52e69866b746f10"}, {file = "pydantic_core-2.46.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:85348b8f89d2c3508b65b16c3c33a4da22b8215138d8b996912bb1532868885f"},
{file = "pydantic_core-2.46.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36b1f99dc451f1a3981f236151465bcf995bbe712d0727c9f7b236fe228a8133"}, {file = "pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1105677a6df914b1fb71a81b96c8cce7726857e1717d86001f29be06a25ee6f8"},
{file = "pydantic_core-2.46.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8641c8d535c2d95b45c2e19b646ecd23ebba35d461e0ae48a3498277006250ab"}, {file = "pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:87082cd65669a33adeba5470769e9704c7cf026cc30afb9cc77fd865578ebaad"},
{file = "pydantic_core-2.46.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:20fb194788a0a50993e87013e693494ba183a2af5b44e99cf060bbae10912b11"}, {file = "pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60e5f66e12c4f5212d08522963380eaaeac5ebd795826cfd19b2dfb0c7a52b9c"},
{file = "pydantic_core-2.46.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9262d11d0cd11ee3303a95156939402bed6cedfe5ed0e331b95a283a4da6eb8b"}, {file = "pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b6cdf19bf84128d5e7c37e8a73a0c5c10d51103a650ac585d42dd6ae233f2b7f"},
{file = "pydantic_core-2.46.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac204542736aa295fa25f713b7fad6fc50b46ab7764d16087575c85f085174f3"}, {file = "pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:031bb17f4885a43773c8c763089499f242aee2ea85cf17154168775dccdecf35"},
{file = "pydantic_core-2.46.2-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9a7c43a0584742dface3ca0daf6f719d46c1ac2f87cf080050f9ae052c75e1b2"}, {file = "pydantic_core-2.46.3-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:bcf2a8b2982a6673693eae7348ef3d8cf3979c1d63b54fca7c397a635cc68687"},
{file = "pydantic_core-2.46.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fd05e1edb6a90ad446fa268ab09e59202766b837597b714b2492db11ee87fab9"}, {file = "pydantic_core-2.46.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28e8cf2f52d72ced402a137145923a762cbb5081e48b34312f7a0c8f55928ec3"},
{file = "pydantic_core-2.46.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:91155b110788b5501abc7ea954f1d08606219e4e28e3c73a94124307c06efb80"}, {file = "pydantic_core-2.46.3-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:17eaface65d9fc5abb940003020309c1bf7a211f5f608d7870297c367e6f9022"},
{file = "pydantic_core-2.46.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:e4e2c72a529fa03ff228be1d2b76944013f428220b764e03cc50ada67e17a42c"}, {file = "pydantic_core-2.46.3-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:93fd339f23408a07e98950a89644f92c54d8729719a40b30c0a30bb9ebc55d23"},
{file = "pydantic_core-2.46.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:56291ec1a11c3499890c99a8fd9053b47e60fe837a77ec72c0671b1b8b3dce24"}, {file = "pydantic_core-2.46.3-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:23cbdb3aaa74dfe0837975dbf69b469753bbde8eacace524519ffdb6b6e89eb7"},
{file = "pydantic_core-2.46.2-cp313-cp313-win32.whl", hash = "sha256:b50f9c5f826ddca1246f055148df939f5f3f2d0d96db73de28e2233f22210d4c"}, {file = "pydantic_core-2.46.3-cp313-cp313-win32.whl", hash = "sha256:610eda2e3838f401105e6326ca304f5da1e15393ae25dacae5c5c63f2c275b13"},
{file = "pydantic_core-2.46.2-cp313-cp313-win_amd64.whl", hash = "sha256:251a57788823230ca8cbc99e6245d1a2ed6e180ec4864f251c94182c580c7f2e"}, {file = "pydantic_core-2.46.3-cp313-cp313-win_amd64.whl", hash = "sha256:68cc7866ed863db34351294187f9b729964c371ba33e31c26f478471c52e1ed0"},
{file = "pydantic_core-2.46.2-cp313-cp313-win_arm64.whl", hash = "sha256:315d32d1a71494d6b4e1e14a9fa7a4329597b4c4340088ad7e1a9dafbeed92a9"}, {file = "pydantic_core-2.46.3-cp313-cp313-win_arm64.whl", hash = "sha256:f64b5537ac62b231572879cd08ec05600308636a5d63bcbdb15063a466977bec"},
{file = "pydantic_core-2.46.2-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:4f59b45f3ef8650c0c736a57f59031d47ed9df4c0a64e83796849d7d14863a2d"}, {file = "pydantic_core-2.46.3-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:afa3aa644f74e290cdede48a7b0bee37d1c35e71b05105f6b340d484af536d9b"},
{file = "pydantic_core-2.46.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3a075a29ebef752784a91532a1a85be6b234ccffec0a9d7978a92696387c3da6"}, {file = "pydantic_core-2.46.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ced3310e51aa425f7f77da8bbbb5212616655bedbe82c70944320bc1dbe5e018"},
{file = "pydantic_core-2.46.2-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d12d786e30c04a9d307c5d7080bf720d9bac7f1668191d8e37633a9562749e2"}, {file = "pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e29908922ce9da1a30b4da490bd1d3d82c01dcfdf864d2a74aacee674d0bfa34"},
{file = "pydantic_core-2.46.2-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0d5e6d6343b0b5dcacb3503b5de90022968da8ed0ab9ab39d3eda71c20cbf84e"}, {file = "pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0c9ff69140423eea8ed2d5477df3ba037f671f5e897d206d921bc9fdc39613e7"},
{file = "pydantic_core-2.46.2-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:233eebac0999b6b9ba76eb56f3ec8fce13164aa16b6d2225a36a79e0f95b5973"}, {file = "pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b675ab0a0d5b1c8fdb81195dc5bcefea3f3c240871cdd7ff9a2de8aa50772eb2"},
{file = "pydantic_core-2.46.2-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cc0eee720dd2f14f3b7c349469402b99ad81a174ab49d3533974529e9d93992"}, {file = "pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0087084960f209a9a4af50ecd1fb063d9ad3658c07bb81a7a53f452dacbfb2ba"},
{file = "pydantic_core-2.46.2-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83ee76bf2c9910513dbc19e7d82367131fa7508dedd6186a462393071cc11059"}, {file = "pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed42e6cc8e1b0e2b9b96e2276bad70ae625d10d6d524aed0c93de974ae029f9f"},
{file = "pydantic_core-2.46.2-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:d61db38eb4ee5192f0c261b7f2d38e420b554df8912245e3546aee5c45e2fd78"}, {file = "pydantic_core-2.46.3-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:f1771ce258afb3e4201e67d154edbbae712a76a6081079fe247c2f53c6322c22"},
{file = "pydantic_core-2.46.2-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8f09a713d17bcd55da8ab02ebd9110c5246a49c44182af213b5212800af8bc83"}, {file = "pydantic_core-2.46.3-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a7610b6a5242a6c736d8ad47fd5fff87fcfe8f833b281b1c409c3d6835d9227f"},
{file = "pydantic_core-2.46.2-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:30cacc5fb696e64b8ef6fd31d9549d394dd7d52760db072eecb98e37e3af1677"}, {file = "pydantic_core-2.46.3-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:ff5e7783bcc5476e1db448bf268f11cb257b1c276d3e89f00b5727be86dd0127"},
{file = "pydantic_core-2.46.2-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:7ccfb105fcfe91a22bbb5563ad3dc124bc1aa75bfd2e53a780ab05f78cdf6108"}, {file = "pydantic_core-2.46.3-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:9d2e32edcc143bc01e95300671915d9ca052d4f745aa0a49c48d4803f8a85f2c"},
{file = "pydantic_core-2.46.2-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:13ffef637dc8370c249e5b26bd18e9a80a4fca3d809618c44e18ec834a7ca7a8"}, {file = "pydantic_core-2.46.3-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:6e42d83d1c6b87fa56b521479cff237e626a292f3b31b6345c15a99121b454c1"},
{file = "pydantic_core-2.46.2-cp314-cp314-win32.whl", hash = "sha256:1b0ab6d756ca2704a938e6c31b53f290c2f9c10d3914235410302a149de1a83e"}, {file = "pydantic_core-2.46.3-cp314-cp314-win32.whl", hash = "sha256:07bc6d2a28c3adb4f7c6ae46aa4f2d2929af127f587ed44057af50bf1ce0f505"},
{file = "pydantic_core-2.46.2-cp314-cp314-win_amd64.whl", hash = "sha256:99ebade8c9ada4df975372d8dd25883daa0e379a05f1cd0c99aa0c04368d01a6"}, {file = "pydantic_core-2.46.3-cp314-cp314-win_amd64.whl", hash = "sha256:8940562319bc621da30714617e6a7eaa6b98c84e8c685bcdc02d7ed5e7c7c44e"},
{file = "pydantic_core-2.46.2-cp314-cp314-win_arm64.whl", hash = "sha256:de87422197cf7f83db91d89c86a21660d749b3cd76cd8a45d115b8e675670f02"}, {file = "pydantic_core-2.46.3-cp314-cp314-win_arm64.whl", hash = "sha256:5dcbbcf4d22210ced8f837c96db941bdb078f419543472aca5d9a0bb7cddc7df"},
{file = "pydantic_core-2.46.2-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:236f22b4a206b5b61db955396b7cf9e2e1ff77f372efe9570128ccfcd6a525eb"}, {file = "pydantic_core-2.46.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:d0fe3dce1e836e418f912c1ad91c73357d03e556a4d286f441bf34fed2dbeecf"},
{file = "pydantic_core-2.46.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c2012f64d2cd7cca50f49f22445aa5a88691ac2b4498ee0a9a977f8ca4f7289f"}, {file = "pydantic_core-2.46.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9ce92e58abc722dac1bf835a6798a60b294e48eb0e625ec9fd994b932ac5feee"},
{file = "pydantic_core-2.46.2-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d07d6c63106d3a9c9a333e2636f9c82c703b1a9e3b079299e58747964e4fdb72"}, {file = "pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a03e6467f0f5ab796a486146d1b887b2dc5e5f9b3288898c1b1c3ad974e53e4a"},
{file = "pydantic_core-2.46.2-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c326a2b4b85e959d9a1fc3a11f32f84611b6ec07c053e1828a860edf8d068208"}, {file = "pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2798b6ba041b9d70acfb9071a2ea13c8456dd1e6a5555798e41ba7b0790e329c"},
{file = "pydantic_core-2.46.2-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac8a65e798f2462552c00d2e013d532c94d646729dda98458beaf51f9ec7b120"}, {file = "pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9be3e221bdc6d69abf294dcf7aff6af19c31a5cdcc8f0aa3b14be29df4bd03b1"},
{file = "pydantic_core-2.46.2-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a3c2bc1cc8164bedbc160b7bb1e8cc1e8b9c27f69ae4f9ae2b976cdae02b2dd"}, {file = "pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f13936129ce841f2a5ddf6f126fea3c43cd128807b5a59588c37cf10178c2e64"},
{file = "pydantic_core-2.46.2-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e69aa5e10b7e8b1bb4a6888650fd12fcbf11d396ca11d4a44de1450875702830"}, {file = "pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28b5f2ef03416facccb1c6ef744c69793175fd27e44ef15669201601cf423acb"},
{file = "pydantic_core-2.46.2-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:4e6df5c3301e65fb42bc5338bf9a1027a02b0a31dc7f54c33775229af474daf0"}, {file = "pydantic_core-2.46.3-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:830d1247d77ad23852314f069e9d7ddafeec5f684baf9d7e7065ed46a049c4e6"},
{file = "pydantic_core-2.46.2-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2c2f6e32548ac8d559b47944effcf8ae4d81c161f6b6c885edc53bc08b8f192d"}, {file = "pydantic_core-2.46.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0793c90c1a3c74966e7975eaef3ed30ebdff3260a0f815a62a22adc17e4c01c"},
{file = "pydantic_core-2.46.2-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:b089a81c58e6ea0485562bbbbbca4f65c0549521606d5ef27fba217aac9b665a"}, {file = "pydantic_core-2.46.3-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:d2d0aead851b66f5245ec0c4fb2612ef457f8bbafefdf65a2bf9d6bac6140f47"},
{file = "pydantic_core-2.46.2-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:7f700a6d6f64112ae9193709b84303bbab84424ad4b47d0253301aabce9dfc70"}, {file = "pydantic_core-2.46.3-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:2f40e4246676beb31c5ce77c38a55ca4e465c6b38d11ea1bd935420568e0b1ab"},
{file = "pydantic_core-2.46.2-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:67db6814beaa5fefe91101ec7eb9efda613795767be96f7cf58b1ca8c9ca9972"}, {file = "pydantic_core-2.46.3-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:cf489cf8986c543939aeee17a09c04d6ffb43bfef8ca16fcbcc5cfdcbed24dba"},
{file = "pydantic_core-2.46.2-cp314-cp314t-win32.whl", hash = "sha256:32fbc7447be8e3be99bf7869f7066308f16be55b61f9882c2cefc7931f5c7664"}, {file = "pydantic_core-2.46.3-cp314-cp314t-win32.whl", hash = "sha256:ffe0883b56cfc05798bf994164d2b2ff03efe2d22022a2bb080f3b626176dd56"},
{file = "pydantic_core-2.46.2-cp314-cp314t-win_amd64.whl", hash = "sha256:b317a2b97019c0b95ce99f4f901ae383f40132da6706cdf1731066a73394c25c"}, {file = "pydantic_core-2.46.3-cp314-cp314t-win_amd64.whl", hash = "sha256:706d9d0ce9cf4593d07270d8e9f53b161f90c57d315aeec4fb4fd7a8b10240d8"},
{file = "pydantic_core-2.46.2-cp314-cp314t-win_arm64.whl", hash = "sha256:7dcb9d40930dfad7ab6b20bcc6ca9d2b030b0f347a0cd9909b54bd53ead521b1"}, {file = "pydantic_core-2.46.3-cp314-cp314t-win_arm64.whl", hash = "sha256:77706aeb41df6a76568434701e0917da10692da28cb69d5fb6919ce5fdb07374"},
{file = "pydantic_core-2.46.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:33741359798f9dc3d4244a66031575d8a86c004f7853eb9961a49e4b6fab2d0b"}, {file = "pydantic_core-2.46.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:fa3eb7c2995aa443687a825bc30395c8521b7c6ec201966e55debfd1128bcceb"},
{file = "pydantic_core-2.46.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f557ce9106850c79252792962d78b987e11fcdc10e5c2252443b9a485d3bfe5"}, {file = "pydantic_core-2.46.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3d08782c4045f90724b44c95d35ebec0d67edb8a957a2ac81d5a8e4b8a200495"},
{file = "pydantic_core-2.46.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd195af20e53aaac6cf5d7862e34dfdf86351720c858581ccb6563e02ae59421"}, {file = "pydantic_core-2.46.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:831eb19aa789a97356979e94c981e5667759301fb708d1c0d5adf1bc0098b873"},
{file = "pydantic_core-2.46.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5a8e486d238850ddf2b25739317b6551d5bef9925ab004b18c552ff6e645f8a2"}, {file = "pydantic_core-2.46.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4335e87c7afa436a0dfa899e138d57a72f8aad542e2cf19c36fb428461caabd0"},
{file = "pydantic_core-2.46.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dfff584138be087457cc474791d082fdfe32b0d427613d5494a679fe9f4eaef5"}, {file = "pydantic_core-2.46.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99421e7684a60f7f3550a1d159ade5fdff1954baedb6bdd407cba6a307c9f27d"},
{file = "pydantic_core-2.46.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:387cbe2b2bcace397da91f9b1165a9e75da254bb306b876a43b824cc10f49ce0"}, {file = "pydantic_core-2.46.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd81f6907932ebac3abbe41378dac64b2380db1287e2aa64d8d88f78d170f51a"},
{file = "pydantic_core-2.46.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a6572f3238851fde28b3194ef98cec9dbe66f1614caf4646239ea87f324121a"}, {file = "pydantic_core-2.46.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f247596366f4221af52beddd65af1218797771d6989bc891a0b86ccaa019168"},
{file = "pydantic_core-2.46.2-cp39-cp39-manylinux_2_31_riscv64.whl", hash = "sha256:b478652b580cd4cf7f2dd40dc9fde594ed1c84e5df4bafefffb8387ddb74049f"}, {file = "pydantic_core-2.46.3-cp39-cp39-manylinux_2_31_riscv64.whl", hash = "sha256:6dff8cc884679df229ebc6d8eb2321ea6f8e091bc7d4886d4dc2e0e71452843c"},
{file = "pydantic_core-2.46.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7b1c9bdca33968c0dcd875f8185b3b6275df753fe000178684b0c1738959f3cd"}, {file = "pydantic_core-2.46.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68ef2f623dda6d5a9067ac014e406c020c780b2a358930a7e5c1b73702900720"},
{file = "pydantic_core-2.46.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e698fe2d8f75c4e9368ee3f4e0d3322d1180be2ec4592d3f73b2572765b1c705"}, {file = "pydantic_core-2.46.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d56bdb4af1767cc15b0386b3c581fdfe659bb9ee4a4f776e92c1cd9d074000d6"},
{file = "pydantic_core-2.46.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:404da669e5e02bf7fb2cc56715a609f63af88aea531287494467109f97865fe3"}, {file = "pydantic_core-2.46.3-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:91249bcb7c165c2fb2a2f852dbc5c91636e2e218e75d96dfdd517e4078e173dd"},
{file = "pydantic_core-2.46.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:28708faed0b47f9d68906551a3471421ab0b15c31519e08fdb70ae6cad04d10b"}, {file = "pydantic_core-2.46.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4b068543bdb707f5d935dab765d99227aa2545ef2820935f2e5dd801795c7dbd"},
{file = "pydantic_core-2.46.2-cp39-cp39-win32.whl", hash = "sha256:5e2b4adb0fa46a842c492423e61063d6639cf9aea56380a02630ddcdd4894067"}, {file = "pydantic_core-2.46.3-cp39-cp39-win32.whl", hash = "sha256:dcda6583921c05a40533f982321532f2d8db29326c7b95c4026941fa5074bd79"},
{file = "pydantic_core-2.46.2-cp39-cp39-win_amd64.whl", hash = "sha256:fa8ab79cea8a1bfe52a21a9b37859c15478d009f242f47737201ecea885b9dd9"}, {file = "pydantic_core-2.46.3-cp39-cp39-win_amd64.whl", hash = "sha256:a35cc284c8dd7edae8a31533713b4d2467dfe7c4f1b5587dd4031f28f90d1d13"},
{file = "pydantic_core-2.46.2-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:7c5a5b3dbb9e8918e223be6580da5ffcf861c0505bbc196ebed7176ce05b7b4e"}, {file = "pydantic_core-2.46.3-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:9715525891ed524a0a1eb6d053c74d4d4ad5017677fb00af0b7c2644a31bae46"},
{file = "pydantic_core-2.46.2-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:bc1e8ce33d5a337f2ba862e0719b8201cd54aaed967406c748e009191d47efdd"}, {file = "pydantic_core-2.46.3-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:9d2f400712a99a013aff420ef1eb9be077f8189a36c1e3ef87660b4e1088a874"},
{file = "pydantic_core-2.46.2-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b737c0b280f41143266445de2689c0e49c79307e51c44ce3a77fef2bedad4994"}, {file = "pydantic_core-2.46.3-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd2aab0e2e9dc2daf36bd2686c982535d5e7b1d930a1344a7bb6e82baab42a76"},
{file = "pydantic_core-2.46.2-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b877d597afb82b4898e35354bba55de6f7f048421ae0edadbb9886ec137b532"}, {file = "pydantic_core-2.46.3-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e9d76736da5f362fabfeea6a69b13b7f2be405c6d6966f06b2f6bfff7e64531"},
{file = "pydantic_core-2.46.2-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:e9fcabd1857492b5bf16f90258babde50f618f55d046b1309972da2396321ff9"}, {file = "pydantic_core-2.46.3-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:b12dd51f1187c2eb489af8e20f880362db98e954b54ab792fa5d92e8bcc6b803"},
{file = "pydantic_core-2.46.2-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:fb3ec2c7f54c07b30d89983ce78dc32c37dd06a972448b8716d609493802d628"}, {file = "pydantic_core-2.46.3-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:f00a0961b125f1a47af7bcc17f00782e12f4cd056f83416006b30111d941dfa3"},
{file = "pydantic_core-2.46.2-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130a6c837d819ef33e8c2bf702ed2c3429237ea69807f1140943d6f4bdaf52fa"}, {file = "pydantic_core-2.46.3-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57697d7c056aca4bbb680200f96563e841a6386ac1129370a0102592f4dddff5"},
{file = "pydantic_core-2.46.2-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2e25417cec5cd9bddb151e33cb08c50160f317479ecc02b22a95ec18f8fe004"}, {file = "pydantic_core-2.46.3-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd35aa21299def8db7ef4fe5c4ff862941a9a158ca7b63d61e66fe67d30416b4"},
{file = "pydantic_core-2.46.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c3ad79ed32004d9de91cacd4b5faaff44d56051392fe1d5526feda596f01af25"}, {file = "pydantic_core-2.46.3-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:13afdd885f3d71280cf286b13b310ee0f7ccfefd1dbbb661514a474b726e2f25"},
{file = "pydantic_core-2.46.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d157c48d28eebe5d46906de06a6a2f2c9e00b67d3e42de1f1b9c2d42b810f77c"}, {file = "pydantic_core-2.46.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f91c0aff3e3ee0928edd1232c57f643a7a003e6edf1860bc3afcdc749cb513f3"},
{file = "pydantic_core-2.46.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b42c6471288dedc979ac8400d9c9770f03967dd187db1f8d3405d4d182cc714"}, {file = "pydantic_core-2.46.3-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6529d1d128321a58d30afcc97b49e98836542f68dd41b33c2e972bb9e5290536"},
{file = "pydantic_core-2.46.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4f27bc4801358dc070d6697b41237fce9923d8e69a1ce1e95606ac36c1552dc1"}, {file = "pydantic_core-2.46.3-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:975c267cff4f7e7272eacbe50f6cc03ca9a3da4c4fbd66fffd89c94c1e311aa1"},
{file = "pydantic_core-2.46.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e094a8f85db41aa7f6a45c5dac2950afc9862e66832934231962252b5d284eed"}, {file = "pydantic_core-2.46.3-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:2b8e4f2bbdf71415c544b4b1138b8060db7b6611bc927e8064c769f64bed651c"},
{file = "pydantic_core-2.46.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:807eeda5551f6884d3b4421578be37be50ddb7a58832348e99617a6714a73748"}, {file = "pydantic_core-2.46.3-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:e61ea8e9fff9606d09178f577ff8ccdd7206ff73d6552bcec18e1033c4254b85"},
{file = "pydantic_core-2.46.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fcaa1c3c846a7f6686b38fe493d1b2e8007380e293bfef6a9354563c026cbf36"}, {file = "pydantic_core-2.46.3-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b504bda01bafc69b6d3c7a0c7f039dcf60f47fab70e06fe23f57b5c75bdc82b8"},
{file = "pydantic_core-2.46.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:154dbfdfb11b8cbd8ff4d00d0b81e3d19f4cb4bedd5aa9f091060ba071474c6a"}, {file = "pydantic_core-2.46.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:b00b76f7142fc60c762ce579bd29c8fa44aaa56592dd3c54fab3928d0d4ca6ff"},
{file = "pydantic_core-2.46.2.tar.gz", hash = "sha256:37bb079f9ee3f1a519392b73fda2a96379b31f2013c6b467fe693e7f2987f596"}, {file = "pydantic_core-2.46.3.tar.gz", hash = "sha256:41c178f65b8c29807239d47e6050262eb6bf84eb695e41101e62e38df4a5bc2c"},
] ]
[package.dependencies] [package.dependencies]
@@ -1984,4 +2043,4 @@ type = ["pytest-mypy"]
[metadata] [metadata]
lock-version = "2.1" lock-version = "2.1"
python-versions = ">=3.10,<4" python-versions = ">=3.10,<4"
content-hash = "5f36b0c7eaace34b3c91fb3cae711fb3f6b38dbfd604ce0d0f9ef102cddb73ba" content-hash = "a6c8f4724724200e183e448094d277a866c529e9afe622e340c8ba2521d0d8c4"

View File

@@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "openbb-cftc" name = "openbb-cftc"
version = "1.3.0" version = "1.4.0"
description = "The mission of the Commodity Futures Trading Commission (CFTC) is to promote the integrity, resilience, and vibrancy of the U.S. derivatives markets through sound regulation." description = "The mission of the Commodity Futures Trading Commission (CFTC) is to promote the integrity, resilience, and vibrancy of the U.S. derivatives markets through sound regulation."
authors = ["OpenBB Team <hello@openbb.co>"] authors = ["OpenBB Team <hello@openbb.co>"]
license = "AGPL-3.0-only" license = "AGPL-3.0-only"
@@ -9,7 +9,8 @@ packages = [{ include = "openbb_cftc" }]
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = ">=3.10,<4" python = ">=3.10,<4"
openbb-core = "^1.6.3" openbb-core = "^1.6.7"
openbb-platform-api = "^1.3.5"
[build-system] [build-system]
requires = ["poetry-core"] requires = ["poetry-core"]
@@ -17,3 +18,6 @@ build-backend = "poetry.core.masonry.api"
[tool.poetry.plugins."openbb_provider_extension"] [tool.poetry.plugins."openbb_provider_extension"]
cftc = "openbb_cftc:cftc_provider" cftc = "openbb_cftc:cftc_provider"
[tool.poetry.plugins."openbb_core_extension"]
cftc = "openbb_cftc.cftc_router:router"

View File

@@ -34,8 +34,6 @@ interactions:
headers: headers:
Access-Control-Allow-Origin: Access-Control-Allow-Origin:
- '*' - '*'
Age:
- '0'
Connection: Connection:
- keep-alive - keep-alive
Content-Encoding: Content-Encoding:
@@ -43,10 +41,10 @@ interactions:
Content-Type: Content-Type:
- application/json;charset=utf-8 - application/json;charset=utf-8
Date: Date:
- Thu, 05 Sep 2024 18:48:26 GMT - Thu, 02 Apr 2026 04:20:30 GMT
Etag: null Etag: null
Last-Modified: Last-Modified:
- Fri, 30 Aug 2024 19:30:46 GMT - Fri, 27 Mar 2026 19:31:05 GMT
Server: Server:
- nginx - nginx
Strict-Transport-Security: Strict-Transport-Security:
@@ -60,9 +58,9 @@ interactions:
X-SODA2-Fields: X-SODA2-Fields:
- '["id","market_and_exchange_names","report_date_as_yyyy_mm_dd","yyyy_report_week_ww","contract_market_name","cftc_contract_market_code","cftc_market_code","cftc_region_code","cftc_commodity_code","commodity_name","open_interest_all","noncomm_positions_long_all","noncomm_positions_short_all","noncomm_postions_spread_all","comm_positions_long_all","comm_positions_short_all","tot_rept_positions_long_all","tot_rept_positions_short","nonrept_positions_long_all","nonrept_positions_short_all","open_interest_old","noncomm_positions_long_old","noncomm_positions_short_old","noncomm_positions_spread","comm_positions_long_old","comm_positions_short_old","tot_rept_positions_long_old","tot_rept_positions_short_1","nonrept_positions_long_old","nonrept_positions_short_old","open_interest_other","noncomm_positions_long_other","noncomm_positions_short_other","noncomm_positions_spread_1","comm_positions_long_other","comm_positions_short_other","tot_rept_positions_long_other","tot_rept_positions_short_2","nonrept_positions_long_other","nonrept_positions_short_other","change_in_open_interest_all","change_in_noncomm_long_all","change_in_noncomm_short_all","change_in_noncomm_spead_all","change_in_comm_long_all","change_in_comm_short_all","change_in_tot_rept_long_all","change_in_tot_rept_short","change_in_nonrept_long_all","change_in_nonrept_short_all","pct_of_open_interest_all","pct_of_oi_noncomm_long_all","pct_of_oi_noncomm_short_all","pct_of_oi_noncomm_spread","pct_of_oi_comm_long_all","pct_of_oi_comm_short_all","pct_of_oi_tot_rept_long_all","pct_of_oi_tot_rept_short","pct_of_oi_nonrept_long_all","pct_of_oi_nonrept_short_all","pct_of_open_interest_old","pct_of_oi_noncomm_long_old","pct_of_oi_noncomm_short_old","pct_of_oi_noncomm_spread_1","pct_of_oi_comm_long_old","pct_of_oi_comm_short_old","pct_of_oi_tot_rept_long_old","pct_of_oi_tot_rept_short_1","pct_of_oi_nonrept_long_old","pct_of_oi_nonrept_short_old","pct_of_open_interest_other","pct_of_oi_noncomm_long_other","pct_of_oi_noncomm_short_other","pct_of_oi_noncomm_spread_2","pct_of_oi_comm_long_other","pct_of_oi_comm_short_other","pct_of_oi_tot_rept_long_other","pct_of_oi_tot_rept_short_2","pct_of_oi_nonrept_long_other","pct_of_oi_nonrept_short_other","traders_tot_all","traders_noncomm_long_all","traders_noncomm_short_all","traders_noncomm_spread_all","traders_comm_long_all","traders_comm_short_all","traders_tot_rept_long_all","traders_tot_rept_short_all","traders_tot_old","traders_noncomm_long_old","traders_noncomm_short_old","traders_noncomm_spead_old","traders_comm_long_old","traders_comm_short_old","traders_tot_rept_long_old","traders_tot_rept_short_old","traders_tot_other","traders_noncomm_long_other","traders_noncomm_short_other","traders_noncomm_spread_other","traders_comm_long_other","traders_comm_short_other","traders_tot_rept_long_other","traders_tot_rept_short_other","conc_gross_le_4_tdr_long","conc_gross_le_4_tdr_short","conc_gross_le_8_tdr_long","conc_gross_le_8_tdr_short","conc_net_le_4_tdr_long_all","conc_net_le_4_tdr_short_all","conc_net_le_8_tdr_long_all","conc_net_le_8_tdr_short_all","conc_gross_le_4_tdr_long_1","conc_gross_le_4_tdr_short_1","conc_gross_le_8_tdr_long_1","conc_gross_le_8_tdr_short_1","conc_net_le_4_tdr_long_old","conc_net_le_4_tdr_short_old","conc_net_le_8_tdr_long_old","conc_net_le_8_tdr_short_old","conc_gross_le_4_tdr_long_2","conc_gross_le_4_tdr_short_2","conc_gross_le_8_tdr_long_2","conc_gross_le_8_tdr_short_2","conc_net_le_4_tdr_long_other","conc_net_le_4_tdr_short_other","conc_net_le_8_tdr_long_other","conc_net_le_8_tdr_short_other","contract_units","commodity","commodity_subgroup_name","commodity_group_name","futonly_or_combined"]' - '["id","market_and_exchange_names","report_date_as_yyyy_mm_dd","yyyy_report_week_ww","contract_market_name","cftc_contract_market_code","cftc_market_code","cftc_region_code","cftc_commodity_code","commodity_name","open_interest_all","noncomm_positions_long_all","noncomm_positions_short_all","noncomm_postions_spread_all","comm_positions_long_all","comm_positions_short_all","tot_rept_positions_long_all","tot_rept_positions_short","nonrept_positions_long_all","nonrept_positions_short_all","open_interest_old","noncomm_positions_long_old","noncomm_positions_short_old","noncomm_positions_spread","comm_positions_long_old","comm_positions_short_old","tot_rept_positions_long_old","tot_rept_positions_short_1","nonrept_positions_long_old","nonrept_positions_short_old","open_interest_other","noncomm_positions_long_other","noncomm_positions_short_other","noncomm_positions_spread_1","comm_positions_long_other","comm_positions_short_other","tot_rept_positions_long_other","tot_rept_positions_short_2","nonrept_positions_long_other","nonrept_positions_short_other","change_in_open_interest_all","change_in_noncomm_long_all","change_in_noncomm_short_all","change_in_noncomm_spead_all","change_in_comm_long_all","change_in_comm_short_all","change_in_tot_rept_long_all","change_in_tot_rept_short","change_in_nonrept_long_all","change_in_nonrept_short_all","pct_of_open_interest_all","pct_of_oi_noncomm_long_all","pct_of_oi_noncomm_short_all","pct_of_oi_noncomm_spread","pct_of_oi_comm_long_all","pct_of_oi_comm_short_all","pct_of_oi_tot_rept_long_all","pct_of_oi_tot_rept_short","pct_of_oi_nonrept_long_all","pct_of_oi_nonrept_short_all","pct_of_open_interest_old","pct_of_oi_noncomm_long_old","pct_of_oi_noncomm_short_old","pct_of_oi_noncomm_spread_1","pct_of_oi_comm_long_old","pct_of_oi_comm_short_old","pct_of_oi_tot_rept_long_old","pct_of_oi_tot_rept_short_1","pct_of_oi_nonrept_long_old","pct_of_oi_nonrept_short_old","pct_of_open_interest_other","pct_of_oi_noncomm_long_other","pct_of_oi_noncomm_short_other","pct_of_oi_noncomm_spread_2","pct_of_oi_comm_long_other","pct_of_oi_comm_short_other","pct_of_oi_tot_rept_long_other","pct_of_oi_tot_rept_short_2","pct_of_oi_nonrept_long_other","pct_of_oi_nonrept_short_other","traders_tot_all","traders_noncomm_long_all","traders_noncomm_short_all","traders_noncomm_spread_all","traders_comm_long_all","traders_comm_short_all","traders_tot_rept_long_all","traders_tot_rept_short_all","traders_tot_old","traders_noncomm_long_old","traders_noncomm_short_old","traders_noncomm_spead_old","traders_comm_long_old","traders_comm_short_old","traders_tot_rept_long_old","traders_tot_rept_short_old","traders_tot_other","traders_noncomm_long_other","traders_noncomm_short_other","traders_noncomm_spread_other","traders_comm_long_other","traders_comm_short_other","traders_tot_rept_long_other","traders_tot_rept_short_other","conc_gross_le_4_tdr_long","conc_gross_le_4_tdr_short","conc_gross_le_8_tdr_long","conc_gross_le_8_tdr_short","conc_net_le_4_tdr_long_all","conc_net_le_4_tdr_short_all","conc_net_le_8_tdr_long_all","conc_net_le_8_tdr_short_all","conc_gross_le_4_tdr_long_1","conc_gross_le_4_tdr_short_1","conc_gross_le_8_tdr_long_1","conc_gross_le_8_tdr_short_1","conc_net_le_4_tdr_long_old","conc_net_le_4_tdr_short_old","conc_net_le_8_tdr_long_old","conc_net_le_8_tdr_short_old","conc_gross_le_4_tdr_long_2","conc_gross_le_4_tdr_short_2","conc_gross_le_8_tdr_long_2","conc_gross_le_8_tdr_short_2","conc_net_le_4_tdr_long_other","conc_net_le_4_tdr_short_other","conc_net_le_8_tdr_long_other","conc_net_le_8_tdr_short_other","contract_units","commodity","commodity_subgroup_name","commodity_group_name","futonly_or_combined"]'
X-SODA2-Secondary-Last-Modified: X-SODA2-Secondary-Last-Modified:
- Fri, 30 Aug 2024 19:30:46 GMT - Fri, 27 Mar 2026 19:31:05 GMT
X-SODA2-Truth-Last-Modified: X-SODA2-Truth-Last-Modified:
- Fri, 30 Aug 2024 19:30:46 GMT - Fri, 27 Mar 2026 19:31:05 GMT
X-SODA2-Types: X-SODA2-Types:
- '["text","text","floating_timestamp","text","text","text","text","text","text","text","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","text","text","text","text","text"]' - '["text","text","floating_timestamp","text","text","text","text","text","text","text","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","number","text","text","text","text","text"]'
X-Socrata-Region: null X-Socrata-Region: null

View File

@@ -0,0 +1,60 @@
interactions:
- request:
body: null
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
method: GET
uri: https://publicreporting.cftc.gov/resource/jun7-fc8e.json?%24group=cftc_contract_market_code%2Ccontract_market_name%2Ccommodity_name%2Ccommodity_group_name%2Ccommodity_subgroup_name%2Ccontract_units&%24limit=MOCK_LIMIT&%24order=MOCK_ORDER&%24select=cftc_contract_market_code%2Ccontract_market_name%2Ccommodity_name%2Ccommodity_group_name%2Ccommodity_subgroup_name%2Ccontract_units&%24where=MOCK_WHERE
response:
body:
string: !!binary |
H4sIAAAAAAAAANWUUU+DMBSF3/crGmKMxmk6HdH41tGaVFlxpeiMMQsCGqKAgZJojP/dwsSMCRvZ
i/rY3Ht6T7+e9vZd8x6kN/OSWKauJ2eRmz4FUq39QDvVBkcnx8Nrra8t12M3KuoInzu2IBhQJgBH
ggB7+xLoEAJhCbPURVHih/KtUhT1EbcQBiNkK6EtLONCyTE1iF0TPKZJ/lLJzihDzKDIVK224M6Y
MFFvz/L7muLnxl8nyONQZqphZ8Gq2pcT4XBWCMgUvIKtQ31X++j1V/MZFnxQO59qBGLMUTMwvaKY
MDyf0oRnseP3iDTaBdMCCuxApUzN3noqRhJnyXPouzLw/0lWvkno8AB2YVEmZLKexcRBXBBu3tSo
/92INPudsxlA2DEkK54O2R9TRqv/ZLN4LJtXt6b81e6ya5yddqdjanAL1P22v/BNXDeYvut9AmVI
m0G7BQAA
headers:
Access-Control-Allow-Origin:
- '*'
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json;charset=utf-8
Date:
- Thu, 02 Apr 2026 04:20:30 GMT
Etag: null
Last-Modified:
- Fri, 27 Mar 2026 19:31:05 GMT
Server:
- nginx
Strict-Transport-Security:
- max-age=31536000; includeSubDomains
Transfer-Encoding:
- chunked
Vary:
- Accept-Encoding
X-SODA2-Data-Out-Of-Date:
- 'false'
X-SODA2-Fields:
- '["cftc_contract_market_code","contract_market_name","commodity_name","commodity_group_name","commodity_subgroup_name","contract_units"]'
X-SODA2-Secondary-Last-Modified:
- Fri, 27 Mar 2026 19:31:05 GMT
X-SODA2-Truth-Last-Modified:
- Fri, 27 Mar 2026 19:31:05 GMT
X-SODA2-Types:
- '["text","text","text","text","text","text"]'
X-Socrata-Region: null
X-Socrata-RequestId: null
status:
code: 200
message: OK
version: 1

View File

@@ -45,7 +45,7 @@ def vcr_config():
def test_cftc_cot_fetcher(credentials=test_credentials): def test_cftc_cot_fetcher(credentials=test_credentials):
"""Test the CFTC COT fetcher.""" """Test the CFTC COT fetcher."""
params = { params = {
"id": "239747", "code": "239747",
"start_date": date(2024, 8, 19), "start_date": date(2024, 8, 19),
"end_date": date(2024, 8, 21), "end_date": date(2024, 8, 21),
} }
@@ -55,7 +55,7 @@ def test_cftc_cot_fetcher(credentials=test_credentials):
assert result is None assert result is None
# The data for this request are local files, so we can't record them. @pytest.mark.record_http
def test_cftc_cot_sarch_fetcher(credentials=test_credentials): def test_cftc_cot_sarch_fetcher(credentials=test_credentials):
"""Test the CFTC COT Search fetcher.""" """Test the CFTC COT Search fetcher."""
params = {"query": "S&P 500"} params = {"query": "S&P 500"}

View File

@@ -6,16 +6,18 @@ from typing import Any
from openbb_core.provider.abstract.data import Data from openbb_core.provider.abstract.data import Data
from openbb_core.provider.abstract.fetcher import Fetcher from openbb_core.provider.abstract.fetcher import Fetcher
from openbb_core.provider.standard_models.cot_search import CotSearchQueryParams from openbb_core.provider.abstract.query_params import QueryParams
from pydantic import Field from pydantic import Field
class SecInstitutionsSearchQueryParams(CotSearchQueryParams): class SecInstitutionsSearchQueryParams(QueryParams):
"""SEC Institutions Search Query. """SEC Institutions Search Query.
Source: https://sec.gov/ Source: https://sec.gov/
""" """
query: str = Field(description="Search query.", default="")
use_cache: bool | None = Field( use_cache: bool | None = Field(
default=True, default=True,
description="Whether or not to use cache.", description="Whether or not to use cache.",

View File

@@ -6,16 +6,19 @@ from typing import Any
from openbb_core.provider.abstract.data import Data from openbb_core.provider.abstract.data import Data
from openbb_core.provider.abstract.fetcher import Fetcher from openbb_core.provider.abstract.fetcher import Fetcher
from openbb_core.provider.standard_models.cot_search import CotSearchQueryParams from openbb_core.provider.abstract.query_params import QueryParams
from pydantic import Field from pydantic import Field
class SecSicSearchQueryParams(CotSearchQueryParams): class SecSicSearchQueryParams(QueryParams):
"""SEC Standard Industrial Classification Code (SIC) Query. """SEC Standard Industrial Classification Code (SIC) Query.
Source: https://sec.gov/ Source: https://sec.gov/
""" """
query: str = Field(
description="Search query to match against SIC code, industry title, or office."
)
use_cache: bool | None = Field( use_cache: bool | None = Field(
default=True, default=True,
description="Whether or not to use cache.", description="Whether or not to use cache.",

View File

@@ -15,7 +15,7 @@ openbb-platform-api = "^1.3.5"
openbb-benzinga = "^1.6.0" openbb-benzinga = "^1.6.0"
openbb-bls = "^1.3.0" openbb-bls = "^1.3.0"
openbb-cftc = "^1.3.0" openbb-cftc = "^1.4.0"
openbb-congress-gov = "^1.2.2" openbb-congress-gov = "^1.2.2"
openbb-econdb = "^1.5.0" openbb-econdb = "^1.5.0"
openbb-federal-reserve = "^1.6.1" openbb-federal-reserve = "^1.6.1"