PriceFrame
A modern, efficient price data management library for Python, built on top of PyArrow, Polars, and pandas.
Overview
PriceFrame provides a canonical, high-performance way to store, manipulate, and analyze financial price data (OHLCV). It combines the speed of PyArrow and Polars with the familiarity of pandas, offering a flexible feature system for technical indicators and quantitative analysis.
Key Features
- High Performance: Built on PyArrow for efficient columnar storage and operations
- Multiple Engine Support: Seamlessly switch between pandas and Polars
- Rich Feature System: Declarative technical indicators (MA, EMA, RSI, ATR, MACD, Bollinger Bands, etc.)
- Multiple Data Sources: Bloomberg, custom databases, and more
- Flexible Time Handling: Automatic timezone normalization and resampling
- Portfolio Analysis: Built-in naive portfolio construction and rebalancing
- Type-Safe: Canonical schema with automatic type casting and validation
Installation
Basic Installation
pip install priceframe
With Optional Dependencies
For Bloomberg Terminal support:
pip install priceframe[bloomberg]
For cryptocurrency data (via CCXT):
pip install priceframe[crypto]
All optional dependencies:
pip install priceframe[bloomberg,crypto]
Quick Start
Creating a PriceFrame
import pandas as pd
from priceframe import PriceFrame
# From pandas DataFrame
df = pd.DataFrame({
'symbol': ['AAPL', 'AAPL', 'AAPL'],
'ts': pd.date_range('2024-01-01', periods=3, tz='UTC'),
'open': [150.0, 151.0, 152.0],
'high': [151.0, 152.0, 153.0],
'low': [149.0, 150.0, 151.0],
'close': [150.5, 151.5, 152.5],
'volume': [1000000, 1100000, 1050000]
})
pf = PriceFrame.from_pandas(df, interval='1d')
Loading from Bloomberg
# Single ticker
pf = PriceFrame.from_bloomberg(
tickers='AAPL US Equity',
start_date='2024-01-01',
end_date='2024-12-31',
interval='1d'
)
# Multiple tickers
pf = PriceFrame.from_bloomberg(
tickers=['AAPL US Equity', 'MSFT US Equity', 'GOOGL US Equity'],
start_date='2024-01-01',
type_='ohlcv',
currency='USD'
)
Adding Technical Indicators
from priceframe.features import FeatureSpec
# Define features declaratively
features = [
# 20-day moving average
FeatureSpec(
name='f_ma_20',
func='ma',
input_col='close',
params={'window': 20}
),
# RSI(14)
FeatureSpec(
name='f_rsi_14',
func='rsi',
input_cols={'close': 'close'},
params={'window': 14, 'method': 'wilder'}
),
# ATR(14)
FeatureSpec(
name='f_atr_14',
func='atr',
input_cols={'high': 'high', 'low': 'low', 'close': 'close'},
params={'window': 14, 'method': 'sma'}
),
# Daily returns
FeatureSpec(
name='f_ret_1',
func='ret',
input_col='close',
params={'horizon': 1}
)
]
# Apply features
pf_with_features = pf.with_feature_specs(features)
# Convert to pandas for analysis
df_result = pf_with_features.to_pandas()
Data Access
# Get OHLCV for a specific symbol
ohlcv = pf.ohlcv('AAPL US Equity', engine='pandas')
# Get close prices only
closes = pf.close_series('AAPL US Equity')
# Create a close price matrix (timestamps × symbols)
close_matrix = pf.close_matrix(
symbols=['AAPL US Equity', 'MSFT US Equity'],
how='inner'
)
Time Operations
# Filter by date range
pf_filtered = pf.range_date(
start='2024-03-01',
end='2024-06-30',
closed='both'
)
# Resample to weekly
pf_weekly = pf.resample('1w')
# Rebase to 100
pf_rebased = pf.rebase(base=100.0, anchor='close')
Portfolio Construction
# Create a naive portfolio
portfolio = pf.naive_portfolio(
symbols=['AAPL US Equity', 'MSFT US Equity', 'GOOGL US Equity'],
weights=[0.4, 0.3, 0.3],
base=100.0,
name='Tech Portfolio',
as_='series'
)
Merging PriceFrames
# Combine two PriceFrames
pf_combined = pf1.add(pf2, require_same_interval=True)
Available Technical Indicators
PriceFrame includes a comprehensive feature registry with the following indicators:
Returns
- ret: Simple returns
- logret: Log returns
Moving Averages
- ma: Simple Moving Average (SMA)
- ema: Exponential Moving Average (EMA)
Volatility
- rolling_vol: Rolling standard deviation
Cross-Sectional
- cs_rank: Cross-sectional rank
- cs_zscore: Cross-sectional z-score
Technical Indicators
- atr: Average True Range
- rsi: Relative Strength Index
- bollinger: Bollinger Bands (mid, upper, lower)
- macd: MACD (macd, signal, histogram)
Custom Features
You can register your own features:
from priceframe.features import feature
import polars as pl
@feature("my_custom_indicator")
def _feat_custom(df: pl.DataFrame, spec) -> pl.DataFrame:
"""Custom indicator implementation."""
window = spec.params.get('window', 10)
col = spec.col('price', default='close')
return df.with_columns(
pl.col(col).rolling_mean(window).over('symbol').alias(spec.name)
)
# Use it
spec = FeatureSpec(
name='f_custom_10',
func='my_custom_indicator',
input_col='close',
params={'window': 10}
)
Data Format
PriceFrame uses a canonical long-format schema:
| Column | Type | Description |
|---|---|---|
| symbol | string | Instrument identifier |
| interval | string | Time interval (e.g., '1d', '1h') |
| ts | timestamp[ms, tz='UTC'] | Timestamp |
| open | float64 | Opening price |
| high | float64 | Highest price |
| low | float64 | Lowest price |
| close | float64 | Closing price |
| volume | float64 | Trading volume |
Additional columns (features, metadata) are preserved.
Conversion Between Formats
# To pandas
df_pandas = pf.to_pandas(index='ts') # or index='multi' for MultiIndex
# To Polars
df_polars = pf.to_polars()
# To PyArrow
table = pf.to_arrow()
# To Excel
pf.to_excel('output.xlsx')
# From close matrix
close_df = pd.DataFrame({
'AAPL': [150, 151, 152],
'MSFT': [300, 301, 302]
}, index=pd.date_range('2024-01-01', periods=3, tz='UTC'))
pf = PriceFrame.from_close_matrix(close_df, interval='1d')
Architecture
PriceFrame is built on three main components:
- Core (
priceframe.core): ThePriceFrameclass and data manipulation functions - Features (
priceframe.features): Declarative feature system with registry - IO (
priceframe.io): Data source connectors (Bloomberg, databases, etc.)
Design Principles
- Immutability: Most operations return new PriceFrame instances
- Type Safety: Automatic type casting and validation
- Performance: PyArrow backend for efficient columnar operations
- Flexibility: Support for both pandas and Polars workflows
Testing
Run the test suite:
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Roadmap
- Additional data sources (Yahoo Finance, Binance, S3 storage, etc.)
- More technical indicators
- Backtesting framework integration (NautilusTrader)
- Performance optimizations
- Quick visualisation with mlpfinance
Requirements
- Python 3.9+
- pandas >= 2.3.3
- polars >= 1.35.2
- pyarrow >= 21.0.0
Optional:
- xbbg >= 0.7.7 (Bloomberg)
- blpapi >= 3.25.10.1 (Bloomberg)
- ccxt >= 4.5.20 (Crypto)
- duckdb >= 1.4.2 (Crypto storage)
Metadata
Release files for priceframe 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| priceframe-0.2.0.tar.gz | 206.7 kB | Without provenance | Details for priceframe-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| priceframe-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for priceframe-0.2.0-py3-none-any.whl |
Total release size: 256.2 kB
Release files / priceframe-0.2.0.tar.gz
| Download URL | priceframe-0.2.0.tar.gz |
|---|---|
| Size | 206.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
852d5b712af7791338db9e2fe961f3b538f3bb92d8017940e17d6dca0ec7050d
|
|
BLAKE2b-256 checksum How to use checksums |
675c17b37129b5480a273ca64b62286331d3d7861f14644c1f32b28f479b2a5a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.11 {"installer":{"name":"uv","version":"0.9.11"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / priceframe-0.2.0-py3-none-any.whl
| Download URL | priceframe-0.2.0-py3-none-any.whl |
|---|---|
| Size | 49.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ba1c5113cc92bca0fb559f7d17d01a73805b85ba20b265fb5f9999e609e6101a
|
|
BLAKE2b-256 checksum How to use checksums |
8eb6bb4f4849e73c439cae209aa00ec69310702eaf90a8ab31c6a0fd34462a97
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.11 {"installer":{"name":"uv","version":"0.9.11"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for priceframe 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.