Run2 fund analysis
[COLM'26] SkillLearnBench is the first benchmark for evaluating continual learning methods that automatically generate agent skills.
npx -y skills add cxcscmu/SkillLearnBench --skill run2_fund_analysisAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its author says it does
Copied from the file, not written here
Analyze individual fund holdings, AUM, and portfolio composition from 13-F data
SKILL.md
4.9 KB, ~1.3k tokens by cl100k_base, as published. Nobody here has run it
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:
# Use case-insensitive contains search
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" # Renaissance Technologies LLC
infotable = pd.read_csv('/root/2025-q3/INFOTABLE.tsv', sep='\t', low_memory=False)
fund_holdings = infotable[infotable['ACCESSION_NUMBER'] == accession]
# AUM = sum of all holdings values (VALUE is in dollars)
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]
# Count unique securities (CUSIPs)
num_holdings = fund_holdings['CUSIP'].nunique()
print(f"Number of holdings: {num_holdings}")
# Alternative: Count rows (if no duplicate CUSIPs per accession)
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]
# Group by CUSIP and aggregate
top_holdings = fund_holdings.groupby('CUSIP').agg({
'NAMEOFISSUER': 'first',
'VALUE': 'sum',
'SSHPRNAMT': 'sum'
}).reset_index()
# Sort by value descending
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
# What % of AUM is in top 10 holdings
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
# Group holdings by sector (requires additional sector mapping)
# This requires matching CUSIP to sector data from another source
# Left as exercise based on available data
Time-Based Analysis
# Check when fund last reported
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
- Confirm ACCESSION_NUMBER exists in both COVERPAGE and INFOTABLE
- Verify sum of INFOTABLE.VALUE matches SUMMARYPAGE.TABLEVALUETOTAL
- Check report date matches expected quarter
- Confirm fund name in FILINGMANAGER_NAME is the intended fund
- Validate holdings count makes sense (typically 50-5000+ positions)
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.