# SEC Insider Trading Tracker — Form 4 API (`ryanclinton/sec-insider-trading`) Actor

Real-time SEC Form 4 API for behavioural insider-trading signal classification. Detects officer cluster buys, executive disposals, regime shifts. Suppresses compensation noise. Deterministic JSON output for hedge funds, compliance, and AI-agent workflows. No API key needed.

- **URL**: https://apify.com/ryanclinton/sec-insider-trading.md
- **Developed by:** [Ryan Clinton](https://apify.com/ryanclinton) (community)
- **Categories:** Developer tools, AI
- **Stats:** 29 total users, 6 monthly users, 98.0% runs succeeded, 3 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 trade fetcheds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## SEC Insider Trading Tracker

**Behavioral insider intelligence from SEC Form 4 filings.**

SEC Insider Trading Tracker is a real-time SEC Form 4 API for insider-trading monitoring, behavioral signal classification, and event-driven alert workflows.

Most insider-trading tools surface transactions. This actor classifies behavioural intent.

It suppresses compensation noise, detects coordinated insider activity, tracks issuer regime shifts, and produces deterministic decision-ready signals for automation and institutional workflows.

Built on raw SEC Form 4 XML filings. No LLMs in the decision layer. Fully auditable, replayable, routing-safe.

SEC Insider Trading Tracker is a **behavioral insider-trading signal platform** — a developer-first insider trading API and monitoring platform with deterministic signal classification, compensation-noise suppression, cluster detection, and workflow-ready escalation primitives. Designed for hedge funds, compliance surveillance teams, quant researchers, corporate IR teams, and AI-agent workflows.

**Real-time Form 4 monitoring with webhook-ready deterministic escalation outputs.** Pair with Apify Schedules for live drift detection, regime-shift alerts, and event-driven downstream workflows — every new Form 4 filing emits a `signalVerdict.classification` + `decisionReadiness.state` gate that automation can branch on without parsing prose.

> *A CEO conviction buy and a tax-withholding sale should not enter a workflow with equal weight. Most insider tools still treat them the same.*

---

### Why insider data fails most investors

Most insider-trading feeds overwhelm users with low-quality activity:

- tax-withholding sales,
- routine options exercises,
- scheduled 10b5-1 dispositions,
- compensation grants,
- low-materiality director sales.

The problem is not access to Form 4 filings. The problem is separating behavioural signal from reporting noise.

This actor is engineered to solve that distinction deterministically.

> *Raw Form 4 filings are data. Behavioural interpretation is the edge.*

---

### What this replaces

Insider workflows usually live across three places — none designed for the question *"which of these actually matters?"*:

| Tool category | Strength | Where it fails |
|---|---|---|
| Bloomberg / FactSet / CapIQ | Coverage, terminal UX, institutional trust | Filter-and-sort UX. No noise suppression. No behavioural interpretation. Analyst-driven synthesis. |
| OpenInsider / RSS / web trackers | Free, comprehensive, public | No prioritization. No signal-quality. No cluster intelligence. No workflow primitives. |
| Internal hedge-fund pipelines | Bespoke conviction scoring + routing | Fragmented. Analyst-specific. Non-portable. Usually not deterministically auditable. |

This actor productizes the institutional reasoning hedge funds usually build internally — deterministic conviction scoring, behavioural archetype classification, signal-decay modelling, decision-readiness gates, contradiction detection — and ships it as a stable JSON contract that downstream automation branches on.

It is **deterministic decision infrastructure** with **honest nullability**: every classification is reproducible; every external dependency is named with its sibling actor.

---

### What a high-quality signal actually looks like

A grade-A CEO open-market buy emits:

````

signalVerdict.classification: high-conviction-bullish
decisionReadiness.state:      thesis-ready
severity:                     critical
escalationRecommendation:     immediate-review
signalGenome:                 \[ceo, open-market-conviction-buy, critical-materiality, rare, low-noise, founder-conviction]

```

A coordinated 4-officer disposal emits:

```

signalVerdict.classification: distribution-risk
decisionReadiness.state:      thesis-ready
severity:                     critical
cluster.pattern:              officer-cluster-sale
regimeState.current:          accelerating-distribution-regime
signalGenome:                 \[senior-officer, strategic-sell, critical-materiality, rare, officer-cluster-confirmed, low-noise, distributor]

```

A routine tax-withholding sale emits:

```

signalVerdict.classification: compensation-noise
decisionReadiness.state:      noise
severity:                     informational
noiseClassification.suppressRecommended: true
signalGenome:                 \[insider, sell, low-materiality, low-noise]

```

Same Form 4 source. Three radically different routing decisions. The classifier is deterministic — the same input always produces the same verdict.

---

### SignalGenome — compressed behavioural recognition

SignalGenome is the most extreme expression of **trust-weighted compression** in the schema — every record carries a compact behavioural fingerprint:

```

\["ceo", "open-market-conviction-buy", "critical-materiality", "rare", "officer-cluster-confirmed", "low-noise"]

````

The same fields that drive routing also drive recognition. SignalGenome compresses **insider role + conviction quality + rarity + cluster participation + materiality + noise level + behavioural deviation** into a single human-scannable structure optimized for:

- Slack alert subjects
- dashboard cells
- PM review queues
- agent tool-call summaries
- compliance triage

Reading the genome takes ~1 second. Reading the equivalent 6 separate fields takes ~10. This is the perception primitive most insider tools lack.

The schema is optimized for operational decision compression, not just data extraction.

---

### What downstream systems branch on

Most downstream automation only needs 5 fields:

| Field | Use |
|---|---|
| `signalVerdict.classification` | 9-value enum — direction + strength + noise tag |
| `decisionReadiness.state` | Production-routing gate (only `thesis-ready` drops into auto-action) |
| `severity` | 6-tier institutional taxonomy (informational → critical) |
| `escalationRecommendation.level` | Routing tier (immediate-review / weekly-review / archive / ignore) |
| `signalGenome` | Token-scannable fingerprint for human + agent recognition |

These five fields compress hundreds of underlying behavioural and regime signals into deterministic routing primitives suitable for Slack escalation, portfolio review queues, compliance workflows, Dify agents, Zapier filters, and PM dashboards. This is the **trust-weighted compression** the actor's downstream consumers actually act on.

The full record carries 100+ fields for analysts who want depth. The 5 fields above are what production routing actually consumes.

This actor converts insider activity into deterministic routing primitives.

---

### Who this is for

| Audience | Primary use |
|---|---|
| Hedge fund research | cluster-buy + officer-disposal intelligence, watchlist drift detection |
| Compliance / surveillance teams | replayable insider-activity audit, regime-shift escalation |
| Quant researchers | structured behavioural features for alpha models |
| Corporate IR teams | governance-deterioration detection on portfolio companies |
| AI-agent builders | deterministic routing primitives, signalVerdict-driven automation |
| Activist / short-side researchers | leadership-consensus breakdown, executive-vs-board divergence |
| Retail investors | rare officer cluster buys + distress-pattern detection (with high-noise suppression) |

Each audience reads the same record differently. The `institutionalNarrative` block ships PM / risk-committee / compliance / short-seller views per record so the same data routes correctly to each desk.

Built for PM review queues, analyst escalation, portfolio surveillance, real-time insider-trading alert pipelines (Slack / PagerDuty / webhooks / Zapier / Make / n8n), event-driven AI-agent tool calls, and live Form 4 monitoring via Apify Schedules.

---

### Detect

- **Strategic insider buying** — rare officer buys, founder-confidence patterns, broad accumulation
- **Executive disposal waves** — multi-officer cluster sales, accelerated dispositions
- **Coordinated selling** — same-week participation, hierarchy spread, timing cohesion
- **Regime shifts** — accumulation → liquidation, executive-confidence-recovery, governance-deterioration
- **Rare insider behaviour** — first-time CEO buys in years, deviation from an insider's profile, extreme materiality
- **Noise vs signal** — automatic suppression of tax-withholding, scheduled 10b5-1, compensation grants

---

### The difference between noise and signal

The rare insider signals that matter are usually buried inside compensation noise.

Most insider-trade tools surface every Form 4 transaction equally. This actor classifies them by **behavioural quality** — a tax-withholding sale and a CEO conviction buy show up differently:

| Filing | Generic tools | This actor |
|---|---|---|
| Tax withholding (code F) | "Insider sold $500k" | `noiseClassification.noiseType: "tax-withholding"`, `signalVerdict.classification: "compensation-noise"`, `suppressRecommended: true` |
| CEO open-market buy | "CEO purchased shares" | `behaviorProfile.profileType: "founder-confidence-buy"`, `signalVerdict.classification: "high-conviction-bullish"`, `severity: "critical"` |
| 4-officer sell within 14 days | "4 insiders sold" | `cluster.pattern: "officer-cluster-sale"`, `regimeState.current: "accelerating-distribution-regime"`, `signalVerdict.classification: "distribution-risk"` |
| Routine options exercise | "Insider exercised options" | `intentClassification.primaryIntent: "compensation-vesting"`, `signalQuality.tier: "background-noise"`, `suppressRecommended: true` |
| Director cluster buy after price drop | "3 directors bought" | `cluster.coordinationSignals.timingCohesion: "tight"`, `signalVerdict.classification: "bullish"`, `regimeState.current: "accumulation-regime"` |

---

### Decision-output stack (what each block answers)

The output is engineered for **trust-weighted compression** — the same data, stratified for different reading speeds:

| Reading speed | What you read | Question answered |
|---|---|---|
| 5 seconds | `signalVerdict.classification` + `severity` + `decisionReadiness.state` | "Should I look at this right now?" |
| 30 seconds | `decisionCards[]` + `signalCards[]` + `signalGenome` + `oneLine` + `headline` | "What's the headline finding for the run?" |
| 5 minutes | Full record — `behaviorProfile` + `intentClassification` + `regimeState` + `confidenceDrivers` + `contradictionSignals` + `narrativeDelta` | "Why does the verdict say what it says?" |
| Reviewer | `decisionSnapshot` + `runManifest` + `inputsHash` | "Is this decision reproducible / auditable?" |

---

### Deterministic decision infrastructure

This actor is engineered as **auditable institutional intelligence**, not black-box AI finance magic. The trust architecture is the core product — every classification, score, and prediction is deterministic, replayable, and proactively honest about its own limits.

Unlike opaque AI scoring systems, this actor uses deterministic behavioural classification over SEC filing patterns. The actor is designed for institutional workflows where explainability and replayability matter more than opaque scoring. The system surfaces uncertainty explicitly instead of masking it behind aggregate scores.

#### Trust surfaces

| Surface | What it does |
|---|---|
| `confidenceCalibration` | Surfaces overconfidence proactively — cold-start records carry `overconfidenceRisk: "high"` even when raw `decision.confidence` reads above 0.8 |
| `modelIntegrity` | Per-record + run-level integrity (classificationIntegrity / dataCompleteness / externalDependencyRisk) |
| `manipulationResistance` | Detects staggered-disposal + wash-pattern + fragmentation. `gamingResistance: "high"` records are clean for production routing |
| `contradictionSignals` | Internal-classifier inconsistency detector — records with high-severity contradictions can never reach `thesis-ready` |
| `decisionReadiness.state` | Production-routing gate — only `thesis-ready` records drop into auto-action queues |
| `signalAttribution` (reserved) | Reserved structure for v5 outcome-validation joins via `finnhub-stock-data` sibling — buyers see the v5 contract baked in today |
| `decisionSnapshot` | Every record carries `eventId + inputsHash + rulesApplied + profileSnapshot`. Same input + same profile = same eventId across runs |

#### Multi-perspective reading

The same record reads differently depending on who's consuming it. The `institutionalNarrative` block ships four perspectives per transaction — `portfolioManagerView` (long-thesis support / pressure), `riskCommitteeView` (concentration limits + risk flags), `complianceView` (routine vs flag), `shortSellerView` (short-thesis support / contradiction). A grade-A insider buy reads as "long-thesis support" to a PM AND "short-thesis contradiction — re-examine entry" to a short-seller. Same data, four deterministic-template frames.

#### Anticipatory layer

`forwardEscalationRisk` predicts the next-14-day trajectory: `probabilityOfEscalation14d` (0-1) + `expectedNextState` + `likelyDrivers[]` + `confidence`. The prediction is heuristic + deterministic — same inputs always produce the same probability, every driver code is on the record, and high-severity contradictions proactively suppress the prediction (the actor doesn't predict when it doesn't trust its own classification).

#### Honest nullability

For fields requiring external data this actor doesn't have — market cap, earnings calendars, multi-year reputation history — the field ships with `null` and a `note` pointing at the sibling actor that delivers it (`finnhub-stock-data`, `sec-edgar-filing-analyzer`). **No fabrication.** Buyers see what's promised AND what's reserved for v5+ in the same schema.

Honest nullability is the trust contract: every promised field that can't be honestly populated today is reserved with a sibling pointer instead of fabricated.

Confidence is capped when behavioural history is insufficient. Signals with internal contradictions cannot escalate automatically.

#### Production-grade contracts

- **Stable enum tokens** — every classification field uses a documented enum that's additive across minor versions
- **Composable JSON-only output** — six record types, one stable contract
- **Routing-safe** — designed for Slack, PagerDuty, Zapier, agent tool calls. The actor produces routing primitives; the customer's automation consumes them
- **Watchlist mode** — opt-in `watchlistName` + named KV store enables cross-run drift, regime-shift detection, cold-start → mature progression. Restricted-permission tokens probe-once and gracefully degrade
- **Low false-positive design** — suppression engine + contradiction detection + cold-start caps + noise-aware scoring conspire to keep `high-conviction-bullish` rare. When it fires, it's worth reading

---

### Architecture — five-layer deterministic decision infrastructure

| Layer | Per-record question | Example fields |
|---|---|---|
| **Extraction** | What does the SEC filing say? | `sharesTraded`, `pricePerShare`, `totalValue`, `transactionType` |
| **Intelligence** | What kind of signal is this? | `direction`, `materiality`, `unusualness`, `insiderRole`, `transactionSignals[]` |
| **Operational** | What's happening across the issuer + cohort? | `clusterMembership`, `issuerState`, `behaviorFingerprint`, `triggersFired[]` |
| **Decision-infrastructure** | Should a human look at this RIGHT NOW? | `decision`, `recommendedAction`, `reviewSla`, `escalationRecommendation`, `priorityQueue` |
| **Temporal** | What changed since last run? | `temporalSignals`, `delta`, `stateTransition`, `regimeShift`, `narrativeDelta`, `runDelta` |

Every transaction emits `recordType: "transaction"`. Every detected cluster emits `recordType: "cluster"`. Every issuer emits `recordType: "issuer-summary"`. Every run ends with one `recordType: "batch-summary"` carrying portfolio state, priority queue, watchlist analytics, and run manifest.

---

### What makes a strong signal?

Most insider-trade tools surface every transaction equally. A $5M CEO buy and a $50k tax-withholding sale both show up as "insider activity." That's noise.

This actor classifies transactions by **behavioural quality**, not just dollar value. The strongest signals carry **multiple converging factors**:

| Signal pattern | Why it matters |
|---|---|
| **Rare open-market officer buy** — CEO/CFO/COO buying with personal money, direct ownership, after months/years of no buys | Senior officers rarely buy on the open market — when they do, it usually correlates with management confidence in upcoming fundamentals. The actor flags these as `behaviorProfile.profileType = "founder-confidence-buy"` or `"conviction-buyer"`. |
| **Multi-officer cluster buy** — 2+ distinct senior officers buying same direction within a 30-day window | Coordinated officer accumulation is one of the highest-quality bullish signals in insider data. The actor flags clusters with `coordinationSignals.executiveConcentration = "high"` and `pattern = "officer-cluster-buy"`. |
| **Strategic distribution by senior officer** — large disposal by CEO/CFO with critical materiality, post-vesting period | Senior-officer disposals at scale can signal sentiment shift or planned liquidity — the materiality + intent classifier separates routine 10b5-1 from discretionary distribution. |
| **Coordinated reduction across hierarchy** — multiple officers + directors selling within days, broad hierarchy spread | The `coordinationSignals.hierarchySpread[]` field surfaces when the cluster crosses CEO/CFO/Director boundaries — a stronger signal than any individual sale. |
| **Behavioural deviation** — insider activity that breaks their established pattern (first buy in years, sudden cluster after silence, accelerated disposal vs scheduled cadence) | The `behaviorProfile.behaviorShift` and `unusualness.factors[]` arrays make deviation explicit. Watchlist mode accumulates per-insider history for stronger deviation detection across runs. |
| **High materiality + high unusualness + low noise** — composite signal where dollar size, position impact, behavioural rarity, and signal-quality scoring all converge | The `signalQuality.tier = "institutional-grade"` (score ≥ 80) is the headline filter for high-conviction analysts and quants. |

**Weak signals (auto-suppressed):**

- **Tax-withholding (transaction code F)** — automatic disposal to cover vesting tax, not discretionary
- **Grant/award (code A)** — equity compensation, not an open-market signal
- **Routine options exercise (code M/C)** — typically scheduled vesting activity
- **Small disposals by non-senior insiders** — likely portfolio rebalancing or 10b5-1 cadence
- **Low-materiality grants from compensation cycles** — predictable comp activity, no signal

The `noiseClassification.suppressRecommended = true` boolean is the production-routing primitive — downstream automation can branch `WHERE noiseClassification.suppressRecommended = false` to filter out compensation noise without silently dropping the records.

### Behavioural archetypes

Every transaction carries a `behaviorProfile.profileType` enum. Same insider × same dollar value, different archetype = different signal. The classifier is deterministic: pattern detection over the insider's run-level activity (and watchlist-level history when watchlist mode is on).

**Bullish archetypes**

- `strategic-accumulator` — repeated direct buys across multiple transactions, all direct ownership
- `conviction-buyer` — single high-materiality officer open-market buy with no offsetting sells
- `opportunistic-buyer` — material officer buys mixed with prior dispositions
- `crisis-accumulator` — accumulation pattern during high-pressure issuer state (requires watchlist context)
- `founder-confidence-buy` — CEO direct open-market buy with critical materiality

**Neutral / compensation archetypes**

- `compensation-cycler` — grants + immediate withholding, dominant compensation activity
- `routine-options-exerciser` — repeat options exercises with no offsetting buys
- `scheduled-seller` — repeated similar-size sales consistent with a 10b5-1 plan
- `liquidity-manager` — mixed buy/sell with no dominant pattern

**Bearish archetypes**

- `strategic-distributor` — sell-dominant senior-officer activity with critical materiality
- `accelerated-disposal` — multiple senior-officer sales within a short window
- `governance-exit-pattern` — senior-officer dispositions correlated with departure indicators (full detection requires watchlist context)
- `pre-event-deleveraging` — sells preceding catalyst events (full detection requires earnings-calendar integration via finnhub-stock-data sibling)

---

### Why use SEC Insider Trading Tracker

Corporate insiders -- officers, directors, and shareholders who own 10% or more of a company's stock -- are legally required to report their transactions to the SEC within two business days via Form 4 filings. These disclosures are among the most closely watched signals on Wall Street because insiders have privileged knowledge of their own company's operations, pipeline, and financial health. When insiders buy with their own money, it often reflects genuine confidence in the company's future. When they sell large blocks, it can signal concern or a simple need for liquidity.

Manually browsing the SEC EDGAR website to find and interpret these filings is tedious and time-consuming. Each Form 4 is filed as a raw XML document that requires careful parsing to extract the meaningful data -- who traded, what they traded, how many shares, at what price, and how much they still hold. This actor automates the entire pipeline from search to structured output, saving hours of manual work per research session.

Whether you are an individual investor screening for insider buying signals, a compliance team monitoring portfolio companies, a financial journalist investigating unusual activity, or a quant researcher building trading models, this actor gives you programmatic access to the same insider trading data used by institutional investors and hedge funds -- at a fraction of the cost of commercial data providers.

---

### Key features

- **Insider behavioural fingerprinting** — Every transaction carries a `behaviorProfile` block with one of 14 archetypes (`strategic-accumulator`, `founder-confidence-buy`, `conviction-buyer`, `compensation-cycler`, `accelerated-disposal`, `strategic-distributor`, …) + confidence + signalReliability + activity-pattern array. Pure deterministic classification — no LLMs, no external APIs.
- **Transaction intent classification** — `intentClassification.primaryIntent` separates `discretionary-conviction-buy` from `tax-obligation` from `scheduled-10b5-1` from `liquidity-stress-sale` (12 stable intents). Lets users filter `WHERE intentClassification.primaryIntent IN ('discretionary-conviction-buy', 'opportunistic-accumulation')` to skip compensation noise.
- **Noise suppression engine** — `noiseClassification.suppressRecommended: boolean` flags compensation cycles, tax withholding, scheduled dispositions, and routine options exercises. Records still appear in the dataset but downstream automation can branch on the boolean to filter without dropping data.
- **Quality-of-Signal scoring** — Top-level `signalQuality` block with composite score 0-100 + tier (`institutional-grade` / `high` / `moderate` / `background-noise`) + rarity enum + confidence. The headline filter for high-conviction analysts and quants.
- **6-tier institutional severity taxonomy** — Every record carries `severity` enum: `informational` / `notable` / `elevated` / `significant` / `exceptional` / `critical`. Standard institutional vocabulary across transactions, clusters, and issuer summaries.
- **Multi-insider cluster coordination signals** — Detected clusters carry `coordinationSignals` with `coordinationStrength` (0-1), `executiveConcentration` (high/medium/low/none), `sameWeekParticipation` count, `hierarchySpread[]` (CEO/CFO/Director hierarchy crossings), and `timingCohesion` (tight/moderate/loose) — cluster intensity beyond just member count.
- **Per-issuer regime classifier** — `regimeState.current` enum: `accumulation-regime` / `liquidation-regime` / `governance-deterioration-regime` / `executive-confidence-recovery` / `insider-silence-breakdown` / `accelerating-distribution-regime` / `mixed-regime` / `no-regime`. Hedge-fund-grade operational state vocabulary.
- **Signal cards (dashboard-ready)** — Each transaction emits up to 3 `signalCards[]` with `type` / `severity` / `headline` / `confidence`. Card types: `rare-ceo-buy`, `senior-officer-buy`, `critical-officer-disposal`, `large-disposal`, `strategic-accumulator`, `founder-confidence-buy`, `liquidity-stress`, `extreme-deviation`. Drop straight into Slack, newsletters, exec emails.
- **Ownership delta intelligence** — `ownershipDelta` block measures position-impact (holdingChangePct, priorHoldings, newHoldings, ownershipConviction) — distinct from raw dollar value. A 40% increase in holdings matters more than $1M.
- **Context narrative** — Paste-ready 3-line narrative per transaction (`historicalSignificance` / `behavioralDeviation` / `timingInterpretation` + summary). Generated deterministically from existing fields — no LLMs, no hallucinations.
- **Direct SEC EDGAR access** — Queries the official EDGAR full-text search index at efts.sec.gov for Form 4 filings with zero third-party dependencies
- **Complete Form 4 XML parsing** — Extracts both non-derivative transactions (stock purchases, sales, gifts) and derivative transactions (options exercises, conversions, expirations)
- **Per-transaction decision layer** — Every record carries `direction`, `materiality` (0-100 score + critical/high/medium/low band), `unusualness`, `insiderRole` (CEO/CFO/COO/Officer/Director/10% Owner with seniorityRank), `decision.posture`, `recommendedAction`, `reviewSla` (P0–P4), and `escalationRecommendation`
- **Cluster detection** — Surfaces ≥2 distinct insiders moving the same direction within a 30-day window, classified as `officer-cluster-buy`, `officer-cluster-sale`, `broad-cluster-buy`, `broad-cluster-sale`, or generic `cluster-buy`/`cluster-sale`
- **Per-issuer state synthesis** — `issuerState` block: sentiment (bullish/bearish/mixed/neutral), `insiderPressureIndex` (0-100 composite), `transactionVelocity`, `governanceFootprint`, `watchStatus` (no-action / monitor / attention-required / urgent / critical)
- **Watchlist mode** — Persists per-issuer state across runs. Emits `temporalSignals`, `delta` (new/changed/unchanged/recovered/degraded), `stateTransition`, `historicalProfile` (cumulative track record), `regimeShift` detection, and `narrativeDelta` (paste-ready exec sentences)
- **Mode presets + persona-shaped routing** — 7 modes (monitoring / cluster-detection / compliance / sentiment / officer-tracking / raw / auto), 7 personas (quant / fundamental-analyst / compliance / hedge-fund-research / retail-monitoring / corporate-ir / generic), 7 routing profiles bundling persona + trigger packs + SLA tightening
- **Trigger packs** — Pre-built deterministic rule bundles: `cluster-buy`, `cluster-sale`, `executive-disposal`, `large-purchase`, `amendment-burst`, `distress-watch`. Add custom rules via the `triggers` input
- **Multi-issuer portfolio mode** — Pass `queries: ["AAPL", "TSLA", "NVDA"]` to operate as a portfolio decision engine. Emits `portfolioState`, `priorityQueue`, `immediateReviewQueue`, and cross-issuer `watchlistAnalytics`
- **Suite navigation** — Every record carries `actorGraph`, `nextActions[]`, `improvementSuggestions[]`, and `inlineEnrichmentHints` pointing at sibling actors (sec-edgar-filing-analyzer, company-deep-research, finnhub-stock-data, congress-stock-tracker)
- **Decision snapshot for compliance replay** — Every record carries `decisionSnapshot` with `inputsHash`, `rulesApplied[]`, and `profileSnapshot` so auditors can reproduce any decision deterministically
- **KV mirrors** — `SUMMARY` (full batch summary), `OUTPUT` (deterministic full output), `MANIFEST` (run manifest with internal-table version pins), `ALERTS` (immediate-review queue), `COST_MODEL` (per-outcome predicted spend)
- **Output profiles** — `minimal` / `standard` / `full` / `llm` shrink the field set without losing the decision primitives
- **Flexible search** — Search by company name ("Apple Inc."), ticker symbol ("AAPL"), CIK number ("320193"), or an insider's name
- **Transaction type filtering** — Narrow results to only purchases, sales, grants/awards, or options exercises
- **Custom date ranges** — Specify start and end dates in YYYY-MM-DD format, or rely on the default 30-day lookback window
- **Minimum value threshold** — Exclude small or insignificant transactions by setting a dollar floor
- **SEC rate-limit compliance** — Built-in throttling at approximately 8 requests per second with exponential backoff retry on 429 responses
- **No API key required** — All data comes from publicly available SEC EDGAR endpoints

---

### Choose your mode

Modes are JOB-named — pick what you're doing, not what features to enable. The original mechanical names (monitoring / cluster-detection / etc.) remain as legacy aliases.

| Mode | Job | Bundles |
|---|---|---|
| `alpha-hunter` | Find rare officer buys, strategic accumulation, high-quality bullish insiders | clusters + issuer state + delta + cluster-buy + large-purchase + distress-watch packs |
| `governance-risk` | Detect executive unloading, clustered exits, deterioration patterns | full output profile + delta + cluster-sale + executive-disposal + amendment-burst + distress-watch packs |
| `compliance-surveillance` | Full activity audit trail with replay-ready decision snapshots | full output profile + delta + every cluster + executive + amendment pack |
| `executive-sentiment` | C-suite directional behaviour only (CEO / CFO / COO / 10% Owner) | clusters + executive-disposal + large-purchase packs |
| `distress-radar` | Liquidity-pattern sells, accelerated disposition, emergency-behaviour signals | clusters + delta + cluster-sale + executive-disposal + distress-watch packs |
| `monitoring` (legacy) | Daily / weekly portfolio scans | clusters + issuer summary + batch insights |
| `cluster-detection` (legacy) | Cluster-only signal feeds | clusters only, no issuer summary |
| `compliance` (legacy alias) | Compliance review pipelines | full surface + delta + audit replay |
| `sentiment` (legacy alias) | Sentiment dashboards | clusters + issuer state + delta |
| `officer-tracking` (legacy alias) | CEO/CFO/COO/10% only | clusters + executive-disposal + large-purchase packs |
| `raw` | Power users — direct data access, no decision layer | no clusters, no summaries, raw transactions |
| `auto` | Auto-detect based on input shape | currently resolves to monitoring; full input-shape detection deferred |

### Choose your persona

| Persona | Suppresses | Escalates on | Audience |
|---|---|---|---|
| `quant` | tax-withholding, small-grant | large-purchase, cluster-buy, cluster-sale | quant-research, algo-signal |
| `fundamental-analyst` | tax-withholding, small-grant, small-exercise | executive-disposal, cluster-buy, large-purchase | equity-research, analyst |
| `compliance` | (nothing — full surface) | executive-disposal, cluster-buy, cluster-sale, amendment-burst | compliance, legal, audit |
| `hedge-fund-research` | tax-withholding | cluster-buy, cluster-sale, distress-watch | hf-pm, hf-analyst |
| `retail-monitoring` | tax-withholding, small-grant, small-exercise, small-sale | cluster-buy, large-purchase | retail, newsletter |
| `corporate-ir` | small-grant | cluster-sale, executive-disposal | ir-team, cfo-office |
| `generic` (default) | tax-withholding | cluster-buy, cluster-sale, large-purchase, executive-disposal | general |

Every persona has a documented `ignoreThreshold`. When `alertQuality.urgency` falls below that threshold for a record, `escalationRecommendation.ignoreRecommendation` is set to `true` so downstream automation can filter the noise without losing the data.

### Choose your routing profile

Routing profiles bundle persona + trigger packs + SLA tightening + alert payloads in one input:

| Profile | Persona | Trigger packs | SLA tightening |
|---|---|---|---|
| `quant-monitor` | quant | cluster-buy, cluster-sale, large-purchase | 0h |
| `compliance-officer` | compliance | cluster-buy, cluster-sale, executive-disposal, amendment-burst | 24h |
| `hedge-fund` | hedge-fund-research | cluster-buy, cluster-sale, distress-watch | 12h |
| `pe-operating` | fundamental-analyst | executive-disposal, cluster-sale | 0h |
| `corporate-ir` | corporate-ir | cluster-sale, executive-disposal, distress-watch | 24h |
| `retail-investor` | retail-monitoring | cluster-buy, large-purchase | 0h |
| `generic` (default) | generic | cluster-buy, cluster-sale, large-purchase | 0h |

### Cohort-scale audits (50+ tickers, year-scale dates)

Apify's default 1h run timeout can be exceeded on large cohorts. Two patterns work:

1. **Override the timeout per run** — set `timeoutSecs: 0` (unlimited) or `timeoutSecs: 14400` (4h) in your run options. The actor's `defaultRunOptions.timeoutSecs` is set to 7200 (2h) so most cohort runs complete naturally.
2. **Chunk by sector via Apify Schedules** — split S&P 500 into ~11 GICS sector batches × ~50 tickers each. Each chunk completes in well under the timeout; merge downstream. Apify Schedules support multiple Tasks per schedule.

The runtime budget (`runtimeBudgetSeconds`, default 3000s) is a separate soft cap that emits partial results instead of letting Apify's hard timeout produce a silent failure. For very large cohorts, raise it.

---

### When NOT to use this actor

| Anti-use case | Use this sibling actor instead |
|---|---|
| You want **all SEC filings** (10-K, 10-Q, 8-K, DEF 14A) — not just Form 4 | [sec-edgar-filing-analyzer](https://apify.com/ryanclinton/sec-edgar-filing-analyzer) |
| You want **full-text search across the EDGAR filing index** with flexible filters | [edgar-filing-search](https://apify.com/ryanclinton/edgar-filing-search) |
| You want **congressional trading** (Members of Congress, not corporate insiders) | [congress-stock-tracker](https://apify.com/ryanclinton/congress-stock-tracker) |
| You want **stock price + fundamentals** to combine with insider signals | [finnhub-stock-data](https://apify.com/ryanclinton/finnhub-stock-data) |
| You want a **broader company intelligence brief** that includes insider activity as one signal | [company-deep-research](https://apify.com/ryanclinton/company-deep-research) |
| You want **13F holdings** (institutional positions, not individual transactions) | [sec-13f-holdings](https://apify.com/ryanclinton/sec-13f-holdings) |

### Comparison vs alternatives

| Capability | This actor (v2) | Bloomberg Terminal | OpenInsider | Form4 RSS feeds |
|---|---|---|---|---|
| Direct SEC EDGAR source | Yes | Indirect | Yes | Yes |
| Per-transaction decision layer (materiality, unusualness, escalation) | Yes | No | No | No |
| Cluster detection | Yes (deterministic) | Manual | Partial | No |
| Per-issuer state engine + watch status | Yes | Manual | No | No |
| Watchlist + cross-run drift + regime shift | Yes | Yes | No | No |
| Persona-shaped escalation (quant / compliance / IR / etc.) | Yes | No | No | No |
| Trigger packs + custom rules | Yes | Yes | No | No |
| Compliance audit replay (decisionSnapshot) | Yes | Limited | No | No |
| Cost | $0.002/transaction | $24,000+/year/seat | Free (web) | Free (web) |

Insider trading data is informational. None of the outputs of this actor are investment advice.

### How to use

#### Using the Apify Console

1. Go to the [SEC Insider Trading Tracker](https://apify.com/ryanclinton/sec-insider-trading) page on the Apify Store.
2. Click **Try for free** to open the actor in your Apify Console.
3. Enter a company name, ticker symbol, or CIK number in the **Search Query** field (e.g., `AAPL`).
4. Optionally select a **Transaction Type** to filter by -- Purchase, Sale, Grant/Award, or Exercise of Options.
5. Optionally set **Date From** and **Date To** fields in YYYY-MM-DD format.
6. Optionally set a **Minimum Transaction Value** in dollars to exclude small trades.
7. Adjust **Max Results** if needed (default is 25, maximum is 200).
8. Click **Start** to run the actor.
9. When the run completes, view results in the **Dataset** tab and export as JSON, CSV, Excel, or XML.

#### Using the Apify API

**cURL:**

```bash
curl "https://api.apify.com/v2/acts/ryanclinton~sec-insider-trading/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \
  -X POST \
  -d '{
    "query": "TSLA",
    "transactionType": "purchase",
    "dateFrom": "2025-06-01",
    "dateTo": "2025-12-31",
    "minTransactionValue": 100000,
    "maxResults": 50
  }' \
  -H "Content-Type: application/json"
````

**JavaScript:**

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });

const run = await client.actor('ryanclinton/sec-insider-trading').call({
    query: 'TSLA',
    transactionType: 'purchase',
    dateFrom: '2025-06-01',
    dateTo: '2025-12-31',
    minTransactionValue: 100000,
    maxResults: 50,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

**Python:**

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")

run = client.actor("ryanclinton/sec-insider-trading").call(run_input={
    "query": "TSLA",
    "transactionType": "purchase",
    "dateFrom": "2025-06-01",
    "dateTo": "2025-12-31",
    "minTransactionValue": 100000,
    "maxResults": 50,
})

items = client.dataset(run["defaultDatasetId"]).list_items().items
for item in items:
    print(f"{item['insiderName']} - {item['transactionType']} - ${item['totalValue']:,.2f}")
```

***

### Input parameters

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `query` | String | Yes | `AAPL` | Single-issuer query — company name, ticker, or CIK |
| `queries` | Array\<String> | No | — | Multi-issuer portfolio — when set, takes precedence over `query` |
| `transactionType` | String | No | `all` | `all` / `purchase` / `sale` / `grant` / `exercise` |
| `dateFrom` | String | No | 30 days ago | Start date (YYYY-MM-DD) |
| `dateTo` | String | No | Today | End date (YYYY-MM-DD) |
| `minTransactionValue` | Number | No | — | Dollar floor for transaction value |
| `maxResults` | Integer | No | `25` | Cap on transaction records (1–200). Cluster + issuer + batch records do NOT count against this cap. |
| `mode` | String | No | `monitoring` | See "Choose your mode" table |
| `persona` | String | No | `generic` | See "Choose your persona" table |
| `routingProfile` | String | No | `generic` | See "Choose your routing profile" table |
| `systemMode` | Boolean | No | `false` | One-flag stateful service — auto-enables clusters + issuer summary + batch insights + (with `watchlistName`) deltaMode |
| `watchlistName` | String | No | — | Names a per-watchlist named KV store for cross-run state |
| `deltaMode` | Boolean | No | `false` | When true (and `watchlistName` set), every transaction carries a `delta` block |
| `includeClusters` | Boolean | No | mode-driven | Detect ≥2 distinct insiders moving same direction within 30d |
| `includeIssuerSummary` | Boolean | No | mode-driven | Emit one issuer-summary record per ticker |
| `includeBatchInsights` | Boolean | No | mode-driven | Emit batch-summary record at run end |
| `triggerPacks` | Array\<String> | No | profile-driven | Pre-built rule bundles (cluster-buy / cluster-sale / executive-disposal / large-purchase / amendment-burst / distress-watch) |
| `triggers` | Array | No | — | Custom rules: `{ name, when: { direction?, minTotalValue?, minClusterSize?, insiderRoleIn?, materialityLevelIn?, unusualnessAtLeast? }, severity? }` |
| `outputProfile` | String | No | `standard` | `minimal` / `standard` / `full` / `llm` |
| `includeAlertPayloads` | Boolean | No | profile-driven | Write immediate-review queue + alerts to the run's `ALERTS` KV key |

**Example input:**

```json
{
    "query": "AAPL",
    "transactionType": "purchase",
    "dateFrom": "2025-01-01",
    "dateTo": "2025-12-31",
    "minTransactionValue": 100000,
    "maxResults": 50
}
```

**Tips for best input:**

- Use ticker symbols (e.g., `TSLA`, `AAPL`, `MSFT`) for the most precise results
- Use a CIK number if your company name search returns filings for the wrong entity
- Widen the date range for smaller companies that file infrequently -- try 90 or 180 days
- Combine `transactionType: "purchase"` with a high `minTransactionValue` to isolate significant insider buying signals
- Leave `transactionType` as `all` for a complete picture of insider activity

***

### Output

The dataset emits multiple record types — branch on `recordType` to route them downstream:

| `recordType` | What it represents | Per-run count |
|---|---|---|
| `transaction` | One Form 4 transaction with full decision enrichment | up to `maxResults` |
| `cluster` | A multi-insider cluster within a 30-day window | 0 – N |
| `issuer-summary` | Per-issuer state synthesis | 1 per distinct issuer |
| `batch-summary` | Run-level portfolio + priority queue + manifest | 1 (or 0 in `raw` mode) |
| `no-results` | Empty-result explanation (no charge) | 0 or 1 |
| `error` | Run-failure record (no charge) | 0 or 1 |

**Example transaction record (v2):**

```json
{
    "schemaVersion": "2.0.0",
    "recordType": "transaction",
    "eventId": "a3f0e89b1c4d2e7f5a6b8c91",
    "filingDate": "2025-08-15",
    "companyName": "Apple Inc.",
    "ticker": "AAPL",
    "cik": "320193",
    "insiderName": "WILLIAMS JEFFREY E",
    "insiderTitle": "COO",
    "relationship": "Officer",
    "transactionType": "Purchase",
    "transactionDate": "2025-08-13",
    "sharesTraded": 15000,
    "pricePerShare": 178.52,
    "totalValue": 2677800,
    "sharesOwnedAfter": 489322,
    "directOrIndirect": "Direct",
    "direction": "buy",
    "insiderRole": { "isCeo": false, "isCfo": false, "isCoo": true, "isOfficer": true, "isDirector": false, "isTenPercent": false, "seniorityRank": 85, "label": "COO" },
    "materiality": { "score": 78, "level": "critical", "drivers": ["value:1M-10M", "role:senior-officer", "position-impact:3-10%", "ownership:direct"], "sharePctOfPriorHoldings": 3.2 },
    "unusualness": { "score": 65, "level": "high", "factors": ["officer-open-market-buy-uncommon", "very-large-dollar-amount"] },
    "decision": { "posture": "investigate", "confidence": 0.81, "confidenceLevel": "high", "drivers": ["senior-officer-buy", "high-materiality"], "whyThisMatters": "COO open-market buy of critical materiality — senior-officer purchases are uncommon and often correlate with management confidence.", "whyNow": "Pattern is unusual — officer-open-market-buy-uncommon; very-large-dollar-amount." },
    "decisionTrace": ["mode:monitoring", "persona:generic", "routing-profile:generic", "direction:buy", "role:coo", "role:officer", "materiality:critical", "unusualness:high", "ownership:direct"],
    "alertQuality": { "novelty": 0.65, "urgency": 0.97, "noiseRisk": 0.19 },
    "recommendedAction": { "actionId": "investigate-today", "label": "Investigate COO buy — critical materiality", "team": "analyst", "urgency": "today", "eta": "24h", "reason": "investigate (critical materiality, COO, persona=generic, profile=generic)", "contributingSignals": ["senior-officer-buy", "high-materiality", "materiality:critical", "role:coo"] },
    "reviewSla": { "recommendedReviewWithinHours": 4, "slaTier": "P1", "reason": "posture=investigate · role=COO · materiality=critical · profile=generic (tighten=0h)" },
    "escalationRecommendation": { "level": "immediate-review", "sla": "24h", "reason": "Escalated as immediate-review — investigate, critical materiality, persona=generic.", "audience": ["general"], "ignoreRecommendation": false },
    "summary": "AAPL — COO WILLIAMS JEFFREY E bought 15000 shares ($2678k) on 2025-08-13. Materiality critical (78/100). Posture: investigate."
}
```

**Example cluster record:**

```json
{
    "schemaVersion": "2.0.0",
    "recordType": "cluster",
    "eventId": "c47b29d8e1a3f5b62c4d8e9f",
    "ticker": "TSLA",
    "cik": "1318605",
    "companyName": "Tesla, Inc.",
    "direction": "sell",
    "pattern": "officer-cluster-sale",
    "insiderCount": 4,
    "transactionCount": 9,
    "totalValue": 47200000,
    "spanDays": 12,
    "confidence": "high",
    "decisionPosture": "flag-disposal",
    "summary": "TSLA — officer-cluster-sale (4 insiders, 9 txns, $47200k) over 12d. Confidence high."
}
```

**Example issuer-summary record:**

```json
{
    "schemaVersion": "2.0.0",
    "recordType": "issuer-summary",
    "ticker": "TSLA",
    "transactionCount": 12,
    "buyCount": 0,
    "sellCount": 9,
    "netInsiderFlow": -47200000,
    "issuerState": { "sentiment": "bearish", "insiderPressureIndex": 78, "insiderPressureBand": "high", "transactionVelocity": "elevated", "governanceFootprint": "high", "watchStatus": "urgent", "headline": "TSLA: urgent — sentiment bearish, pressure 78/100 (high), 12 txns / 1 clusters." },
    "triggersFired": [{ "name": "cluster-sale:officer-cluster", "severity": "high", "matchedSignals": ["cluster:officer-cluster-sale:4"] }],
    "decisionTrace": ["sentiment:bearish", "pressure-band:high", "watch-status:urgent", "velocity:elevated", "governance:high", "trigger:cluster-sale:officer-cluster"],
    "recommendedAction": { "team": "analyst", "urgency": "today", "label": "Investigate COO disposal — high materiality" },
    "reviewSla": { "slaTier": "P1", "recommendedReviewWithinHours": 4 },
    "escalationRecommendation": { "level": "immediate-review", "ignoreRecommendation": false }
}
```

### Stable enum tokens

These enums are **additive across minor versions** — values can be added, never renamed or repurposed within a major version:

- `recordType`: `transaction` / `cluster` / `issuer-summary` / `batch-summary` / `no-results` / `error`
- `direction`: `buy` / `sell` / `grant` / `exercise` / `gift` / `other`
- `materiality.level`: `critical` / `high` / `medium` / `low`
- `unusualness.level`: `high` / `medium` / `low`
- `decision.posture`: `investigate` / `flag-cluster` / `flag-disposal` / `monitor-sentiment` / `monitor` / `no-action`
- `escalationRecommendation.level`: `immediate-review` / `weekly-review` / `monthly-review` / `archive` / `ignore`
- `recommendedAction.team`: `compliance` / `ir` / `legal` / `finance` / `executive-review` / `analyst` / `quant` / `archive`
- `recommendedAction.urgency`: `immediate` / `today` / `this-week` / `this-month` / `no-action`
- `reviewSla.slaTier`: `P0` (1h) / `P1` (4h) / `P2` (48h) / `P3` (1 week) / `P4` (no SLA)
- `issuerState.watchStatus`: `no-action` / `monitor` / `attention-required` / `urgent` / `critical`
- `issuerState.sentiment`: `bullish` / `bearish` / `mixed` / `neutral` / `unknown`
- `issuerState.insiderPressureBand`: `critical` / `high` / `elevated` / `normal` / `quiet`
- `cluster.pattern`: `officer-cluster-buy` / `officer-cluster-sale` / `broad-cluster-buy` / `broad-cluster-sale` / `cluster-buy` / `cluster-sale`
- `delta.type`: `new` / `changed` / `unchanged` / `recovered` / `degraded`
- `failureCategory`: `no-results` / `edgar-search-failure` / `xml-parse-failure` / `validation` / `rate-limit` / `timeout` / `transient-network` / `unknown`
- `severity` (6-tier institutional taxonomy): `informational` / `notable` / `elevated` / `significant` / `exceptional` / `critical`
- `behaviorProfile.profileType` (14 archetypes): `strategic-accumulator` / `conviction-buyer` / `opportunistic-buyer` / `crisis-accumulator` / `founder-confidence-buy` / `compensation-cycler` / `routine-options-exerciser` / `scheduled-seller` / `liquidity-manager` / `strategic-distributor` / `accelerated-disposal` / `governance-exit-pattern` / `pre-event-deleveraging` / `unclassified`
- `behaviorProfile.historicalBias`: `buy-heavy` / `sell-heavy` / `mixed` / `compensation-only` / `insufficient-data`
- `behaviorProfile.signalReliability`: `high` / `medium` / `low` / `cold-start`
- `intentClassification.primaryIntent` (12 intents): `discretionary-conviction-buy` / `discretionary-open-market-buy` / `opportunistic-accumulation` / `strategic-disposal` / `liquidity-stress-sale` / `coordinated-reduction` / `compensation-vesting` / `tax-obligation` / `scheduled-10b5-1` / `estate-transfer` / `trust-reallocation` / `unclassified`
- `noiseClassification.noiseType`: `routine-compensation-cycle` / `scheduled-disposition` / `tax-withholding` / `options-exercise` / `low-materiality-grant` / `none` / `unclassified`
- `signalQuality.tier`: `institutional-grade` / `high` / `moderate` / `background-noise`
- `signalQuality.rarity`: `extreme` / `rare` / `uncommon` / `common` / `routine`
- `regimeState.current` (8 regimes): `accumulation-regime` / `liquidation-regime` / `governance-deterioration-regime` / `executive-confidence-recovery` / `insider-silence-breakdown` / `accelerating-distribution-regime` / `mixed-regime` / `no-regime`
- `coordinationSignals.executiveConcentration`: `high` / `medium` / `low` / `none`
- `coordinationSignals.timingCohesion`: `tight` / `moderate` / `loose`
- `ownershipDelta.direction`: `increased` / `decreased` / `unchanged` / `unknown`
- `ownershipDelta.ownershipConviction`: `high` / `moderate` / `low` / `unknown`
- `signalReputation.reputationTier`: `elite` / `high` / `moderate` / `low` / `cold-start`
- `signalVerdict.classification` (9 values): `high-conviction-bullish` / `bullish` / `speculative-bullish` / `governance-risk` / `distribution-risk` / `bearish` / `compensation-noise` / `informational` / `mixed-signal`
- `signalVerdict.actionability`: `immediate-review` / `weekly-review` / `monitor` / `archive` / `ignore`
- `signalVerdict.institutionalRelevance`: `high` / `medium` / `low`
- `signalLifecycle.freshness`: `fresh` / `recent` / `aging` / `stale`
- `signalLifecycle.signalDecayRisk`: `low` / `medium` / `high`
- `signalMaturity.stage`: `cold-start` / `emerging` / `developing` / `mature`
- `decisionReadiness.state`: `thesis-ready` / `partial-thesis` / `monitor` / `insufficient-data` / `noise`
- `expectationDeviation.deviationSeverity`: `extreme` / `high` / `moderate` / `low` / `none` / `first-sight`
- `behavioralDrift.directionalShift`: `bullish-to-defensive` / `defensive-to-bullish` / `accumulation-to-distribution` / `distribution-to-accumulation` / `stable` / `mixed` / `first-sight`
- `behavioralDrift.driftVelocity`: `accelerating` / `steady` / `decelerating` / `none` / `unknown`
- `governanceDynamics.executiveAlignment`: `aligned` / `fractured` / `mixed` / `unknown`
- `governanceDynamics.boardConfidence`: `rising` / `stable` / `falling` / `unknown`
- `governanceDynamics.boardVsExecutiveDirection`: `same` / `opposite` / `unknown`
- `modelIntegrity.classificationIntegrity`: `high` / `medium` / `low`
- `reviewEconomics.expectedSignalValue`: `high` / `medium` / `low` / `noise`
- `reviewEconomics.triageEfficiency`: `excellent` / `good` / `fair` / `poor`
- `signalObfuscationRisk.distributionFragmentation`: `high` / `medium` / `low` / `none`
- `signalObfuscationRisk.concealmentLikelihood`: `high` / `moderate` / `low` / `none`
- `portfolioExposureImpact.portfolioRiskShift`: `increasing` / `decreasing` / `stable` / `first-sight`
- `portfolioExposureImpact.concentrationConcern`: `high` / `medium` / `low` / `none`
- `confidenceCalibration.calibrationQuality`: `well-calibrated` / `overconfident` / `underconfident` / `cold-start` / `unknown`
- `confidenceCalibration.overconfidenceRisk`: `high` / `medium` / `low` / `unknown`
- `signalAttribution.observedOutcome`: `bullish-confirmed` / `bearish-confirmed` / `neutral` / `pending` / `unknown`
- `signalAttribution.signalEffectiveness`: `high` / `medium` / `low` / `pending` / `unknown`
- `leadershipConsensusModel.consensusState`: `aligned` / `softening` / `breaking-down` / `fractured` / `unknown`
- `leadershipConsensusModel.dominantFaction`: `executive` / `board` / `tenpct-owner` / `mixed` / `none`
- `manipulationResistance.gamingResistance`: `high` / `medium` / `low`
- `manipulationResistance.washPatternRisk`: `high` / `medium` / `low` / `none`
- `macroSensitivity.marketRegime`: `risk-on` / `risk-off` / `neutral` / `unknown`
- `humanFeedbackLoop.analystDisposition`: `validated` / `overridden` / `pending` / `unknown`

**Output field descriptions:**

| Field | Type | Description |
|-------|------|-------------|
| `filingDate` | String | Date the Form 4 was filed with the SEC (YYYY-MM-DD) |
| `companyName` | String | Full legal name of the issuing company |
| `ticker` | String | Stock ticker symbol |
| `cik` | String | SEC Central Index Key for the company |
| `insiderName` | String | Name of the reporting insider (Last, First format) |
| `insiderTitle` | String | Official title -- CEO, CFO, VP, General Counsel, etc. |
| `relationship` | String | Insider role: Director, Officer, 10% Owner, Other, or a combination |
| `transactionType` | String | Transaction label -- Purchase, Sale, Grant/Award, Exercise/Conversion, Gift, Tax Withholding, etc. |
| `transactionDate` | String | Date the transaction was executed (YYYY-MM-DD) |
| `sharesTraded` | Number or null | Number of shares involved in the transaction |
| `pricePerShare` | Number or null | Price per share at time of transaction in USD |
| `totalValue` | Number or null | Total dollar value (sharesTraded x pricePerShare) |
| `sharesOwnedAfter` | Number or null | Total shares held by the insider after the transaction |
| `directOrIndirect` | String | `Direct` for personally held shares, `Indirect` for shares held through trusts or entities |
| `filingUrl` | String | Direct URL to the original Form 4 XML filing on SEC.gov |
| `secUrl` | String | URL to browse all Form 4 filings for this company on EDGAR |

***

### Use cases

- **Investment research** -- Screen for insider buying clusters as a bullish signal before earnings announcements or major catalysts
- **Compliance monitoring** -- Audit insider trading activity across portfolio companies to flag potential conflicts or suspicious timing
- **Financial journalism** -- Identify unusually large insider sales or purchases for investigative reporting
- **Quantitative signals** -- Build algorithmic trading models that incorporate insider transaction patterns as alpha factors
- **Corporate governance analysis** -- Track whether executives are increasing or decreasing their ownership stakes over time
- **Venture and PE due diligence** -- Check whether insiders at a target company are buying or selling ahead of a potential deal
- **Academic research** -- Gather structured insider trading datasets for financial economics studies and market efficiency research
- **Alert and notification systems** -- Feed results into Slack, email, or webhook pipelines to get notified when specific insiders trade
- **Portfolio risk management** -- Monitor insider selling activity across your holdings as an early warning indicator

***

### API & Integration

The SEC Form 4 API is exposed via the standard Apify Run-Sync endpoint, returning structured JSON for any insider-trading monitoring or alert workflow.

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("ryanclinton/sec-insider-trading").call(run_input={
    "query": "MSFT",
    "transactionType": "sale",
    "maxResults": 100,
})
for item in client.dataset(run["defaultDatasetId"]).list_items().items:
    print(f"{item['insiderName']}: {item['transactionType']} {item['sharesTraded']} shares @ ${item['pricePerShare']}")
```

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });
const run = await client.actor('ryanclinton/sec-insider-trading').call({
    query: 'MSFT',
    transactionType: 'sale',
    maxResults: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => console.log(`${item.insiderName}: $${item.totalValue?.toLocaleString()}`));
```

#### cURL

```bash
curl "https://api.apify.com/v2/acts/ryanclinton~sec-insider-trading/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \
  -X POST \
  -d '{"query": "MSFT", "transactionType": "sale", "maxResults": 100}' \
  -H "Content-Type: application/json"
```

#### Platform integrations

- **[Zapier](https://apify.com/integrations/zapier)** -- Trigger workflows in thousands of apps when insider trades are detected
- **[Make (Integromat)](https://apify.com/integrations/make)** -- Build visual automation scenarios with insider trading data
- **[Google Sheets](https://apify.com/integrations/google-sheets)** -- Export results directly to a spreadsheet for collaborative analysis
- **[Slack](https://apify.com/integrations/slack)** -- Send real-time notifications when high-value insider trades are filed
- **[Webhooks](https://docs.apify.com/platform/integrations/webhooks)** -- Trigger downstream actions when a run completes
- **[Scheduled runs](https://docs.apify.com/platform/schedules)** -- Set up daily or weekly monitoring of insider trading activity

***

### Use in Dify

Drop this actor into [Dify](https://docs.apify.com/platform/integrations/dify) workflows via the Apify plugin's Run Actor node. Each run returns scored, classified, and routed Form 4 activity as structured JSON — `recordType` (transaction / cluster / issuer-summary / batch-summary), `escalationRecommendation.level` (immediate-review / weekly-review / monthly-review / archive / ignore), `decision.posture` (investigate / flag-disposal / monitor-sentiment / monitor / no-action), and `reviewSla.slaTier` (P0 / P1 / P2 / P3 / P4) — plus the `decisionCards[]` and `priorityQueue[]` your downstream node branches on. Bloomberg or OpenInsider pointed at the same Form 4 filings return raw transactions; this returns decisions.

- **Actor ID:** `ryanclinton/sec-insider-trading`
- **Sample input** (compliance-officer routing across a portfolio):

```json
{
    "queries": ["TSLA", "NVDA", "AAPL", "MSFT", "META"],
    "mode": "compliance",
    "routingProfile": "compliance-officer",
    "watchlistName": "tech-megacaps-weekly",
    "systemMode": true
}
```

**Branching example** — a Dify if/else node routing on `escalationRecommendation.level`:

```
IF escalationRecommendation.level == "immediate-review"
    → Send Slack alert to #compliance-urgent
    → Open Jira P0 ticket via HTTP node
ELIF escalationRecommendation.level == "weekly-review"
    → Append to weekly review queue (Notion / Airtable)
ELIF cluster.category == "risk" AND cluster.confidence == "high"
    → Run sec-edgar-filing-analyzer for the same ticker
ELSE
    → Archive
```

**Opt-in modes Dify workflows can leverage:**

- `mode: "monitoring"` (default) — every run emits clusters + issuer summaries + batch insights. Pair with a daily Dify schedule.
- `mode: "compliance"` — full decision surface + delta tracking. Pair with `watchlistName` + `systemMode: true` for cross-run drift detection.
- `mode: "officer-tracking"` — narrows to CEO/CFO/COO/10% owner activity. Useful when the Dify workflow only routes on senior-officer signals.
- `outputProfile: "llm"` — strips diagnostic blocks, keeps `decisionCards`, `escalationRecommendation`, `decision`, `materiality`, `summary`, `headline`, `oneLine`. The LLM-friendly subset for agent consumers that branch on enums and quote prose verbatim.

The `decisionCards[]` array, `priorityQueue[]` array, `nextActions[]` array, and `improvementSuggestions[]` array are usable verbatim — every string field (`title`, `shortReason`, `summary`, `narrativeDelta.summary`, `recommendedAction.label`) is paste-ready into the next node's prompt or into a Slack/email body. No LLM rewriting required.

For agent consumers, branch directly on `recommendedAction.executionHint.type` — six stable values (`investigate-officer-buy` / `review-officer-disposal` / `monitor-cluster` / `monitor-sentiment` / `archive` / `no-action`) plus `executionHint.targetTicker` + `executionHint.targetCik` give a runtime-routable surface without parsing any prose.

***

### How it works

The actor follows a multi-step pipeline to search, retrieve, parse, filter, and output insider trading data from SEC EDGAR.

1. **Search EDGAR** -- Sends a paginated query to the SEC EDGAR full-text search index (`efts.sec.gov/LATEST/search-index`) filtering for Form 4 filings within the specified date range. Retrieves up to 3x the requested `maxResults` to allow for post-filtering.
2. **Build XML URLs** -- Extracts the accession number and filename from each search hit ID, then constructs the direct URL to the Form 4 XML filing on SEC.gov Archives.
3. **Fetch Form 4 XML** -- Downloads each raw Form 4 XML filing, respecting the SEC's rate limits with 120ms pauses between requests and exponential backoff on 429 responses.
4. **Parse XML** -- Uses `fast-xml-parser` to parse the XML into a structured JavaScript object, handling both single and multiple reporting owners, non-derivative transactions, and derivative transactions.
5. **Extract transactions** -- Pulls out every reportable transaction including shares traded, price per share, total value, post-transaction holdings, insider identity, relationship, and ownership type.
6. **Apply filters** -- Filters transactions by the requested transaction type (purchase, sale, grant, exercise) and minimum transaction value threshold.
7. **Sort and limit** -- Sorts results by filing date descending, then by total value descending, and trims to the requested `maxResults` count.
8. **Output** -- Pushes the final structured results to the Apify dataset for download or API retrieval.

```
  Query (ticker/name/CIK)
           |
           v
  +-----------------+
  | EDGAR Full-Text |
  | Search Index    |
  +-----------------+
           |
     Form 4 hits
           |
           v
  +-----------------+
  | Build XML URLs  |
  | from accession  |
  +-----------------+
           |
           v
  +-----------------+
  | Fetch Form 4    |
  | XML (rate-      |
  | limited)        |
  +-----------------+
           |
           v
  +-----------------+
  | Parse XML &     |
  | extract trades  |
  +-----------------+
           |
           v
  +-----------------+
  | Filter, sort,   |
  | limit results   |
  +-----------------+
           |
           v
     Apify Dataset
     (JSON/CSV/Excel)
```

***

### Performance & cost

| Metric | Value |
|--------|-------|
| Memory | 256 MB |
| Typical run time (25 results) | 15--45 seconds |
| Typical run time (100 results) | 45--120 seconds |
| Typical run time (200 results) | 2--4 minutes |
| Compute units (25 results) | ~0.005 CU |
| Compute units (100 results) | ~0.02 CU |
| Compute units (200 results) | ~0.04 CU |
| Estimated cost (25 results) | ~$0.005 |
| Estimated cost (200 results) | ~$0.04 |
| Free tier capacity | ~1,000 runs/month on Apify's $5 free credit |

Run time depends primarily on the number of Form 4 filings fetched from SEC EDGAR and the SEC's rate-limiting behavior. The actor does not use a browser, so memory and CPU usage remain minimal.

***

### Limitations

- **SEC rate limits** -- The SEC imposes a 10 requests-per-second limit. The actor throttles to approximately 8/sec, but heavy EDGAR traffic or concurrent users may trigger 429 responses that slow processing.
- **Form 4 coverage only** -- This actor searches Form 4 filings specifically. It does not cover Form 3 (initial ownership statements), Form 5 (annual reports of changes), or 13D/13G (beneficial ownership filings).
- **XML parsing edge cases** -- A small number of Form 4 filings use non-standard XML structures, footnote-only values, or amended formats that may result in null fields for shares, price, or value.
- **Search index latency** -- While most filings appear in the EDGAR search index within minutes, some may take several hours to be indexed after submission.
- **Name matching** -- EDGAR full-text search does fuzzy matching, which can sometimes return results for similarly named companies. Use ticker symbols or CIK numbers for precise targeting.
- **No historical backfill** -- The EDGAR search index has practical limits on how far back paginated results extend. For deep historical analysis, consider using the EDGAR Filing Search actor.
- **200 result cap** -- A single run returns a maximum of 200 transactions. For larger datasets, run multiple queries with narrower date ranges.

***

### Responsible use

- **Public data only** -- This actor accesses publicly available SEC EDGAR filings. It does not scrape private, authenticated, or restricted data sources.
- **SEC fair access compliance** -- The actor respects SEC EDGAR's rate limits and identifies itself with a proper User-Agent header, following SEC guidelines for automated access.
- **Not investment advice** -- Insider trading data is informational. It should not be treated as a recommendation to buy, sell, or hold any security. Always do your own research and consult a financial advisor.
- **Respect filing context** -- Insider sales do not necessarily indicate negative sentiment. Many sales are pre-planned under Rule 10b5-1 plans, related to tax obligations, or part of portfolio diversification.
- **Privacy considerations** -- While Form 4 data is public, use insider names and transaction details responsibly and in accordance with applicable laws and your organization's policies.

***

### FAQ

**Q: Is this a SEC Form 4 API?**
**A:** Yes. SEC Insider Trading Tracker is a SEC Form 4 API — a developer-first insider trading API for monitoring, parsing, classifying, and routing Form 4 filings in real time. Output is structured JSON with deterministic enums (`signalVerdict.classification`, `decisionReadiness.state`, `severity`), suitable for Slack alerts, PagerDuty rules, Zapier filters, Dify workflows, and AI-agent tool calls. Pair with Apify Schedules for live SEC Form 4 monitoring.

**Q: Does this actor require an API key or SEC registration?**
**A:** No. The actor queries the public SEC EDGAR full-text search index and parses publicly available Form 4 XML filings. No API key, registration, or authentication is needed.

**Q: What is a Form 4 filing?**
**A:** Form 4 is the SEC filing that corporate insiders -- officers, directors, and shareholders who own 10% or more of a company's stock -- must submit within two business days of buying, selling, or otherwise transacting in their company's securities.

**Q: What transaction types can I filter by?**
**A:** You can filter by Purchase (open-market buys), Sale (including tax withholding dispositions), Grant/Award (equity compensation grants), or Exercise (options exercises and conversions). Select "all" to see every transaction type including gifts, dispositions, and swaps.

**Q: How current is the data?**
**A:** The actor queries the live SEC EDGAR search index, so filings appear as soon as the SEC processes them -- typically within minutes to hours of submission. By default, the actor searches the last 30 days.

**Q: Why are some transactions missing price or value data?**
**A:** Some Form 4 filings report transactions at $0 (such as gifts, certain grants, or tax withholding at no cost) or omit price data entirely. The actor returns `null` for fields not present in the original XML filing.

**Q: Can I search for a specific insider by name?**
**A:** Yes. Enter the insider's name in the query field. EDGAR's full-text search indexes insider names from Form 4 filings, so searching for "Elon Musk" or "Tim Cook" will return their filings.

**Q: What is the difference between Direct and Indirect ownership?**
**A:** Direct ownership means the insider personally holds the shares. Indirect ownership means the shares are held through a trust, family member, partnership, LLC, or other entity where the insider has beneficial interest.

**Q: How does the actor handle derivative transactions like options?**
**A:** The actor parses both the non-derivative table (common stock transactions) and the derivative table (options, warrants, convertible securities) from each Form 4 filing. Derivative transactions include the security title in the transaction type field (e.g., "Exercise/Conversion (Stock Option)").

**Q: Can I schedule this actor to run automatically?**
**A:** Yes. Use the Apify platform's [Schedules](https://docs.apify.com/platform/schedules) feature to run the actor daily, weekly, or at any custom interval. Combine with webhooks or Slack integration for automated alerts.

**Q: What happens if the SEC rate limits the actor?**
**A:** The actor handles 429 (Too Many Requests) responses with exponential backoff -- waiting 2, 4, then 8 seconds between retries. It will automatically recover and continue processing without losing data.

**Q: Why does the actor fetch more filings than my maxResults setting?**
**A:** The actor fetches up to 3x your requested `maxResults` from the EDGAR search index, then filters and deduplicates the parsed transactions. This over-fetching ensures enough results survive filtering by transaction type and minimum value.

**Q: How is this different from the SEC EDGAR Filing Analyzer actor?**
**A:** The SEC EDGAR Filing Analyzer searches across all filing types (10-K, 10-Q, 8-K, etc.) and extracts filing metadata. This actor focuses exclusively on Form 4 insider trading filings and deeply parses the XML to extract individual transaction details including shares, prices, and values.

***

### Related actors

| Actor | Description |
|-------|-------------|
| [SEC EDGAR Filing Analyzer](https://apify.com/ryanclinton/sec-edgar-filing-analyzer) | Search and analyze all SEC EDGAR filing types -- 10-K, 10-Q, 8-K, and more |
| [EDGAR Filing Search](https://apify.com/ryanclinton/edgar-filing-search) | Full-text search across the complete EDGAR filing index with flexible filters |
| [Congressional Stock Trade Tracker](https://apify.com/ryanclinton/congress-stock-tracker) | Track stock trades disclosed by members of the U.S. Congress |
| [Finnhub Stock Market Data](https://apify.com/ryanclinton/finnhub-stock-data) | Real-time and historical stock market data including quotes and company profiles |
| [Company Deep Research Agent](https://apify.com/ryanclinton/company-deep-research) | Comprehensive company intelligence from multiple public data sources |
| [OFAC Sanctions Search](https://apify.com/ryanclinton/ofac-sanctions-search) | Search the OFAC Specially Designated Nationals list for sanctioned entities |

# Actor input Schema

## `query` (type: `string`):

Company name, ticker symbol, or CIK number. Single-issuer mode. Use 'queries' for multi-issuer portfolios.

## `queries` (type: `array`):

List of tickers, company names, or CIKs to process in one run. When set, takes precedence over 'query'. Enables portfolio-state, priority queue, and watchlist analytics across the cohort.

## `transactionType` (type: `string`):

Filter by transaction type. 'sale' includes tax-withholding dispositions.

## `dateFrom` (type: `string`):

Start date (YYYY-MM-DD). Defaults to 30 days ago.

## `dateTo` (type: `string`):

End date (YYYY-MM-DD). Defaults to today.

## `transactionDateFrom` (type: `string`):

Optional: filter by the underlying transaction date inside the Form 4, not the SEC filing date. A 2024 amendment for a 2022 transaction is filtered OUT when transactionDateFrom is 2024-01-01. Use when the audit semantics is 'what insider activity happened in this period' rather than 'which Form 4s were filed in this period'. Format: YYYY-MM-DD.

## `transactionDateTo` (type: `string`):

Optional companion to transactionDateFrom. Format: YYYY-MM-DD.

## `queryMatchMode` (type: `string`):

fuzzy (default) — passes the query string to EDGAR's full-text search, matching company-name substrings (e.g. 'KKR' returns KKR Real Estate Select Trust + KKR FS Income Trust + KKR Inc all together). exact — resolves each query against SEC's ticker→CIK index (company\_tickers.json) and filters returned filings to the resolved CIK set, eliminating cross-issuer matches. Use exact for cohort-scale audits where issuer identity must be precise.

## `minTransactionValue` (type: `number`):

Only include transactions with a total value above this dollar amount.

## `maxResults` (type: `integer`):

Maximum number of transactions to emit. Cluster, issuer-summary, and batch-summary records are NOT counted against this cap. For cohort-scale audits, raise this — defaults work for single-issuer monitoring but cap at 200 caused silent truncation on rare-event searches across S\&P 500 cohorts.

## `mode` (type: `string`):

Bundles output flags + trigger packs + decision layer activation. Pick based on the JOB you're doing — alpha-hunter for rare officer buys, governance-risk for executive unloading + clustered exits, compliance-surveillance for full audit trail, executive-sentiment for C-suite directional behavior, distress-radar for liquidity-pattern signals. The original mechanical names (monitoring / cluster-detection / compliance / sentiment / officer-tracking / raw / auto) are kept for back-compat.

## `persona` (type: `string`):

Shapes escalation + suppression + materiality weighting. Different personas suppress different signals (e.g. retail-monitoring suppresses tax-withholding; quant suppresses small grants).

## `routingProfile` (type: `string`):

Bundles persona + trigger packs + SLA tightening + alert format. Pick the profile that matches your downstream consumer.

## `systemMode` (type: `boolean`):

One-flag stateful service. When true, auto-enables clusters, issuer summary, batch insights, and (with watchlistName) deltaMode. Recurring scheduled-run friendly.

## `watchlistName` (type: `string`):

Names a per-watchlist named KV store for cross-run state — temporal signals, state transitions, regime shift detection, narrative delta. Two pipelines on different watchlists don't interfere.

## `deltaMode` (type: `boolean`):

When true (and watchlistName set), every transaction carries a delta block: new / changed / unchanged / recovered / degraded.

## `includeClusters` (type: `boolean`):

Detect ≥2 distinct insiders moving same direction within a 30d window. On by default for most modes.

## `includeIssuerSummary` (type: `boolean`):

Emit one issuer-summary record per ticker — sentiment, insiderPressureIndex, watchStatus, triggers fired, escalation routing.

## `includeBatchInsights` (type: `boolean`):

Emit a single batch-summary record at the end with portfolio state + priority queue + run manifest + watchlist analytics.

## `triggerPacks` (type: `array`):

Pre-built rule bundles that fire alerts on matching transactions / clusters. Mode + routing-profile pre-select packs; this input adds more. Valid values: cluster-buy, cluster-sale, executive-disposal, large-purchase, amendment-burst, distress-watch.

## `triggers` (type: `array`):

User-defined alert rules. Schema: { name, when: { direction?, minTotalValue?, minClusterSize?, insiderRoleIn?, materialityLevelIn?, unusualnessAtLeast? }, severity? }.

## `outputProfile` (type: `string`):

Field-set shrinkage. minimal = core fields only. standard = decision layer included. full = every block. llm = LLM-friendly subset for agent consumers.

## `includeAlertPayloads` (type: `boolean`):

Write the immediate-review queue + cluster alerts + issuer alerts to the ALERTS key in the run's KV store.

## `referenceRunId` (type: `string`):

(Reserved) — diff this run against a specific prior run instead of the most recent watchlist snapshot. Currently informational only.

## `concurrency` (type: `integer`):

How many tickers (and per-ticker filings) to process in parallel. Higher = faster cohort scans, throttled globally by SEC's 10 req/sec rate limit. Default 8.

## `preFilterByTransactionType` (type: `boolean`):

EXPERIMENTAL. When true (and transactionType is purchase/sale/grant/exercise), does a cheap EDGAR probe per ticker to skip tickers with zero matching filings. Default FALSE. Known limitation: EDGAR's full-text indexer does not reliably preserve XML tags, so the probe can produce false negatives — verified against year-scale + low-frequency-event inputs (e.g. XOM 2024 purchases). Use with caution; off by default for correctness.

## `runtimeBudgetSeconds` (type: `integer`):

Soft runtime cap on the FETCH phase. When elapsed time exceeds this, the actor stops fetching new data and emits partial results. AUTO-CLAMPING: the actor reads Apify's deadline (APIFY\_TIMEOUT\_AT) and automatically clamps this value to (deadline - emit-reserve), where emit-reserve scales with maxResults (5-15min). This prevents Apify hard-killing during the EMIT phase (filter/enrich/cluster/issuer-build/KV/dataset-push). If you set this ≥ Apify's timeoutSecs, it WILL be auto-clamped down — the clamp is logged at startup. Default 3000 (50 minutes).

## Actor input object example

```json
{
  "query": "AAPL",
  "transactionType": "all",
  "queryMatchMode": "fuzzy",
  "maxResults": 25,
  "mode": "monitoring",
  "persona": "generic",
  "routingProfile": "generic",
  "systemMode": false,
  "deltaMode": false,
  "outputProfile": "standard",
  "concurrency": 8,
  "preFilterByTransactionType": false,
  "runtimeBudgetSeconds": 3000
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "query": "AAPL"
};

// Run the Actor and wait for it to finish
const run = await client.actor("ryanclinton/sec-insider-trading").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "query": "AAPL" }

# Run the Actor and wait for it to finish
run = client.actor("ryanclinton/sec-insider-trading").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "query": "AAPL"
}' |
apify call ryanclinton/sec-insider-trading --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=ryanclinton/sec-insider-trading",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "SEC Insider Trading Tracker — Form 4 API",
        "description": "Real-time SEC Form 4 API for behavioural insider-trading signal classification. Detects officer cluster buys, executive disposals, regime shifts. Suppresses compensation noise. Deterministic JSON output for hedge funds, compliance, and AI-agent workflows. No API key needed.",
        "version": "2.1",
        "x-build-id": "vBfGQEIv40AvmPla6"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/ryanclinton~sec-insider-trading/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-ryanclinton-sec-insider-trading",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/ryanclinton~sec-insider-trading/runs": {
            "post": {
                "operationId": "runs-sync-ryanclinton-sec-insider-trading",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/ryanclinton~sec-insider-trading/run-sync": {
            "post": {
                "operationId": "run-sync-ryanclinton-sec-insider-trading",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "query"
                ],
                "properties": {
                    "query": {
                        "title": "Search Query",
                        "type": "string",
                        "description": "Company name, ticker symbol, or CIK number. Single-issuer mode. Use 'queries' for multi-issuer portfolios.",
                        "default": "AAPL"
                    },
                    "queries": {
                        "title": "Search Queries (multi-issuer portfolio)",
                        "type": "array",
                        "description": "List of tickers, company names, or CIKs to process in one run. When set, takes precedence over 'query'. Enables portfolio-state, priority queue, and watchlist analytics across the cohort.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "transactionType": {
                        "title": "Transaction Type",
                        "enum": [
                            "all",
                            "purchase",
                            "sale",
                            "grant",
                            "exercise"
                        ],
                        "type": "string",
                        "description": "Filter by transaction type. 'sale' includes tax-withholding dispositions.",
                        "default": "all"
                    },
                    "dateFrom": {
                        "title": "Date From",
                        "type": "string",
                        "description": "Start date (YYYY-MM-DD). Defaults to 30 days ago."
                    },
                    "dateTo": {
                        "title": "Date To",
                        "type": "string",
                        "description": "End date (YYYY-MM-DD). Defaults to today."
                    },
                    "transactionDateFrom": {
                        "title": "Transaction Date From (post-parse filter)",
                        "type": "string",
                        "description": "Optional: filter by the underlying transaction date inside the Form 4, not the SEC filing date. A 2024 amendment for a 2022 transaction is filtered OUT when transactionDateFrom is 2024-01-01. Use when the audit semantics is 'what insider activity happened in this period' rather than 'which Form 4s were filed in this period'. Format: YYYY-MM-DD."
                    },
                    "transactionDateTo": {
                        "title": "Transaction Date To (post-parse filter)",
                        "type": "string",
                        "description": "Optional companion to transactionDateFrom. Format: YYYY-MM-DD."
                    },
                    "queryMatchMode": {
                        "title": "Query Match Mode",
                        "enum": [
                            "fuzzy",
                            "exact"
                        ],
                        "type": "string",
                        "description": "fuzzy (default) — passes the query string to EDGAR's full-text search, matching company-name substrings (e.g. 'KKR' returns KKR Real Estate Select Trust + KKR FS Income Trust + KKR Inc all together). exact — resolves each query against SEC's ticker→CIK index (company_tickers.json) and filters returned filings to the resolved CIK set, eliminating cross-issuer matches. Use exact for cohort-scale audits where issuer identity must be precise.",
                        "default": "fuzzy"
                    },
                    "minTransactionValue": {
                        "title": "Minimum Transaction Value ($)",
                        "type": "number",
                        "description": "Only include transactions with a total value above this dollar amount."
                    },
                    "maxResults": {
                        "title": "Max Results",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Maximum number of transactions to emit. Cluster, issuer-summary, and batch-summary records are NOT counted against this cap. For cohort-scale audits, raise this — defaults work for single-issuer monitoring but cap at 200 caused silent truncation on rare-event searches across S&P 500 cohorts.",
                        "default": 25
                    },
                    "mode": {
                        "title": "Execution Mode",
                        "enum": [
                            "alpha-hunter",
                            "governance-risk",
                            "compliance-surveillance",
                            "executive-sentiment",
                            "distress-radar",
                            "monitoring",
                            "cluster-detection",
                            "compliance",
                            "sentiment",
                            "officer-tracking",
                            "raw",
                            "auto"
                        ],
                        "type": "string",
                        "description": "Bundles output flags + trigger packs + decision layer activation. Pick based on the JOB you're doing — alpha-hunter for rare officer buys, governance-risk for executive unloading + clustered exits, compliance-surveillance for full audit trail, executive-sentiment for C-suite directional behavior, distress-radar for liquidity-pattern signals. The original mechanical names (monitoring / cluster-detection / compliance / sentiment / officer-tracking / raw / auto) are kept for back-compat.",
                        "default": "monitoring"
                    },
                    "persona": {
                        "title": "Persona",
                        "enum": [
                            "quant",
                            "fundamental-analyst",
                            "compliance",
                            "hedge-fund-research",
                            "retail-monitoring",
                            "corporate-ir",
                            "generic"
                        ],
                        "type": "string",
                        "description": "Shapes escalation + suppression + materiality weighting. Different personas suppress different signals (e.g. retail-monitoring suppresses tax-withholding; quant suppresses small grants).",
                        "default": "generic"
                    },
                    "routingProfile": {
                        "title": "Routing Profile",
                        "enum": [
                            "quant-monitor",
                            "compliance-officer",
                            "hedge-fund",
                            "pe-operating",
                            "corporate-ir",
                            "retail-investor",
                            "generic"
                        ],
                        "type": "string",
                        "description": "Bundles persona + trigger packs + SLA tightening + alert format. Pick the profile that matches your downstream consumer.",
                        "default": "generic"
                    },
                    "systemMode": {
                        "title": "System Mode",
                        "type": "boolean",
                        "description": "One-flag stateful service. When true, auto-enables clusters, issuer summary, batch insights, and (with watchlistName) deltaMode. Recurring scheduled-run friendly.",
                        "default": false
                    },
                    "watchlistName": {
                        "title": "Watchlist Name",
                        "type": "string",
                        "description": "Names a per-watchlist named KV store for cross-run state — temporal signals, state transitions, regime shift detection, narrative delta. Two pipelines on different watchlists don't interfere."
                    },
                    "deltaMode": {
                        "title": "Delta Mode",
                        "type": "boolean",
                        "description": "When true (and watchlistName set), every transaction carries a delta block: new / changed / unchanged / recovered / degraded.",
                        "default": false
                    },
                    "includeClusters": {
                        "title": "Include Cluster Detection",
                        "type": "boolean",
                        "description": "Detect ≥2 distinct insiders moving same direction within a 30d window. On by default for most modes."
                    },
                    "includeIssuerSummary": {
                        "title": "Include Issuer Summary Records",
                        "type": "boolean",
                        "description": "Emit one issuer-summary record per ticker — sentiment, insiderPressureIndex, watchStatus, triggers fired, escalation routing."
                    },
                    "includeBatchInsights": {
                        "title": "Include Batch Summary Record",
                        "type": "boolean",
                        "description": "Emit a single batch-summary record at the end with portfolio state + priority queue + run manifest + watchlist analytics."
                    },
                    "triggerPacks": {
                        "title": "Trigger Packs",
                        "type": "array",
                        "description": "Pre-built rule bundles that fire alerts on matching transactions / clusters. Mode + routing-profile pre-select packs; this input adds more. Valid values: cluster-buy, cluster-sale, executive-disposal, large-purchase, amendment-burst, distress-watch.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "triggers": {
                        "title": "Custom Triggers",
                        "type": "array",
                        "description": "User-defined alert rules. Schema: { name, when: { direction?, minTotalValue?, minClusterSize?, insiderRoleIn?, materialityLevelIn?, unusualnessAtLeast? }, severity? }."
                    },
                    "outputProfile": {
                        "title": "Output Profile",
                        "enum": [
                            "minimal",
                            "standard",
                            "full",
                            "llm"
                        ],
                        "type": "string",
                        "description": "Field-set shrinkage. minimal = core fields only. standard = decision layer included. full = every block. llm = LLM-friendly subset for agent consumers.",
                        "default": "standard"
                    },
                    "includeAlertPayloads": {
                        "title": "Include Alert Payloads",
                        "type": "boolean",
                        "description": "Write the immediate-review queue + cluster alerts + issuer alerts to the ALERTS key in the run's KV store."
                    },
                    "referenceRunId": {
                        "title": "Reference Run ID",
                        "type": "string",
                        "description": "(Reserved) — diff this run against a specific prior run instead of the most recent watchlist snapshot. Currently informational only."
                    },
                    "concurrency": {
                        "title": "Parallel Ticker Concurrency",
                        "minimum": 1,
                        "maximum": 16,
                        "type": "integer",
                        "description": "How many tickers (and per-ticker filings) to process in parallel. Higher = faster cohort scans, throttled globally by SEC's 10 req/sec rate limit. Default 8.",
                        "default": 8
                    },
                    "preFilterByTransactionType": {
                        "title": "Pre-filter by Transaction Type (EXPERIMENTAL — may produce false negatives)",
                        "type": "boolean",
                        "description": "EXPERIMENTAL. When true (and transactionType is purchase/sale/grant/exercise), does a cheap EDGAR probe per ticker to skip tickers with zero matching filings. Default FALSE. Known limitation: EDGAR's full-text indexer does not reliably preserve XML tags, so the probe can produce false negatives — verified against year-scale + low-frequency-event inputs (e.g. XOM 2024 purchases). Use with caution; off by default for correctness.",
                        "default": false
                    },
                    "runtimeBudgetSeconds": {
                        "title": "Runtime Budget (seconds)",
                        "minimum": 60,
                        "maximum": 21600,
                        "type": "integer",
                        "description": "Soft runtime cap on the FETCH phase. When elapsed time exceeds this, the actor stops fetching new data and emits partial results. AUTO-CLAMPING: the actor reads Apify's deadline (APIFY_TIMEOUT_AT) and automatically clamps this value to (deadline - emit-reserve), where emit-reserve scales with maxResults (5-15min). This prevents Apify hard-killing during the EMIT phase (filter/enrich/cluster/issuer-build/KV/dataset-push). If you set this ≥ Apify's timeoutSecs, it WILL be auto-clamped down — the clamp is logged at startup. Default 3000 (50 minutes).",
                        "default": 3000
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
