Securities and Exchange Commission

US SEC 13F Whales

Introduction

The US SEC 13F Whales dataset by the US Securities and Exchange Commission (SEC) tracks the holdings of institutional investment managers with at least $100 million in assets under management. The data covers 18,877 US Equities, starts in May 2013, and is delivered on a daily frequency. This dataset is created by parsing Form 13F filings.

This dataset depends on the US Equity Security Master dataset because the US Equity Security Master dataset contains information on splits, dividends, and symbol changes.

For more information about the US SEC 13F Whales dataset, including CLI commands and pricing, see the dataset listing.

About the Provider

The mission of the U.S. Securities and Exchange Commission is to protect investors, maintain fair, orderly, and efficient markets, and facilitate capital formation. The SEC oversees the key participants in the securities world, including securities exchanges, securities brokers and dealers, investment advisors, and mutual funds. The SEC is concerned primarily with promoting the disclosure of important market-related information, maintaining fair dealing, and protecting against fraud.

Getting Started

The following snippet demonstrates how to request data from the SEC Whales dataset:

self._symbol = self.add_equity("AAPL", Resolution.DAILY).symbol
self._holdings_symbol = self.add_data(SEC13FHoldings, self._symbol).symbol
_symbol = AddEquity("AAPL", Resolution.Daily).Symbol;
_holdingsSymbol = AddData<SEC13FHoldings>(_symbol).Symbol;

Data Summary

The following table describes the dataset properties:

PropertyValue
Start DateMay 2013
Asset Coverage*18,877 US Equities
Data DensitySparse
ResolutionDaily
TimezoneNew York

* The coverage includes all assets since the start date. It increases over time.

Requesting Data

To add SEC Whales data to your algorithm, call the AddDataadd_data method. Save a reference to the dataset Symbol so you can access the data later in your algorithm.

class SEC13FDataAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2020, 10, 1)
        self.set_end_date(2020, 12, 31)
        self.set_cash(100000)

        self._symbol = self.add_equity("AAPL", Resolution.DAILY).symbol
        self._dataset_symbol = self.add_data(SEC13FHoldings, self._symbol).symbol
public class SEC13FDataAlgorithm : QCAlgorithm
{
    private Symbol _symbol, _datasetSymbol;

    public override void Initialize()
    {
        SetStartDate(2020, 10, 1);
        SetEndDate(2020, 12, 31);
        SetCash(100000);

        _symbol = AddEquity("AAPL", Resolution.Daily).Symbol;
        _datasetSymbol = AddData<SEC13FHoldings>(_symbol).Symbol;
    }
}

Accessing Data

To get the current SEC Whales data, index the current Slice with the dataset Symbol. Slice objects deliver unique events to your algorithm as they happen, but the Slice may not contain data for your dataset at every time step. To avoid issues, check if the Slice contains the data you want before you index it.

def on_data(self, slice: Slice) -> None:
    if slice.contains_key(self._dataset_symbol):
        for holding in slice[self._dataset_symbol]:
            self.log(f"{self._dataset_symbol} CIK {holding.manager_cik} at {slice.time}: {holding.amount} {holding.amount_type}")
public override void OnData(Slice slice)
{
    if (slice.ContainsKey(_datasetSymbol))
    {
        foreach (SEC13FHolding holding in slice[_datasetSymbol])
        {
            Log($"{_datasetSymbol} CIK {holding.ManagerCik} at {slice.Time}: {holding.Amount} {holding.AmountType}");
        }
    }
}

To iterate through all of the dataset objects in the current Slice, call the Getget method.

def on_data(self, slice: Slice) -> None:
    for dataset_symbol, holdings in slice.get(SEC13FHoldings).items():
        for holding in holdings:
            self.log(f"{dataset_symbol} CIK {holding.manager_cik} at {slice.time}: {holding.amount} {holding.amount_type}")
public override void OnData(Slice slice)
{
    foreach (var kvp in slice.Get<SEC13FHoldings>())
    {
        var datasetSymbol = kvp.Key;
        foreach (SEC13FHolding holding in kvp.Value)
        {
            Log($"{datasetSymbol} CIK {holding.ManagerCik} at {slice.Time}: {holding.Amount} {holding.AmountType}");
        }
    }
}

Historical Data

To get historical SEC Whales data, call the Historyhistory method with the dataset Symbol. If there is no data in the period you request, the history result is empty.

# DataFrame
history_df = self.history(SEC13FHoldings, self._dataset_symbol, timedelta(days=60), Resolution.DAILY, flatten=True)

# Dataset objects
history_bars = self.history[SEC13FHoldings](self._dataset_symbol, timedelta(days=60), Resolution.DAILY)
var history = History<SEC13FHoldings>(_datasetSymbol, TimeSpan.FromDays(60), Resolution.Daily);

For more information about historical data, see History Requests.

Remove Subscriptions

To remove your subscription to SEC Whales data, call the RemoveSecurityremove_security method.

self.remove_security(self._dataset_symbol)
RemoveSecurity(_datasetSymbol);

If you subscribe to SEC Whales data for assets in a dynamic universe, remove the dataset subscription when the asset leaves your universe. To view a common design pattern, see Track Security Changes.

Supported Managers

To follow a manager, filter the holdings by its CIK with the ManagerCikmanager_cik property. The following table shows the 50 largest managers by reported value in the second quarter of 2026:

CIKManager
2012383BlackRock Inc.
2100119VANGUARD CAPITAL MANAGEMENT LLC
93751STATE STREET CORP
315066FMR LLC
2100121VANGUARD PORTFOLIO MANAGEMENT LLC
895421MORGAN STANLEY
1214717GEODE CAPITAL MANAGEMENT LLC
19617JPMORGAN CHASE & CO
70858BANK OF AMERICA CORP /DE/
914208Invesco Ltd.
1374170NORGES BANK
80255PRICE T ROWE ASSOCIATES INC /MD/
886982GOLDMAN SACHS GROUP INC
73124NORTHERN TRUST CORP
1422849Capital World Investors
884546CHARLES SCHWAB INVESTMENT MANAGEMENT INC
1422848Capital Research Global Investors
1610520UBS Group AG
1390777Bank of New York Mellon Corp
1000275ROYAL BANK OF CANADA
902219WELLINGTON MANAGEMENT GROUP LLP
72971WELLS FARGO & COMPANY/MN
354204DIMENSIONAL FUND ADVISORS LP
861177UBS AM a distinct business unit of UBS ASSET MANAGEMENT AMERICAS LLC
820027AMERIPRISE FINANCIAL INC
1562230Capital International Investors
764068Legal & General Group Plc
38777FRANKLIN RESOURCES INC
933478VANGUARD FIDUCIARY TRUST CO
1403438LPL Financial LLC
1407543ENVESTNET ASSET MANAGEMENT INC
1871926Nuveen LLC
1330387Amundi
720005RAYMOND JAMES FINANCIAL INC
948046DEUTSCHE BANK AG
850529Fisher Asset Management LLC
312069BARCLAYS PLC
912938MASSACHUSETTS FINANCIAL SERVICES CO /MA/
1109448ALLIANCEBERNSTEIN L.P.
1067983Berkshire Hathaway Inc
1167557AQR CAPITAL MANAGEMENT LLC
927971BANK OF MONTREAL /CAN/
815917JONES FINANCIAL COMPANIES LLLP
2146052Jupiter Topco LLC
748054AMERICAN CENTURY COMPANIES INC
1164508ARROWSTREET CAPITAL LIMITED PARTNERSHIP
1811242Vanguard Global Advisers LLC
831001CITIGROUP INC
873630HSBC HOLDINGS PLC
1126328PRINCIPAL FINANCIAL GROUP INC

Example Applications

The US SEC 13F Whales dataset enables you to follow what large institutional investors hold and how their positions change. Examples include the following strategies:

  • Following the quarterly positions of specific fund managers on the premise that they are more informed
  • Buying the securities that institutions are accumulating and selling the ones they are reducing
  • Avoiding crowded securities that many managers hold at the same time

Classic Algorithm Example

The following example algorithm buys AAPL when Parnassus Investments reports more shares of it than in the previous quarter. Otherwise, it liquidates the position.

from AlgorithmImports import *


class SEC13FDataAlgorithm(QCAlgorithm):

    def initialize(self):
        self.set_start_date(2019, 1, 1)
        self.set_end_date(2020, 8, 31)
        self.set_cash(100000)

        self.equity = self.add_equity("AAPL", Resolution.DAILY).symbol
        self.add_data(SEC13FHoldings, self.equity)

        self.shares_by_quarter = {}

    def on_data(self, slice):
        for _, point in slice.get(SEC13FHoldings).items():
            for holding in point:
                # Sum the share lines Parnassus Investments reports for each quarter.
                if (holding.manager_cik != 948669 or holding.form_type != "13F-HR"
                        or holding.amount_type != "SH" or holding.put_call is not None):
                    continue

                quarter = holding.period_end
                self.shares_by_quarter[quarter] = self.shares_by_quarter.get(quarter, 0) + (holding.amount or 0)
                self.log(f"{self.time:%Y-%m-%d} {holding.manager_name} reports {holding.amount:,.0f} shares "
                         f"for {quarter:%Y-%m-%d}")

        quarters = [self.shares_by_quarter[q] for q in sorted(self.shares_by_quarter)]
        if len(quarters) < 2 or slice.bars.count == 0:
            return

        # Buy when the manager adds shares, otherwise liquidate.
        if quarters[-1] > quarters[-2]:
            self.set_holdings(self.equity, 1)
        else:
            self.liquidate(self.equity)
using System;
using System.Collections.Generic;
using System.Linq;
using QuantConnect;
using QuantConnect.Algorithm;
using QuantConnect.Data;
using QuantConnect.DataSource;

    public class SEC13FDataAlgorithm : QCAlgorithm
    {
        private Symbol _equity;
        private readonly Dictionary<DateTime, decimal> _sharesByQuarter = new();

        public override void Initialize()
        {
            SetStartDate(2019, 1, 1);
            SetEndDate(2020, 8, 31);
            SetCash(100000);

            _equity = AddEquity("AAPL", Resolution.Daily).Symbol;
            AddData<SEC13FHoldings>(_equity);
        }

        public override void OnData(Slice slice)
        {
            foreach (var (_, point) in slice.Get<SEC13FHoldings>())
            {
                // Sum the share lines Parnassus Investments reports for each quarter.
                foreach (var holding in point.OfType<SEC13FHolding>().Where(holding =>
                             holding.ManagerCik == 948669 && holding.FormType == "13F-HR" &&
                             holding.AmountType == "SH" && !holding.PutCall.HasValue))
                {
                    _sharesByQuarter.TryGetValue(holding.PeriodEnd, out var reported);
                    _sharesByQuarter[holding.PeriodEnd] = reported + (holding.Amount ?? 0);
                    Log($"{Time:yyyy-MM-dd} {holding.ManagerName} reports {holding.Amount:N0} shares " +
                        $"for {holding.PeriodEnd:yyyy-MM-dd}");
                }
            }

            var quarters = _sharesByQuarter.OrderBy(entry => entry.Key).Select(entry => entry.Value).ToList();
            if (quarters.Count < 2 || slice.Bars.Count == 0)
            {
                return;
            }

            // Buy when the manager adds shares, otherwise liquidate.
            if (quarters[^1] > quarters[^2])
            {
                SetHoldings(_equity, 1);
            }
            else
            {
                Liquidate(_equity);
            }
        }
    }

Framework Algorithm Example

The following example algorithm compares how many managers report AAPL in two consecutive quarters once their 45-day filing deadline has passed. It emits an up insight when the later quarter has more managers and a down insight when it has fewer.

from AlgorithmImports import *


class SEC13FFrameworkAlgorithm(QCAlgorithm):

    def initialize(self):
        self.set_start_date(2020, 1, 1)
        self.set_end_date(2020, 12, 31)
        self.set_cash(100000)

        self.universe_settings.resolution = Resolution.DAILY
        self.set_universe_selection(ManualUniverseSelectionModel(
            [Symbol.create("AAPL", SecurityType.EQUITY, Market.USA)]))

        self.add_alpha(SEC13FCrowdingAlphaModel())
        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
        self.set_execution(ImmediateExecutionModel())


class SEC13FCrowdingAlphaModel(AlphaModel):

    # Count a quarter only after its 45-day filing deadline has passed.
    FILING_DEADLINE = timedelta(days=45)

    def __init__(self):
        self._holdings = {}
        self._managers = {}
        self._emitted = set()

    def update(self, algorithm, data):
        insights = []

        for holdings_symbol, point in data.get(SEC13FHoldings).items():
            equity = holdings_symbol.underlying
            by_period = self._managers.setdefault(equity, {})

            for holding in point:
                if (holding.form_type != "13F-HR" or holding.amount_type != "SH"
                        or holding.put_call is not None
                        or algorithm.time > holding.period_end + self.FILING_DEADLINE):
                    continue
                by_period.setdefault(holding.period_end, set()).add(holding.manager_cik)

            closed = [p for p in sorted(by_period) if algorithm.time >= p + self.FILING_DEADLINE]
            if len(closed) < 2 or (equity, closed[-1]) in self._emitted:
                continue

            self._emitted.add((equity, closed[-1]))
            latest, previous = len(by_period[closed[-1]]), len(by_period[closed[-2]])
            if latest == previous:
                continue

            algorithm.log(f"{algorithm.time:%Y-%m-%d} {equity.value}: {previous} -> {latest} managers")
            direction = InsightDirection.UP if latest > previous else InsightDirection.DOWN
            insights.append(Insight.price(equity, timedelta(days=30), direction))

        return insights

    def on_securities_changed(self, algorithm, changes):
        for security in changes.added_securities:
            self._holdings[security.symbol] = algorithm.add_data(SEC13FHoldings, security.symbol).symbol

        for security in changes.removed_securities:
            holdings_symbol = self._holdings.pop(security.symbol, None)
            if holdings_symbol is not None:
                algorithm.remove_security(holdings_symbol)
using System;
using System.Collections.Generic;
using System.Linq;
using QuantConnect;
using QuantConnect.Algorithm;
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Algorithm.Framework.Execution;
using QuantConnect.Algorithm.Framework.Portfolio;
using QuantConnect.Algorithm.Framework.Selection;
using QuantConnect.Data;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.DataSource;

    public class SEC13FFrameworkAlgorithm : QCAlgorithm
    {
        public override void Initialize()
        {
            SetStartDate(2020, 1, 1);
            SetEndDate(2020, 12, 31);
            SetCash(100000);

            UniverseSettings.Resolution = Resolution.Daily;
            SetUniverseSelection(new ManualUniverseSelectionModel(
                QuantConnect.Symbol.Create("AAPL", SecurityType.Equity, Market.USA)));

            AddAlpha(new SEC13FCrowdingAlphaModel());
            SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
            SetExecution(new ImmediateExecutionModel());
        }
    }

    public class SEC13FCrowdingAlphaModel : AlphaModel
    {
        // Count a quarter only after its 45-day filing deadline has passed.
        private static readonly TimeSpan FilingDeadline = TimeSpan.FromDays(45);

        private readonly Dictionary<Symbol, Symbol> _holdings = new();
        private readonly Dictionary<Symbol, Dictionary<DateTime, HashSet<int>>> _managers = new();
        private readonly HashSet<(Symbol, DateTime)> _emitted = new();

        public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
        {
            var insights = new List<Insight>();

            foreach (var (holdingsSymbol, point) in data.Get<SEC13FHoldings>())
            {
                var equity = holdingsSymbol.Underlying;
                if (!_managers.TryGetValue(equity, out var byPeriod))
                {
                    _managers[equity] = byPeriod = new Dictionary<DateTime, HashSet<int>>();
                }

                foreach (var holding in point.OfType<SEC13FHolding>().Where(holding =>
                             holding.FormType == "13F-HR" && holding.AmountType == "SH" &&
                             !holding.PutCall.HasValue &&
                             algorithm.Time <= holding.PeriodEnd + FilingDeadline))
                {
                    if (!byPeriod.TryGetValue(holding.PeriodEnd, out var managers))
                    {
                        byPeriod[holding.PeriodEnd] = managers = new HashSet<int>();
                    }

                    managers.Add(holding.ManagerCik);
                }

                var closed = byPeriod.Keys.Where(p => algorithm.Time >= p + FilingDeadline)
                    .OrderBy(p => p).ToList();
                if (closed.Count < 2 || !_emitted.Add((equity, closed[^1])))
                {
                    continue;
                }

                var latest = byPeriod[closed[^1]].Count;
                var previous = byPeriod[closed[^2]].Count;
                if (latest == previous)
                {
                    continue;
                }

                algorithm.Log($"{algorithm.Time:yyyy-MM-dd} {equity.Value}: {previous} -> {latest} managers");
                var direction = latest > previous ? InsightDirection.Up : InsightDirection.Down;
                insights.Add(Insight.Price(equity, TimeSpan.FromDays(30), direction));
            }

            return insights;
        }

        public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
        {
            foreach (var security in changes.AddedSecurities)
            {
                _holdings[security.Symbol] = algorithm.AddData<SEC13FHoldings>(security.Symbol).Symbol;
            }

            foreach (var security in changes.RemovedSecurities)
            {
                if (_holdings.Remove(security.Symbol, out var holdingsSymbol))
                {
                    algorithm.RemoveSecurity(holdingsSymbol);
                }
            }
        }
    }

Data Point Attributes

The SEC Whales dataset provides SEC13FHoldings and SEC13FHolding objects.

SEC13FHoldings

SEC13FHoldings objects have the following attributes:

SEC13FHolding

SEC13FHolding objects have the following attributes:

You can also see our Videos. You can also get in touch with us via Discord.

Did you find this page helpful?

Contribute to the documentation: