Skip to content

Commit fb4e524

Browse files
committed
Add Fed data
1 parent 4b3c8ab commit fb4e524

File tree

9 files changed

+1771
-1257
lines changed

9 files changed

+1771
-1257
lines changed

notebooks/api/data/fed.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
================
2+
Federal Reserve
3+
================
4+
5+
.. currentmodule:: quantflow.data.fed
6+
7+
.. autoclass:: FederalReserve
8+
:members:
9+
:member-order: groupwise
10+
:autosummary:
11+
:autosummary-nosignatures:

notebooks/api/data/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ pip install quantflow[data]
1414
:maxdepth: 1
1515

1616
fmp
17+
fed
1718
fred
1819
deribit

notebooks/data/fed.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
jupytext:
3+
text_representation:
4+
extension: .md
5+
format_name: myst
6+
format_version: 0.13
7+
jupytext_version: 1.16.6
8+
kernelspec:
9+
display_name: Python 3 (ipykernel)
10+
language: python
11+
name: python3
12+
---
13+
14+
# Federal Reserve Data
15+
16+
```{code-cell} ipython3
17+
from quantflow.data.fed import FederalReserve
18+
```
19+
20+
```{code-cell} ipython3
21+
async with FederalReserve() as fed:
22+
rates = await fed.ref_rates()
23+
```
24+
25+
```{code-cell} ipython3
26+
rates
27+
```
28+
29+
```{code-cell} ipython3
30+
async with FederalReserve() as fed:
31+
curves = await fed.yield_curves()
32+
```
33+
34+
```{code-cell} ipython3
35+
curves
36+
```
37+
38+
```{code-cell} ipython3
39+
40+
```

notebooks/data/fmp.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,45 +16,45 @@ kernelspec:
1616

1717
The library provides a python client for the [Financial Modelling Prep API](https://site.financialmodelingprep.com/developer/docs). To use the client one needs to provide the API key aither directly to the client or via the `FMP_API_KEY` environment variable. The API offers 1 minute, 5 minutes, 15 minutes, 30 minutes, 1 hour and daily historical prices.
1818

19-
```{code-cell}
19+
```{code-cell} ipython3
2020
from quantflow.data.fmp import FMP
2121
cli = FMP()
2222
cli.url
2323
```
2424

25-
```{code-cell}
25+
```{code-cell} ipython3
2626
stock = "KNOS.L"
2727
```
2828

2929
## Company Profile
3030

31-
```{code-cell}
31+
```{code-cell} ipython3
3232
d = await cli.profile(stock)
3333
d
3434
```
3535

36-
```{code-cell}
36+
```{code-cell} ipython3
3737
c = await cli.peers(stock)
3838
c
3939
```
4040

4141
## Executive trading
4242

43-
```{code-cell}
43+
```{code-cell} ipython3
4444
stock = "KNOS.L"
4545
```
4646

47-
```{code-cell}
47+
```{code-cell} ipython3
4848
await cli.executives(stock)
4949
```
5050

51-
```{code-cell}
51+
```{code-cell} ipython3
5252
await cli.insider_trading(stock)
5353
```
5454

5555
## News
5656

57-
```{code-cell}
57+
```{code-cell} ipython3
5858
c = await cli.news(stock)
5959
c
6060
```

notebooks/data/timeseries.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,27 @@ kernelspec:
1313

1414
## Timeseries
1515

16-
```{code-cell}
16+
```{code-cell} ipython3
1717
from quantflow.data.fmp import FMP
1818
from quantflow.utils.plot import candlestick_plot
1919
cli = FMP()
2020
```
2121

22-
```{code-cell}
22+
```{code-cell} ipython3
2323
prices = await cli.prices("ethusd", frequency="")
2424
```
2525

26-
```{code-cell}
26+
```{code-cell} ipython3
2727
candlestick_plot(prices).update_layout(height=500)
2828
```
2929

30-
```{code-cell}
30+
```{code-cell} ipython3
3131
from quantflow.utils.df import DFutils
3232
3333
df = DFutils(prices).with_rogers_satchel().with_parkinson()
3434
df
3535
```
3636

37-
```{code-cell}
37+
```{code-cell} ipython3
3838
3939
```

notebooks/examples/gaussian_sampling.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ jupytext:
66
format_version: 0.13
77
jupytext_version: 1.16.6
88
kernelspec:
9-
display_name: .venv
9+
display_name: Python 3 (ipykernel)
1010
language: python
1111
name: python3
1212
---

poetry.lock

Lines changed: 1590 additions & 1243 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

quantflow/data/fed.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import io
2+
from dataclasses import dataclass, field
3+
from typing import Any
4+
5+
import numpy as np
6+
import pandas as pd
7+
from fluid.utils.http_client import AioHttpClient
8+
9+
URL = (
10+
"https://www.federalreserve.gov/datadownload/Output.aspx?"
11+
"rel=H15&series=bf17364827e38702b42a58cf8eaa3f78&lastobs=&"
12+
)
13+
14+
maturities = [
15+
"month_1",
16+
"month_3",
17+
"month_6",
18+
"year_1",
19+
"year_2",
20+
"year_3",
21+
"year_5",
22+
"year_7",
23+
"year_10",
24+
"year_20",
25+
"year_30",
26+
]
27+
28+
29+
@dataclass
30+
class FederalReserve(AioHttpClient):
31+
"""Federal Reserve API client.
32+
33+
This class is used to fetch yield curves from the Federal Reserve at
34+
https://www.federalreserve.gov/datadownload/
35+
"""
36+
37+
url: str = "https://www.federalreserve.gov/datadownload/Output.aspx"
38+
default_params: dict[str, Any] = field(
39+
default_factory=lambda: {
40+
"from": "",
41+
"to": "",
42+
"lastobs": "",
43+
"filetype": "csv",
44+
"label": "include",
45+
"layout": "seriescolumn",
46+
"type": "package",
47+
}
48+
)
49+
50+
async def yield_curves(self, **params: Any) -> pd.DataFrame:
51+
"""Get treasury constant maturities rates"""
52+
params.update(series="bf17364827e38702b42a58cf8eaa3f78", rel="H15")
53+
data = await self._get_text(params)
54+
df = pd.read_csv(data, header=5, index_col=None, parse_dates=True)
55+
df.columns = ["date"] + maturities # type: ignore
56+
df = df.set_index("date").replace("ND", np.nan)
57+
return df.dropna(axis=0, how="all").reset_index()
58+
59+
async def ref_rates(self, **params: Any) -> pd.DataFrame:
60+
"""Get policy rates
61+
62+
Prior to 2021-07-08 it is the rate on excess reserves (IOER rate)
63+
After 2021-07-08 it is the rate on reserve balances (IORB rate)
64+
65+
The IOER rate was the primary tool used by the Federal Reserve to set
66+
a floor on the federal funds rate.
67+
While the Interest rate on required reserves (IORR rate) existed,
68+
the IOER rate had a more direct impact on market rates,
69+
as banks typically held far more excess reserves than required reserves.
70+
Therefore, the IOER rate was more influential
71+
in the Fed's monetary policy implementation.
72+
"""
73+
params.update(series="c27939ee810cb2e929a920a6bd77d9f6", rel="PRATES")
74+
data = await self._get_text(params)
75+
df = pd.read_csv(data, header=5, index_col=None, parse_dates=True)
76+
ioer = df["RESBME_N.D"]
77+
iorb = df["RESBM_N.D"]
78+
rate = iorb.combine_first(ioer)
79+
return pd.DataFrame(
80+
{
81+
"date": df["Time Period"],
82+
"rate": rate,
83+
}
84+
)
85+
86+
async def _get_text(self, params: dict[str, Any]) -> io.StringIO:
87+
"""Get parameters for the request."""
88+
params = {**self.default_params, **params}
89+
response = await self.get(self.url, params=params, callback=True)
90+
data = await response.text()
91+
return io.StringIO(data)

quantflow_tests/test_data.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
from typing import AsyncIterator
22

33
import pytest
4+
from aiohttp.client_exceptions import ClientError
45

6+
from quantflow.data.fed import FederalReserve
57
from quantflow.data.fmp import FMP
68

79
pytestmark = pytest.mark.skipif(not FMP().key, reason="No FMP API key found")
@@ -26,3 +28,25 @@ async def test_historical(fmp: FMP) -> None:
2628
async def test_dividends(fmp: FMP) -> None:
2729
data = await fmp.dividends()
2830
assert data is not None
31+
32+
33+
async def test_fed_yc() -> None:
34+
try:
35+
async with FederalReserve() as fed:
36+
df = await fed.yield_curves()
37+
assert df is not None
38+
assert df.shape[0] > 0
39+
assert df.shape[1] == 12
40+
except (ConnectionError, ClientError) as e:
41+
pytest.skip(f"Skipping test_fed due to network issue: {e}")
42+
43+
44+
async def test_fed_rates() -> None:
45+
try:
46+
async with FederalReserve() as fed:
47+
df = await fed.ref_rates()
48+
assert df is not None
49+
assert df.shape[0] > 0
50+
assert df.shape[1] == 2
51+
except (ConnectionError, ClientError) as e:
52+
pytest.skip(f"Skipping test_fed due to network issue: {e}")

0 commit comments

Comments
 (0)