Expand description
§Finmoney
A precise money library for Rust. Provides currency-aware arithmetic, exchange-grade
tick handling, configurable rounding, and fair allocation. Built on rust_decimal
for exact decimal calculations. 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 arithmetic, allocation, currency conversion, formatting, and tick-based rounding.FinMoneyCurrency— represents a currency with a code, optional name, and decimal precision. No predefined currencies — create your own viaFinMoneyCurrency::new().FinMoneyRoundingStrategy— an enum of rounding strategies used by arithmetic and conversion operations.FinMoneyError— error enum covering currency mismatches, division by zero, and invalid inputs.
§Design Principles
- Ergonomic by default. Comparisons (
<,>,<=,>=), scalar arithmetic (+ Decimal,* Decimal), and in-place operations (+=,-=,*=) return direct values. - Result where it matters. Only operations with real runtime failure modes
(currency mismatch between two
FinMoneyvalues, division by zero) returnResult. - Checked variants available. Every panicking method has a
Result-returning counterpart (unchecked_plus↔plus_money,*↔multiplied_by_decimal). - Precise.
rust_decimal128-bit decimals — no floating-point surprises. - Currency-agnostic. No predefined currencies — define any currency with any precision for any domain (fiat, crypto, game tokens, loyalty points).
- 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::new(1, "USD", None::<&str>, 2)?;
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_cur = FinMoneyCurrency::new(1, "USD", None::<&str>, 2)?;
let eur_cur = FinMoneyCurrency::new(3, "EUR", None::<&str>, 2)?;
let usd_amount = FinMoney::new(dec!(100), usd_cur);
let eur_amount = usd_amount.convert_to(eur_cur, dec!(0.92), FinMoneyRoundingStrategy::MidpointNearestEven)?;
// 92.00 EUR§Summing Iterators
use finmoney::{FinMoney, FinMoneyCurrency, dec};
let usd = FinMoneyCurrency::new(1, "USD", None::<&str>, 2)?;
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 usd = FinMoneyCurrency::new(1, "USD", None::<&str>, 2).unwrap();
let m = FinMoney::new(dec!(1234567.89), 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.