Common Code Patterns#

This page provides reusable code snippets for common OUCH 5.0 operations.

Session Setup#

Basic Session Initialization#

#include <nasdaq/ouch50/Session.h>
#include <nasdaq/ouch50/net/IOContext.h>

using namespace b2bits::nasdaq::ouch5;

// Create IO context
auto io_ctx = std::make_shared<IOContext>(IOContext::Settings{"main", 0, false});
io_ctx->start();

// Configure session
Settings settings;
settings.transport_.username_ = "TRADER01";
settings.transport_.password_ = "password123";
settings.transport_.remote_a_ = Endpoint{"192.168.1.100", 64002};
settings.initial_user_ref_num_ = 1;

// Create session
Session session(io_ctx, settings);

Session with Message Buffering#

Settings settings;
// ... basic settings ...

// Enable message buffering
OutboundMessageBufferSettings buffer_settings;
buffer_settings.max_messages_ = 10000;
buffer_settings.max_bytes_ = 10 * 1024 * 1024;
buffer_settings.track_acknowledgments_ = true;
settings.buffer_settings_ = buffer_settings;
settings.auto_retransmit_on_reconnect_ = true;

Session session(io_ctx, settings);

Listener Patterns#

Function Object Pattern#

struct Handler {
    void operator()(Session* s, std::uint64_t seq, const OrderAccepted* msg) {
        // Handle OrderAccepted
    }
    void operator()(Session* s, std::uint64_t seq, const OrderExecuted* msg) {
        // Handle OrderExecuted
    }
};

Handler handler;
session.attach_listener(std::ref(handler));

Lambda Pattern#

session.attach_listener(
    [](Session* s, std::uint64_t seq, const OrderAccepted* msg) {
        // Handle OrderAccepted
    },
    [](Session* s, std::uint64_t seq, const OrderExecuted* msg) {
        // Handle OrderExecuted
    }
);

Overloaded Pattern#

#include <nasdaq/common/Overloaded.h>

session.attach_listener(Overloaded(
    [](Session* s, std::uint64_t seq, const OrderAccepted* msg) {
        // Handle OrderAccepted
    },
    [](Session* s, std::uint64_t seq, const OrderExecuted* msg) {
        // Handle OrderExecuted
    }
));

Sending Orders#

Enter Order#

auto& refnum_gen = session.get_user_refnum_generator();
UInt32 user_ref_num = refnum_gen.next();

EnterOrder order;
order.set_user_ref_num(user_ref_num);
order.set_side(Side::Buy);
order.set_quantity(1000);
order.set_symbol("AAPL");
order.set_price(Price::from_double(150.50));
order.set_time_in_force(TimeInForce::Day);
order.set_display(DisplayFlag::Visible);
order.set_capacity(Capacity::Agency);
order.set_intermarket_sweep_elig('N');
order.set_cross_type(CrossType::None);
order.set_cl_ord_id("ORD001");

session.send_message(&order);

Replace Order#

ReplaceOrderRequest replace;
replace.set_orig_user_ref_num(orig_user_ref_num);
replace.set_user_ref_num(new_user_ref_num);  // Must be strictly increasing
replace.set_quantity(2000);
replace.set_price(Price::from_double(150.75));
replace.set_time_in_force(TimeInForce::Day);
replace.set_display(DisplayFlag::Visible);
replace.set_intermarket_sweep_elig('N');
replace.set_cl_ord_id("ORD002");

session.send_message(&replace);

Cancel Order#

CancelOrderRequest cancel;
cancel.set_user_ref_num(user_ref_num);
cancel.set_quantity(0);  // 0 = cancel all, >0 = partial cancel

session.send_message(&cancel);

TagValue Appendages#

Adding Optional Fields#

EnterOrder order;
// ... set required fields ...

// Add optional fields
auto& appendage = order.get_appendage_writer();
appendage.add_min_qty(100);
appendage.add_max_floor(5000);
appendage.add_firm("FIRM");
appendage.add_customer_type(CustomerType::Retail);
appendage.add_price_type(PriceType::Limit);
appendage.add_post_only(PostOnly::No);
appendage.add_expire_time(3600);  // 1 hour

session.send_message(&order);

Reading Optional Fields#

void on_order_accepted(Session* s, std::uint64_t seq, const OrderAccepted* msg) {
    // Using convenience accessor
    if (auto min_qty = msg->get_min_qty()) {
        std::cout << "MinQty: " << *min_qty << std::endl;
    }
    
    // Using appendage reader directly
    auto appendage = msg->get_appendage();
    if (auto element = appendage.find(TagValue::MIN_QTY)) {
        UInt32 min_qty = element->as_uint32();
        std::cout << "MinQty: " << min_qty << std::endl;
    }
}

UserRefNum Management#

Generate UserRefNum#

auto& refnum_gen = session.get_user_refnum_generator();
UInt32 user_ref_num = refnum_gen.next();  // Strictly increasing

Recover UserRefNum#

// Send Account Query Request
AccountQueryRequest query;
session.send_message(&query);

// In AccountQueryResponse handler:
void on_account_query_response(Session* s, std::uint64_t seq, const AccountQueryResponse* msg) {
    UInt32 next_user_ref_num = msg->get_next_user_ref_num();
    s->get_user_refnum_generator().reset(next_user_ref_num);
}

Message Buffering#

Mark Messages as Acknowledged#

void on_order_accepted(Session* s, std::uint64_t seq, const OrderAccepted* msg) {
    if (auto* buffer = s->get_message_buffer()) {
        buffer->mark_acknowledged(msg->get_user_ref_num());
    }
}

void on_order_replaced(Session* s, std::uint64_t seq, const OrderReplaced* msg) {
    if (auto* buffer = s->get_message_buffer()) {
        buffer->mark_acknowledged(msg->get_user_ref_num());
    }
}

Thread Safety#

Sending from Another Thread#

// From main thread or other thread
io_ctx->post([session = session.get(), order]() {
    // Now on IOContext's thread - safe to use Session
    session->send_message(&order);  // Safe
});

Async Operations#

// Can be called from any thread
session->async_login("", 0, std::chrono::milliseconds(2000),
    [](std::uint64_t seq, const std::error_code& ec) {
        // Callback runs on IOContext's thread
        if (!ec) {
            std::cout << "Logged in with sequence: " << seq << std::endl;
        }
    });

Error Handling#

Check Send Result#

std::error_code ec = session.send_message(&order);
if (ec) {
    std::cerr << "Failed to send order: " << ec.message() << std::endl;
}

Handle Rejected Orders#

void on_rejected(Session* s, std::uint64_t seq, const Rejected* msg) {
    std::cerr << "Order rejected: UserRefNum=" << msg->get_user_ref_num()
              << " Reason=" << static_cast<int>(msg->get_reason()) << std::endl;
}