Order Management


Placing and managing orders is an integral part of every trading system. With Trading System API an order is more than a simple message. Orders are implemented as reference counted objects with a lifetime that persists beyond the order being filled, cancelled or rejected. It is thus possible to access an order's properties even when the order is no longer 'active'. Developers only interact with objects of class order_ref. These objects represent a handle on the underlying order object. The underlying order is only destroyed once the last order_ref object goes out of scope or is explicitly instructed to releases the order it references.

 

Creating Orders


Orders are created via member functions of class instrument such as instrument::buy() and instrument::sell().

 

          instrument sp500;

                              

void on_bar_close(void) {

                              

          if (buy_signal)

          {

                    sp500.buy(1);   // Order is sent immediately

          }

          if (sell_signal)

          {

                    sp500.sell(1);

          }

}

By default class instrument's order functions will transmit an order immediately and return a corresponding order_ref object. In a simulated environment market orders are filled in their entirety immediately, but in a live environment many things can go wrong and it is a good idea to retain an handle on all orders so order status can be queried at all time.  

 

instrument sp500;

 

          order_ref entry_order, exit_order;

 

          void on_bar_close(void) {

 

                    if (buy_signal)

                    {

                              entry_order = sp500.buy(1);   // Retain a reference to new order

                    }

                    if (sell_signal)

                    {

                              exit_order = sp500.sell(1);

                    }

          }

Order Identification


Orders are identified in several ways.

Order-ID Type

Function

Description

 native

 order_ref::id()

 This is the ID assigned by the strategy itself. It look something like: 1000000000055

where the 1 in front is the ID of the strategy's instrument object which generated it, and the back number is the actual order number. This allows fast routing of confirmations back to the originating instrument.

 external

 order_ref::external_id()

This is the ID as assigned by the platform session. Your broker/platform probably has a way to reset this sequence if required.

 permanent

 order_ref::permanent_id()

A permanent ID which persists across platform sessions, also returned by your broker/platform.

 

Order Status


An order's status can be checked by invoking order_ref::status().

 

     order_ref o = mkt.buy(10);

order::status s = o.status();

 

An order's status can be any of the following:

 

State

Description

order::created

The order has been created but has not been transmitted, and can still be modified.

order::pending_submit

The order has been transmitted. It is has not yet been confirmed as submitted but we must assume that is has been.

order::pre_submitted

The order is held by the platform until elected for submission. This can happen when the order is submitted outside trading hours, or when a particular order type is simulated by the platform.

order::submitted

The order is confirmed working at the exchange. It may already be filled.

order::pending_cancel

A cancellation request has been sent, but the order is not yet confirmed cancelled. In this state the order may already be filled.

order::pending_cancel_replace

A request to cancel-replace the order has been made, but no confirmation has been received.

order::paused

The exchange has notified that the order is paused, due to exchange issues.

order::filled

The order has been filled in its entirety.

order::cancelled

The order is confirmed cancelled and is no longer active.

order::rejected

The order has been rejected.

 

These are alternate functions for checking order status:

 

order_ref::is_filled()

order_ref::is_sent()

order_ref::is_active()

order_ref::is_partially_filled()

order_ref::is_cancelled()

order_ref::is_pending_submit()

order_ref::is_pre_submitted()

order_ref::is_acknowledged()

order_ref::is_submitted()

order_ref::is_pending_cancel()

order_ref::is_cancelled()

 

 

Order 'Active' Status


An order is considered active if it's status is not any of: order::created, order::filled, order::cancelled or order::rejected. Use the order_ref::is_active() member to check if an order is active. Active orders are orders that can still cause financial loss if not handled properly. It is thus important not to lose knowledge of such orders. To prevent the loss of handles a safeguard has been built into class order_ref:

Safeguard: You cannot assign, using operator=(), an order_ref object to an existing order_ref object if the existing object still references an active order! Attempting such an assignment would cause an exception to be thrown.

 

order_ref my_order;

//. . .

my_order = sp500.buy_limit(...);

assert(my_order.is_active());

my_order = sp500.sell_limit(...); // exception here! Assignment to 'active' order not allowed.

 

By disallowing the second assignment the strategy prevents you from losing the handle on your active limit order. Needless to say, it's important to catch such errors during the strategy testing phase. Such errors should not occur during live strategy deployment.

On occasions it makes sense to replace a reference. For the assignment to succeed the existing reference must first be released using order_ref::release() like so:

 

          order_ref my_order;

//. . .

my_order = sp500.buy_limit(...);

my_order.release();

my_order = sp500.sell_limit(...);    // success!

 

Verifying an Order Reference is 'Defined'


The default order_ref constructor leaves the object in an undefined state. Before you call any members of a given order_ref object, you must check if the object is in a defined state by calling order_ref::defined() or order_ref::is_defined().

 

          order_ref my_order;

//. . .

if(my_order.is_defined())  // check if order reference is defined

{

          my_order.cancel();

}

 

class order_ref also defines an operator bool(). This makes it possible to skip calling order_ref::is_defined() and simply write:

 

          if(my_order)  // uses operator bool() to see if 'defined'

{

          my_order.cancel();

}

 

order_ref::is_active() can be invoked even if the object is in an undefined state!

In such a case the function simply returns false. So rather than write:

     if(my_order)  // check if object is 'defined'

{

          if(my_order.is_active()){

        my_order.cancel();

     }

}

you can simply write:

if(my_order.is_active())  // return false if order_ref is undefined

{

     my_order.cancel();

}

 

 

 

Creating and Transmitting Orders


Orders can be transmitted immediately or transmission can be delayed to allow setting various order properties. Every order creation function like for example:

 

order_ref o;

//. . .

o = buy_limit(...);

 

has a counterpart with a postfix '_order' which delays transmission and for which transmission needs to be explicit like:

 

order_ref o;

//. . .

o = buy_limit_order(...); 

o.time_in_force(order::day);  // amend order

o.send();                                            // explicitly send order

 

The full set of class instrument's order creation functions is:

 

order_ref buy(quantity_t quantity);

order_ref buy_order(quantity_t quantity);   // '_order' postfix means delayed transmission.

order_ref sell(quantity_t quantity);

order_ref sell_order(quantity_t quantity);

order_ref buy_stop(quantity_t quantity, double stop_price);

order_ref buy_stop_order(quantity_t quantity, double stop_price);

order_ref sell_stop(quantity_t quantity, double stop_price);

order_ref sell_stop_order(quantity_t quantity, double stop_price);

order_ref buy_stop_limit(quantity_t quantity, double stop_price, double price_limit);          

order_ref buy_stop_limit_order(quantity_t quantity, double stop_price, double price_limit);

order_ref sell_stop_limit(quantity_t quantity, double stop_price, double price_limit);

order_ref sell_stop_limit_order(quantity_t quantity, double stop_price, double limit_price);

order_ref buy_limit(quantity_t quantity, double limit_price);

order_ref buy_limit_order(quantity_t quantity, double limit_price);

order_ref sell_limit(quantity_t quantity, double limit_price);

order_ref sell_limit_order(quantity_t quantity, double limit_price); 

 

Order 'Properties' Maintained by the Instrument Object

The order creation functions shown above have simple declaration. These functions don't require more parameters as they are members of class instrument which keeps track of all relevant order related properties such as :

symbol

expiry

exchange,

broker,

currency,

tick-size

tick-value

etc.

 

Most of these properties are required for live deployment only at which time the information is automatically retrieved from the server. For strategy simulations, the information required is limited.

 

class order_ref Members


Orders are normally manipulated via order_ref objects. It is possible to access the internally managed order objects as well, but there is usually little reason to do so. Every member of class order has a corresponding member in class order_ref. The following function name list is an overview of order_ref class members. For a full listing with documentation, please consult the API's Reference Manual.

 

send();

cancel();

update_price();

update_quantity();

release()

get()

print()

symbol()

exchange()

id()

instrument_id()

tag()

time_in_force()

expiry_time_point()

price()

fixed_fill_price();

group_id()

is_in_group()

quantity()

 

 

remaining()

size()

min_fill_quantity()

action()

type()

aux_price()

is_stop_limit()

exec_interval()

create_bar_ordinal()

age_in_bars()

age()

defined()

operator bool()

is_filled()

is_sent()

active()

is_active()

is_partially_filled()

 

 

 

cancelled()

is_cancelled()

marked_for_deletion()

status()

prev_status()

filled_quantity()

last_fill_timestamp()

create_timestamp()

is_pending_submit();

is_pre_submitted();

is_acknowledged();

is_submitted();

is_pending_cancel();

is_cancelled();

update_status();

external_id()

permanent_id()

 

 

Minimum Tick and Price Rounding


Transaction prices for exchange traded securities are restricted to increments of 'tick-size'. For regular shares this tick-size is usually 1/100 of a currency unit. For futures contracts this value varies. The reason why the tick size is important is because limit and stop orders submit one or more prices, such as the limit price, the stop price, or the stop limit price. When these prices are submitted to the trading platform / broker, they must be valid prices, that is they most be multiples of the minimum tick, or else they will be rejected.

 

During live deployment with the Trading System API - Server, the tick-size will be set automatically (provided the security was set up properly in the server) for each instrument and all stop and limit prices will be rounded automatically to the nearest multiple.

Automatic rounding is not enabled for simulations. This is because simulations often involve heavily normalized, back adjusted data which no longer corresponds to a traded price. For heavily split and divided adjusted data series, the minimum tick value would also have to be adjusted for the simulation to be meaningful.  

 

Some order functions define a price parameter, such as the 'limit-price' or 'stop-price'.

 

When you pass a price argument to the instrument::limit_order() function, the given  price will be automatically rounded to a multiple of the instrument's min-tick value. This tick-size value can be set via the instrument::tick() member. This same member also defines a flag parameter that enables or disables automatic rounding. 

 

          instrument sp500;

          // . . .

          void on_start(void)   override

          {

                    sp500.connect("emini.daily");

                      bool auto_round = true;

                    sp500.tick(0.1, 25.0, auto_round);  // set tick-size, tick-value, and auto-rounding

          }

 

The above call to tick sets the tick-size to 0.1 of an (index) point, with a value of 25.0 dollars per tick. To disable auto-rounding pass 'false' as third argument.

 

Order Related Members of Class Instrument


Under normal circumstances orders will be managed via instances of class order_ref which features a large set of useful member.  But occasionally, it may come in handy to get a list of all internally managed orders, or cancel an order based on its order-id. Please consult the API's Reference Manual for more details.

 

void instrument::cancel_all_orders(void);

void instrument::cancel_order(identifier_t id);

bool instrument::order_exists(identifier_t id)const;

void instrument::get_orders(

std::vector<order>& v, bool active_only = true)const;

std::vector<order_ref> instrument::orders(void)const;

std::vector<order_ref> instrument::active_orders(void)const;

bool instrument::has_active_orders(void)const;

void instrument::get_active_orders(

std::vector<order_ref>&, order::type, order::action) const;

order_ref instrument::get_order(identifier_t id) const;

order* instrument::get_order_ptr(identifier_t id) const;

size_t instrument::active_order_count(void) const;

size_t instrument::order_count() const;

 

 

Order Related Strategy Members


The following functions provide access to orders via the order-ID.

          

          void strategy::cancel_order(identifier_t order_id, identifier_t instrument_id);

          order_ref strategy::get_order_ref(identifier_t order_id) const;

          order* strategy::order_ptr(identifier_t order_id) const; // Access to order via ID          

Iterating through all Strategy Orders

It is possible to iterate through all strategy orders by iterating through all strategy instrument members via strategy::instruments() and then fetch all orders from each instrument using instrument::orders() and instrument::active_orders().

 

The number of orders owned by all instruments in the strategy is returned by:

 

          size_t strategy::active_order_count(void) const// Number of active orders

          size_t strategy::order_count(void) const; // Number of all orders

 

Tutorial 303 shows how this is done. Please see the on_bar_close() member in the tutorial project for a full code listing:

 

                    // access all instruments

                    std::vector<instrument*> all_instruments = instruments();

 

                    // access all orders in all instruments

                    for(auto* i_ptr : all_instruments)

                    {

                              // all orders

                              std::vector<tsa::order_ref> all_orders = i_ptr->orders();

                              for (auto o : all_orders) {

                                        //o.print(std::cout);

                              }          

                              //active orders only

                              std::vector<tsa::order_ref> active_orders = i_ptr->active_orders();

                              for (auto o : active_orders) {

                                        //o.print(std::cout);

                              }

                    }