Price Type#

OUCH 5.0 uses a custom price format: UInt64 on wire (8 bytes), UInt32 for value (4 bytes) with 4 implied decimals. The library provides a Price type for type-safe price handling.

Overview#

OUCH 5.0 prices are encoded as 64-bit unsigned integers on the wire (8 bytes), though only the lower 32 bits are used, with 4 implied decimal places:

  • Raw value: Integer representation (e.g., 1505000)

  • Decimal value: $150.50 (1505000 / 10000)

The Price type provides:

  • Type-safe price operations

  • Conversion to/from floating-point values

  • Market order sentinel value for cross orders

  • Automatic handling of the 4-decimal format

Creating Prices#

From Double#

The most common way to create a price:

Price price = Price::from_double(150.50);  // $150.50 -> 1505000 (raw value)

From Raw Value#

If you have the raw integer value:

UInt64 raw_value = 1505000;  // $150.50
Price price(raw_value);
// Or using factory method:
Price price = Price::from_uint64(1505000);
// For backward compatibility with UInt32:
Price price = Price::from_uint32(1505000);

Converting Prices#

To Double#

Price price = Price::from_double(150.50);
double float_value = price.to_double();  // 150.50

To Raw Value#

Price price = Price::from_double(150.50);
UInt64 raw_value = price.value();  // 1505000

Market Order Sentinel#

For market orders in cross orders, OUCH 5.0 uses a special sentinel value:

Price market_price = Price::market_order_sentinel();
// Raw value: 0xFFFFFFFF (4294967295)
// Used as market order indicator in cross orders

Price Operations#

Comparison#

Price price1 = Price::from_double(150.50);
Price price2 = Price::from_double(150.75);

if (price1 < price2) {
    // price1 is lower
}

if (price1 == price2) {
    // prices are equal
}

Arithmetic#

The Price type does not provide arithmetic operators. To perform arithmetic operations, convert to raw values:

Price price1 = Price::from_double(150.50);
Price price2 = Price::from_double(0.25);

// Manual arithmetic using raw values
UInt64 sum_raw = price1.value() + price2.value();
Price sum = Price::from_uint64(sum_raw);

UInt64 diff_raw = price1.value() - price2.value();
Price diff = Price::from_uint64(diff_raw);

Using Prices in Messages#

Setting Prices#

EnterOrder order;
order.set_price(Price::from_double(150.50));

Getting Prices#

void on_order_accepted(Session* s, std::uint64_t seq, const OrderAccepted* msg) {
    Price accepted_price = msg->get_price();
    double price_value = accepted_price.to_double();
    std::cout << "Accepted price: $" << price_value << std::endl;
}

Price Limits#

OUCH 5.0 has specific price limits:

  • Maximum price: $199,999.9900 (raw value: 0x7735939C)

  • Market order sentinel: 0xFFFFFFFF (4294967295) - used as indicator for market orders in cross orders

API Reference#

Price Class#

class Price {
public:
    // Constructors
    Price();
    explicit Price(UInt64 value);
    
    // Factory methods
    static Price from_double(double price);
    static Price from_uint64(UInt64 raw_value) noexcept;
    static Price from_uint32(UInt32 raw_value) noexcept;  // Backward compatibility
    static Price market_order_sentinel();
    
    // Conversions
    double to_double() const;
    UInt64 value() const;  // Get raw UInt64 value
    
    // Validation
    bool is_market_order_sentinel() const;
    bool is_valid() const;
    
    // Comparison operators
    bool operator==(const Price& other) const noexcept;
    bool operator!=(const Price& other) const noexcept;
    bool operator<(const Price& other) const noexcept;
    bool operator<=(const Price& other) const noexcept;
    bool operator>(const Price& other) const noexcept;
    bool operator>=(const Price& other) const noexcept;
};

from_double#

static Price from_double(double value);

Creates a Price from a floating-point value.

Parameters:

  • value: Price as double (e.g., 150.50)

Returns: Price object

Example:

Price price = Price::from_double(150.50);

to_double#

double to_double() const;

Converts the price to a floating-point value.

Returns: Price as double

Example:

Price price = Price::from_double(150.50);
double value = price.to_double();  // 150.50

value#

UInt64 value() const;

Returns the raw integer value (UInt64, with 4 implied decimals).

Returns: Raw price value as UInt64

Example:

Price price = Price::from_double(150.50);
UInt64 raw = price.value();  // 1505000

market_order_sentinel#

static Price market_order_sentinel();

Returns the special sentinel value used for market orders in cross orders.

Returns: Market order sentinel price

Example:

Price market = Price::market_order_sentinel();
// Use in cross orders
order.set_price(market);

Example: Complete Price Usage#

#include <nasdaq/ouch50/Types.h>

using namespace b2bits::nasdaq::ouch5;

// Create prices
Price limit_price = Price::from_double(150.50);
Price market_price = Price::market_order_sentinel();

// Use in order
EnterOrder order;
order.set_price(limit_price);

// Compare prices
Price price1 = Price::from_double(150.50);
Price price2 = Price::from_double(150.75);

if (price1 < price2) {
    std::cout << "Price1 is lower" << std::endl;
}

// Convert for display
double display_price = limit_price.to_double();
std::cout << "Price: $" << display_price << std::endl;

// Get price from message
void on_order_executed(Session* s, std::uint64_t seq, const OrderExecuted* msg) {
    Price exec_price = msg->get_execution_price();
    double price_value = exec_price.to_double();
    std::cout << "Executed at: $" << price_value << std::endl;
}

Best Practices#

  1. Use from_double(): Prefer Price::from_double() for creating prices from user input

  2. Type safety: Always use Price type instead of raw integers

  3. Market orders: Use market_order_sentinel() for market orders in cross orders

  4. Display: Convert to double only when displaying to users

  5. Precision: Be aware of the 4-decimal precision limit