finzdata 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,64 @@
1
+ Metadata-Version: 2.4
2
+ Name: finzdata
3
+ Version: 0.1.0
4
+ Summary: FinzData market data client: yfinance-style prices plus COT, SEC fundamentals, point-in-time macro and more
5
+ Project-URL: Homepage, https://finzdata.com
6
+ Project-URL: Documentation, https://finzdata.com/docs
7
+ Project-URL: Pricing, https://finzdata.com/pricing
8
+ Project-URL: Status, https://finzdata.com/status
9
+ Keywords: market data,stocks,yfinance,cot,sec,fred,finance,api
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Intended Audience :: Financial and Insurance Industry
12
+ Classifier: Topic :: Office/Business :: Financial :: Investment
13
+ Classifier: Operating System :: OS Independent
14
+ Requires-Python: >=3.9
15
+ Description-Content-Type: text/markdown
16
+ Requires-Dist: pandas>=1.5
17
+ Requires-Dist: httpx>=0.24
18
+ Requires-Dist: pyarrow>=12
19
+
20
+ # finzdata
21
+
22
+ Python client for the [FinzData](https://finzdata.com) market data API. It works like yfinance and adds
23
+ the datasets yfinance doesn't have.
24
+
25
+ ```
26
+ pip install finzdata
27
+ ```
28
+
29
+ Get a free API key at https://api.finzdata.com/ and set `FINZDATA_API_KEY`.
30
+
31
+ ```python
32
+ import finzdata as yf
33
+
34
+ msft = yf.Ticker("MSFT")
35
+ daily = msft.history(start="2020-01-01") # daily bars, split and dividend adjusted
36
+ bars = msft.history(interval="5m", start="2026-10-01") # 1m, 5m, 1h bars (Researcher+)
37
+ both = yf.download(["SPY", "QQQ"], period="max")
38
+
39
+ c = yf.Client()
40
+ gold = c.cot(report="legacy_fo", market="GOLD") # CFTC Commitments of Traders
41
+ rev = c.fundamentals(ticker="AAPL", concept="Revenues", as_of="2025-06-30") # SEC, point-in-time
42
+ cpi = c.macro("CPIAUCSL", as_of="2022-06-30") # US macro, as known on that date
43
+ regime = c.model("latest") # FinzData Quantitative Model (Researcher+)
44
+ hy = c.licensed("BAMLH0A0HYM2") # licensed third-party series (Researcher+)
45
+ ```
46
+
47
+ ## Datasets
48
+
49
+ - US equity bars, daily (incl. delisted names) and intraday 1-minute, 5-minute and hourly
50
+ - Splits and dividends
51
+ - CFTC Commitments of Traders, all reports, since 1986
52
+ - SEC XBRL fundamentals, as reported and point-in-time
53
+ - US macro series with every vintage (FRED/ALFRED), plus a release calendar
54
+ - FinzData Quantitative Model: macro regime labels, a nowcast and a market-stress probability
55
+ - Licensed series: Moody's, University of Michigan, Case-Shiller, ICE BofA, Cboe (incl. the VIX futures curve)
56
+
57
+ Free samples and the full file specification: https://finzdata.com/samples ·
58
+ Pricing: https://finzdata.com/pricing · Data status: https://finzdata.com/status ·
59
+ API reference: https://api.finzdata.com/docs
60
+
61
+ Bulk downloads (Researcher and above): `POST /v1/batch`, then fetch the `download_url`.
62
+ Full-history bundles and nightly updates: `GET /v1/bundles`.
63
+
64
+ Data is provided under the FinzData subscriber licence; redistribution is prohibited.
@@ -0,0 +1,45 @@
1
+ # finzdata
2
+
3
+ Python client for the [FinzData](https://finzdata.com) market data API. It works like yfinance and adds
4
+ the datasets yfinance doesn't have.
5
+
6
+ ```
7
+ pip install finzdata
8
+ ```
9
+
10
+ Get a free API key at https://api.finzdata.com/ and set `FINZDATA_API_KEY`.
11
+
12
+ ```python
13
+ import finzdata as yf
14
+
15
+ msft = yf.Ticker("MSFT")
16
+ daily = msft.history(start="2020-01-01") # daily bars, split and dividend adjusted
17
+ bars = msft.history(interval="5m", start="2026-10-01") # 1m, 5m, 1h bars (Researcher+)
18
+ both = yf.download(["SPY", "QQQ"], period="max")
19
+
20
+ c = yf.Client()
21
+ gold = c.cot(report="legacy_fo", market="GOLD") # CFTC Commitments of Traders
22
+ rev = c.fundamentals(ticker="AAPL", concept="Revenues", as_of="2025-06-30") # SEC, point-in-time
23
+ cpi = c.macro("CPIAUCSL", as_of="2022-06-30") # US macro, as known on that date
24
+ regime = c.model("latest") # FinzData Quantitative Model (Researcher+)
25
+ hy = c.licensed("BAMLH0A0HYM2") # licensed third-party series (Researcher+)
26
+ ```
27
+
28
+ ## Datasets
29
+
30
+ - US equity bars, daily (incl. delisted names) and intraday 1-minute, 5-minute and hourly
31
+ - Splits and dividends
32
+ - CFTC Commitments of Traders, all reports, since 1986
33
+ - SEC XBRL fundamentals, as reported and point-in-time
34
+ - US macro series with every vintage (FRED/ALFRED), plus a release calendar
35
+ - FinzData Quantitative Model: macro regime labels, a nowcast and a market-stress probability
36
+ - Licensed series: Moody's, University of Michigan, Case-Shiller, ICE BofA, Cboe (incl. the VIX futures curve)
37
+
38
+ Free samples and the full file specification: https://finzdata.com/samples ·
39
+ Pricing: https://finzdata.com/pricing · Data status: https://finzdata.com/status ·
40
+ API reference: https://api.finzdata.com/docs
41
+
42
+ Bulk downloads (Researcher and above): `POST /v1/batch`, then fetch the `download_url`.
43
+ Full-history bundles and nightly updates: `GET /v1/bundles`.
44
+
45
+ Data is provided under the FinzData subscriber licence; redistribution is prohibited.
@@ -0,0 +1,371 @@
1
+ from __future__ import annotations
2
+
3
+ import datetime as dt
4
+ import io
5
+ import os
6
+ from typing import Any, Optional
7
+
8
+ import httpx
9
+ import pandas as pd
10
+
11
+ __version__ = "0.1.0"
12
+
13
+ _DATE_COLUMNS = ("date", "ts", "start", "end", "filed")
14
+ _DATE_COLUMNS = tuple(dict.fromkeys(tuple(_DATE_COLUMNS) + ("realtime_start",)))
15
+ _DATE_COLUMNS = tuple(dict.fromkeys(tuple(_DATE_COLUMNS) + ("trade_date",)))
16
+ # realtime_end stays text: the open vintage is 9999-12-31, outside pandas timestamp range
17
+
18
+
19
+ class FinzError(Exception):
20
+ def __init__(self, status: int, detail: str):
21
+ super().__init__(f"{status}: {detail}")
22
+ self.status = int(status)
23
+ self.detail = str(detail)
24
+
25
+
26
+ def _iso(value: Any) -> Any:
27
+ if value is None:
28
+ return None
29
+ if isinstance(value, (dt.date, dt.datetime)):
30
+ return value.isoformat()
31
+ if isinstance(value, pd.Timestamp):
32
+ return value.isoformat()
33
+ return value
34
+
35
+
36
+ def _clean(params: dict) -> dict:
37
+ out = {}
38
+ for key, value in params.items():
39
+ if value is None:
40
+ continue
41
+ out[key] = _iso(value)
42
+ return out
43
+
44
+
45
+ class Client:
46
+ def __init__(self, api_key=None, base_url=None, http=None, timeout=60):
47
+ self.api_key = api_key if api_key is not None else os.environ.get("FINZDATA_API_KEY")
48
+ self.base_url = base_url if base_url is not None else (
49
+ os.environ.get("FINZDATA_URL") or "http://127.0.0.1:8787"
50
+ )
51
+ self.timeout = timeout
52
+ if http is not None:
53
+ self.http = http
54
+ else:
55
+ self.http = httpx.Client(base_url=self.base_url, timeout=timeout)
56
+
57
+ def _get(self, path: str, params: Optional[dict] = None):
58
+ response = self.http.get(
59
+ path,
60
+ params=_clean(params or {}),
61
+ headers={"X-API-Key": self.api_key},
62
+ )
63
+ if not (200 <= response.status_code < 300):
64
+ detail = None
65
+ try:
66
+ payload = response.json()
67
+ if isinstance(payload, dict):
68
+ detail = payload.get("detail")
69
+ except Exception:
70
+ detail = None
71
+ if detail is None:
72
+ detail = response.text
73
+ if not isinstance(detail, str):
74
+ detail = str(detail)
75
+ raise FinzError(response.status_code, detail)
76
+ return response.json()
77
+
78
+ def _frame(self, path: str, params: Optional[dict] = None) -> pd.DataFrame:
79
+ payload = self._get(path, params)
80
+ rows = payload.get("data", []) if isinstance(payload, dict) else []
81
+ frame = pd.DataFrame(rows)
82
+ for column in _DATE_COLUMNS:
83
+ if column in frame.columns:
84
+ frame[column] = pd.to_datetime(frame[column])
85
+ return frame
86
+
87
+ def me(self) -> dict:
88
+ return self._get("/v1/me")
89
+
90
+ def datasets(self):
91
+ return self._frame("/v1/datasets", {})
92
+
93
+ def cot(self, report=None, code=None, market=None, start=None, end=None) -> pd.DataFrame:
94
+ return self._frame(
95
+ "/v1/cot",
96
+ {"report": report, "code": code, "market": market, "start": start, "end": end},
97
+ )
98
+
99
+ def cot_markets(self, report="legacy_fo"):
100
+ return self._frame("/v1/cot/markets", {"report": report})
101
+
102
+ def prices(self, symbol, start=None, end=None, adjust="splits") -> pd.DataFrame:
103
+ return self._frame(
104
+ "/v1/prices/daily",
105
+ {"symbol": symbol, "start": start, "end": end, "adjust": adjust},
106
+ )
107
+
108
+ def minutes(self, symbol, start=None, end=None, interval="1min", adjust="none") -> pd.DataFrame:
109
+ """Intraday bars. interval: 1min | 5min | 1hour. adjust: none | all (splits + dividends)."""
110
+ return self._frame(
111
+ "/v1/prices/minute",
112
+ {"symbol": symbol, "start": start, "end": end, "interval": interval, "adjust": adjust},
113
+ )
114
+
115
+ def actions(self, symbol) -> pd.DataFrame:
116
+ return self._frame("/v1/actions", {"symbol": symbol})
117
+
118
+ def fundamentals(self, ticker=None, cik=None, concept=None, as_of=None) -> pd.DataFrame:
119
+ return self._frame(
120
+ "/v1/fundamentals",
121
+ {"ticker": ticker, "cik": cik, "concept": concept, "as_of": as_of},
122
+ )
123
+
124
+
125
+ _default: Optional[Client] = None
126
+
127
+
128
+ def set_default_client(client: Optional[Client]) -> None:
129
+ global _default
130
+ _default = client
131
+
132
+
133
+ def get_client() -> Client:
134
+ global _default
135
+ if _default is None:
136
+ _default = Client()
137
+ return _default
138
+
139
+
140
+ def period_start(period, today=None):
141
+ if today is None:
142
+ today = dt.date.today()
143
+ if isinstance(today, dt.datetime):
144
+ today = today.date()
145
+ if period is None:
146
+ raise ValueError(f"invalid period: {period!r}")
147
+ text = str(period).strip().lower()
148
+ if text == "max":
149
+ return None
150
+ if text == "ytd":
151
+ return dt.date(today.year, 1, 1)
152
+ for suffix, days in (("wk", 7), ("mo", 31), ("d", 1), ("y", 366)):
153
+ if text.endswith(suffix):
154
+ number = text[: -len(suffix)]
155
+ if number.isdigit():
156
+ return today - dt.timedelta(days=days * int(number))
157
+ raise ValueError(f"invalid period: {period!r}")
158
+
159
+
160
+ _HISTORY_COLUMNS = ["Open", "High", "Low", "Close", "Volume"]
161
+
162
+
163
+ def _empty_history(index_name: str = "Date") -> pd.DataFrame:
164
+ index = pd.DatetimeIndex([], name=index_name)
165
+ return pd.DataFrame(columns=_HISTORY_COLUMNS, index=index)
166
+
167
+
168
+ class Ticker:
169
+ def __init__(self, symbol, client=None):
170
+ self.ticker = str(symbol).upper()
171
+ self.client = client if client is not None else get_client()
172
+
173
+ def history(self, period="1mo", interval="1d", start=None, end=None, auto_adjust=True) -> pd.DataFrame:
174
+ if start is None:
175
+ start = period_start(period)
176
+ if interval == "1d":
177
+ frame = self.client.prices(
178
+ self.ticker,
179
+ start=start,
180
+ end=end,
181
+ adjust="all" if auto_adjust else "none",
182
+ )
183
+ index_name = "Date"
184
+ elif interval in _INTRADAY:
185
+ frame = self.client.minutes(
186
+ self.ticker,
187
+ start=start,
188
+ end=end,
189
+ interval=_INTRADAY[interval],
190
+ adjust="all" if auto_adjust else "none",
191
+ )
192
+ index_name = "Datetime"
193
+ else:
194
+ raise ValueError(f"invalid interval: {interval!r}")
195
+ return _normalize_history(frame, index_name)
196
+
197
+ @property
198
+ def dividends(self) -> pd.Series:
199
+ return self._action_series("dividend", "Dividends")
200
+
201
+ @property
202
+ def splits(self) -> pd.Series:
203
+ return self._action_series("split", "Stock Splits")
204
+
205
+ def _action_series(self, kind: str, name: str) -> pd.Series:
206
+ frame = self.client.actions(self.ticker)
207
+ index = pd.DatetimeIndex([], name="Date")
208
+ series = pd.Series([], dtype="float64", index=index, name=name)
209
+ if frame is None or frame.empty or "type" not in frame.columns:
210
+ return series
211
+ mask = frame["type"].astype(str).str.lower().str.contains(kind)
212
+ subset = frame[mask]
213
+ if subset.empty:
214
+ return series
215
+ dates = None
216
+ for column in ("date", "ts"):
217
+ if column in subset.columns:
218
+ dates = pd.to_datetime(subset[column])
219
+ break
220
+ if dates is None:
221
+ dates = pd.to_datetime(subset.index)
222
+ values = None
223
+ for column in ("value", "amount", "dividend", "split"):
224
+ if column in subset.columns:
225
+ values = subset[column]
226
+ break
227
+ if values is None:
228
+ numeric = [c for c in subset.columns if c not in ("type", "date", "ts")]
229
+ values = subset[numeric[0]] if numeric else pd.Series([1.0] * len(subset))
230
+ series = pd.Series(
231
+ pd.to_numeric(values, errors="coerce").to_numpy(),
232
+ index=pd.DatetimeIndex(dates, name="Date"),
233
+ name=name,
234
+ )
235
+ return series.sort_index()
236
+
237
+ @property
238
+ def actions(self) -> pd.DataFrame:
239
+ dividends = self.dividends
240
+ splits = self.splits
241
+ frame = pd.DataFrame({"Dividends": dividends, "Stock Splits": splits})
242
+ frame = frame.fillna(0.0)
243
+ frame.index = pd.DatetimeIndex(frame.index, name="Date")
244
+ return frame
245
+
246
+ def facts(self, concept=None, as_of=None) -> pd.DataFrame:
247
+ return self.client.fundamentals(ticker=self.ticker, concept=concept, as_of=as_of)
248
+
249
+
250
+ def _normalize_history(frame: pd.DataFrame, index_name: str) -> pd.DataFrame:
251
+ if frame is None or frame.empty:
252
+ return _empty_history(index_name)
253
+ frame = frame.copy()
254
+ date_column = None
255
+ for column in ("date", "ts"):
256
+ if column in frame.columns:
257
+ date_column = column
258
+ break
259
+ if date_column is not None:
260
+ frame.index = pd.DatetimeIndex(pd.to_datetime(frame[date_column]), name=index_name)
261
+ frame = frame.drop(columns=[date_column])
262
+ else:
263
+ frame.index = pd.DatetimeIndex(pd.to_datetime(frame.index), name=index_name)
264
+ rename = {}
265
+ for column in frame.columns:
266
+ lowered = str(column).lower()
267
+ for target in _HISTORY_COLUMNS:
268
+ if lowered == target.lower():
269
+ rename[column] = target
270
+ frame = frame.rename(columns=rename)
271
+ for column in _HISTORY_COLUMNS:
272
+ if column not in frame.columns:
273
+ frame[column] = pd.Series(dtype="float64")
274
+ frame = frame[_HISTORY_COLUMNS]
275
+ return frame.sort_index()
276
+
277
+
278
+ def _parse_tickers(tickers) -> list:
279
+ if isinstance(tickers, str):
280
+ parts = tickers.replace(",", " ").split()
281
+ return [part.upper() for part in parts]
282
+ return [str(ticker).upper() for ticker in tickers]
283
+
284
+
285
+ _INTRADAY = {"1m": "1min", "5m": "5min", "60m": "1hour", "1h": "1hour"}
286
+
287
+
288
+ def download(tickers, start=None, end=None, period="1mo", interval="1d", auto_adjust=True, client=None) -> pd.DataFrame:
289
+ symbols = _parse_tickers(tickers)
290
+ frames = {}
291
+ for symbol in symbols:
292
+ ticker = Ticker(symbol, client=client)
293
+ frames[symbol] = ticker.history(
294
+ period=period,
295
+ interval=interval,
296
+ start=start,
297
+ end=end,
298
+ auto_adjust=auto_adjust,
299
+ )
300
+ if not frames:
301
+ return pd.DataFrame()
302
+ combined = pd.concat(frames, axis=1)
303
+ combined.columns = combined.columns.swaplevel(0, 1)
304
+ combined = combined.sort_index(axis=1, level=0)
305
+ return combined.sort_index()
306
+
307
+
308
+ def cot(**kw) -> pd.DataFrame:
309
+ return get_client().cot(**kw)
310
+
311
+
312
+ # --- macro data (FRED/ALFRED, point-in-time) -------------------------------------------
313
+ def _clean(params: dict) -> dict:
314
+ return {k: (v.isoformat() if hasattr(v, "isoformat") else v) for k, v in params.items() if v is not None}
315
+
316
+
317
+ def _macro(self, series, start=None, end=None, vintage="latest", as_of=None) -> pd.DataFrame:
318
+ """Macro series. vintage: 'latest' (current values), 'first' (as first released) or 'all';
319
+ as_of='YYYY-MM-DD' returns only what was known on that date (point-in-time, Researcher+)."""
320
+ return self._frame("/v1/macro", _clean({"series": series, "start": start, "end": end, "vintage": vintage, "as_of": as_of}))
321
+
322
+
323
+ def _macro_series(self, category=None) -> pd.DataFrame:
324
+ """Catalog of available macro series (id, title, units, frequency, category, ...)."""
325
+ return self._frame("/v1/macro/series", _clean({"category": category}))
326
+
327
+
328
+ def _macro_calendar(self, start=None, end=None) -> pd.DataFrame:
329
+ """Upcoming and recent economic release dates."""
330
+ return self._frame("/v1/macro/calendar", _clean({"start": start, "end": end}))
331
+
332
+
333
+ Client.macro = _macro
334
+ Client.macro_series = _macro_series
335
+ Client.macro_calendar = _macro_calendar
336
+
337
+
338
+ def macro(series, **kw):
339
+ return get_client().macro(series, **kw)
340
+
341
+
342
+ def _licensed(self, series_id, start=None, end=None) -> pd.DataFrame:
343
+ """Third-party licensed series (paid plans). Each row carries its `source` citation."""
344
+ return self._frame("/v1/licensed/series", _clean({"id": series_id, "start": start, "end": end}))
345
+
346
+
347
+ def _licensed_catalog(self) -> pd.DataFrame:
348
+ """Licensed series, their owners, citations and availability."""
349
+ return self._frame("/v1/licensed/catalog", {})
350
+
351
+
352
+ def _vix_futures(self, start=None, end=None) -> pd.DataFrame:
353
+ """Daily VIX futures settlements by expiry (paid plans)."""
354
+ return self._frame("/v1/licensed/vix-futures", _clean({"start": start, "end": end}))
355
+
356
+
357
+ Client.licensed = _licensed
358
+ Client.licensed_catalog = _licensed_catalog
359
+ Client.vix_futures = _vix_futures
360
+
361
+
362
+ def _model(self, what="latest", series=None, start=None, end=None):
363
+ """FinzData Quantitative Model (paid plans): what = latest | labels | nowcast | stress | catalog."""
364
+ if what not in ("latest", "labels", "nowcast", "stress", "catalog"):
365
+ raise ValueError("what must be latest, labels, nowcast, stress or catalog")
366
+ if what == "latest":
367
+ return self._get("/v1/model/latest", {})
368
+ return self._frame(f"/v1/model/{what}", _clean({"series": series, "start": start, "end": end}))
369
+
370
+
371
+ Client.model = _model
@@ -0,0 +1,64 @@
1
+ Metadata-Version: 2.4
2
+ Name: finzdata
3
+ Version: 0.1.0
4
+ Summary: FinzData market data client: yfinance-style prices plus COT, SEC fundamentals, point-in-time macro and more
5
+ Project-URL: Homepage, https://finzdata.com
6
+ Project-URL: Documentation, https://finzdata.com/docs
7
+ Project-URL: Pricing, https://finzdata.com/pricing
8
+ Project-URL: Status, https://finzdata.com/status
9
+ Keywords: market data,stocks,yfinance,cot,sec,fred,finance,api
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Intended Audience :: Financial and Insurance Industry
12
+ Classifier: Topic :: Office/Business :: Financial :: Investment
13
+ Classifier: Operating System :: OS Independent
14
+ Requires-Python: >=3.9
15
+ Description-Content-Type: text/markdown
16
+ Requires-Dist: pandas>=1.5
17
+ Requires-Dist: httpx>=0.24
18
+ Requires-Dist: pyarrow>=12
19
+
20
+ # finzdata
21
+
22
+ Python client for the [FinzData](https://finzdata.com) market data API. It works like yfinance and adds
23
+ the datasets yfinance doesn't have.
24
+
25
+ ```
26
+ pip install finzdata
27
+ ```
28
+
29
+ Get a free API key at https://api.finzdata.com/ and set `FINZDATA_API_KEY`.
30
+
31
+ ```python
32
+ import finzdata as yf
33
+
34
+ msft = yf.Ticker("MSFT")
35
+ daily = msft.history(start="2020-01-01") # daily bars, split and dividend adjusted
36
+ bars = msft.history(interval="5m", start="2026-10-01") # 1m, 5m, 1h bars (Researcher+)
37
+ both = yf.download(["SPY", "QQQ"], period="max")
38
+
39
+ c = yf.Client()
40
+ gold = c.cot(report="legacy_fo", market="GOLD") # CFTC Commitments of Traders
41
+ rev = c.fundamentals(ticker="AAPL", concept="Revenues", as_of="2025-06-30") # SEC, point-in-time
42
+ cpi = c.macro("CPIAUCSL", as_of="2022-06-30") # US macro, as known on that date
43
+ regime = c.model("latest") # FinzData Quantitative Model (Researcher+)
44
+ hy = c.licensed("BAMLH0A0HYM2") # licensed third-party series (Researcher+)
45
+ ```
46
+
47
+ ## Datasets
48
+
49
+ - US equity bars, daily (incl. delisted names) and intraday 1-minute, 5-minute and hourly
50
+ - Splits and dividends
51
+ - CFTC Commitments of Traders, all reports, since 1986
52
+ - SEC XBRL fundamentals, as reported and point-in-time
53
+ - US macro series with every vintage (FRED/ALFRED), plus a release calendar
54
+ - FinzData Quantitative Model: macro regime labels, a nowcast and a market-stress probability
55
+ - Licensed series: Moody's, University of Michigan, Case-Shiller, ICE BofA, Cboe (incl. the VIX futures curve)
56
+
57
+ Free samples and the full file specification: https://finzdata.com/samples ·
58
+ Pricing: https://finzdata.com/pricing · Data status: https://finzdata.com/status ·
59
+ API reference: https://api.finzdata.com/docs
60
+
61
+ Bulk downloads (Researcher and above): `POST /v1/batch`, then fetch the `download_url`.
62
+ Full-history bundles and nightly updates: `GET /v1/bundles`.
63
+
64
+ Data is provided under the FinzData subscriber licence; redistribution is prohibited.
@@ -0,0 +1,8 @@
1
+ README_CLIENT.md
2
+ pyproject.toml
3
+ finzdata/__init__.py
4
+ finzdata.egg-info/PKG-INFO
5
+ finzdata.egg-info/SOURCES.txt
6
+ finzdata.egg-info/dependency_links.txt
7
+ finzdata.egg-info/requires.txt
8
+ finzdata.egg-info/top_level.txt
@@ -0,0 +1,3 @@
1
+ pandas>=1.5
2
+ httpx>=0.24
3
+ pyarrow>=12
@@ -0,0 +1 @@
1
+ finzdata
@@ -0,0 +1,27 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "finzdata"
7
+ version = "0.1.0"
8
+ description = "FinzData market data client: yfinance-style prices plus COT, SEC fundamentals, point-in-time macro and more"
9
+ readme = "README_CLIENT.md"
10
+ requires-python = ">=3.9"
11
+ dependencies = ["pandas>=1.5", "httpx>=0.24", "pyarrow>=12"]
12
+ keywords = ["market data", "stocks", "yfinance", "cot", "sec", "fred", "finance", "api"]
13
+ classifiers = [
14
+ "Programming Language :: Python :: 3",
15
+ "Intended Audience :: Financial and Insurance Industry",
16
+ "Topic :: Office/Business :: Financial :: Investment",
17
+ "Operating System :: OS Independent",
18
+ ]
19
+
20
+ [project.urls]
21
+ Homepage = "https://finzdata.com"
22
+ Documentation = "https://finzdata.com/docs"
23
+ Pricing = "https://finzdata.com/pricing"
24
+ Status = "https://finzdata.com/status"
25
+
26
+ [tool.setuptools]
27
+ packages = ["finzdata"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+