form4api 0.2.0__tar.gz → 0.3.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.
- {form4api-0.2.0 → form4api-0.3.0}/PKG-INFO +1 -1
- {form4api-0.2.0 → form4api-0.3.0}/form4api/_types.py +10 -3
- form4api-0.3.0/form4api/resources/_signals.py +57 -0
- {form4api-0.2.0 → form4api-0.3.0}/form4api/resources/_transactions.py +5 -1
- {form4api-0.2.0 → form4api-0.3.0}/form4api.egg-info/PKG-INFO +1 -1
- {form4api-0.2.0 → form4api-0.3.0}/pyproject.toml +1 -1
- {form4api-0.2.0 → form4api-0.3.0}/tests/test_client.py +7 -0
- form4api-0.2.0/form4api/resources/_signals.py +0 -29
- {form4api-0.2.0 → form4api-0.3.0}/LICENSE +0 -0
- {form4api-0.2.0 → form4api-0.3.0}/README.md +0 -0
- {form4api-0.2.0 → form4api-0.3.0}/form4api/__init__.py +0 -0
- {form4api-0.2.0 → form4api-0.3.0}/form4api/_client.py +0 -0
- {form4api-0.2.0 → form4api-0.3.0}/form4api/_errors.py +0 -0
- {form4api-0.2.0 → form4api-0.3.0}/form4api/_webhook_utils.py +0 -0
- {form4api-0.2.0 → form4api-0.3.0}/form4api/resources/__init__.py +0 -0
- {form4api-0.2.0 → form4api-0.3.0}/form4api/resources/_companies.py +0 -0
- {form4api-0.2.0 → form4api-0.3.0}/form4api/resources/_insiders.py +0 -0
- {form4api-0.2.0 → form4api-0.3.0}/form4api/resources/_webhooks.py +0 -0
- {form4api-0.2.0 → form4api-0.3.0}/form4api.egg-info/SOURCES.txt +0 -0
- {form4api-0.2.0 → form4api-0.3.0}/form4api.egg-info/dependency_links.txt +0 -0
- {form4api-0.2.0 → form4api-0.3.0}/form4api.egg-info/requires.txt +0 -0
- {form4api-0.2.0 → form4api-0.3.0}/form4api.egg-info/top_level.txt +0 -0
- {form4api-0.2.0 → form4api-0.3.0}/setup.cfg +0 -0
|
@@ -9,11 +9,18 @@ class Transaction:
|
|
|
9
9
|
company_name: str
|
|
10
10
|
insider_name: str
|
|
11
11
|
insider_cik: str
|
|
12
|
+
insider_title: str | None
|
|
13
|
+
is_director: bool
|
|
14
|
+
is_officer: bool
|
|
15
|
+
is10_pct_owner: bool
|
|
12
16
|
accession_number: str
|
|
13
17
|
security_title: str
|
|
14
18
|
transaction_code: str
|
|
19
|
+
is_open_market: bool
|
|
20
|
+
is10b5_plan: bool
|
|
15
21
|
shares_amount: float
|
|
16
22
|
price_per_share: float | None
|
|
23
|
+
total_value: float | None
|
|
17
24
|
shares_owned_after: float | None
|
|
18
25
|
direct_indirect: str | None
|
|
19
26
|
is_derivative: bool
|
|
@@ -83,6 +90,6 @@ class WebhookEvent:
|
|
|
83
90
|
last_status_code: int | None
|
|
84
91
|
is_dead: bool
|
|
85
92
|
payload: str
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Generator
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from form4api._types import InsiderSignal
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from form4api._client import Form4ApiClient
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SignalsResource:
|
|
13
|
+
def __init__(self, client: Form4ApiClient) -> None:
|
|
14
|
+
self._client = client
|
|
15
|
+
|
|
16
|
+
def list(
|
|
17
|
+
self,
|
|
18
|
+
*,
|
|
19
|
+
ticker: str | None = None,
|
|
20
|
+
cluster_buy: bool | None = None,
|
|
21
|
+
cluster_sell: bool | None = None,
|
|
22
|
+
page: int = 1,
|
|
23
|
+
per_page: int = 100,
|
|
24
|
+
) -> list[InsiderSignal]:
|
|
25
|
+
params: dict[str, str] = {"page": str(page), "per_page": str(per_page)}
|
|
26
|
+
if ticker is not None:
|
|
27
|
+
params["ticker"] = ticker
|
|
28
|
+
if cluster_buy is not None:
|
|
29
|
+
params["cluster_buy"] = str(cluster_buy).lower()
|
|
30
|
+
if cluster_sell is not None:
|
|
31
|
+
params["cluster_sell"] = str(cluster_sell).lower()
|
|
32
|
+
data = self._client._get("/v1/signals", params)
|
|
33
|
+
return [InsiderSignal(**item) for item in data]
|
|
34
|
+
|
|
35
|
+
def paginate(
|
|
36
|
+
self,
|
|
37
|
+
*,
|
|
38
|
+
ticker: str | None = None,
|
|
39
|
+
cluster_buy: bool | None = None,
|
|
40
|
+
cluster_sell: bool | None = None,
|
|
41
|
+
per_page: int = 100,
|
|
42
|
+
) -> Generator[list[InsiderSignal], None, None]:
|
|
43
|
+
page = 1
|
|
44
|
+
while True:
|
|
45
|
+
batch = self.list(
|
|
46
|
+
ticker=ticker, cluster_buy=cluster_buy, cluster_sell=cluster_sell,
|
|
47
|
+
page=page, per_page=per_page,
|
|
48
|
+
)
|
|
49
|
+
if not batch:
|
|
50
|
+
break
|
|
51
|
+
yield batch
|
|
52
|
+
if len(batch) < per_page:
|
|
53
|
+
break
|
|
54
|
+
page += 1
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
@@ -22,6 +22,7 @@ class TransactionsResource:
|
|
|
22
22
|
code: str | None = None,
|
|
23
23
|
from_date: str | None = None,
|
|
24
24
|
to_date: str | None = None,
|
|
25
|
+
exclude_10b5: bool | None = None,
|
|
25
26
|
page: int = 1,
|
|
26
27
|
per_page: int = 50,
|
|
27
28
|
) -> list[Transaction]:
|
|
@@ -38,6 +39,8 @@ class TransactionsResource:
|
|
|
38
39
|
params["from"] = from_date
|
|
39
40
|
if to_date is not None:
|
|
40
41
|
params["to"] = to_date
|
|
42
|
+
if exclude_10b5 is not None:
|
|
43
|
+
params["exclude_10b5"] = str(exclude_10b5).lower()
|
|
41
44
|
data = self._client._get("/v1/transactions", params)
|
|
42
45
|
return [Transaction(**item) for item in data]
|
|
43
46
|
|
|
@@ -50,6 +53,7 @@ class TransactionsResource:
|
|
|
50
53
|
code: str | None = None,
|
|
51
54
|
from_date: str | None = None,
|
|
52
55
|
to_date: str | None = None,
|
|
56
|
+
exclude_10b5: bool | None = None,
|
|
53
57
|
per_page: int = 50,
|
|
54
58
|
) -> Generator[list[Transaction], None, None]:
|
|
55
59
|
page = 1
|
|
@@ -57,7 +61,7 @@ class TransactionsResource:
|
|
|
57
61
|
batch = self.list(
|
|
58
62
|
ticker=ticker, cik=cik, insider_cik=insider_cik,
|
|
59
63
|
code=code, from_date=from_date, to_date=to_date,
|
|
60
|
-
page=page, per_page=per_page,
|
|
64
|
+
exclude_10b5=exclude_10b5, page=page, per_page=per_page,
|
|
61
65
|
)
|
|
62
66
|
if not batch:
|
|
63
67
|
break
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "form4api"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.0"
|
|
8
8
|
description = "Python client for the Form4API — real-time SEC Form 4 insider trading data"
|
|
9
9
|
requires-python = ">=3.11"
|
|
10
10
|
dependencies = ["httpx>=0.27"]
|
|
@@ -23,11 +23,18 @@ TX = {
|
|
|
23
23
|
"companyName": "Apple Inc.",
|
|
24
24
|
"insiderName": "Cook Timothy D",
|
|
25
25
|
"insiderCik": "0001214156",
|
|
26
|
+
"insiderTitle": "Chief Executive Officer",
|
|
27
|
+
"isDirector": False,
|
|
28
|
+
"isOfficer": True,
|
|
29
|
+
"is10PctOwner": False,
|
|
26
30
|
"accessionNumber": "0001234567-26-000001",
|
|
27
31
|
"securityTitle": "Common Stock",
|
|
28
32
|
"transactionCode": "P",
|
|
33
|
+
"isOpenMarket": True,
|
|
34
|
+
"is10b5Plan": False,
|
|
29
35
|
"sharesAmount": 1000.0,
|
|
30
36
|
"pricePerShare": 212.45,
|
|
37
|
+
"totalValue": 212450.0,
|
|
31
38
|
"sharesOwnedAfter": 5000.0,
|
|
32
39
|
"directIndirect": "D",
|
|
33
40
|
"isDerivative": False,
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
4
|
-
|
|
5
|
-
from form4api._types import InsiderSignal
|
|
6
|
-
|
|
7
|
-
if TYPE_CHECKING:
|
|
8
|
-
from form4api._client import Form4ApiClient
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class SignalsResource:
|
|
12
|
-
def __init__(self, client: Form4ApiClient) -> None:
|
|
13
|
-
self._client = client
|
|
14
|
-
|
|
15
|
-
def list(
|
|
16
|
-
self,
|
|
17
|
-
*,
|
|
18
|
-
ticker: str | None = None,
|
|
19
|
-
page: int = 1,
|
|
20
|
-
per_page: int = 100,
|
|
21
|
-
) -> list[InsiderSignal]:
|
|
22
|
-
params: dict[str, str] = {"page": str(page), "per_page": str(per_page)}
|
|
23
|
-
if ticker is not None:
|
|
24
|
-
params["ticker"] = ticker
|
|
25
|
-
data = self._client._get("/v1/signals", params)
|
|
26
|
-
return [InsiderSignal(**item) for item in data]
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|