Access Portfolio Holdings & Cover Pages of Form 13F Filings with Python
This Python tutorial demonstrates how to access and download the holdings and cover pages of Form 13F filings using the sec-api
Python package and the Form 13F APIs. The number of unique holdings of a fund is calculated as well as the total portfolio value. The cover page of the corresponding Form 13F filing is also downloaded, allowing for confirmation of the fund's name, address, other managers, and more.
!pip install sec-api
import json
import pandas as pd
API_KEY_SEC_API = "YOUR_API_KEY"
from sec_api import Form13FHoldingsApi, Form13FCoverPagesApi
form13FHoldingsApi = Form13FHoldingsApi(API_KEY_SEC_API)
form13FCoverPagesApi = Form13FCoverPagesApi(API_KEY_SEC_API)
search_params = {
"query": "cik:1350694 AND periodOfReport:2024-03-31",
"from": "0",
"size": "1",
"sort": [{"periodOfReport": {"order": "desc"}}],
}
# load holdings
response = form13FHoldingsApi.get_data(search_params)
filings = response["data"]
holdings = filings[0]["holdings"]
# load cover page
response = form13FCoverPagesApi.get_data(search_params)
cover_page = response["data"][0]
Holdings from Form 13F Filings
The following example demonstrates how to retrieve a fund's holdings from Form 13F filings. The get_data(search_params)
method of the Form13FHoldingsApi
class extracts holdings from Form 13F filings that match the specified search criteria. In this example, we obtain the portfolio holdings of Bridgewater Associates (CIK: 1350694) as reported in their 13F filing for the first quarter of 2024.
from sec_api import Form13FHoldingsApi
form13FHoldingsApi = Form13FHoldingsApi(API_KEY_SEC_API)
search_params = {
"query": "cik:1350694 AND periodOfReport:2024-03-31",
"from": "0",
"size": "1",
"sort": [{"periodOfReport": {"order": "desc"}}],
}
response = form13FHoldingsApi.get_data(search_params)
filings = response["data"]
holdings_json = filings[0]["holdings"]
holdings = pd.DataFrame(holdings_json)
holdings
cusip | ticker | cik | investmentDiscretion | votingAuthority | nameOfIssuer | value | shrsOrPrnAmt | titleOfClass | |
---|---|---|---|---|---|---|---|---|---|
0 | 88579Y101 | MMM | 66740 | SOLE | {'Sole': 13726, 'Shared': 0, 'None': 0} | 3M CO | 1455917 | {'sshPrnamtType': 'SH', 'sshPrnamt': 13726} | COM |
1 | 002824100 | ABT | 1800 | SOLE | {'Sole': 1728482, 'Shared': 0, 'None': 7675} | ABBOTT LABS | 197331605 | {'sshPrnamtType': 'SH', 'sshPrnamt': 1736157} | COM |
2 | 00287Y109 | ABBV | 1551152 | SOLE | {'Sole': 449779, 'Shared': 0, 'None': 0} | ABBVIE INC | 81904756 | {'sshPrnamtType': 'SH', 'sshPrnamt': 449779} | COM |
3 | 00404A109 | ACHC | 1520697 | SOLE | {'Sole': 82943, 'Shared': 0, 'None': 408} | ACADIA HEALTHCARE COMPANY IN | 6603066 | {'sshPrnamtType': 'SH', 'sshPrnamt': 83351} | COM |
4 | G1151C101 | ACN | 1467373 | SOLE | {'Sole': 5269, 'Shared': 0, 'None': 0} | ACCENTURE PLC IRELAND | 1826288 | {'sshPrnamtType': 'SH', 'sshPrnamt': 5269} | SHS CLASS A |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
672 | 98954M200 | Z | 1617640 | SOLE | {'Sole': 98269, 'Shared': 0, 'None': 0} | ZILLOW GROUP INC | 4793562 | {'sshPrnamtType': 'SH', 'sshPrnamt': 98269} | CL C CAP STK |
673 | 98956P102 | ZBH | 1136869 | SOLE | {'Sole': 353985, 'Shared': 0, 'None': 918} | ZIMMER BIOMET HOLDINGS INC | 46840098 | {'sshPrnamtType': 'SH', 'sshPrnamt': 354903} | COM |
674 | 98978V103 | ZTS | 1555280 | SOLE | {'Sole': 60434, 'Shared': 0, 'None': 0} | ZOETIS INC | 10226037 | {'sshPrnamtType': 'SH', 'sshPrnamt': 60434} | CL A |
675 | 98980F104 | ZI | 1794515 | SOLE | {'Sole': 70792, 'Shared': 0, 'None': 0} | ZOOMINFO TECHNOLOGIES INC | 1134796 | {'sshPrnamtType': 'SH', 'sshPrnamt': 70792} | COMMON STOCK |
676 | 98980A105 | ZTO | 1677250 | SOLE | {'Sole': 523693, 'Shared': 0, 'None': 0} | ZTO EXPRESS CAYMAN INC | 10966131 | {'sshPrnamtType': 'SH', 'sshPrnamt': 523693} | SPONSORED ADS A |
677 rows × 9 columns
columns_to_explode = ["votingAuthority", "shrsOrPrnAmt"]
for column in columns_to_explode:
holdings = pd.concat(
[
holdings.drop(columns=column),
pd.json_normalize(holdings[column]).add_prefix(f"{column}_"),
],
axis=1,
)
holdings
cusip | ticker | cik | investmentDiscretion | nameOfIssuer | value | titleOfClass | votingAuthority_Sole | votingAuthority_Shared | votingAuthority_None | shrsOrPrnAmt_sshPrnamtType | shrsOrPrnAmt_sshPrnamt | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 88579Y101 | MMM | 66740 | SOLE | 3M CO | 1455917 | COM | 13726 | 0 | 0 | SH | 13726 |
1 | 002824100 | ABT | 1800 | SOLE | ABBOTT LABS | 197331605 | COM | 1728482 | 0 | 7675 | SH | 1736157 |
2 | 00287Y109 | ABBV | 1551152 | SOLE | ABBVIE INC | 81904756 | COM | 449779 | 0 | 0 | SH | 449779 |
3 | 00404A109 | ACHC | 1520697 | SOLE | ACADIA HEALTHCARE COMPANY IN | 6603066 | COM | 82943 | 0 | 408 | SH | 83351 |
4 | G1151C101 | ACN | 1467373 | SOLE | ACCENTURE PLC IRELAND | 1826288 | SHS CLASS A | 5269 | 0 | 0 | SH | 5269 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
672 | 98954M200 | Z | 1617640 | SOLE | ZILLOW GROUP INC | 4793562 | CL C CAP STK | 98269 | 0 | 0 | SH | 98269 |
673 | 98956P102 | ZBH | 1136869 | SOLE | ZIMMER BIOMET HOLDINGS INC | 46840098 | COM | 353985 | 0 | 918 | SH | 354903 |
674 | 98978V103 | ZTS | 1555280 | SOLE | ZOETIS INC | 10226037 | CL A | 60434 | 0 | 0 | SH | 60434 |
675 | 98980F104 | ZI | 1794515 | SOLE | ZOOMINFO TECHNOLOGIES INC | 1134796 | COMMON STOCK | 70792 | 0 | 0 | SH | 70792 |
676 | 98980A105 | ZTO | 1677250 | SOLE | ZTO EXPRESS CAYMAN INC | 10966131 | SPONSORED ADS A | 523693 | 0 | 0 | SH | 523693 |
677 rows × 12 columns
unique_holdings_by_cusip = holdings.groupby("cusip").first().reset_index()
print(f"Number of unique holdings: {len(unique_holdings_by_cusip)}")
Number of unique holdings: 677
total_portfolio_value = holdings["value"].sum() / 1_000_000_000
print(f"Total portfolio value: ${total_portfolio_value:,.3f} billion")
Total portfolio value: $19.775 billion
Cover Pages from Form 13F Filings
To retrieve the cover page of Bridgewater's Form 13F filing for the first quarter of 2024, we use the get_data(search_params)
method of the Form13FCoverPagesApi
class.
from sec_api import Form13FCoverPagesApi
form13FCoverPagesApi = Form13FCoverPagesApi(API_KEY_SEC_API)
search_params = {
"query": "cik:1350694 AND periodOfReport:2024-03-31",
"from": "0",
"size": "1",
"sort": [{"periodOfReport": {"order": "desc"}}],
}
response = form13FCoverPagesApi.get_data(search_params)
cover_page = response["data"][0]
print(json.dumps(cover_page, indent=2))
{
"id": "d1a4cbcd2eab004e9415e402a2701c46",
"accessionNo": "0001172661-24-002257",
"filedAt": "2024-05-14T12:37:20-04:00",
"formType": "13F-HR",
"cik": "1350694",
"crdNumber": "105129",
"secFileNumber": "801-35875",
"form13FFileNumber": "028-11794",
"periodOfReport": "2024-03-31",
"isAmendment": false,
"amendmentInfo": {},
"filingManager": {
"name": "Bridgewater Associates, LP",
"address": {
"street": "One Nyala Farms Road",
"city": "Westport",
"stateOrCountry": "CT",
"zipCode": 6880
}
},
"reportType": "13F HOLDINGS REPORT",
"otherManagersReportingForThisManager": [],
"provideInfoForInstruction5": false,
"signature": {
"name": "Michael Kitson",
"title": "Chief Compliance Officer and Counsel",
"phone": "203-226-3030",
"signature": "Michael Kitson",
"city": "Westport",
"stateOrCountry": "CT",
"signatureDate": "05-14-2024"
},
"tableEntryTotal": 677,
"tableEntryTotalAsReported": 677,
"tableValueTotal": 19775432137,
"tableValueTotalAsReported": 19775432137,
"otherIncludedManagersCount": 0,
"otherIncludedManagers": []
}