| name | run2_fund_analysis |
| description | Analyze individual fund holdings, AUM, and portfolio composition from 13-F data |
Fund Analysis from 13-F Data
Overview
Analyze specific hedge funds or asset managers using 13-F filings to answer questions about AUM, holdings count, and portfolio composition.
Finding a Fund's Accession Number
Method 1: Exact Name Search
When you know the exact manager name:
import pandas as pd
coverpage = pd.read_csv('/root/2025-q3/COVERPAGE.tsv', sep='\t')
fund = coverpage[coverpage['FILINGMANAGER_NAME'] == 'Renaissance Technologies LLC']
accession = fund['ACCESSION_NUMBER'].values[0]
Method 2: Fuzzy/Partial Name Search
When name might be slightly different:
fund = coverpage[coverpage['FILINGMANAGER_NAME'].str.contains('Renaissance', case=False, na=False)]
accession = fund['ACCESSION_NUMBER'].values[0]
Method 3: Using fuzzy-name-search Skill
python3 scripts/search_fund.py --keywords "renaissance technologies" --quarter 2025-q3 --topk 10
Best Practice: Start with exact name search in raw data, then use fuzzy search if not found.
Extracting Fund Metrics
Q1: Get Fund AUM (Assets Under Management)
Method: Use INFOTABLE VALUE sum (more reliable than SUMMARYPAGE)
accession = "0001037389-25-000064"
infotable = pd.read_csv('/root/2025-q3/INFOTABLE.tsv', sep='\t', low_memory=False)
fund_holdings = infotable[infotable['ACCESSION_NUMBER'] == accession]
aum = fund_holdings['VALUE'].sum()
print(f"AUM: ${aum:,.0f}")
Note: The VALUE column is in actual dollars (not thousands). This can be verified by comparing with SUMMARYPAGE.TABLEVALUETOTAL which should match exactly.
Q2: Count Total Holdings
Method: Count distinct CUSIPs
fund_holdings = infotable[infotable['ACCESSION_NUMBER'] == accession]
num_holdings = fund_holdings['CUSIP'].nunique()
print(f"Number of holdings: {num_holdings}")
num_holdings = len(fund_holdings)
Q3: Get Top Holdings by Value
Method: Group by CUSIP and sort by VALUE
fund_holdings = infotable[infotable['ACCESSION_NUMBER'] == accession]
top_holdings = fund_holdings.groupby('CUSIP').agg({
'NAMEOFISSUER': 'first',
'VALUE': 'sum',
'SSHPRNAMT': 'sum'
}).reset_index()
top_holdings = top_holdings.sort_values('VALUE', ascending=False)
print(top_holdings[['NAMEOFISSUER', 'VALUE']].head(10))
Q4: Identify Fund Manager from Holdings
When you have an accession number and want the fund name:
coverpage = pd.read_csv('/root/2025-q3/COVERPAGE.tsv', sep='\t')
fund_info = coverpage[coverpage['ACCESSION_NUMBER'] == accession]
fund_name = fund_info['FILINGMANAGER_NAME'].values[0]
Common Fund Analysis Patterns
Portfolio Concentration
fund_holdings = infotable[infotable['ACCESSION_NUMBER'] == accession]
top_10_value = fund_holdings.nlargest(10, 'VALUE')['VALUE'].sum()
total_value = fund_holdings['VALUE'].sum()
concentration = (top_10_value / total_value) * 100
print(f"Top 10 concentration: {concentration:.1f}%")
Sector Analysis
Time-Based Analysis
coverpage = pd.read_csv('/root/2025-q3/COVERPAGE.tsv', sep='\t')
fund_info = coverpage[coverpage['ACCESSION_NUMBER'] == accession]
report_date = fund_info['REPORTCALENDARORQUARTER'].values[0]
print(f"Last reported: {report_date}")
Key Metrics Summary
For a given accession number:
- AUM:
INFOTABLE[ACCESSION].VALUE.sum()
- Holdings Count:
INFOTABLE[ACCESSION].CUSIP.nunique()
- Average Position Size: AUM / Holdings Count
- Top 5 Holdings:
nlargest(5, 'VALUE')
- Fund Manager:
COVERPAGE[ACCESSION].FILINGMANAGER_NAME
- Report Date:
COVERPAGE[ACCESSION].REPORTCALENDARORQUARTER
Important Considerations
- Handle Multiple Managers: Some holdings may list multiple managers in OTHERMANAGER columns
- Amendment Status: Check ISAMENDMENT in COVERPAGE (some filings are restated)
- Confidential Filings: Some funds may have confidential positions omitted
- CUSIP Aggregation: When grouping by CUSIP, sum VALUE as some holdings may be split across rows
Validation Checklist