# SEC Form 13F Institutional Holdings

> **Module**: `packages/be/src/institutional/`
> **Migration**: `db/migrations/241_institutional_holdings.sql`
> **Shipped**: 2026-05-17

## Overview

SEC Form 13F institutional holdings tracking system that:
- Fetches quarterly 13F filings from SEC EDGAR (free, no API key required)
- Tracks institutional ownership, position changes, and smart money flows
- Provides 6 DSL primitives for algorithmic trading strategies
- Integrates with Stock Hunter for research reports
- Surfaces data via 5 API endpoints

Investment managers with >$100M in assets under management (AUM) must file Form 13F quarterly with the SEC, disclosing their equity holdings. This data provides insight into "smart money" positioning.

## Database Schema

5 tables in the `predict` schema:

| Table | Purpose |
|-------|---------|
| `institutional_filers` | Investment managers (CIK, name, AUM, classification) |
| `institutional_holdings` | Per-symbol holdings per quarter |
| `institutional_position_changes` | QoQ deltas (new/increased/decreased/closed) |
| `institutional_ownership_snapshots` | Aggregated metrics per symbol |
| `institutional_sync_status` | Sync job tracking |
| `cusip_symbol_mapping` | CUSIP to symbol resolution (seeded with ~30 common CUSIPs) |

## Architecture

```
packages/be/src/institutional/
├── types.ts          # TypeScript interfaces
├── repository.ts     # Database CRUD operations
├── sec-fetcher.ts    # SEC EDGAR integration + OpenFIGI CUSIP resolution
├── service.ts        # Business logic orchestration
├── dsl-wrappers.ts   # DSL primitive implementations with caching
└── index.ts          # Module exports
```

## SEC EDGAR Integration

### Data Source

- **RSS Feed**: `https://www.sec.gov/cgi-bin/browse-edgar?action=getcurrent&type=13F-HR&output=atom`
- **Rate Limit**: 1 request/second (SEC guideline)
- **User-Agent**: `Agencio Predict (support@agencio.cloud)`

### Filing Structure

| Form Type | Description |
|-----------|-------------|
| 13F-HR | Holdings Report (quarterly) |
| 13F-HR/A | Amendment to previous filing |
| 13F-NT | Notice (no holdings change) |

### Filing Timeline

- **Deadline**: 45 days after quarter end
- **Q1 (Mar 31)**: Due May 15
- **Q2 (Jun 30)**: Due Aug 14
- **Q3 (Sep 30)**: Due Nov 14
- **Q4 (Dec 31)**: Due Feb 14

### CUSIP Resolution

13F filings use CUSIP identifiers, not ticker symbols. Resolution flow:

1. Check local `cusip_symbol_mapping` table (seeded with ~30 common CUSIPs)
2. If not found, call OpenFIGI API (free tier: 25 req/min)
3. Cache successful resolutions for future lookups

## DSL Primitives

6 primitives available in the Algorithm Builder:

| Primitive | Category | Returns | Description |
|-----------|----------|---------|-------------|
| `institutional_ownership_pct(symbol)` | fundamental | number | % of shares held by institutions (0-100) |
| `institutional_change_qoq(symbol)` | fundamental | number | QoQ ownership change in percentage points |
| `top_holder_concentration(symbol)` | fundamental | number | % of institutional ownership held by top 10 |
| `smart_money_accumulating(symbol)` | fundamental | boolean | True if AUM>$1B institutions are net buyers |
| `institutional_holders_count(symbol)` | fundamental | number | Number of institutional holders |
| `new_institutional_positions(symbol)` | fundamental | number | Count of new positions this quarter |

### Example Strategy

```yaml
name: Smart Money Following
entry:
  - smart_money_accumulating($symbol)
  - institutional_change_qoq($symbol) > 2
  - new_institutional_positions($symbol) >= 5
exit:
  - not smart_money_accumulating($symbol)
  - institutional_change_qoq($symbol) < -3
```

## API Endpoints

### Public Endpoints

| Method | Route | Description |
|--------|-------|-------------|
| GET | `/api/predict/v1/institutional/{symbol}` | Symbol summary + top holders |
| GET | `/api/predict/v1/institutional/{symbol}/history` | Quarterly history |
| GET | `/api/predict/v1/institutional/filers?q=search` | Search filers |
| GET | `/api/predict/v1/institutional/filers/{cik}` | Filer portfolio |

### Admin Endpoints

| Method | Route | Description |
|--------|-------|-------------|
| POST | `/api/predict/v1/admin/institutional/sync` | Trigger manual sync |
| GET | `/api/predict/v1/admin/institutional/sync` | Get sync status |

### Response Examples

**GET /institutional/AAPL**
```json
{
  "data": {
    "symbol": "AAPL",
    "reportDate": "2026-03-31",
    "snapshot": {
      "totalInstitutionalShares": 14500000000,
      "totalInstitutionalValue": 2850000000000,
      "institutionalHoldersCount": 5842,
      "ownershipPct": 62.5,
      "sharesChangeQoq": 150000000,
      "smartMoneyBuyers": 245,
      "smartMoneySellers": 112
    },
    "topHolders": [
      {
        "filerName": "Vanguard Group",
        "shares": 1350000000,
        "marketValue": 265000000000,
        "changeType": "increased",
        "sharesChangePct": 2.3
      }
    ],
    "quarterlyTrend": [...]
  }
}
```

## Scheduler Jobs

3 jobs in `packages/be/src/scheduler/index.ts`:

| Job | Interval | Description |
|-----|----------|-------------|
| `sync-13f-incremental` | Weekly (Mondays) | Fetch recent 13F filings (100 count) |
| `sync-13f-quarterly-check` | Daily | Full sync during filing windows (Feb/May/Aug/Nov 15-25) |
| `refresh-institutional-metrics` | Daily | Recompute ownership snapshots |

## Stock Hunter Integration

Institutional data is automatically included in Stock Hunter research reports:

- **StockDataBundle**: `institutional: InstitutionalData | null`
- **Data Quality**: `institutionalAvailable` flag added
- **Report Sections**: Institutional data included in Executive Summary and Risk Analysis

### Skipped Asset Classes

Institutional data is skipped for:
- `crypto` - Not covered by 13F (US securities only)
- `forex` - Not covered by 13F

## Tick Context Integration

Institutional data is prefetched in `tick-context.ts` for paper/live algorithm execution:

```typescript
interface PrefetchedTickContext {
  // ... other fields
  institutionalData: PrefetchedInstitutionalData | null;
}
```

Cached for 24 hours (institutional data updates quarterly).

## Smart Money Signals

### Definition

"Smart Money" is defined as institutions with AUM > $1 billion. These are typically:
- Large hedge funds
- Major pension funds
- Sovereign wealth funds
- Top mutual fund families

### Signal Interpretation

| Signal | Interpretation |
|--------|----------------|
| `smartMoneyBuyers > smartMoneySellers` | Large institutions accumulating |
| `smartMoneyNetFlow > 0` | Net positive dollar flow from smart money |
| High `top10ConcentrationPct` (>50%) | Concentrated ownership, potential volatility |
| High `newPositions` count | Fresh institutional interest |

## Data Freshness

| Metric | Update Frequency |
|--------|------------------|
| Holdings data | Quarterly (45 days after quarter end) |
| Position changes | Computed on sync |
| Ownership snapshots | Daily refresh |
| DSL cache | 24-hour TTL |

## Performance Considerations

- **Storage**: ~500 bytes per holding, ~1000 holdings per major filer, ~5000 filers = ~2.5GB for full history
- **Query Performance**: Indexes on (symbol, report_date) ensure <100ms for typical queries
- **SEC Rate Limit**: 1 req/sec conservatively (SEC allows 10 req/sec)
- **OpenFIGI**: 25 req/min free tier (sufficient for batch CUSIP resolution)

## Smoke Test Status (2026-05-18)

| Check | Status | Notes |
|-------|--------|-------|
| TypeScript Compilation | ✅ PASS | All packages compile |
| Migration Syntax | ✅ PASS | Migration 241 valid SQL |
| API Routes Created | ✅ PASS | 4 routes configured |
| Scheduler Jobs Registered | ✅ PASS | Weekly sync + daily metrics refresh |
| DSL Primitives Wired | ✅ PASS | 6 primitives in evaluator + executor |
| Stock Hunter Integration | ✅ PASS | InstitutionalData in StockDataBundle |

## Verification Checklist

1. **Migration Applied**
   ```bash
   psql -U predict -d predict -c "\dt predict.institutional_*"
   ```

2. **Sync Job Execution**
   ```bash
   curl -X POST http://localhost:3333/api/predict/v1/admin/institutional/sync \
     -H "Authorization: Bearer <admin-token>" \
     -H "Content-Type: application/json"
   ```

3. **API Verification**
   ```bash
   curl http://localhost:3333/api/predict/v1/institutional/AAPL
   ```

4. **DSL Primitive Test**
   Create algorithm with condition: `smart_money_accumulating('AAPL')`

5. **Stock Hunter Report**
   Generate research report for AAPL and verify institutional section appears
