openbb-aurastream 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ # Publishes to PyPI when a GitHub release is published, using PyPI trusted publishing (no token stored here).
2
+ name: Publish to PyPI
3
+
4
+ on:
5
+ release:
6
+ types: [published]
7
+
8
+ jobs:
9
+ publish:
10
+ runs-on: ubuntu-latest
11
+ environment: pypi
12
+ permissions:
13
+ id-token: write
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-python@v5
17
+ with:
18
+ python-version: "3.12"
19
+ - run: python -m pip install --upgrade build
20
+ - run: python -m build
21
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,18 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with:
15
+ python-version: "3.12"
16
+ - run: python -m pip install openbb -e ".[test]"
17
+ - run: python -c "import openbb; openbb.build()"
18
+ - run: python -m pytest -q
@@ -0,0 +1,5 @@
1
+ .venv/
2
+ __pycache__/
3
+ dist/
4
+ *.egg-info/
5
+ .pytest_cache/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Unbiased Alpha
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,108 @@
1
+ Metadata-Version: 2.5
2
+ Name: openbb-aurastream
3
+ Version: 0.1.0
4
+ Summary: AuraStream data for the OpenBB Platform: EU net short positions, USDA WASDE, FRED vintages, SEC fails-to-deliver and Binance funding rates.
5
+ Project-URL: Homepage, https://aurastream.unbiased-alpha.com
6
+ Project-URL: Documentation, https://aurastream.unbiased-alpha.com/docs/
7
+ Project-URL: Source, https://github.com/UnbiasedAlpha/openbb-aurastream
8
+ Author: Unbiased Alpha
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: aurastream,fred,market data,openbb,quant,short selling,wasde
12
+ Requires-Python: >=3.10
13
+ Requires-Dist: aiohttp>=3.9
14
+ Requires-Dist: openbb-core<3,>=2.0
15
+ Provides-Extra: test
16
+ Requires-Dist: pytest>=8; extra == 'test'
17
+ Description-Content-Type: text/markdown
18
+
19
+ # openbb-aurastream
20
+
21
+ [AuraStream](https://aurastream.unbiased-alpha.com) data for the [OpenBB Platform](https://github.com/OpenBB-finance/OpenBB). The extension adds five commands under `obb.aurastream`. Each covers a dataset that the other OpenBB providers don't offer:
22
+
23
+ | Command | Data |
24
+ |---|---|
25
+ | `net_short` | EU net short positions of 0.5% or more, with the holder's name, from the French (AMF), Dutch (AFM) and Spanish (CNMV) registers, back to 2010–2012 |
26
+ | `wasde` | USDA WASDE projections since July 2010: US balance sheets and world tables by country, one row per monthly report |
27
+ | `fred_vintages` | FRED series with every revision, stamped at the date each value was published |
28
+ | `fails_to_deliver` | SEC fails-to-deliver for any US stock or ETF |
29
+ | `funding_rates` | Binance USD-M perpetual funding rates |
30
+
31
+ ## Install
32
+
33
+ ```
34
+ pip install openbb openbb-aurastream
35
+ ```
36
+
37
+ OpenBB rebuilds its Python interface the first time you import it after installing.
38
+
39
+ ## Credentials
40
+
41
+ You need an AuraStream API key. The free plan includes 500 calls a month, with no credit card required: [sign up here](https://aurastream.unbiased-alpha.com/sign-up).
42
+
43
+ ```python
44
+ from openbb import obb
45
+
46
+ obb.user.credentials.aurastream_api_key = "..."
47
+ # Only for fred_vintages: your own free FRED key (https://fred.stlouisfed.org/docs/api/api_key.html)
48
+ obb.user.credentials.aurastream_fred_api_key = "..."
49
+ # Only for fails_to_deliver: the SEC asks automated requests to name the sender
50
+ obb.user.credentials.aurastream_sec_user_agent = "Jane Doe jane@example.com"
51
+ ```
52
+
53
+ You can also keep them in `~/.openbb_platform/user_settings.json`.
54
+
55
+ ## Examples
56
+
57
+ ```python
58
+ from openbb import obb
59
+
60
+ # Who is short Ubisoft, and by how much
61
+ shorts = obb.aurastream.net_short("ubisoft", start_date="2024-01-01", country="FR").to_df()
62
+ shorts.pivot_table(index=shorts.index.date, columns="holder", values="net_short_pct").ffill()
63
+
64
+ # Every position one fund has disclosed
65
+ obb.aurastream.net_short("all", holder="citadel", start_date="2026-01-01").to_df()
66
+
67
+ # How the USDA's projection of US corn ending stocks changed, report by report
68
+ corn = obb.aurastream.wasde("corn:ending_stocks", start_date="2024-01-01").to_df()
69
+ corn["revision"] = corn["value"] - corn["previous"]
70
+
71
+ # Brazil's soybean crop from the world tables
72
+ obb.aurastream.wasde("soybeans:production:Brazil").to_df()
73
+
74
+ # CPI as first published vs. after revisions
75
+ cpi = obb.aurastream.fred_vintages("CPIAUCSL", start_date="2020-01-01").to_df()
76
+ first_print = cpi.groupby("reference_date")["value"].first()
77
+ latest = cpi.groupby("reference_date")["value"].last()
78
+
79
+ # Fails-to-deliver in GameStop
80
+ obb.aurastream.fails_to_deliver("GME", start_date="2024-01-01", end_date="2025-01-01").to_df()
81
+
82
+ # Funding rates of the Bitcoin and Ether perpetuals
83
+ obb.aurastream.funding_rates("BTCUSDT,ETHUSDT", start_date="2025-06-01").to_df()
84
+ ```
85
+
86
+ Without `start_date`, each command returns the last year.
87
+
88
+ ## Timing
89
+
90
+ All five datasets are historical, not real-time, and each row is stamped when the data became public:
91
+
92
+ - EU net short positions are published by the next trading day, so lag them by one day in a backtest.
93
+ - WASDE rows are stamped at the report's release, 12:00 New York time.
94
+ - For `fred_vintages`, `start_date` and `end_date` filter on the publication date.
95
+ - The SEC publishes fails-to-deliver twice a month, about two weeks after each half-month ends.
96
+
97
+ See the [AuraStream docs](https://aurastream.unbiased-alpha.com/docs/) for the field definitions and coverage of each source.
98
+
99
+ ## Data terms
100
+
101
+ - France: source Autorité des marchés financiers (AMF), data.gouv.fr, Licence Ouverte 2.0.
102
+ - Netherlands: source AFM.
103
+ - Spain: this information can be obtained free of charge from the CNMV website (www.cnmv.es).
104
+ - Holder names can belong to individuals, so treat them as personal data under the GDPR.
105
+
106
+ ## License
107
+
108
+ MIT. This package is by Unbiased Alpha and is not affiliated with OpenBB.
@@ -0,0 +1,90 @@
1
+ # openbb-aurastream
2
+
3
+ [AuraStream](https://aurastream.unbiased-alpha.com) data for the [OpenBB Platform](https://github.com/OpenBB-finance/OpenBB). The extension adds five commands under `obb.aurastream`. Each covers a dataset that the other OpenBB providers don't offer:
4
+
5
+ | Command | Data |
6
+ |---|---|
7
+ | `net_short` | EU net short positions of 0.5% or more, with the holder's name, from the French (AMF), Dutch (AFM) and Spanish (CNMV) registers, back to 2010–2012 |
8
+ | `wasde` | USDA WASDE projections since July 2010: US balance sheets and world tables by country, one row per monthly report |
9
+ | `fred_vintages` | FRED series with every revision, stamped at the date each value was published |
10
+ | `fails_to_deliver` | SEC fails-to-deliver for any US stock or ETF |
11
+ | `funding_rates` | Binance USD-M perpetual funding rates |
12
+
13
+ ## Install
14
+
15
+ ```
16
+ pip install openbb openbb-aurastream
17
+ ```
18
+
19
+ OpenBB rebuilds its Python interface the first time you import it after installing.
20
+
21
+ ## Credentials
22
+
23
+ You need an AuraStream API key. The free plan includes 500 calls a month, with no credit card required: [sign up here](https://aurastream.unbiased-alpha.com/sign-up).
24
+
25
+ ```python
26
+ from openbb import obb
27
+
28
+ obb.user.credentials.aurastream_api_key = "..."
29
+ # Only for fred_vintages: your own free FRED key (https://fred.stlouisfed.org/docs/api/api_key.html)
30
+ obb.user.credentials.aurastream_fred_api_key = "..."
31
+ # Only for fails_to_deliver: the SEC asks automated requests to name the sender
32
+ obb.user.credentials.aurastream_sec_user_agent = "Jane Doe jane@example.com"
33
+ ```
34
+
35
+ You can also keep them in `~/.openbb_platform/user_settings.json`.
36
+
37
+ ## Examples
38
+
39
+ ```python
40
+ from openbb import obb
41
+
42
+ # Who is short Ubisoft, and by how much
43
+ shorts = obb.aurastream.net_short("ubisoft", start_date="2024-01-01", country="FR").to_df()
44
+ shorts.pivot_table(index=shorts.index.date, columns="holder", values="net_short_pct").ffill()
45
+
46
+ # Every position one fund has disclosed
47
+ obb.aurastream.net_short("all", holder="citadel", start_date="2026-01-01").to_df()
48
+
49
+ # How the USDA's projection of US corn ending stocks changed, report by report
50
+ corn = obb.aurastream.wasde("corn:ending_stocks", start_date="2024-01-01").to_df()
51
+ corn["revision"] = corn["value"] - corn["previous"]
52
+
53
+ # Brazil's soybean crop from the world tables
54
+ obb.aurastream.wasde("soybeans:production:Brazil").to_df()
55
+
56
+ # CPI as first published vs. after revisions
57
+ cpi = obb.aurastream.fred_vintages("CPIAUCSL", start_date="2020-01-01").to_df()
58
+ first_print = cpi.groupby("reference_date")["value"].first()
59
+ latest = cpi.groupby("reference_date")["value"].last()
60
+
61
+ # Fails-to-deliver in GameStop
62
+ obb.aurastream.fails_to_deliver("GME", start_date="2024-01-01", end_date="2025-01-01").to_df()
63
+
64
+ # Funding rates of the Bitcoin and Ether perpetuals
65
+ obb.aurastream.funding_rates("BTCUSDT,ETHUSDT", start_date="2025-06-01").to_df()
66
+ ```
67
+
68
+ Without `start_date`, each command returns the last year.
69
+
70
+ ## Timing
71
+
72
+ All five datasets are historical, not real-time, and each row is stamped when the data became public:
73
+
74
+ - EU net short positions are published by the next trading day, so lag them by one day in a backtest.
75
+ - WASDE rows are stamped at the report's release, 12:00 New York time.
76
+ - For `fred_vintages`, `start_date` and `end_date` filter on the publication date.
77
+ - The SEC publishes fails-to-deliver twice a month, about two weeks after each half-month ends.
78
+
79
+ See the [AuraStream docs](https://aurastream.unbiased-alpha.com/docs/) for the field definitions and coverage of each source.
80
+
81
+ ## Data terms
82
+
83
+ - France: source Autorité des marchés financiers (AMF), data.gouv.fr, Licence Ouverte 2.0.
84
+ - Netherlands: source AFM.
85
+ - Spain: this information can be obtained free of charge from the CNMV website (www.cnmv.es).
86
+ - Holder names can belong to individuals, so treat them as personal data under the GDPR.
87
+
88
+ ## License
89
+
90
+ MIT. This package is by Unbiased Alpha and is not affiliated with OpenBB.
@@ -0,0 +1,32 @@
1
+ """Run each command once against the live AuraStream API (uses 5 calls).
2
+
3
+ Reads the key from the AURASTREAM_API_KEY environment variable; FRED and
4
+ fails-to-deliver run only when FRED_API_KEY / SEC_USER_AGENT are set too.
5
+ """
6
+
7
+ import os
8
+
9
+ from openbb import obb
10
+
11
+ obb.user.credentials.aurastream_api_key = os.environ["AURASTREAM_API_KEY"]
12
+ if os.environ.get("FRED_API_KEY"):
13
+ obb.user.credentials.aurastream_fred_api_key = os.environ["FRED_API_KEY"]
14
+ if os.environ.get("SEC_USER_AGENT"):
15
+ obb.user.credentials.aurastream_sec_user_agent = os.environ["SEC_USER_AGENT"]
16
+
17
+ checks = {
18
+ "net_short": lambda: obb.aurastream.net_short("ubisoft", start_date="2025-01-01", country="FR"),
19
+ "wasde": lambda: obb.aurastream.wasde("corn:ending_stocks", start_date="2025-06-01"),
20
+ "funding_rates": lambda: obb.aurastream.funding_rates("BTCUSDT", start_date="2025-06-01", end_date="2025-06-03"),
21
+ }
22
+ if os.environ.get("FRED_API_KEY"):
23
+ checks["fred_vintages"] = lambda: obb.aurastream.fred_vintages("CPIAUCSL", start_date="2025-01-01", end_date="2025-04-01")
24
+ if os.environ.get("SEC_USER_AGENT"):
25
+ checks["fails_to_deliver"] = lambda: obb.aurastream.fails_to_deliver("GME", start_date="2024-05-01", end_date="2024-06-01")
26
+
27
+ for name, call in checks.items():
28
+ try:
29
+ df = call().to_df()
30
+ print(f"OK {name}: {len(df)} rows, columns {list(df.columns)[:6]}")
31
+ except Exception as exc: # noqa: BLE001
32
+ print(f"FAIL {name}: {type(exc).__name__}: {str(exc)[:300]}")
@@ -0,0 +1,31 @@
1
+ """OpenBB AuraStream Provider Module."""
2
+
3
+ from openbb_core.provider.abstract.provider import Provider
4
+
5
+ from openbb_aurastream.models.fails_to_deliver import AuraStreamFailsToDeliverFetcher
6
+ from openbb_aurastream.models.fred_vintages import AuraStreamFredVintagesFetcher
7
+ from openbb_aurastream.models.funding_rates import AuraStreamFundingRatesFetcher
8
+ from openbb_aurastream.models.net_short import AuraStreamNetShortFetcher
9
+ from openbb_aurastream.models.wasde import AuraStreamWasdeFetcher
10
+
11
+ aurastream_provider = Provider(
12
+ name="aurastream",
13
+ website="https://aurastream.unbiased-alpha.com",
14
+ description="AuraStream, a unified market data API for quants by Unbiased Alpha:"
15
+ " EU net short positions, USDA WASDE projections, FRED with every revision,"
16
+ " SEC fails-to-deliver and Binance funding rates.",
17
+ credentials=["api_key", "fred_api_key", "sec_user_agent"],
18
+ fetcher_dict={
19
+ "AuraStreamNetShort": AuraStreamNetShortFetcher,
20
+ "AuraStreamWasde": AuraStreamWasdeFetcher,
21
+ "AuraStreamFredVintages": AuraStreamFredVintagesFetcher,
22
+ "AuraStreamFailsToDeliver": AuraStreamFailsToDeliverFetcher,
23
+ "AuraStreamFundingRates": AuraStreamFundingRatesFetcher,
24
+ },
25
+ repr_name="AuraStream",
26
+ instructions="Get a free API key (500 calls a month, no credit card) at"
27
+ " https://aurastream.unbiased-alpha.com/sign-up and set it as aurastream_api_key."
28
+ " fred_vintages also needs your own free FRED key (aurastream_fred_api_key), and"
29
+ " fails_to_deliver a contact string for the SEC (aurastream_sec_user_agent),"
30
+ " e.g. 'Jane Doe jane@example.com'.",
31
+ )
@@ -0,0 +1,117 @@
1
+ """AuraStream Router."""
2
+
3
+ from openbb_core.app.model.command_context import CommandContext
4
+ from openbb_core.app.model.example import APIEx
5
+ from openbb_core.app.model.obbject import OBBject
6
+ from openbb_core.app.provider_interface import (
7
+ ExtraParams,
8
+ ProviderChoices,
9
+ StandardParams,
10
+ )
11
+ from openbb_core.app.query import Query
12
+ from openbb_core.app.router import Router
13
+
14
+ router = Router(prefix="", description="AuraStream market data.")
15
+
16
+
17
+ @router.command(
18
+ model="AuraStreamNetShort",
19
+ examples=[
20
+ APIEx(
21
+ description="Disclosed short positions in Ubisoft on the French register.",
22
+ parameters={"symbol": "ubisoft", "country": "FR", "provider": "aurastream"},
23
+ ),
24
+ APIEx(
25
+ description="Every position one fund has disclosed in the period.",
26
+ parameters={"symbol": "all", "holder": "citadel", "provider": "aurastream"},
27
+ ),
28
+ ],
29
+ )
30
+ async def net_short(
31
+ cc: CommandContext,
32
+ provider_choices: ProviderChoices,
33
+ standard_params: StandardParams,
34
+ extra_params: ExtraParams,
35
+ ) -> OBBject:
36
+ """Get disclosed net short positions of 0.5% or more in European shares (AMF, AFM, CNMV)."""
37
+ return await OBBject.from_query(Query(**locals()))
38
+
39
+
40
+ @router.command(
41
+ model="AuraStreamWasde",
42
+ examples=[
43
+ APIEx(
44
+ description="How the USDA's projection of US corn ending stocks changed, report by report.",
45
+ parameters={"symbol": "corn:ending_stocks", "provider": "aurastream"},
46
+ ),
47
+ APIEx(
48
+ description="Brazil's soybean crop from the world tables.",
49
+ parameters={"symbol": "soybeans:production:Brazil", "provider": "aurastream"},
50
+ ),
51
+ ],
52
+ )
53
+ async def wasde(
54
+ cc: CommandContext,
55
+ provider_choices: ProviderChoices,
56
+ standard_params: StandardParams,
57
+ extra_params: ExtraParams,
58
+ ) -> OBBject:
59
+ """Get USDA WASDE projections since July 2010, one row per monthly report."""
60
+ return await OBBject.from_query(Query(**locals()))
61
+
62
+
63
+ @router.command(
64
+ model="AuraStreamFredVintages",
65
+ examples=[
66
+ APIEx(
67
+ description="Every published version of US CPI, by publication date.",
68
+ parameters={"symbol": "CPIAUCSL", "provider": "aurastream"},
69
+ ),
70
+ ],
71
+ )
72
+ async def fred_vintages(
73
+ cc: CommandContext,
74
+ provider_choices: ProviderChoices,
75
+ standard_params: StandardParams,
76
+ extra_params: ExtraParams,
77
+ ) -> OBBject:
78
+ """Get FRED series with every revision, stamped at the date each value was published."""
79
+ return await OBBject.from_query(Query(**locals()))
80
+
81
+
82
+ @router.command(
83
+ model="AuraStreamFailsToDeliver",
84
+ examples=[
85
+ APIEx(
86
+ description="Fails-to-deliver in GameStop.",
87
+ parameters={"symbol": "GME", "provider": "aurastream"},
88
+ ),
89
+ ],
90
+ )
91
+ async def fails_to_deliver(
92
+ cc: CommandContext,
93
+ provider_choices: ProviderChoices,
94
+ standard_params: StandardParams,
95
+ extra_params: ExtraParams,
96
+ ) -> OBBject:
97
+ """Get SEC fails-to-deliver for a US stock or ETF, one row per settlement date."""
98
+ return await OBBject.from_query(Query(**locals()))
99
+
100
+
101
+ @router.command(
102
+ model="AuraStreamFundingRates",
103
+ examples=[
104
+ APIEx(
105
+ description="Funding rates of the Bitcoin and Ether perpetuals.",
106
+ parameters={"symbol": "BTCUSDT,ETHUSDT", "provider": "aurastream"},
107
+ ),
108
+ ],
109
+ )
110
+ async def funding_rates(
111
+ cc: CommandContext,
112
+ provider_choices: ProviderChoices,
113
+ standard_params: StandardParams,
114
+ extra_params: ExtraParams,
115
+ ) -> OBBject:
116
+ """Get Binance USD-M perpetual funding rates at each funding time."""
117
+ return await OBBject.from_query(Query(**locals()))
@@ -0,0 +1 @@
1
+ """AuraStream models."""
@@ -0,0 +1,99 @@
1
+ """AuraStream Fails-to-Deliver Model."""
2
+
3
+ from datetime import date as dateType, datetime
4
+ from typing import Any
5
+
6
+ from openbb_core.provider.abstract.data import Data
7
+ from openbb_core.provider.abstract.fetcher import Fetcher
8
+ from openbb_core.provider.standard_models.bls_series import SeriesQueryParams
9
+ from pydantic import Field
10
+
11
+ from openbb_aurastream.utils.client import (
12
+ api_key,
13
+ default_start,
14
+ fetch,
15
+ require_key,
16
+ split_symbols,
17
+ to_rows,
18
+ )
19
+
20
+
21
+ class AuraStreamFailsToDeliverQueryParams(SeriesQueryParams):
22
+ """AuraStream Fails-to-Deliver Query.
23
+
24
+ Source: https://aurastream.unbiased-alpha.com/docs/data-sources/edgar/
25
+ """
26
+
27
+ __json_schema_extra__ = {"symbol": {"multiple_items_allowed": True}}
28
+
29
+ symbol: str = Field(
30
+ description="US stock or ETF symbol (e.g. 'GME') or 9-character CUSIP."
31
+ )
32
+ start_date: dateType | None = Field(
33
+ default=None, description="Start date. Default: one year ago."
34
+ )
35
+ end_date: dateType | None = Field(
36
+ default=None, description="End date. Default: today."
37
+ )
38
+
39
+
40
+ class AuraStreamFailsToDeliverData(Data):
41
+ """AuraStream Fails-to-Deliver Data. One row per settlement date with fails outstanding."""
42
+
43
+ date: datetime = Field(description="Settlement date.")
44
+ symbol: str = Field(description="Security symbol.")
45
+ fails: int | None = Field(
46
+ default=None, description="Total fails-to-deliver balance, in shares."
47
+ )
48
+ price: float | None = Field(
49
+ default=None, description="Previous day's closing price."
50
+ )
51
+ cusip: str | None = Field(default=None, description="CUSIP of the security.")
52
+ description: str | None = Field(default=None, description="Security description.")
53
+
54
+
55
+ class AuraStreamFailsToDeliverFetcher(
56
+ Fetcher[AuraStreamFailsToDeliverQueryParams, list[AuraStreamFailsToDeliverData]]
57
+ ):
58
+ """Fetch SEC fails-to-deliver from AuraStream."""
59
+
60
+ require_credentials = False
61
+
62
+ @staticmethod
63
+ def transform_query(params: dict[str, Any]) -> AuraStreamFailsToDeliverQueryParams:
64
+ """Transform the query."""
65
+ return AuraStreamFailsToDeliverQueryParams(**params)
66
+
67
+ @staticmethod
68
+ async def aextract_data(
69
+ query: AuraStreamFailsToDeliverQueryParams,
70
+ credentials: dict[str, str] | None,
71
+ **kwargs: Any,
72
+ ) -> list[dict]:
73
+ """Return the raw rows."""
74
+ key = api_key(credentials)
75
+ user_agent = require_key(
76
+ credentials,
77
+ "aurastream_sec_user_agent",
78
+ "The SEC asks every automated request to name the sender: your name or company"
79
+ " and a contact email, e.g. 'Jane Doe jane@example.com'.",
80
+ )
81
+ symbols = [s.upper() for s in split_symbols(query.symbol)]
82
+ body = {
83
+ "tickerlist": symbols,
84
+ "start": str(query.start_date or default_start()),
85
+ "end": str(query.end_date or dateType.today()),
86
+ "interval": "1d",
87
+ "source": "edgar",
88
+ "dataset": "ftd",
89
+ "credentials": {"user_agent": user_agent},
90
+ }
91
+ data = await fetch(body, key)
92
+ return to_rows(data, symbols)
93
+
94
+ @staticmethod
95
+ def transform_data(
96
+ query: AuraStreamFailsToDeliverQueryParams, data: list[dict], **kwargs: Any
97
+ ) -> list[AuraStreamFailsToDeliverData]:
98
+ """Transform the data."""
99
+ return [AuraStreamFailsToDeliverData.model_validate(d) for d in data]
@@ -0,0 +1,112 @@
1
+ """AuraStream FRED Vintages Model."""
2
+
3
+ from datetime import date as dateType, datetime
4
+ from typing import Any
5
+
6
+ from openbb_core.provider.abstract.data import Data
7
+ from openbb_core.provider.abstract.fetcher import Fetcher
8
+ from openbb_core.provider.standard_models.bls_series import SeriesQueryParams
9
+ from openbb_core.provider.utils.errors import EmptyDataError
10
+ from pydantic import Field
11
+
12
+ from openbb_aurastream.utils.client import (
13
+ api_key,
14
+ default_start,
15
+ fetch,
16
+ parse_timestamp,
17
+ require_key,
18
+ split_symbols,
19
+ )
20
+
21
+
22
+ class AuraStreamFredVintagesQueryParams(SeriesQueryParams):
23
+ """AuraStream FRED Vintages Query.
24
+
25
+ Source: https://aurastream.unbiased-alpha.com/docs/data-sources/fred/
26
+ """
27
+
28
+ __json_schema_extra__ = {"symbol": {"multiple_items_allowed": True}}
29
+
30
+ symbol: str = Field(
31
+ description="FRED series ID, e.g. 'CPIAUCSL', 'UNRATE', 'GDPC1'."
32
+ )
33
+ start_date: dateType | None = Field(
34
+ default=None,
35
+ description="First publication date. Default: one year ago.",
36
+ )
37
+ end_date: dateType | None = Field(
38
+ default=None, description="Last publication date. Default: today."
39
+ )
40
+
41
+
42
+ class AuraStreamFredVintagesData(Data):
43
+ """AuraStream FRED Vintages Data. One row per published value."""
44
+
45
+ date: datetime = Field(description="Publication date of the value.")
46
+ symbol: str = Field(description="FRED series ID.")
47
+ reference_date: datetime = Field(description="The period the value describes.")
48
+ value: float | None = Field(default=None, description="The value as published.")
49
+
50
+
51
+ class AuraStreamFredVintagesFetcher(
52
+ Fetcher[AuraStreamFredVintagesQueryParams, list[AuraStreamFredVintagesData]]
53
+ ):
54
+ """Fetch every published version of FRED series from AuraStream."""
55
+
56
+ require_credentials = False
57
+
58
+ @staticmethod
59
+ def transform_query(params: dict[str, Any]) -> AuraStreamFredVintagesQueryParams:
60
+ """Transform the query."""
61
+ return AuraStreamFredVintagesQueryParams(**params)
62
+
63
+ @staticmethod
64
+ async def aextract_data(
65
+ query: AuraStreamFredVintagesQueryParams,
66
+ credentials: dict[str, str] | None,
67
+ **kwargs: Any,
68
+ ) -> list[dict]:
69
+ """Return one row per (publication date, period)."""
70
+ key = api_key(credentials)
71
+ fred_key = require_key(
72
+ credentials,
73
+ "aurastream_fred_api_key",
74
+ "FRED needs a free key of your own: https://fred.stlouisfed.org/docs/api/api_key.html.",
75
+ )
76
+ symbols = [s.upper() for s in split_symbols(query.symbol)]
77
+ body = {
78
+ "tickerlist": symbols,
79
+ "start": str(query.start_date or default_start()),
80
+ "end": str(query.end_date or dateType.today()),
81
+ "interval": "1d", # ignored: each series comes at its own frequency
82
+ "source": "fred",
83
+ "credentials": {"key": fred_key},
84
+ }
85
+ data = await fetch(body, key)
86
+
87
+ rows: list[dict] = []
88
+ for symbol in symbols:
89
+ series = data.get(symbol)
90
+ if not isinstance(series, dict):
91
+ continue
92
+ for published, row in series.items():
93
+ for update in (row or {}).get("updates") or []:
94
+ rows.append(
95
+ {
96
+ "date": parse_timestamp(published),
97
+ "symbol": symbol,
98
+ "reference_date": parse_timestamp(update["reference_date"]),
99
+ "value": update.get("value"),
100
+ }
101
+ )
102
+ if not rows:
103
+ raise EmptyDataError(f"AuraStream returned no data for {', '.join(symbols)}.")
104
+ rows.sort(key=lambda r: (r["date"], r["symbol"], r["reference_date"]))
105
+ return rows
106
+
107
+ @staticmethod
108
+ def transform_data(
109
+ query: AuraStreamFredVintagesQueryParams, data: list[dict], **kwargs: Any
110
+ ) -> list[AuraStreamFredVintagesData]:
111
+ """Transform the data."""
112
+ return [AuraStreamFredVintagesData.model_validate(d) for d in data]