You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
58 lines
2.0 KiB
Python
58 lines
2.0 KiB
Python
"""Oracle insider transactions (Form 4) and activist ownership (13D/G) service."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import datetime as dt
|
|
from typing import Any
|
|
|
|
from libs.oracle_client.client import OracleClient
|
|
from libs.oracle_client.models import (
|
|
Form4Transaction,
|
|
Form4AggregateResult,
|
|
ActivistEvent,
|
|
)
|
|
|
|
|
|
class InsiderService:
|
|
def __init__(self, client: OracleClient) -> None:
|
|
self._client = client
|
|
|
|
async def get_form4(
|
|
self,
|
|
ticker: str,
|
|
as_of: dt.date,
|
|
start: dt.date | None = None,
|
|
buy_only: bool = False,
|
|
csuite_only: bool = False,
|
|
) -> list[Form4Transaction]:
|
|
"""PIT-safe Form 4 transactions (filing_date <= as_of)."""
|
|
params: dict[str, Any] = {"as_of": str(as_of), "buy_only": buy_only, "csuite_only": csuite_only}
|
|
if start:
|
|
params["start"] = str(start)
|
|
data = await self._client.get(f"/api/v1/insider/form4/{ticker}", params=params)
|
|
return [Form4Transaction.model_validate(t) for t in data.get("transactions", [])]
|
|
|
|
async def get_form4_aggregate(
|
|
self,
|
|
ticker: str,
|
|
as_of: dt.date,
|
|
window_days: int = 30,
|
|
) -> Form4AggregateResult:
|
|
"""Aggregated insider buy metrics (P-code only, PIT-safe)."""
|
|
params: dict[str, Any] = {"as_of": str(as_of), "window_days": window_days}
|
|
data = await self._client.get(f"/api/v1/insider/form4/aggregate/{ticker}", params=params)
|
|
return Form4AggregateResult.model_validate(data)
|
|
|
|
async def get_activist_events(
|
|
self,
|
|
ticker: str,
|
|
as_of: dt.date,
|
|
start: dt.date | None = None,
|
|
) -> list[ActivistEvent]:
|
|
"""SC 13D/13G activist ownership events (filing_date <= as_of)."""
|
|
params: dict[str, Any] = {"as_of": str(as_of)}
|
|
if start:
|
|
params["start"] = str(start)
|
|
data = await self._client.get(f"/api/v1/ownership/13dg/{ticker}", params=params)
|
|
return [ActivistEvent.model_validate(e) for e in data.get("events", [])]
|