paft
====
Facade crate for Provider Agnostic Financial Types.
[](https://crates.io/crates/paft)
[](https://docs.rs/paft)
[](https://crates.io/crates/paft)
Use this crate when you want one dependency that re-exports the paft workspace:
money and decimal primitives, domain identifiers, market data, fundamentals,
optional aggregate snapshots, optional prediction-market types, and a unified
`paft::Error` / `paft::Result`.
- `paft::prelude` imports the common public types enabled by your features
- `paft::money` exposes currency, money, price, and quantity primitives
- `paft::domain`, `paft::market`, and `paft::fundamentals` are enabled by default
- `paft::aggregates`, `paft::prediction`, and `paft::dataframe` are feature-gated
- `paft::Decimal` follows the active decimal backend
Install
-------
Most applications should start with the default feature set:
```toml
[dependencies]
paft = "0.9.0"
```
The default features are `domain`, `market`, and `fundamentals`. For a smaller
dependency, disable defaults and opt into only what you use:
```toml
[dependencies]
paft = { version = "0.9.0", default-features = false, features = ["domain"] }
```
Add one or more optional features to the default set:
```toml
[dependencies]
paft = { version = "0.9.0", features = ["aggregates", "prediction", "dataframe"] }
```
Use `full` when you want every domain crate plus DataFrame support:
```toml
[dependencies]
paft = { version = "0.9.0", features = ["full"] }
```
Use `bigdecimal` when you need an arbitrary-precision decimal backend:
```toml
[dependencies]
paft = { version = "0.9.0", features = ["bigdecimal"] }
```
Features
--------
- `domain` (default): instruments, exchanges, identifiers, periods, horizons, and market state
- `market` (default, enables `domain`): quotes, history, options, order books, news, search, downloads, and request builders
- `fundamentals` (default, enables `domain`): profiles, statements, analysis rows, holders, ESG, and key statistics
- `aggregates` (enables `domain`): `Snapshot` instrument snapshots
- `prediction`: prediction-market venue/id, event/market metadata, fixed-point price, book, quote, and trade types
- `dataframe`: Polars DataFrame traits and implementations for enabled paft types
- `bigdecimal`: switch the shared decimal backend from `rust_decimal` to `bigdecimal`
- `money-formatting`: locale-aware `Money` formatting and strict parsing APIs
- `panicking-money-ops`: opt in to `Money` arithmetic operators that panic on invalid operations
- `tracing`: lightweight instrumentation in selected constructors and validators
- `full`: convenience bundle for `domain`, `market`, `fundamentals`, `aggregates`, `prediction`, and `dataframe`
Quickstart
----------
```rust
use paft::prelude::*;
fn run() -> Result<()> {
let instrument =
Instrument::from_symbol_and_exchange("AAPL", Exchange::NASDAQ, AssetKind::Equity)?;
let currency = Currency::Iso(IsoCurrency::USD);
let mut quote = Quote::new(instrument.clone(), currency.clone());
quote.name = Some("Apple Inc.".to_string());
quote.price = Some(PriceAmount::new(Decimal::from(19012) / Decimal::from(100)));
quote.day_volume = Some(QuantityAmount::from_decimal(Decimal::from(78_900_000))?);
quote.market_state = Some(MarketState::Regular);
assert_eq!(quote.instrument.display_key(), "AAPL@NASDAQ");
let request = HistoryRequest::builder()
.range(Range::M6)
.interval(Interval::D1)
.prefer_adjusted_prices(true)
.build()?;
assert_eq!(request.interval(), Interval::D1);
assert!(request.prefer_adjusted_prices());
Ok(())
}
run().unwrap();
```
Global security identifiers are strongly typed. Use the flat `Instrument`
fields when FIGI or ISIN data is available:
```rust
use paft::prelude::*;
let instrument = Instrument {
symbol: Symbol::new("AAPL").unwrap(),
exchange: Some(Exchange::NASDAQ),
figi: Some(Figi::new("BBG000B9XRY4").unwrap()),
isin: Some(Isin::new("US0378331005").unwrap()),
kind: AssetKind::Equity,
};
```
DataFrame support
-----------------
Enable the `dataframe` feature and import the traits from the facade prelude:
```toml
[dependencies]
paft = { version = "0.9.0", features = ["dataframe"] }
```
```rust
use paft::prelude::*;
let quotes = vec![quote];
let df = quotes.to_dataframe()?;
```
Contextual price fields flatten into amount columns such as `price.amount`;
the containing record carries denomination in its `currency` column. Provider
metadata columns are namespaced under `provider.*`.
Money formatting
----------------
Enable `money-formatting` when you need localized presentation or strict
locale-aware parsing. Canonical `Display` remains stable as `"<amount> <CODE>"`.
```toml
[dependencies]
paft = { version = "0.9.0", features = ["money-formatting"] }
```
```rust
use paft::prelude::{Currency, IsoCurrency, Locale, Money};
let usd = Currency::Iso(IsoCurrency::USD);
let money = Money::from_canonical_str("1234.56", usd.clone())?;
assert_eq!(money.format(), "1234.56 USD");
assert_eq!(money.format_with_locale(Locale::EnUs)?, "$1,234.56");
let parsed = Money::from_str_locale("$1,234.56", usd, Locale::EnUs)?;
assert_eq!(parsed, money);
```
Examples
--------
- [`examples/v09_ergonomics.rs`](examples/v09_ergonomics.rs): default facade usage without provider metadata
- [`examples/provider_metadata.rs`](examples/provider_metadata.rs): generic provider metadata payloads
- [`examples/metadata_dataframe.rs`](examples/metadata_dataframe.rs): DataFrame export with provider metadata
- [`examples/nested_metadata_propagation.rs`](examples/nested_metadata_propagation.rs): independent provider metadata at each nested layer
- [`examples/extensible_enums.rs`](examples/extensible_enums.rs): unknown provider tokens and typed `Other` wrappers
Links
-----
- API docs: https://docs.rs/paft
- Workspace overview: https://github.com/paft-rs/paft/blob/main/README.md
- License: [LICENSE](../LICENSE)