Order Types

Roboquant comes out of the box with support for different types of orders. The following diagram shows which orders are supported and also their class relationship to each other.

order types

All orders refer to a single asset, including advanced order types like BracketOrders. The reason for putting this restriction in place is that real brokers only have limited support for multi-asset orders and this could lead to issues that are only discovered during live trading. Additionally, it makes back testing difficult if the price for one asset is known but not for the other.

Creating Orders

The Policy that is used during a run is responsible for creating the orders. This can be based on the received signals from the Strategy, but can also be done for other reasons (like for example cyclic portfolio re-balancing)

An example on how to convert a list of signals into a list of (market) orders:

val orders = mutableListOf<Order>()
for (signal in signals) {
    val size = if (signal.rating.isPositive) 100 else -100
    val order = MarketOrder(signal.asset, size)
there is no explicit notion of BUY or SELL order in roboquant. A BUY order is just any order with a positive size and a SELL order has a negative size. But other than that, they are equal and created the same way.

Most advanced order types are often constructed using multiple SingleOrder types. The following snippet shows how to instantiate a BracketOrder using three individual SingleOrders.

val size = Size(10)
val order = BracketOrder(
    MarketOrder(asset, size), // main order
    LimitOrder(asset, -size, price * 1.05), // take profit order
    StopOrder(asset, -size, price * 0.95) // stop loss order
always make sure to only use order types during back testing that are also supported by the broker you want to use for live trading. Also be aware the way these advanced order types are exactly executed might differ between brokers.

TIF (Time In Force)

TIF sets an execution policy for an order under which conditions the order remains valid. Roughly speaking, there are two types of TIF:

  1. Time based, defining how long the order stays valid. Two common ones are GTD (Good Till Day) and GTC (Good Till Cancelled)

  2. Fill based, defining under which fill conditions the order stays valid. A common one if FOK (Fill Or Kill)

The default TIF for orders in roboquant used if none is explicitly specified, is GTC (Good Till Cancelled). All TIF policies are only becoming active once an Order has been ACCEPTED (so not anymore in its INITIAL state)

Custom Order Types

Orders can be extended with your own order types if the ones that come out of the box are not sufficient. The steps required to make to use yor own order types are:

  1. Extend the Order abstract class

  2. If you want to use these orders also in back testing, you’ll also need to implement and register an OrderHandler

After that, you can use this new order type in your policy just like any of the included order types.

// Simple custom order type
class MyOrder(asset: Asset, val size: Size, val customProperty: Int, id:Int = nextId()) : Order(asset, id)

// Define a handler for your custom order type.
// This is only required if you want your order to be supported by the SimBroker
class MyOrderHandler(val order: MyOrder) : TradeOrderHandler {

    override var state = OrderState(order)

    override fun execute(pricing: Pricing, time: Instant): List<Execution> {

        // Set state to accepted
        state = OrderState(order, OrderStatus.ACCEPTED, time)

        // some logic for the order type
        // ....

        // Calculate the price to use
        val price = pricing.marketPrice(order.size)

        // Set the state to be COMPLETED. As long as the state is not in a Closed state, this handler stays active.
        state = OrderState(order, OrderStatus.COMPLETED, time, time)

        // Return the executions
        return listOf(Execution(order, order.size, price))


// Register the handler
ExecutionEngine.register<MyOrder> { MyOrderHandler(it) }