Financial Value
The core abstraction in Metric Engine - a type-safe, policy-aware container for financial data that handles arithmetic operations, unit conversions, and null propagation automatically.
What is a Financial Value?
A FinancialValue is an immutable wrapper around financial data that combines:
Numerical value - The amount (automatically converted to
Decimalfor precision)Unit type - Money, Percent, Ratio, or Dimensionless
Policy - Formatting rules, decimal places, rounding behavior
Null safety - Automatic handling of invalid/missing data
Think of it as a smart number that knows how to behave in financial calculations.
Core Design Principles
1. Immutability
Every operation returns a new FinancialValue - no mutations, no surprises:
from metricengine import FinancialValue as FV
price = FV(100.00)
total = price * 3 # Creates new FV(300.00), price unchanged
2. Type Safety with Units
Units prevent meaningless operations and ensure mathematical correctness:
from metricengine import money, percent
revenue = money(100_000)
margin = percent(15.5, input="percent") # 15.5%
# Valid: Money * Percent = Money
profit = revenue * margin # FV($15,500)
# Invalid: Money + Percent would return None
# invalid = revenue + margin # None - can't add dollars to percentages
3. Automatic Precision Handling
All values use Decimal internally to avoid floating-point errors:
# No precision loss
price = FV(0.1) + FV(0.2) # Exactly 0.3, not 0.30000000000000004
print(price.as_str()) # "0.30"
4. Null Propagation
Invalid operations return None values that propagate safely through calculations:
valid = FV(100)
invalid = FV("invalid_input") # None
result = valid + invalid # None (doesn't crash)
final = result * 2 # Still None
print(final.is_none()) # True
Unit System
Metric Engine provides four core unit types, each with specific behaviors:
Money
Represents currency amounts with automatic formatting:
from metricengine import money
amount = money(1234.56)
print(amount) # "$1,234.56" (with default policy)
# Money arithmetic rules:
# Money + Money = Money ✓
# Money * Ratio = Money ✓
# Money + Percent = None ✗ (meaningless)
Percent
For percentage values with intelligent display:
from metricengine import percent
# Input as percentage (15.5%)
tax_rate = percent(15.5, input="percent")
print(tax_rate) # "15.50%"
# Input as ratio (0.155)
growth_rate = percent(0.155, input="ratio")
print(growth_rate) # "15.50%"
# Both store the same value internally (0.155)
assert tax_rate.as_decimal() == growth_rate.as_decimal()
Ratio
For pure ratios without percentage formatting:
from metricengine import ratio
multiplier = ratio(1.25)
print(multiplier) # "1.25"
# Useful for calculations that shouldn't display as percentages
debt_to_equity = ratio(0.75) # Not "75%" - just "0.75"
Dimensionless
For quantities without units:
from metricengine import dimensionless
units_sold = dimensionless(150)
employee_count = dimensionless(42)
Policy-Driven Formatting
Policies control how values are displayed and rounded:
from metricengine import Policy, money
# Custom policy
euro_policy = Policy(
decimal_places=2,
currency_symbol="€",
currency_position="suffix",
thousands_sep=True
)
amount = money(1234.567, policy=euro_policy)
print(amount) # "1,234.57 €"
Real-World Example: Revenue Calculation
from metricengine import money, percent, ratio
# Sales data
units_sold = 1_250
unit_price = money(89.99)
discount_rate = percent(12, input="percent")
tax_rate = percent(8.25, input="percent")
# Calculate step by step
gross_revenue = unit_price * units_sold
discount_amount = gross_revenue * discount_rate
net_revenue = gross_revenue - discount_amount
tax_amount = net_revenue * tax_rate
final_revenue = net_revenue + tax_amount
print(f"Gross Revenue: {gross_revenue}") # "$112,487.50"
print(f"Discount: {discount_amount}") # "$13,498.50"
print(f"Net Revenue: {net_revenue}") # "$98,989.00"
print(f"Tax: {tax_amount}") # "$8,166.59"
print(f"Final Revenue: {final_revenue}") # "$107,155.59"
# All operations are type-safe and precision-preserving
Advanced Features
Safe Division
Division by zero returns None instead of crashing:
result = FV(100) / FV(0)
print(result.is_none()) # True
# Configure to raise exceptions instead
from metricengine import NullBinaryMode
with null_binary_mode(NullBinaryMode.RAISE):
result = FV(100) / FV(0) # Raises ZeroDivisionError
Policy Inheritance
Operations inherit policies intelligently:
high_precision = Policy(decimal_places=4)
value1 = money(100.1234, policy=high_precision)
value2 = money(200) # Default policy (2 decimal places)
result = value1 + value2 # Inherits high_precision policy
print(result) # "$300.1234"
Percentage Conversions
Easy switching between percentage and ratio representations:
growth = percent(15, input="percent") # 15%
as_ratio = growth.ratio() # 0.15 (for calculations)
back_to_percent = as_ratio.as_percentage() # 15% (for display)
Best Practices
1. Use Factory Functions
Prefer the factory functions over direct constructor calls:
# Good
revenue = money(100_000)
margin = percent(12.5, input="percent")
# Also valid, but more verbose
from metricengine import FinancialValue, Money, Percent
revenue = FinancialValue(100_000, unit=Money)
2. Handle Null Values
Always check for None results in uncertain operations:
def safe_divide(a, b):
result = a / b
if result.is_none():
return "Division not possible"
return result
3. Use Appropriate Units
Choose the right unit for your use case:
# Good: Clear intent
profit_margin = percent(15, input="percent") # Display as 15%
price_multiplier = ratio(1.15) # Display as 1.15
revenue = money(50_000) # Display as $50,000
# Avoid: Confusing mixed units
# margin = ratio(0.15) # Displays as 0.15, not 15%
Common Patterns
Financial Calculations
# Revenue growth analysis
q1_revenue = money(250_000)
q2_revenue = money(280_000)
growth_amount = q2_revenue - q1_revenue # $30,000
growth_rate = (q2_revenue / q1_revenue - ratio(1)).as_percentage() # 12%
Portfolio Returns
initial_value = money(10_000)
final_value = money(11_500)
total_return = (final_value / initial_value - ratio(1)).as_percentage()
print(f"Total return: {total_return}") # "15.00%"
Margin Analysis
revenue = money(100_000)
costs = money(75_000)
gross_profit = revenue - costs
margin = (gross_profit / revenue).as_percentage()
print(f"Gross margin: {margin}") # "25.00%"
Financial Values provide the foundation for all calculations in Metric Engine, ensuring your financial computations are accurate, type-safe, and properly formatted.