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 Decimal for 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.