You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
124 lines
4.2 KiB
Markdown
124 lines
4.2 KiB
Markdown
> NOTE: ETF API has been deprecated and removed. This document remains only as historical reference for how historical ETF holdings were previously fetched from SEC (NPORT/N-Q) and parsed. A new design will replace it.
|
|
|
|
## Key Features
|
|
|
|
### 1. Automatic CIK Resolution
|
|
The API automatically converts between ticker symbols and CIK numbers:
|
|
- Input ticker → Automatically finds CIK
|
|
- Input CIK → Returns data with associated ticker
|
|
- Unknown tickers → Attempts auto-lookup from SEC
|
|
|
|
### 2. Date Validation
|
|
The API validates requested dates against ETF launch dates:
|
|
- Returns error if ETF didn't exist on requested date
|
|
- Provides ETF launch date and first available NPORT date
|
|
- Automatically finds closest available data when possible
|
|
|
|
### 3. Performance Optimization
|
|
- Launch date caching for instant validation (<0.02s)
|
|
- Intelligent date range searching
|
|
- Compressed responses when holdings not needed
|
|
|
|
### 4. Availability Information
|
|
All error responses include `availability` field with:
|
|
- `exists_for_date`: Whether ETF existed on requested date
|
|
- `etf_launch_date`: When the ETF was launched
|
|
- `first_nport_date`: First available NPORT filing date
|
|
- `available_date_range`: Start and end dates of available data
|
|
- `days_before_launch`: How many days before ETF launch (if applicable)
|
|
|
|
## Data Sources
|
|
- **Primary Source**: SEC EDGAR NPORT-P filings
|
|
- **Filing Frequency**:
|
|
- Monthly filings (published quarterly) from 2019
|
|
- Quarterly filings before 2019 (N-Q forms)
|
|
- **Data Availability**: Generally 2019 onwards for most ETFs
|
|
- **Update Frequency**: New filings typically available 60 days after period end
|
|
|
|
## Supported ETFs
|
|
|
|
### Major Fund Families
|
|
| Fund Family | Example Tickers | CIK |
|
|
|------------|----------------|-----|
|
|
| Invesco | QQQ, QQQM, XLG | Various |
|
|
| SPDR | SPY, XLF, XLE, XLK | 884394, 1064641 |
|
|
| iShares | IWM, EFA, EEM, MTUM | 1100663 |
|
|
| Vanguard | VTI, VOO, VEA, VWO | 851229 |
|
|
| ARK | ARKK, ARKQ, ARKW | 1679090 |
|
|
|
|
### Auto-Lookup Support
|
|
ETFs not in the pre-configured list will be automatically looked up from SEC data.
|
|
|
|
## Rate Limits
|
|
- No hard rate limits for local deployment
|
|
- SEC EDGAR has rate limits (10 requests/second)
|
|
- Cached responses bypass SEC limits
|
|
|
|
## Error Codes
|
|
| Status | Description |
|
|
|--------|-------------|
|
|
| 200 | Success or data validation error with availability info |
|
|
| 400 | Invalid request parameters |
|
|
| 404 | ETF ticker/CIK not found |
|
|
| 500 | Internal server error |
|
|
|
|
## Best Practices
|
|
|
|
1. **Check Availability First**: Use `include_holdings=false` to quickly check data availability
|
|
2. **Use Recent Dates**: NPORT data typically lags by 60 days
|
|
3. **Cache Responses**: Holdings data doesn't change for historical dates
|
|
4. **Handle Availability Info**: Parse the `availability` field to show users available date ranges
|
|
|
|
## Examples
|
|
|
|
### Python
|
|
```python
|
|
import requests
|
|
|
|
# Get current holdings
|
|
response = requests.get("http://localhost:18001/api/v1/etf/holdings/QQQ")
|
|
data = response.json()
|
|
|
|
if data["success"]:
|
|
print(f"Found {data['data']['holdings_count']} holdings")
|
|
for holding in data["data"]["holdings"][:5]:
|
|
print(f"- {holding['name']}: {holding['percentage']:.2f}%")
|
|
else:
|
|
print(f"Error: {data['error']}")
|
|
if data.get("availability"):
|
|
print(f"Available from: {data['availability']['available_date_range']['start']}")
|
|
```
|
|
|
|
### JavaScript
|
|
```javascript
|
|
// Get historical holdings
|
|
fetch('http://localhost:18001/api/v1/etf/holdings/SPY?as_of_date=2023-12-31')
|
|
.then(res => res.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
console.log(`Holdings as of ${data.as_of_date}`);
|
|
data.data.holdings.slice(0, 5).forEach(h => {
|
|
console.log(`- ${h.name}: ${h.percentage.toFixed(2)}%`);
|
|
});
|
|
} else {
|
|
console.error(data.error);
|
|
if (data.availability) {
|
|
console.log('Available range:', data.availability.available_date_range);
|
|
}
|
|
}
|
|
});
|
|
```
|
|
|
|
## Changelog
|
|
|
|
### Version 2.0 (Latest)
|
|
- Added `availability` field to all error responses
|
|
- Implemented ETF launch date validation
|
|
- Added automatic date range detection
|
|
- Performance optimization with launch date caching
|
|
- Response time improved from 35s to <0.1s for date validation
|
|
|
|
### Version 1.0
|
|
- Initial ETF holdings API
|
|
- Support for ticker and CIK lookup
|
|
- Historical NPORT data access |