roboquant avatar

Orders

Order Types

Roboquant version 3 comes out of the box with support for limit orders. These orders can be created, updated or cancelled.

An order always refers 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 unpredictable if the price is only known for one of the assets.

Creating Orders

The Trader 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 orders:

val orders = mutableListOf<Order>()
for (signal in signals) {
    val size = if (signal.isBuy) Size(10) else Size(-10)
    val limit = event.getPrice(signal.asset, "CLOSE")
    if (limit != null) {
        val order = Order(signal.asset, size, limit)
        orders.add(order)
    }
}
There is no explicit notion of BUY or SELL order in roboquant. A BUY order is just an 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.

TIF (Time In Force)

TIF sets an execution policy for an order, defining under what conditions the order remains valid. There are two types of TIF:

  1. Time based, defining how long the order remains 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 following diagram shows the time in force policies that are available out of the box:

tif

The default TIF for orders in roboquant, if none is explicitly specified, is GTC (Good Till Cancelled). All TIF policies only become active once an CreateOrder has been ACCEPTED (so it’s not any more in the INITIAL state).

Own order logic

Although you typically would use the run method to handle method invocations on the various components, you can also invoke these methods directly from your own code.

For example, if you want to place an order, you can directly invoke the Broker.place method:

// Connect to the broker
val broker = AlpacaBroker {
    publicKey = "..."
    secretKey = "..."
}

// create the order
val tesla = Stock("TSLA")
val order = Order(tesla, Size(10), 420.0)

// place the order
broker.placeOrders(listOf(order))

// Get an updated versions of your broker account
repeat(10) {
    val account = broker.sync()
    println(account)
    Thread.sleep(1_000)
}