Asset Finder API¶
The AssetFinder is rustybt's interface for querying and retrieving assets (stocks, futures, etc.) from bundles. This guide covers the ParquetAssetFinder implementation used by modern Parquet-based bundles.
Overview¶
The AssetFinder provides methods to:
- Retrieve all assets in a bundle
- Look up assets by symbol
- Retrieve assets by identifier (sid)
- Query bundle metadata
All Parquet bundles (yfinance-profiling, csvdir, custom adapters) use the ParquetAssetFinder implementation.
Common Use Cases¶
Get All Assets in a Bundle¶
The most common use case - retrieve all assets programmatically to iterate over them in your strategy.
from rustybt.api import symbol
from rustybt.utils.run_algo import run_algorithm
import pandas as pd
def initialize(context):
"""Initialize strategy with all assets in bundle."""
# Get all asset identifiers
all_sids = context.asset_finder.sids
# Retrieve all asset objects
all_assets = context.asset_finder.retrieve_all(all_sids)
# Store for use in handle_data
context.all_assets = all_assets
print(f"Found {len(all_assets)} assets in bundle:")
for asset in all_assets:
print(f" - {asset.symbol} (sid: {asset.sid})")
def handle_data(context, data):
"""Process data for all assets."""
# Iterate over all assets
for asset in context.all_assets:
current_price = data.current(asset, 'price')
print(f"{asset.symbol}: ${current_price}")
if __name__ == "__main__":
result = run_algorithm(
initialize=initialize,
handle_data=handle_data,
bundle='yfinance-profiling',
start=pd.Timestamp('2024-01-01'),
end=pd.Timestamp('2024-01-31'),
capital_base=10000,
)
Look Up Asset by Symbol¶
Retrieve a specific asset by its ticker symbol:
def initialize(context):
"""Look up specific assets."""
# Single asset lookup
aapl = context.asset_finder.lookup_symbol('AAPL')
print(f"Found: {aapl.symbol} with sid {aapl.sid}")
# Multiple asset lookup
tech_stocks = context.asset_finder.lookup_symbols(['AAPL', 'GOOGL', 'MSFT'])
context.tech_portfolio = tech_stocks
Retrieve Asset by SID¶
If you have an asset identifier (sid), retrieve the asset object directly:
def initialize(context):
"""Retrieve assets by identifier."""
# Get specific asset by sid
asset = context.asset_finder.retrieve_asset(0)
print(f"SID 0 is: {asset.symbol}")
# Get multiple assets by sids
sids = [0, 1, 2]
assets = context.asset_finder.retrieve_all(sids)
context.portfolio_assets = assets
Filter Assets Dynamically¶
Combine methods to build custom asset filters:
def initialize(context):
"""Select assets based on criteria."""
# Get all assets
all_assets = context.asset_finder.retrieve_all(
context.asset_finder.sids
)
# Filter by some criterion (e.g., symbol pattern)
tech_assets = [
asset for asset in all_assets
if asset.symbol in ['AAPL', 'GOOGL', 'MSFT', 'AMZN', 'META', 'NVDA', 'TSLA']
]
context.watchlist = tech_assets
print(f"Monitoring {len(tech_assets)} tech stocks")
API Reference¶
Properties¶
.sids¶
Returns all asset identifiers in the bundle.
Returns: pd.Index - Index of all asset identifiers (sids)
Example:
def initialize(context):
all_sids = context.asset_finder.sids
print(f"Bundle contains {len(all_sids)} assets")
print(f"SID range: {all_sids.min()} to {all_sids.max()}")
Methods¶
.retrieve_all(sids)¶
Retrieve multiple assets by their identifiers.
Parameters:
sids(iterable[int]): Asset identifiers to retrieve
Returns: list[Asset] - List of Asset objects
Raises:
SidsNotFound: If any sid does not exist in the bundle
Example:
def initialize(context):
# Get all assets
all_assets = context.asset_finder.retrieve_all(
context.asset_finder.sids
)
# Or get specific subset
selected_sids = [0, 1, 2, 3, 4]
selected_assets = context.asset_finder.retrieve_all(selected_sids)
.retrieve_asset(sid, default_none=False)¶
Retrieve a single asset by its identifier.
Parameters:
sid(int): Asset identifierdefault_none(bool, optional): If True, return None instead of raising exception. Default: False
Returns: Asset | None - Asset object, or None if not found and default_none=True
Raises:
SidsNotFound: If sid does not exist anddefault_none=False
Example:
def initialize(context):
# Get asset, raise exception if not found
asset = context.asset_finder.retrieve_asset(0)
# Get asset, return None if not found
maybe_asset = context.asset_finder.retrieve_asset(999, default_none=True)
if maybe_asset is None:
print("Asset 999 not found")
.lookup_symbol(symbol, as_of_date=None, fuzzy=False, country_code=None)¶
Look up an asset by its ticker symbol.
Parameters:
symbol(str): Ticker symbol (e.g., 'AAPL', 'GOOGL')as_of_date(pd.Timestamp, optional): Not used in Parquet bundles (all symbols always available)fuzzy(bool, optional): Not implemented for Parquet bundlescountry_code(str, optional): Not used in Parquet bundles
Returns: Asset - The asset with the given symbol
Raises:
SymbolNotFound: If no asset with the given symbol exists
Example:
def initialize(context):
try:
aapl = context.asset_finder.lookup_symbol('AAPL')
context.primary_asset = aapl
except SymbolNotFound:
print("AAPL not in bundle")
.lookup_symbols(symbols, as_of_date=None, fuzzy=False)¶
Look up multiple assets by their ticker symbols.
Parameters:
symbols(iterable[str]): Ticker symbols to look upas_of_date(pd.Timestamp, optional): Not used in Parquet bundlesfuzzy(bool, optional): Not implemented for Parquet bundles
Returns: list[Asset] - List of assets
Raises:
SymbolNotFound: If any symbol does not exist
Example:
def initialize(context):
# Look up multiple symbols at once
watchlist = context.asset_finder.lookup_symbols([
'AAPL', 'GOOGL', 'MSFT', 'AMZN'
])
context.watchlist = watchlist
Asset Object¶
Assets retrieved from the AssetFinder have the following key attributes:
Equity Assets¶
asset = context.asset_finder.lookup_symbol('AAPL')
# Common attributes
print(asset.sid) # Asset identifier (int)
print(asset.symbol) # Ticker symbol (str)
print(asset.asset_name) # Full name (str)
print(asset.exchange) # Exchange (str, e.g., 'NASDAQ')
print(asset.start_date) # First available date
print(asset.end_date) # Last available date
print(asset.first_traded) # First trade date
Future Assets¶
Futures have additional attributes:
future = context.asset_finder.lookup_symbol('ESH21')
# Future-specific attributes
print(future.root_symbol) # Root symbol (e.g., 'ES')
print(future.expiration_date) # Contract expiration
print(future.notice_date) # First notice date
print(future.tick_size) # Minimum price movement
print(future.multiplier) # Contract size multiplier
Error Handling¶
SymbolNotFound¶
Raised when a symbol doesn't exist in the bundle:
from rustybt.errors import SymbolNotFound
def initialize(context):
try:
asset = context.asset_finder.lookup_symbol('INVALID')
except SymbolNotFound as e:
print(f"Symbol not found: {e}")
# Fallback to a different asset
asset = context.asset_finder.lookup_symbol('AAPL')
SidsNotFound¶
Raised when one or more sids don't exist:
from rustybt.errors import SidsNotFound
def initialize(context):
try:
assets = context.asset_finder.retrieve_all([0, 1, 999])
except SidsNotFound as e:
print(f"Invalid sids: {e.sids}")
# Retry with valid sids only
assets = context.asset_finder.retrieve_all([0, 1])
Performance Tips¶
Cache Asset Lookups¶
Look up assets once in initialize() and store them:
def initialize(context):
# ✅ Good: Lookup once, reuse many times
context.all_assets = context.asset_finder.retrieve_all(
context.asset_finder.sids
)
def handle_data(context, data):
# Use cached assets
for asset in context.all_assets:
price = data.current(asset, 'price')
Avoid Repeated Symbol Lookups¶
# ❌ Bad: Looking up symbol every bar
def handle_data(context, data):
aapl = context.asset_finder.lookup_symbol('AAPL') # Slow!
price = data.current(aapl, 'price')
# ✅ Good: Lookup once in initialize
def initialize(context):
context.aapl = context.asset_finder.lookup_symbol('AAPL')
def handle_data(context, data):
price = data.current(context.aapl, 'price') # Fast!
Common Patterns¶
Universe Selection¶
Select a subset of assets for trading:
def initialize(context):
"""Select top N liquid assets."""
# Get all assets
all_assets = context.asset_finder.retrieve_all(
context.asset_finder.sids
)
# In production, you might filter by:
# - Market cap
# - Average volume
# - Sector/industry
# Here we just take first 10 for example
context.universe = all_assets[:10]
print(f"Trading universe: {[a.symbol for a in context.universe]}")
Symbol to Asset Mapping¶
Create a dictionary for quick lookups:
def initialize(context):
"""Create symbol-to-asset mapping."""
all_assets = context.asset_finder.retrieve_all(
context.asset_finder.sids
)
# Build lookup dict
context.asset_map = {
asset.symbol: asset
for asset in all_assets
}
# Now you can quickly access any asset
context.watchlist_symbols = ['AAPL', 'GOOGL', 'MSFT']
def handle_data(context, data):
"""Use the mapping."""
for symbol in context.watchlist_symbols:
asset = context.asset_map[symbol]
price = data.current(asset, 'price')
Bundle Compatibility¶
The ParquetAssetFinder API is consistent across all Parquet-based bundles:
| Bundle Type | AssetFinder | Notes |
|---|---|---|
yfinance-profiling |
ParquetAssetFinder |
Free Yahoo Finance data |
csvdir |
ParquetAssetFinder |
Custom CSV data |
| Custom adapters | ParquetAssetFinder |
Your own data sources |
| Legacy bundles | May differ | Older bundles may use different AssetFinder |
All examples on this page work with any Parquet bundle.
Related Documentation¶
- Quick Start Guide - Basic strategy examples
- Bundle System - Understanding bundles
- Data Portal API - Accessing price data
- Pipeline API - Advanced data processing
Frequently Asked Questions¶
Why doesn't retrieve_equities() exist?¶
The ParquetAssetFinder uses a unified interface:
# ❌ Old pattern (doesn't exist)
# all_equities = context.asset_finder.retrieve_equities(all_sids)
# ✅ Correct pattern
all_assets = context.asset_finder.retrieve_all(context.asset_finder.sids)
The retrieve_all() method works for all asset types (equities, futures, etc.).
How do I filter for only equities?¶
Check the asset type:
from rustybt.assets import Equity
def initialize(context):
all_assets = context.asset_finder.retrieve_all(
context.asset_finder.sids
)
# Filter for equities only
equities = [asset for asset in all_assets if isinstance(asset, Equity)]
context.equity_portfolio = equities
Can I get the full symbol list without retrieving assets?¶
Yes, but you need to retrieve assets to get symbols:
def initialize(context):
# Get all sids (fast)
all_sids = context.asset_finder.sids
# Get assets to access symbols (required)
all_assets = context.asset_finder.retrieve_all(all_sids)
# Extract symbols
symbols = [asset.symbol for asset in all_assets]
print(f"Available symbols: {symbols}")
What if a symbol doesn't exist in my bundle?¶
Handle the SymbolNotFound exception:
from rustybt.errors import SymbolNotFound
def initialize(context):
desired_symbols = ['AAPL', 'GOOGL', 'TSLA', 'NONEXISTENT']
context.portfolio = []
for symbol in desired_symbols:
try:
asset = context.asset_finder.lookup_symbol(symbol)
context.portfolio.append(asset)
except SymbolNotFound:
print(f"Warning: {symbol} not in bundle, skipping")
print(f"Portfolio: {[a.symbol for a in context.portfolio]}")
Source Code¶
Implementation: rustybt/data/polars/parquet_asset_finder.py