profitelligence 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.
Files changed (31) hide show
  1. profitelligence-0.1.0/.gitignore +7 -0
  2. profitelligence-0.1.0/CHANGELOG.md +20 -0
  3. profitelligence-0.1.0/LICENSE +21 -0
  4. profitelligence-0.1.0/PKG-INFO +236 -0
  5. profitelligence-0.1.0/README.md +185 -0
  6. profitelligence-0.1.0/codegen/generate.py +304 -0
  7. profitelligence-0.1.0/codegen/spec.json +6943 -0
  8. profitelligence-0.1.0/pyproject.toml +74 -0
  9. profitelligence-0.1.0/src/profitelligence/__init__.py +155 -0
  10. profitelligence-0.1.0/src/profitelligence/_base.py +34 -0
  11. profitelligence-0.1.0/src/profitelligence/_http.py +347 -0
  12. profitelligence-0.1.0/src/profitelligence/_version.py +3 -0
  13. profitelligence-0.1.0/src/profitelligence/client.py +123 -0
  14. profitelligence-0.1.0/src/profitelligence/errors.py +185 -0
  15. profitelligence-0.1.0/src/profitelligence/py.typed +0 -0
  16. profitelligence-0.1.0/src/profitelligence/resources/__init__.py +42 -0
  17. profitelligence-0.1.0/src/profitelligence/resources/analytics.py +315 -0
  18. profitelligence-0.1.0/src/profitelligence/resources/company.py +391 -0
  19. profitelligence-0.1.0/src/profitelligence/resources/discovery.py +155 -0
  20. profitelligence-0.1.0/src/profitelligence/resources/filings.py +160 -0
  21. profitelligence-0.1.0/src/profitelligence/resources/financials.py +296 -0
  22. profitelligence-0.1.0/src/profitelligence/resources/form4.py +1130 -0
  23. profitelligence-0.1.0/src/profitelligence/resources/fred.py +168 -0
  24. profitelligence-0.1.0/src/profitelligence/resources/graph.py +128 -0
  25. profitelligence-0.1.0/src/profitelligence/resources/institutional.py +582 -0
  26. profitelligence-0.1.0/src/profitelligence/table.py +407 -0
  27. profitelligence-0.1.0/tests/conftest.py +28 -0
  28. profitelligence-0.1.0/tests/test_client.py +104 -0
  29. profitelligence-0.1.0/tests/test_errors.py +139 -0
  30. profitelligence-0.1.0/tests/test_live.py +53 -0
  31. profitelligence-0.1.0/tests/test_table.py +109 -0
@@ -0,0 +1,7 @@
1
+ .venv/
2
+ dist/
3
+ *.egg-info/
4
+ __pycache__/
5
+ .pytest_cache/
6
+ .ruff_cache/
7
+ uv.lock
@@ -0,0 +1,20 @@
1
+ # Changelog
2
+
3
+ The Python client versions independently of the web app. Releases go out from
4
+ the public mirror at github.com/profitelligence/profitelligence-py; the
5
+ package itself is developed and generated upstream.
6
+
7
+ ## 0.1.0 — unreleased
8
+
9
+ First release.
10
+
11
+ - A typed client over the public Profitelligence API: 68 endpoints in nine
12
+ namespaces, generated from the API reference so the package cannot drift
13
+ from the documented contract.
14
+ - Pipe-delimited CSV responses parse into a `Table` of typed rows. Numbers are
15
+ numbers, dates are dates, and empty cells are `None`.
16
+ - `Table.to_pandas()` for a DataFrame, behind the `[pandas]` extra.
17
+ - API-key auth with the `ApiKey` scheme, or guest access with no key at all.
18
+ - Errors say what happened: `UpgradeRequired` carries the tier message,
19
+ `RateLimited` carries the retry window, and an in-band `error,...` body on a
20
+ 200 becomes `BadRequest` or `NoData` instead of a silent empty result.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Profitelligence
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,236 @@
1
+ Metadata-Version: 2.5
2
+ Name: profitelligence
3
+ Version: 0.1.0
4
+ Summary: SEC filings, insider trading and market signals in Python.
5
+ Project-URL: Homepage, https://profitelligence.com
6
+ Project-URL: Documentation, https://profitelligence.com/api-reference
7
+ Project-URL: Changelog, https://github.com/profitelligence/profitelligence-py/blob/main/CHANGELOG.md
8
+ Project-URL: Issues, https://github.com/profitelligence/profitelligence-py/issues
9
+ Project-URL: Source, https://github.com/profitelligence/profitelligence-py
10
+ Author-email: Profitelligence <support@profitelligence.com>
11
+ License: MIT License
12
+
13
+ Copyright (c) 2026 Profitelligence
14
+
15
+ Permission is hereby granted, free of charge, to any person obtaining a copy
16
+ of this software and associated documentation files (the "Software"), to deal
17
+ in the Software without restriction, including without limitation the rights
18
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19
+ copies of the Software, and to permit persons to whom the Software is
20
+ furnished to do so, subject to the following conditions:
21
+
22
+ The above copyright notice and this permission notice shall be included in all
23
+ copies or substantial portions of the Software.
24
+
25
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
+ SOFTWARE.
32
+ License-File: LICENSE
33
+ Keywords: 13f,api-client,edgar,finance,form4,fred,insider-trading,institutional-holdings,market-data,quant,sec
34
+ Classifier: Development Status :: 4 - Beta
35
+ Classifier: Intended Audience :: Financial and Insurance Industry
36
+ Classifier: Intended Audience :: Science/Research
37
+ Classifier: License :: OSI Approved :: MIT License
38
+ Classifier: Operating System :: OS Independent
39
+ Classifier: Programming Language :: Python :: 3
40
+ Classifier: Programming Language :: Python :: 3.10
41
+ Classifier: Programming Language :: Python :: 3.11
42
+ Classifier: Programming Language :: Python :: 3.12
43
+ Classifier: Programming Language :: Python :: 3.13
44
+ Classifier: Topic :: Office/Business :: Financial :: Investment
45
+ Classifier: Typing :: Typed
46
+ Requires-Python: >=3.10
47
+ Requires-Dist: httpx<1,>=0.27
48
+ Provides-Extra: pandas
49
+ Requires-Dist: pandas>=2.0; extra == 'pandas'
50
+ Description-Content-Type: text/markdown
51
+
52
+ # profitelligence
53
+
54
+ SEC filings, insider trading and market signals in Python.
55
+
56
+ ```bash
57
+ pip install profitelligence
58
+ ```
59
+
60
+ ```python
61
+ import profitelligence as prof
62
+
63
+ prof.api_key("pk_live_...") # or set PROFITELLIGENCE_API_KEY
64
+ prices = prof.company.ohlc("AAPL", days=90) # 90 rows, typed
65
+ prices[0].close # 305.69, a float
66
+ prices.df # a DataFrame, with [pandas]
67
+ ```
68
+
69
+ That is the whole idea. The Profitelligence API answers in pipe-delimited CSV.
70
+ This package parses it, types it, and hands you rows you can work with.
71
+
72
+ ---
73
+
74
+ ## What you get
75
+
76
+ Nine namespaces cover 68 endpoints. Every method is generated from the same API
77
+ reference the documentation site renders, so the package cannot describe an
78
+ endpoint the API does not have.
79
+
80
+ | Namespace | Data |
81
+ |---|---|
82
+ | `prof.company` | Profiles, daily prices, technical signals, corporate actions |
83
+ | `prof.filings` | 8-K summaries and filing patterns |
84
+ | `prof.form4` | Insider transactions, clusters, insider profiles |
85
+ | `prof.institutional` | 13F holdings, managers, crowded trades |
86
+ | `prof.financials` | Income statement, balance sheet, cash flow |
87
+ | `prof.fred` | Economic series from the Federal Reserve |
88
+ | `prof.discovery` | Search, spotlights, interesting companies |
89
+ | `prof.graph` | The knowledge graph |
90
+ | `prof.analytics` | Correlations, opportunity scores, strategies |
91
+
92
+ Every method carries the endpoint's own documentation. In a notebook,
93
+ `prof.form4.clusters?` shows the arguments, the tier it needs, and the columns
94
+ it returns.
95
+
96
+ ## Authentication
97
+
98
+ Get a key at [profitelligence.com/account/api-keys](https://profitelligence.com/account/api-keys).
99
+
100
+ ```python
101
+ prof.api_key("pk_live_...") # for a notebook
102
+ ```
103
+
104
+ ```bash
105
+ export PROFITELLIGENCE_API_KEY=pk_live_...
106
+ ```
107
+
108
+ You can also call with no key at all. Guests reach the free endpoints on the
109
+ top 500 symbols, which is enough to try the package before you sign up.
110
+
111
+ In a service, build a client and hold it. One client is one connection pool.
112
+
113
+ ```python
114
+ from profitelligence import Client
115
+
116
+ with Client(api_key="pk_live_...", timeout=60) as prof:
117
+ holdings = prof.institutional.manager_top_holdings("0001067983")
118
+ ```
119
+
120
+ ## Tables
121
+
122
+ CSV endpoints return a `Table`: named columns, typed values, one row object per
123
+ record. It is a normal Python sequence, so index it, slice it, and iterate it.
124
+
125
+ ```python
126
+ prices = prof.company.ohlc("AAPL,MSFT", days=180)
127
+
128
+ prices.columns # ['symbol', 'time', 'open', 'high', 'low', 'close']
129
+ len(prices) # 360
130
+ prices[0].close # 305.69 a float
131
+ prices[0].time # date(2026, 8, 17) a date
132
+ prices.column("close") # the whole column
133
+ prices.to_dicts() # plain dictionaries
134
+ ```
135
+
136
+ Types come from the API reference where it declares them, and from the data
137
+ where it does not. A column is typed as a whole: if one value will not parse,
138
+ the column stays text rather than becoming a mix you cannot do arithmetic on.
139
+ An empty cell is `None`, never `0` and never `""`.
140
+
141
+ For pandas, install the extra:
142
+
143
+ ```bash
144
+ pip install 'profitelligence[pandas]'
145
+ ```
146
+
147
+ ```python
148
+ frame = prices.df # or prices.to_pandas()
149
+ frame.set_index("time").close.resample("W").last()
150
+ ```
151
+
152
+ Date columns arrive as `datetime64`, so resampling and plotting work with no
153
+ further conversion.
154
+
155
+ JSON endpoints — the page routes, FRED, search, and the knowledge graph —
156
+ return the decoded body as it stands.
157
+
158
+ ## When a call does not work
159
+
160
+ Errors say what happened, in the API's own words.
161
+
162
+ ```python
163
+ try:
164
+ scores = prof.analytics.opportunities()
165
+ except prof.UpgradeRequired as error:
166
+ print(error.message) # the plan this endpoint needs
167
+ except prof.RateLimited as error:
168
+ print(error.retry_after) # seconds until the window resets
169
+ ```
170
+
171
+ | Error | Means |
172
+ |---|---|
173
+ | `AuthenticationError` | The key is absent, wrong, or revoked |
174
+ | `UpgradeRequired` | Your plan does not include this endpoint or this symbol |
175
+ | `RateLimited` | The window is spent. `retry_after`, `limit`, `remaining`, `reset` |
176
+ | `BadRequest` | An argument is missing or out of range |
177
+ | `NoData` | The API looked and found nothing to return |
178
+ | `ServerError` | The API failed. The client already retried twice |
179
+ | `Timeout` | No answer inside the timeout |
180
+
181
+ All of them inherit `ProfitelligenceError`.
182
+
183
+ A rate limit is never retried behind your back. A notebook that sleeps for a
184
+ minute without telling you is worse than an error you can see. Server errors
185
+ and timeouts are retried twice, with backoff.
186
+
187
+ Two of these deserve a word. The API sometimes reports a problem in-band: HTTP
188
+ 200, with a body of `error,<message>`. Read raw, that looks like success and
189
+ parses to nothing. This package raises instead — `BadRequest` when you caused
190
+ it, `NoData` when the API simply had nothing — so an empty result never passes
191
+ for a real one. A genuinely empty result, which the API returns as a header row
192
+ with no data rows, stays an empty `Table`.
193
+
194
+ ## What this package does not do
195
+
196
+ It reads. There is nothing here that writes to your account, and nothing that
197
+ places a trade.
198
+
199
+ It reports what filings and prices show. It does not advise, predict, or
200
+ recommend. What you do with the data is your decision, and a licensed advisor
201
+ is the right person to help you make it.
202
+
203
+ ## Rate limits and tiers
204
+
205
+ Each key has a request window and a symbol list that follow your plan. Guests
206
+ and Free see the top 500 symbols, Pro the top 6,000, Elite all of them. A
207
+ symbol outside your tier raises `UpgradeRequired` with the plan it needs.
208
+
209
+ ## How this package is built
210
+
211
+ The client is **generated**. The nine modules under
212
+ `src/profitelligence/resources/` are produced by `codegen/generate.py` from
213
+ `codegen/spec.json`, which is exported from the same API reference that renders
214
+ at [profitelligence.com/api-reference](https://profitelligence.com/api-reference).
215
+ That reference is the contract: an endpoint reaches this package by being
216
+ documented, not by someone hand-writing a signature.
217
+
218
+ Editing a generated file therefore has no lasting effect — the next generation
219
+ replaces it. The hand-written part is the core: `client.py`, `_http.py`,
220
+ `table.py` and `errors.py`.
221
+
222
+ ```bash
223
+ uv sync --group dev
224
+ pytest # offline, every response mocked
225
+ pytest -m live # hits the public API; no key needed for the free endpoints
226
+ ruff check . && ruff format --check .
227
+ ```
228
+
229
+ Development happens in a private repository and is pushed here in one
230
+ direction, so a pull request cannot be merged into this tree. Bug reports are
231
+ genuinely useful and are acted on — see
232
+ [CONTRIBUTING.md](CONTRIBUTING.md) for what helps most.
233
+
234
+ ## License
235
+
236
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,185 @@
1
+ # profitelligence
2
+
3
+ SEC filings, insider trading and market signals in Python.
4
+
5
+ ```bash
6
+ pip install profitelligence
7
+ ```
8
+
9
+ ```python
10
+ import profitelligence as prof
11
+
12
+ prof.api_key("pk_live_...") # or set PROFITELLIGENCE_API_KEY
13
+ prices = prof.company.ohlc("AAPL", days=90) # 90 rows, typed
14
+ prices[0].close # 305.69, a float
15
+ prices.df # a DataFrame, with [pandas]
16
+ ```
17
+
18
+ That is the whole idea. The Profitelligence API answers in pipe-delimited CSV.
19
+ This package parses it, types it, and hands you rows you can work with.
20
+
21
+ ---
22
+
23
+ ## What you get
24
+
25
+ Nine namespaces cover 68 endpoints. Every method is generated from the same API
26
+ reference the documentation site renders, so the package cannot describe an
27
+ endpoint the API does not have.
28
+
29
+ | Namespace | Data |
30
+ |---|---|
31
+ | `prof.company` | Profiles, daily prices, technical signals, corporate actions |
32
+ | `prof.filings` | 8-K summaries and filing patterns |
33
+ | `prof.form4` | Insider transactions, clusters, insider profiles |
34
+ | `prof.institutional` | 13F holdings, managers, crowded trades |
35
+ | `prof.financials` | Income statement, balance sheet, cash flow |
36
+ | `prof.fred` | Economic series from the Federal Reserve |
37
+ | `prof.discovery` | Search, spotlights, interesting companies |
38
+ | `prof.graph` | The knowledge graph |
39
+ | `prof.analytics` | Correlations, opportunity scores, strategies |
40
+
41
+ Every method carries the endpoint's own documentation. In a notebook,
42
+ `prof.form4.clusters?` shows the arguments, the tier it needs, and the columns
43
+ it returns.
44
+
45
+ ## Authentication
46
+
47
+ Get a key at [profitelligence.com/account/api-keys](https://profitelligence.com/account/api-keys).
48
+
49
+ ```python
50
+ prof.api_key("pk_live_...") # for a notebook
51
+ ```
52
+
53
+ ```bash
54
+ export PROFITELLIGENCE_API_KEY=pk_live_...
55
+ ```
56
+
57
+ You can also call with no key at all. Guests reach the free endpoints on the
58
+ top 500 symbols, which is enough to try the package before you sign up.
59
+
60
+ In a service, build a client and hold it. One client is one connection pool.
61
+
62
+ ```python
63
+ from profitelligence import Client
64
+
65
+ with Client(api_key="pk_live_...", timeout=60) as prof:
66
+ holdings = prof.institutional.manager_top_holdings("0001067983")
67
+ ```
68
+
69
+ ## Tables
70
+
71
+ CSV endpoints return a `Table`: named columns, typed values, one row object per
72
+ record. It is a normal Python sequence, so index it, slice it, and iterate it.
73
+
74
+ ```python
75
+ prices = prof.company.ohlc("AAPL,MSFT", days=180)
76
+
77
+ prices.columns # ['symbol', 'time', 'open', 'high', 'low', 'close']
78
+ len(prices) # 360
79
+ prices[0].close # 305.69 a float
80
+ prices[0].time # date(2026, 8, 17) a date
81
+ prices.column("close") # the whole column
82
+ prices.to_dicts() # plain dictionaries
83
+ ```
84
+
85
+ Types come from the API reference where it declares them, and from the data
86
+ where it does not. A column is typed as a whole: if one value will not parse,
87
+ the column stays text rather than becoming a mix you cannot do arithmetic on.
88
+ An empty cell is `None`, never `0` and never `""`.
89
+
90
+ For pandas, install the extra:
91
+
92
+ ```bash
93
+ pip install 'profitelligence[pandas]'
94
+ ```
95
+
96
+ ```python
97
+ frame = prices.df # or prices.to_pandas()
98
+ frame.set_index("time").close.resample("W").last()
99
+ ```
100
+
101
+ Date columns arrive as `datetime64`, so resampling and plotting work with no
102
+ further conversion.
103
+
104
+ JSON endpoints — the page routes, FRED, search, and the knowledge graph —
105
+ return the decoded body as it stands.
106
+
107
+ ## When a call does not work
108
+
109
+ Errors say what happened, in the API's own words.
110
+
111
+ ```python
112
+ try:
113
+ scores = prof.analytics.opportunities()
114
+ except prof.UpgradeRequired as error:
115
+ print(error.message) # the plan this endpoint needs
116
+ except prof.RateLimited as error:
117
+ print(error.retry_after) # seconds until the window resets
118
+ ```
119
+
120
+ | Error | Means |
121
+ |---|---|
122
+ | `AuthenticationError` | The key is absent, wrong, or revoked |
123
+ | `UpgradeRequired` | Your plan does not include this endpoint or this symbol |
124
+ | `RateLimited` | The window is spent. `retry_after`, `limit`, `remaining`, `reset` |
125
+ | `BadRequest` | An argument is missing or out of range |
126
+ | `NoData` | The API looked and found nothing to return |
127
+ | `ServerError` | The API failed. The client already retried twice |
128
+ | `Timeout` | No answer inside the timeout |
129
+
130
+ All of them inherit `ProfitelligenceError`.
131
+
132
+ A rate limit is never retried behind your back. A notebook that sleeps for a
133
+ minute without telling you is worse than an error you can see. Server errors
134
+ and timeouts are retried twice, with backoff.
135
+
136
+ Two of these deserve a word. The API sometimes reports a problem in-band: HTTP
137
+ 200, with a body of `error,<message>`. Read raw, that looks like success and
138
+ parses to nothing. This package raises instead — `BadRequest` when you caused
139
+ it, `NoData` when the API simply had nothing — so an empty result never passes
140
+ for a real one. A genuinely empty result, which the API returns as a header row
141
+ with no data rows, stays an empty `Table`.
142
+
143
+ ## What this package does not do
144
+
145
+ It reads. There is nothing here that writes to your account, and nothing that
146
+ places a trade.
147
+
148
+ It reports what filings and prices show. It does not advise, predict, or
149
+ recommend. What you do with the data is your decision, and a licensed advisor
150
+ is the right person to help you make it.
151
+
152
+ ## Rate limits and tiers
153
+
154
+ Each key has a request window and a symbol list that follow your plan. Guests
155
+ and Free see the top 500 symbols, Pro the top 6,000, Elite all of them. A
156
+ symbol outside your tier raises `UpgradeRequired` with the plan it needs.
157
+
158
+ ## How this package is built
159
+
160
+ The client is **generated**. The nine modules under
161
+ `src/profitelligence/resources/` are produced by `codegen/generate.py` from
162
+ `codegen/spec.json`, which is exported from the same API reference that renders
163
+ at [profitelligence.com/api-reference](https://profitelligence.com/api-reference).
164
+ That reference is the contract: an endpoint reaches this package by being
165
+ documented, not by someone hand-writing a signature.
166
+
167
+ Editing a generated file therefore has no lasting effect — the next generation
168
+ replaces it. The hand-written part is the core: `client.py`, `_http.py`,
169
+ `table.py` and `errors.py`.
170
+
171
+ ```bash
172
+ uv sync --group dev
173
+ pytest # offline, every response mocked
174
+ pytest -m live # hits the public API; no key needed for the free endpoints
175
+ ruff check . && ruff format --check .
176
+ ```
177
+
178
+ Development happens in a private repository and is pushed here in one
179
+ direction, so a pull request cannot be merged into this tree. Bug reports are
180
+ genuinely useful and are acted on — see
181
+ [CONTRIBUTING.md](CONTRIBUTING.md) for what helps most.
182
+
183
+ ## License
184
+
185
+ MIT. See [LICENSE](LICENSE).