Skip to main content
Version: nightly

Value Types

NautilusTrader provides specialized value types for representing core trading concepts: Price, Quantity, and Money. These types use fixed-point arithmetic internally to ensure highly performant and deterministic calculations across different platforms and environments.

Overview

TypePurposeSignedCurrency
QuantityTrade sizes, order amounts, positions.No-
PriceMarket prices, quotes, price levels.Yes-
MoneyMonetary amounts, P&L, account balances.YesYes

Immutability

All value types are immutable. Once a value is constructed, it cannot be changed. Arithmetic operations always return new instances rather than modifying existing ones.

from nautilus_trader.model.objects import Quantity

qty1 = Quantity(100, precision=0)
qty2 = Quantity(50, precision=0)

# This creates a NEW Quantity; qty1 and qty2 are unchanged
result = qty1 + qty2

print(qty1) # 100
print(qty2) # 50
print(result) # 150

This design provides several benefits:

  • Thread safety: Immutable values can be safely shared across threads without synchronization.
  • Predictability: Values never change unexpectedly, making debugging easier.
  • Hashability: Immutable types can be used as dictionary keys and in sets.

Arithmetic operations

Value types support standard arithmetic operators (+, -, *, /, %, //). The return type depends on the operand types.

Same-type operations

When both operands are the same value type, the result is also that type:

OperationResult
Quantity + QuantityQuantity
Quantity - QuantityQuantity
Price + PricePrice
Price - PricePrice
Money + MoneyMoney
Money - MoneyMoney
from nautilus_trader.model.objects import Price

price1 = Price(100.50, precision=2)
price2 = Price(0.25, precision=2)

result = price1 + price2 # Returns Price(100.75, precision=2)
print(type(result)) # <class 'Price'>

Mixed-type operations

When operating with other numeric types, the result type follows Python's numeric tower conventions. The general principle is that operations widen to the more general type: float operations return float, while int and Decimal operations return Decimal for precision preservation.

Left operandRight operandResult type
Value typeintDecimal
Value typefloatfloat
Value typeDecimalDecimal
intValue typeDecimal
floatValue typefloat
DecimalValue typeDecimal
from decimal import Decimal
from nautilus_trader.model.objects import Quantity

qty = Quantity(100, precision=0)

# Quantity + int → Decimal
result1 = qty + 50
print(type(result1)) # <class 'decimal.Decimal'>

# Quantity + float → float
result2 = qty + 50.5
print(type(result2)) # <class 'float'>

# Quantity + Decimal → Decimal
result3 = qty + Decimal("50")
print(type(result3)) # <class 'decimal.Decimal'>

Precision handling

Each value type stores a precision field indicating the number of decimal places. When performing arithmetic between values with different precisions, the result uses the maximum precision of the operands.

from nautilus_trader.model.objects import Price

price1 = Price(100.5, precision=1) # 1 decimal place
price2 = Price(0.125, precision=3) # 3 decimal places

result = price1 + price2
print(result) # 100.625
print(result.precision) # 3 (max of 1 and 3)

Type-specific constraints

Quantity

Quantity represents non-negative amounts. Attempting to create a negative quantity or subtract a larger quantity from a smaller one raises an error:

from nautilus_trader.model.objects import Quantity

# This raises ValueError: Quantity cannot be negative
qty = Quantity(-100, precision=0)

# This also raises ValueError
qty1 = Quantity(50, precision=0)
qty2 = Quantity(100, precision=0)
result = qty1 - qty2 # Would be -50, which is invalid

Money

Money values include a currency. Arithmetic between Money values requires matching currencies:

from nautilus_trader.model.objects import Money
from nautilus_trader.model.currencies import USD, EUR

usd_amount = Money(100.00, USD)
eur_amount = Money(50.00, EUR)

# This works - same currency
result = usd_amount + Money(25.00, USD)

# This raises ValueError - currency mismatch
result = usd_amount + eur_amount

Common patterns

Accumulating values

Since value types are immutable, accumulate by reassigning:

from nautilus_trader.model.objects import Money
from nautilus_trader.model.currencies import USD

total = Money(0.00, USD)
amounts = [Money(100.00, USD), Money(50.00, USD), Money(25.00, USD)]

for amount in amounts:
total = total + amount # Reassign to new Money instance

print(total) # 175.00 USD

Converting to other types

Value types provide conversion methods:

from nautilus_trader.model.objects import Price

price = Price(123.456, precision=3)

# Convert to Decimal (preserves precision)
decimal_value = price.as_decimal()

# Convert to float
float_value = price.as_double()

# Convert to string
string_value = str(price) # "123.456"

Creating from strings

Parse value types from string representations:

from nautilus_trader.model.objects import Quantity, Price, Money

qty = Quantity.from_str("100.5")
price = Price.from_str("99.95")
money = Money.from_str("1000.00 USD")