Expand description
§Finmoney
A precise, panic-free money library for Rust. It provides safe monetary arithmetic, currency-aware values, configurable rounding strategies, and exchange-grade tick handling. Designed for trading systems, bots, and financial apps where correctness and determinism matter.
§Architecture
The crate is organized into four modules, each with a clear responsibility:
FinMoney— the core type representing a monetary value bound to a currency. Supports checked arithmetic, allocation, currency conversion, formatting, and tick-based rounding.FinMoneyCurrency— represents a currency with a code, optional name, and decimal precision. Ships with 11 predefined currencies (USD, EUR, BTC, ETH, GBP, JPY, CHF, CNY, RUB, USDT, SOL).FinMoneyRoundingStrategy— an enum of rounding strategies used by arithmetic and conversion operations.FinMoneyError— a comprehensive error enum covering currency mismatches, overflow, division by zero, and invalid inputs. Provides convenience predicates likeFinMoneyError::is_overflow().
§Features
- Precise arithmetic — built on
rust_decimalfor exact decimal calculations. All operations use checked arithmetic and returnResulton overflow. - Currency safety — prevents mixing different currencies in operations.
- Configurable rounding — multiple
FinMoneyRoundingStrategyvariants for different use cases. - Tick handling — exchange-grade price/quantity rounding to valid tick sizes.
- Allocation — split a monetary amount by weights without losing a single cent
via
FinMoney::allocate(). - Currency conversion — convert between currencies at a given rate with
FinMoney::convert_to(), or compute the implied rate withFinMoney::exchange_rate_to(). - Iterator support —
FinMoneyimplementsSumand providesFinMoney::try_sum()as a safe, non-panicking alternative. - Flexible formatting —
FinMoney::format_with_separator()for locale-aware thousand separators andFinMoney::format_padded()for zero-padded decimal output. - Serde support — optional serialization/deserialization (feature
serde). Amounts are serialized as strings to preserve precision.
§Quick Start
use finmoney::{FinMoney, FinMoneyCurrency, FinMoneyRoundingStrategy};
use rust_decimal_macros::dec;
// Create a currency
let usd = FinMoneyCurrency::new(1, "USD", Some("US Dollar"), 2)?;
// Create money values
let price = FinMoney::new(dec!(10.50), usd);
let quantity = FinMoney::new(dec!(3), usd);
// Perform arithmetic
let total = (price + quantity)?;
println!("{}", total); // 13.50 USD
// Round to tick size
let rounded = price.to_tick_nearest(dec!(0.25))?;§Allocation
Split a sum into weighted parts with zero remainder loss:
use finmoney::{FinMoney, FinMoneyCurrency, dec};
let usd = FinMoneyCurrency::USD;
let total = FinMoney::new(dec!(100), usd);
let parts = total.allocate(&[dec!(1), dec!(1), dec!(1)])?;
// parts: [33.34, 33.33, 33.33] — sum is exactly 100.00§Currency Conversion
use finmoney::{FinMoney, FinMoneyCurrency, FinMoneyRoundingStrategy, dec};
let usd_amount = FinMoney::new(dec!(100), FinMoneyCurrency::USD);
let eur = FinMoneyCurrency::EUR;
let eur_amount = usd_amount.convert_to(eur, dec!(0.92), FinMoneyRoundingStrategy::MidpointNearestEven)?;
// 92.00 EUR§Summing Iterators
use finmoney::{FinMoney, FinMoneyCurrency, dec};
let usd = FinMoneyCurrency::USD;
let values = vec![
FinMoney::new(dec!(10), usd),
FinMoney::new(dec!(20), usd),
FinMoney::new(dec!(30), usd),
];
// Safe version (returns Result)
let total = FinMoney::try_sum(values.into_iter())?;
// 60.00 USD§Formatting
use finmoney::{FinMoney, FinMoneyCurrency, dec};
let m = FinMoney::new(dec!(1234567.89), FinMoneyCurrency::USD);
assert_eq!(m.format_with_separator(',', '.'), "1,234,567.89 USD");
assert_eq!(m.format_padded(4), "1234567.8900 USD");Re-exports§
pub use currency::FinMoneyCurrency;pub use error::FinMoneyError;pub use money::FinMoney;pub use rounding::FinMoneyRoundingStrategy;
Modules§
- currency
- Currency representation and management.
- error
- Error types for the finmoney library.
- money
- Core FinMoney type and operations.
- rounding
- Rounding strategies for monetary calculations.
Macros§
- dec
- Transform a literal number directly to a
Decimalat compile time.
Structs§
- Decimal
Decimalrepresents a 128 bit representation of a fixed-precision decimal number. The finite set of values of typeDecimalare of the form m / 10e, where m is an integer such that -296 < m < 296, and e is an integer between 0 and 28 inclusive.