Provides a canonical, high-performance way to store, manipulate, and analyze financial price data (OHLCV, OHLC or Close only). It combines the speed of PyArrow and Polars with the familiarity of pandas, offering a flexible feature system for technical indicators and quantitative analysis.
Project description
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)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file priceframe-0.2.0.tar.gz.
File metadata
- Download URL: priceframe-0.2.0.tar.gz
- Upload date:
- Size: 206.7 kB
- Tags: Source
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
852d5b712af7791338db9e2fe961f3b538f3bb92d8017940e17d6dca0ec7050d
|
|
| MD5 |
376f887763cbefb8d1a0f55bab7dcfb7
|
|
| BLAKE2b-256 |
675c17b37129b5480a273ca64b62286331d3d7861f14644c1f32b28f479b2a5a
|
File details
Details for the file priceframe-0.2.0-py3-none-any.whl.
File metadata
- Download URL: priceframe-0.2.0-py3-none-any.whl
- Upload date:
- Size: 49.5 kB
- Tags: Python 3
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ba1c5113cc92bca0fb559f7d17d01a73805b85ba20b265fb5f9999e609e6101a
|
|
| MD5 |
c6550693725d0ac40df8d95eeccd99c2
|
|
| BLAKE2b-256 |
8eb6bb4f4849e73c439cae209aa00ec69310702eaf90a8ab31c6a0fd34462a97
|