pit-fundamentals 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,25 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ .eggs/
6
+
7
+ .venv/
8
+ venv/
9
+ env/
10
+ .env
11
+ .env.local
12
+
13
+ .pytest_cache/
14
+ .mypy_cache/
15
+ .ruff_cache/
16
+
17
+ .DS_Store
18
+ Thumbs.db
19
+
20
+ .idea/
21
+ .vscode/
22
+ *.swp
23
+
24
+ *.log
25
+ data-staging/
@@ -0,0 +1,90 @@
1
+ Metadata-Version: 2.5
2
+ Name: pit-fundamentals
3
+ Version: 0.1.0
4
+ Summary: Point-in-time company fundamentals from official regulator filings (US SEC EDGAR, Taiwan TWSE, Korea OpenDART) — as-first-reported, keyed by filing date, exportable. Zero dependencies.
5
+ Project-URL: Homepage, https://www.tradingagentapp.com/fundamentals
6
+ Project-URL: Documentation, https://www.tradingagentapp.com/developers
7
+ Project-URL: Licence terms, https://www.tradingagentapp.com/licences/personal
8
+ Author-email: WU Capital Limited <tradingagentapp@gmail.com>
9
+ License: MIT
10
+ Keywords: EDGAR,OpenDART,PIT,SEC,TWSE,backtesting,factor,financial-data,fundamentals,korea,look-ahead-bias,point-in-time,quant,stock-data,taiwan
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Financial and Insurance Industry
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Topic :: Office/Business :: Financial :: Investment
17
+ Requires-Python: >=3.9
18
+ Description-Content-Type: text/markdown
19
+
20
+ # pit-fundamentals
21
+
22
+ **Point-in-time company fundamentals from official regulator filings — as
23
+ first reported, keyed by filing date, exportable.** Zero dependencies
24
+ (pandas optional).
25
+
26
+ Backtests leak the future when they use restated numbers or use figures
27
+ before their filing date. This dataset stores every figure **as it was first
28
+ reported** and stamps it with its **filing date**, so `as_of` queries return
29
+ exactly what was public on that day.
30
+
31
+ | Market | Source | Coverage |
32
+ |---|---|---|
33
+ | US | SEC EDGAR (public domain) | ~6,900 filers · annual + quarterly · 2014→ |
34
+ | Taiwan | TWSE OpenAPI (Open Government Data License 1.0) | every listed company · accumulating quarterly |
35
+ | Korea | FSS OpenDART | full market · loading |
36
+
37
+ ## Install
38
+
39
+ ```bash
40
+ pip install pit-fundamentals
41
+ ```
42
+
43
+ ## 60-second start (no signup — public demo key built in)
44
+
45
+ ```python
46
+ import pit_fundamentals as pf
47
+
48
+ # TSMC's history, as first reported
49
+ rows = pf.fundamentals("2330.TW")
50
+
51
+ # What a backtest running on 2022-01-01 was allowed to know about Apple
52
+ snap = pf.latest("AAPL", as_of="2022-01-01")
53
+ print(snap["revenue"]) # FY2021, filed 2021-10-29 — nothing newer leaks
54
+
55
+ # The scored, resolved prediction panel (history incl. losses; delayed on free)
56
+ panel = pf.signals(market="TW", horizon="21d", limit=1000)
57
+
58
+ # pandas users
59
+ df = pf.to_df(rows)
60
+ ```
61
+
62
+ The demo key covers **25 flagship tickers (US · TW · KR) at full fidelity** —
63
+ full fields, full history. Paid plans unlock every ticker; your code doesn't
64
+ change:
65
+
66
+ ```bash
67
+ export PIT_FUNDAMENTALS_KEY=ta_live_xxxxxxxx
68
+ ```
69
+
70
+ ## Pricing & licences
71
+
72
+ Free / Personal US$29/mo / Commercial US$149/mo / Redistribution US$499/mo —
73
+ plans and full licence texts: <https://www.tradingagentapp.com/fundamentals>
74
+
75
+ What makes the licence unusual: **no export bans, no display-only clause, and
76
+ your derived research is yours forever** (explicitly, in writing — including
77
+ after cancellation). We ingest from public filings directly, so no upstream
78
+ vendor licence forbids you taking the data with you.
79
+
80
+ ## Notes worth knowing
81
+
82
+ - **Taiwan income statements are cumulative year-to-date** (Taiwan reporting
83
+ convention: Q2 = H1 total). Difference adjacent quarters for single-quarter
84
+ flows. Balance-sheet items are point-in-time as usual.
85
+ - Every API response embeds its statutory source attribution (e.g. 臺灣證券
86
+ 交易所 under OGDL 1.0).
87
+ - Factual, historical data only — no forecasts, no advice, no price/OHLCV.
88
+
89
+ Docs: <https://www.tradingagentapp.com/developers> ·
90
+ Field dictionary and examples included.
@@ -0,0 +1,71 @@
1
+ # pit-fundamentals
2
+
3
+ **Point-in-time company fundamentals from official regulator filings — as
4
+ first reported, keyed by filing date, exportable.** Zero dependencies
5
+ (pandas optional).
6
+
7
+ Backtests leak the future when they use restated numbers or use figures
8
+ before their filing date. This dataset stores every figure **as it was first
9
+ reported** and stamps it with its **filing date**, so `as_of` queries return
10
+ exactly what was public on that day.
11
+
12
+ | Market | Source | Coverage |
13
+ |---|---|---|
14
+ | US | SEC EDGAR (public domain) | ~6,900 filers · annual + quarterly · 2014→ |
15
+ | Taiwan | TWSE OpenAPI (Open Government Data License 1.0) | every listed company · accumulating quarterly |
16
+ | Korea | FSS OpenDART | full market · loading |
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ pip install pit-fundamentals
22
+ ```
23
+
24
+ ## 60-second start (no signup — public demo key built in)
25
+
26
+ ```python
27
+ import pit_fundamentals as pf
28
+
29
+ # TSMC's history, as first reported
30
+ rows = pf.fundamentals("2330.TW")
31
+
32
+ # What a backtest running on 2022-01-01 was allowed to know about Apple
33
+ snap = pf.latest("AAPL", as_of="2022-01-01")
34
+ print(snap["revenue"]) # FY2021, filed 2021-10-29 — nothing newer leaks
35
+
36
+ # The scored, resolved prediction panel (history incl. losses; delayed on free)
37
+ panel = pf.signals(market="TW", horizon="21d", limit=1000)
38
+
39
+ # pandas users
40
+ df = pf.to_df(rows)
41
+ ```
42
+
43
+ The demo key covers **25 flagship tickers (US · TW · KR) at full fidelity** —
44
+ full fields, full history. Paid plans unlock every ticker; your code doesn't
45
+ change:
46
+
47
+ ```bash
48
+ export PIT_FUNDAMENTALS_KEY=ta_live_xxxxxxxx
49
+ ```
50
+
51
+ ## Pricing & licences
52
+
53
+ Free / Personal US$29/mo / Commercial US$149/mo / Redistribution US$499/mo —
54
+ plans and full licence texts: <https://www.tradingagentapp.com/fundamentals>
55
+
56
+ What makes the licence unusual: **no export bans, no display-only clause, and
57
+ your derived research is yours forever** (explicitly, in writing — including
58
+ after cancellation). We ingest from public filings directly, so no upstream
59
+ vendor licence forbids you taking the data with you.
60
+
61
+ ## Notes worth knowing
62
+
63
+ - **Taiwan income statements are cumulative year-to-date** (Taiwan reporting
64
+ convention: Q2 = H1 total). Difference adjacent quarters for single-quarter
65
+ flows. Balance-sheet items are point-in-time as usual.
66
+ - Every API response embeds its statutory source attribution (e.g. 臺灣證券
67
+ 交易所 under OGDL 1.0).
68
+ - Factual, historical data only — no forecasts, no advice, no price/OHLCV.
69
+
70
+ Docs: <https://www.tradingagentapp.com/developers> ·
71
+ Field dictionary and examples included.
@@ -0,0 +1,36 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "pit-fundamentals"
7
+ version = "0.1.0"
8
+ description = "Point-in-time company fundamentals from official regulator filings (US SEC EDGAR, Taiwan TWSE, Korea OpenDART) — as-first-reported, keyed by filing date, exportable. Zero dependencies."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "WU Capital Limited", email = "tradingagentapp@gmail.com" }]
13
+ keywords = [
14
+ "point-in-time", "fundamentals", "PIT", "backtesting", "look-ahead-bias",
15
+ "SEC", "EDGAR", "taiwan", "TWSE", "korea", "OpenDART", "quant", "factor",
16
+ "financial-data", "stock-data",
17
+ ]
18
+ classifiers = [
19
+ "Development Status :: 4 - Beta",
20
+ "Intended Audience :: Financial and Insurance Industry",
21
+ "Intended Audience :: Science/Research",
22
+ "License :: OSI Approved :: MIT License",
23
+ "Programming Language :: Python :: 3",
24
+ "Topic :: Office/Business :: Financial :: Investment",
25
+ ]
26
+
27
+ [project.urls]
28
+ Homepage = "https://www.tradingagentapp.com/fundamentals"
29
+ Documentation = "https://www.tradingagentapp.com/developers"
30
+ "Licence terms" = "https://www.tradingagentapp.com/licences/personal"
31
+
32
+ [tool.hatch.build.targets.wheel]
33
+ packages = ["src/pit_fundamentals"]
34
+
35
+ [tool.hatch.build.targets.sdist]
36
+ include = ["src/pit_fundamentals", "README.md"]
@@ -0,0 +1,137 @@
1
+ """pit-fundamentals — point-in-time company fundamentals, zero dependencies.
2
+
3
+ As-first-reported figures from official regulator filings (US SEC EDGAR,
4
+ Taiwan TWSE, Korea FSS OpenDART), keyed by their FILING DATE so a backtest at
5
+ date T sees only what was public at T. Served by Trading Agent Data
6
+ (https://www.tradingagentapp.com/fundamentals).
7
+
8
+ Quickstart (works immediately — the public demo key covers 25 flagship
9
+ tickers at full fidelity, no signup):
10
+
11
+ import pit_fundamentals as pf
12
+
13
+ rows = pf.fundamentals("2330.TW") # full history
14
+ snap = pf.latest("AAPL", as_of="2022-01-01") # PIT snapshot
15
+ panel = pf.signals(market="TW", horizon="21d") # scored predictions
16
+
17
+ # with pandas installed:
18
+ df = pf.to_df(rows)
19
+
20
+ Paid keys unlock every ticker — set PIT_FUNDAMENTALS_KEY (or TRADING_AGENT_API_KEY)
21
+ in the environment, or pass api_key=... . Your code does not change otherwise.
22
+
23
+ Data licences: https://www.tradingagentapp.com/licences/personal
24
+ Taiwan data note: income-statement figures are cumulative year-to-date per
25
+ Taiwan reporting convention (Q2 = H1 total) — difference adjacent quarters for
26
+ single-quarter flows. Every response embeds its statutory source attribution.
27
+ """
28
+
29
+ from __future__ import annotations
30
+
31
+ import json
32
+ import os
33
+ import urllib.parse
34
+ import urllib.request
35
+
36
+ __all__ = ["fundamentals", "latest", "coverage", "signals", "to_df", "ApiError"]
37
+ __version__ = "0.1.0"
38
+
39
+ BASE_URL = os.environ.get("PIT_FUNDAMENTALS_BASE", "https://www.tradingagentapp.com/api/v1")
40
+ DEMO_KEY = "demo"
41
+
42
+
43
+ class ApiError(RuntimeError):
44
+ """Raised when the API returns a non-2xx response."""
45
+
46
+ def __init__(self, status: int, body: str):
47
+ super().__init__(f"HTTP {status}: {body[:300]}")
48
+ self.status = status
49
+ self.body = body
50
+
51
+
52
+ def _key(api_key: str | None) -> str:
53
+ return (
54
+ api_key
55
+ or os.environ.get("PIT_FUNDAMENTALS_KEY")
56
+ or os.environ.get("TRADING_AGENT_API_KEY")
57
+ or DEMO_KEY
58
+ )
59
+
60
+
61
+ def _get(path: str, params: dict, api_key: str | None):
62
+ qs = urllib.parse.urlencode({k: v for k, v in params.items() if v is not None})
63
+ req = urllib.request.Request(
64
+ f"{BASE_URL}{path}?{qs}",
65
+ headers={
66
+ "Authorization": f"Bearer {_key(api_key)}",
67
+ "User-Agent": f"pit-fundamentals/{__version__}",
68
+ },
69
+ )
70
+ try:
71
+ with urllib.request.urlopen(req, timeout=60) as r:
72
+ return json.loads(r.read().decode("utf-8"))
73
+ except urllib.error.HTTPError as e: # pragma: no cover - passthrough
74
+ raise ApiError(e.code, e.read().decode("utf-8", "replace")) from None
75
+
76
+
77
+ def fundamentals(
78
+ ticker: str,
79
+ *,
80
+ as_of: str | None = None,
81
+ metric: str | None = None,
82
+ from_: str | None = None,
83
+ market: str | None = None,
84
+ api_key: str | None = None,
85
+ ) -> list[dict]:
86
+ """As-first-reported history for one ticker (list of row dicts).
87
+
88
+ Row fields: m (metric), fy/fp (fiscal year/period), end (period end),
89
+ filed (filing date — the point-in-time key), v (value), u (unit).
90
+ `as_of` returns only rows with filed <= as_of (no look-ahead).
91
+ """
92
+ out = _get(
93
+ "/fundamentals",
94
+ {"ticker": ticker, "as_of": as_of, "metric": metric, "from": from_, "market": market},
95
+ api_key,
96
+ )
97
+ return out.get("data", [])
98
+
99
+
100
+ def latest(ticker: str, *, as_of: str | None = None, api_key: str | None = None) -> dict:
101
+ """The as-of snapshot: latest value per metric with filed <= as_of."""
102
+ out = _get("/fundamentals", {"ticker": ticker, "as_of": as_of, "view": "latest"}, api_key)
103
+ return out.get("data", {})
104
+
105
+
106
+ def coverage(api_key: str | None = None) -> dict:
107
+ """Markets, tickers, per-market manifests, and (free tier) the ticker allowlist."""
108
+ return _get("/fundamentals", {}, api_key)
109
+
110
+
111
+ def signals(
112
+ *,
113
+ market: str | None = None,
114
+ horizon: str | None = None,
115
+ from_: str | None = None,
116
+ to: str | None = None,
117
+ limit: int | None = None,
118
+ api_key: str | None = None,
119
+ ) -> list[dict]:
120
+ """The resolved (historical, scored) prediction panel — wins and losses.
121
+
122
+ Free/demo keys get a ~90-day-delayed view; this is factual history, not
123
+ forward recommendations. predicted_pct / actual_pct are FRACTIONS.
124
+ """
125
+ out = _get(
126
+ "/signals",
127
+ {"market": market, "horizon": horizon, "from": from_, "to": to, "limit": limit},
128
+ api_key,
129
+ )
130
+ return out.get("data", [])
131
+
132
+
133
+ def to_df(rows: list[dict]):
134
+ """Convert a row list to a pandas DataFrame (pandas required only here)."""
135
+ import pandas as pd # local import: the package itself stays zero-dep
136
+
137
+ return pd.DataFrame(rows)