metricengine.value

FinancialValue wrapper for immutable financial data with policy-aware formatting.

This module provides the core FinancialValue class that wraps financial data with immutable, policy-aware behavior. FinancialValue instances support safe arithmetic operations, automatic formatting, and None propagation through calculations.

Key Features:
  • Immutable financial data wrapper with automatic Decimal conversion

  • Policy-aware formatting and rounding (decimal places, rounding mode)

  • Safe arithmetic operations (division by zero returns None)

  • None propagation through calculations

  • Percentage formatting and ratio conversion

  • Type-flexible input (int, float, str, Decimal, FinancialValue)

  • Hashable and comparable instances

Example

>>> from metricengine import FinancialValue as FV
>>> price = FV(100.50)
>>> quantity = FV(3)
>>> total = price * quantity
>>> print(total.as_str())  # "301.50"
>>> print(total.as_decimal())  # Decimal('301.50')
>>> # Safe operations
>>> result = FV(100) / FV(0)  # Returns FV(None), not error
>>> print(result.is_none())  # True
>>> # Percentage handling
>>> margin = FV(0.15).as_percentage()
>>> print(margin.as_str())  # "15%"
>>> print(margin.ratio())   # FV(0.15)
>>> # Policy inheritance
>>> custom_policy = Policy(decimal_places=4)
>>> value = FV(123.4567, policy=custom_policy)
>>> result = value + 50  # Inherits custom_policy
>>> print(result.as_str())  # "173.4567"

See README.md for comprehensive usage examples and best practices.

class metricengine.value.EqualityMode(value)[source]

Bases: Enum

VALUE_ONLY = 1
VALUE_AND_UNIT = 2
VALUE_UNIT_AND_POLICY = 3
class metricengine.value.FinancialValue(_value, policy=None, unit=<class 'metricengine.units.Dimensionless'>, _is_percentage=False, _prov=None)[source]

Bases: Generic[U]

policy: Policy | None = None
unit

alias of Dimensionless

as_decimal()[source]
Return type:

Decimal | None

as_float()[source]
Return type:

float | None

as_int()[source]
Return type:

int | None

as_str()[source]
Return type:

str

is_percentage()[source]
Return type:

bool

render(fmt='text', **context)[source]

Render this FinancialValue using a registered renderer.

Parameters:
  • fmt (str) – Name of the renderer to use (default: “text”)

  • **context – Additional context passed to the renderer

Return type:

str

Returns:

Rendered string representation

Raises:

KeyError – If the specified renderer is not registered

Example

>>> amount = money(1234.56)
>>> amount.render("html")  # '<span class="fv positive">$1,234.56</span>'
>>> amount.render("html", css_classes="highlight")
to(unit, *, at=None, meta=None)[source]

Convert this FinancialValue to a different unit.

This method performs explicit unit conversion using the registered conversion functions. It creates a new FinancialValue with the target unit and converted value, preserving the original policy and percentage flag.

Parameters:
  • unit (NewUnit) – Target unit to convert to

  • at (str | None) – Optional timestamp for rate lookups (e.g., “2025-09-06T10:30:00Z”)

  • meta (dict[str, str] | None) – Optional metadata dictionary for conversion context (e.g., {“rate”: “0.79”, “source”: “ECB”})

Return type:

FinancialValue

Returns:

New FinancialValue with the target unit and converted value

Raises:
  • KeyError – If no conversion is registered between the units

  • ValueError – If this FinancialValue has a None value

  • TypeError – If this FinancialValue doesn’t use the new unit system

Example

>>> from metricengine import FinancialValue as FV
>>> from metricengine.units import MoneyUnit
>>>
>>> usd = MoneyUnit("USD")
>>> gbp = MoneyUnit("GBP")
>>> amount = FV(100, unit=usd)
>>>
>>> # Convert with default context
>>> converted = amount.to(gbp)
>>>
>>> # Convert with specific rate and timestamp
>>> converted = amount.to(gbp, at="2025-09-06T10:30:00Z",
...                      meta={"rate": "0.79", "source": "ECB"})
is_none()[source]
Return type:

bool

get_provenance()[source]

Get the provenance record for this FinancialValue.

Return type:

Provenance | None

Returns:

Provenance record if available, None otherwise

has_provenance()[source]

Check if this FinancialValue has provenance information.

Return type:

bool

Returns:

True if provenance is available, False otherwise

get_operation()[source]

Get the operation that created this FinancialValue.

Return type:

str | None

Returns:

Operation string if provenance is available, None otherwise

Example

>>> a = FinancialValue(10)
>>> b = FinancialValue(5)
>>> result = a + b
>>> print(result.get_operation())  # "+"
get_inputs()[source]

Get the input provenance IDs that contributed to this FinancialValue.

Return type:

tuple[str, ...]

Returns:

Tuple of provenance IDs for inputs, empty tuple if no provenance

Example

>>> a = FinancialValue(10)
>>> b = FinancialValue(5)
>>> result = a + b
>>> inputs = result.get_inputs()
>>> print(len(inputs))  # 2
get_provenance_metadata()[source]

Get the metadata associated with this FinancialValue’s provenance.

Return type:

dict[str, Any]

Returns:

Dictionary of metadata, empty dict if no provenance

Example

>>> with calc_span("analysis"):
...     result = FinancialValue(10) + FinancialValue(5)
>>> meta = result.get_provenance_metadata()
>>> print(meta.get("span"))  # "analysis"
get_provenance_id()[source]

Get the unique provenance ID for this FinancialValue.

Return type:

str | None

Returns:

Provenance ID string if available, None otherwise

Example

>>> value = FinancialValue(100)
>>> prov_id = value.get_provenance_id()
>>> print(prov_id[:8])  # First 8 chars of hash
trace_calculation(max_depth=10)[source]

Generate a human-readable trace of how this value was calculated.

This method provides a detailed explanation of the calculation chain that led to this FinancialValue, useful for debugging and auditing.

Parameters:

max_depth (int) – Maximum depth to traverse in the calculation tree

Return type:

str

Returns:

Formatted string showing the calculation trace

Example

>>> revenue = FinancialValue(1000)
>>> cost = FinancialValue(600)
>>> profit = revenue - cost
>>> print(profit.trace_calculation())
get_calculation_summary()[source]

Get a brief summary of how this value was calculated.

Return type:

str

Returns:

Brief string summary of the calculation

Example

>>> result = FinancialValue(10) + FinancialValue(5)
>>> print(result.get_calculation_summary())  # "Op: + | Inputs: 2"
export_provenance_graph()[source]

Export the complete provenance graph for this FinancialValue.

Return type:

dict[str, Any]

Returns:

Dictionary containing the provenance graph in JSON-serializable format

Example

>>> result = FinancialValue(10) + FinancialValue(5)
>>> graph = result.export_provenance_graph()
>>> print(graph['root'])  # Root provenance ID
has_operation(operation)[source]

Check if this FinancialValue was created by a specific operation.

Parameters:

operation (str) – Operation string to check for (e.g., “+”, “literal”, “calc:margin”)

Return type:

bool

Returns:

True if the operation matches, False otherwise

Example

>>> result = FinancialValue(10) + FinancialValue(5)
>>> print(result.has_operation("+"))  # True
>>> print(result.has_operation("*"))  # False
is_literal()[source]

Check if this FinancialValue is a literal (not computed from other values).

Return type:

bool

Returns:

True if this is a literal value, False if computed

Example

>>> literal = FinancialValue(100)
>>> computed = FinancialValue(50) + FinancialValue(50)
>>> print(literal.is_literal())   # True
>>> print(computed.is_literal())  # False
is_computed()[source]

Check if this FinancialValue was computed from other values.

Return type:

bool

Returns:

True if this value was computed, False if it’s a literal

Example

>>> literal = FinancialValue(100)
>>> computed = FinancialValue(50) + FinancialValue(50)
>>> print(literal.is_computed())   # False
>>> print(computed.is_computed())  # True
get_input_count()[source]

Get the number of inputs that contributed to this FinancialValue.

Return type:

int

Returns:

Number of input values, 0 for literals or values without provenance

Example

>>> result = FinancialValue(10) + FinancialValue(5)
>>> print(result.get_input_count())  # 2
as_percentage()[source]

Convert this FinancialValue to percentage representation with provenance tracking.

Return type:

FinancialValue[Percent]

ratio()[source]

Convert this FinancialValue to ratio representation with provenance tracking.

Return type:

FinancialValue[Ratio]

with_policy(policy)[source]

Create a new FinancialValue with a different policy, maintaining provenance.

Return type:

FinancialValue

classmethod zero(policy=None, unit=<class 'metricengine.units.Dimensionless'>)[source]

Create a zero FinancialValue with appropriate provenance.

classmethod none(policy=None)[source]

Create a None FinancialValue with appropriate provenance.

Return type:

FinancialValue

classmethod none_with_unit(unit, policy=None)[source]

Create a None FinancialValue with specific unit and appropriate provenance.

Return type:

FinancialValue

classmethod constant(value, policy=None, unit=<class 'metricengine.units.Dimensionless'>)[source]

Create a constant FinancialValue with appropriate provenance.

metricengine.value.FV

alias of FinancialValue

Core Value Types

class metricengine.value.FinancialValue(_value, policy=None, unit=<class 'metricengine.units.Dimensionless'>, _is_percentage=False, _prov=None)[source]

Bases: Generic[U]

policy: Policy | None = None
unit

alias of Dimensionless

as_decimal()[source]
Return type:

Decimal | None

as_float()[source]
Return type:

float | None

as_int()[source]
Return type:

int | None

as_str()[source]
Return type:

str

is_percentage()[source]
Return type:

bool

render(fmt='text', **context)[source]

Render this FinancialValue using a registered renderer.

Parameters:
  • fmt (str) – Name of the renderer to use (default: “text”)

  • **context – Additional context passed to the renderer

Return type:

str

Returns:

Rendered string representation

Raises:

KeyError – If the specified renderer is not registered

Example

>>> amount = money(1234.56)
>>> amount.render("html")  # '<span class="fv positive">$1,234.56</span>'
>>> amount.render("html", css_classes="highlight")
to(unit, *, at=None, meta=None)[source]

Convert this FinancialValue to a different unit.

This method performs explicit unit conversion using the registered conversion functions. It creates a new FinancialValue with the target unit and converted value, preserving the original policy and percentage flag.

Parameters:
  • unit (NewUnit) – Target unit to convert to

  • at (str | None) – Optional timestamp for rate lookups (e.g., “2025-09-06T10:30:00Z”)

  • meta (dict[str, str] | None) – Optional metadata dictionary for conversion context (e.g., {“rate”: “0.79”, “source”: “ECB”})

Return type:

FinancialValue

Returns:

New FinancialValue with the target unit and converted value

Raises:
  • KeyError – If no conversion is registered between the units

  • ValueError – If this FinancialValue has a None value

  • TypeError – If this FinancialValue doesn’t use the new unit system

Example

>>> from metricengine import FinancialValue as FV
>>> from metricengine.units import MoneyUnit
>>>
>>> usd = MoneyUnit("USD")
>>> gbp = MoneyUnit("GBP")
>>> amount = FV(100, unit=usd)
>>>
>>> # Convert with default context
>>> converted = amount.to(gbp)
>>>
>>> # Convert with specific rate and timestamp
>>> converted = amount.to(gbp, at="2025-09-06T10:30:00Z",
...                      meta={"rate": "0.79", "source": "ECB"})
__add__(other)[source]
__sub__(other)[source]
__mul__(other)[source]
__truediv__(other)[source]
is_none()[source]
Return type:

bool

get_provenance()[source]

Get the provenance record for this FinancialValue.

Return type:

Provenance | None

Returns:

Provenance record if available, None otherwise

has_provenance()[source]

Check if this FinancialValue has provenance information.

Return type:

bool

Returns:

True if provenance is available, False otherwise

get_operation()[source]

Get the operation that created this FinancialValue.

Return type:

str | None

Returns:

Operation string if provenance is available, None otherwise

Example

>>> a = FinancialValue(10)
>>> b = FinancialValue(5)
>>> result = a + b
>>> print(result.get_operation())  # "+"
get_inputs()[source]

Get the input provenance IDs that contributed to this FinancialValue.

Return type:

tuple[str, ...]

Returns:

Tuple of provenance IDs for inputs, empty tuple if no provenance

Example

>>> a = FinancialValue(10)
>>> b = FinancialValue(5)
>>> result = a + b
>>> inputs = result.get_inputs()
>>> print(len(inputs))  # 2
get_provenance_metadata()[source]

Get the metadata associated with this FinancialValue’s provenance.

Return type:

dict[str, Any]

Returns:

Dictionary of metadata, empty dict if no provenance

Example

>>> with calc_span("analysis"):
...     result = FinancialValue(10) + FinancialValue(5)
>>> meta = result.get_provenance_metadata()
>>> print(meta.get("span"))  # "analysis"
get_provenance_id()[source]

Get the unique provenance ID for this FinancialValue.

Return type:

str | None

Returns:

Provenance ID string if available, None otherwise

Example

>>> value = FinancialValue(100)
>>> prov_id = value.get_provenance_id()
>>> print(prov_id[:8])  # First 8 chars of hash
trace_calculation(max_depth=10)[source]

Generate a human-readable trace of how this value was calculated.

This method provides a detailed explanation of the calculation chain that led to this FinancialValue, useful for debugging and auditing.

Parameters:

max_depth (int) – Maximum depth to traverse in the calculation tree

Return type:

str

Returns:

Formatted string showing the calculation trace

Example

>>> revenue = FinancialValue(1000)
>>> cost = FinancialValue(600)
>>> profit = revenue - cost
>>> print(profit.trace_calculation())
get_calculation_summary()[source]

Get a brief summary of how this value was calculated.

Return type:

str

Returns:

Brief string summary of the calculation

Example

>>> result = FinancialValue(10) + FinancialValue(5)
>>> print(result.get_calculation_summary())  # "Op: + | Inputs: 2"
export_provenance_graph()[source]

Export the complete provenance graph for this FinancialValue.

Return type:

dict[str, Any]

Returns:

Dictionary containing the provenance graph in JSON-serializable format

Example

>>> result = FinancialValue(10) + FinancialValue(5)
>>> graph = result.export_provenance_graph()
>>> print(graph['root'])  # Root provenance ID
has_operation(operation)[source]

Check if this FinancialValue was created by a specific operation.

Parameters:

operation (str) – Operation string to check for (e.g., “+”, “literal”, “calc:margin”)

Return type:

bool

Returns:

True if the operation matches, False otherwise

Example

>>> result = FinancialValue(10) + FinancialValue(5)
>>> print(result.has_operation("+"))  # True
>>> print(result.has_operation("*"))  # False
is_literal()[source]

Check if this FinancialValue is a literal (not computed from other values).

Return type:

bool

Returns:

True if this is a literal value, False if computed

Example

>>> literal = FinancialValue(100)
>>> computed = FinancialValue(50) + FinancialValue(50)
>>> print(literal.is_literal())   # True
>>> print(computed.is_literal())  # False
is_computed()[source]

Check if this FinancialValue was computed from other values.

Return type:

bool

Returns:

True if this value was computed, False if it’s a literal

Example

>>> literal = FinancialValue(100)
>>> computed = FinancialValue(50) + FinancialValue(50)
>>> print(literal.is_computed())   # False
>>> print(computed.is_computed())  # True
get_input_count()[source]

Get the number of inputs that contributed to this FinancialValue.

Return type:

int

Returns:

Number of input values, 0 for literals or values without provenance

Example

>>> result = FinancialValue(10) + FinancialValue(5)
>>> print(result.get_input_count())  # 2
as_percentage()[source]

Convert this FinancialValue to percentage representation with provenance tracking.

Return type:

FinancialValue[Percent]

ratio()[source]

Convert this FinancialValue to ratio representation with provenance tracking.

Return type:

FinancialValue[Ratio]

with_policy(policy)[source]

Create a new FinancialValue with a different policy, maintaining provenance.

Return type:

FinancialValue

classmethod zero(policy=None, unit=<class 'metricengine.units.Dimensionless'>)[source]

Create a zero FinancialValue with appropriate provenance.

classmethod none(policy=None)[source]

Create a None FinancialValue with appropriate provenance.

Return type:

FinancialValue

classmethod none_with_unit(unit, policy=None)[source]

Create a None FinancialValue with specific unit and appropriate provenance.

Return type:

FinancialValue

classmethod constant(value, policy=None, unit=<class 'metricengine.units.Dimensionless'>)[source]

Create a constant FinancialValue with appropriate provenance.

__init__(_value, policy=None, unit=<class 'metricengine.units.Dimensionless'>, _is_percentage=False, _prov=None)
class metricengine.value.Money[source]

Bases: Unit

Unit for monetary values.

code: str = 'USD'