AlgoTraderAlgoTrader Documentation

Chapter 20. OrderManagement

20.1. Place Order
20.1.1. Trade Suggestions
20.1.2. Order Properties
20.2. Receive Fills
20.3. Internal Order Id Format
20.4. Symbology

Before sending an Order, it is advised to call the validate method on the order. This will validate the order regarding limits, amount, quantity, etc. In case validation fails, the order can be modified.

The method sendOrder of the OrderService is responsible for placing Orders. This method takes an Order Entity or Order Value Object as parameter.

Sending an order using and Order Entity looks like this:

MarketOrder order = MarketOrder.Factory.newInstance();

order.setStrategy(strategy);
order.setAccount(account);
order.setSecurity(security);
order.setQuantity(orderQuantity);
order.setSide(Side.BUY);
getOrderService().sendOrder(order);

The associated Entities (i.e. strategy, account and security) can be retrieved via the LookupService.

Sending an order using Order Value Objects looks like this:

MarketOrderVO order = MarketOrderVOBuilder.create()

.setStrategyId(strategyId)
.setAccountId(accountId)
.setSecurityId(securityId)
.setQuantity(orderQuantity)
.setSide(Side.BUY)
.build();
getOrderService().sendOrder(order);

Sending of AlgoTrader orders is currently only supported via Order Entities. Creating and sending an AlgoOrder looks like this:

SlicingOrder order = new SlicingOrder();

order.setStrategy(strategy);
order.setAccount(account);
order.setSecurity(security);
order.setQuantity(orderQuantity);
order.setSide(Side.BUY);
order.setMinQuantity(BigDecimal.valueOf(10));
order.setMaxQuantity(BigDecimal.valueOf(100));
order.setMinVolPct(0.01);
order.setMaxVolPct(0.1);
order.setMinDuration(1);
order.setMaxDuration(5);
order.setMinDelay(1);
order.setMaxDelay(5);
getOrderService().sendOrder(order);

As AlgoOrders typically have a lot of parameters (e.g. minQuantity, maxQuantity for the SlicingOrder) it is possible to save a set of settings using the OrderPreference Entity. The following OrderPreference SLICING is contained within the db-samples (/algotrader-core/src/main/resources/db-samples/mysql/mysql-data.sql):

INSERT INTO `order_preference` (`ID`, `NAME`, `ORDER_TYPE`, `DEFAULT_ACCOUNT_FK`, `VERSION`) VALUES
  (201,'SLICING','SLICING',100,0);

INSERT INTO `property` (`ID`, `NAME`, `PERSISTENT`, `INT_VALUE`, `DOUBLE_VALUE`, `TEXT_VALUE`, `PROPERTY_HOLDER_FK`, `VERSION`) VALUES 
  (37,'minVolPct',1,NULL,0.2,NULL,201,0),
  (39,'maxVolPct',1,NULL,1,NULL,201,0),
  (40,'maxQuantity',1,20,NULL,NULL,201,0),
  (41,'minDuration',1,NULL,1,NULL,201,0),
  (42,'maxDuration',1,NULL,2,NULL,201,0),
  (43,'minDelay',1,NULL,2,NULL,201,0),
  (44,'maxDelay',1,NULL,3,NULL,201,0);

The OrderPreference SLICING defines default settings for the Slicing Order. Through the column DEFAULT_ACCOUNT_FK it is also possible to define a default account for the AlgoOrder. With this information available in the database an order can now be created as follows:

Order order = getOrderService().createOrderByOrderPreference("SLICING");

order.setStrategy(strategy);
order.setSecurity(security);
order.setQuantity(orderQuantity);
order.setSide(Side.BUY);
getOrderService().sendOrder(order);

The sendOrder method is responsible for invoking the broker / exchange specific method sendOrder of the SimpleOrderExecService. The method sendOrder is contained within the generic SimpleOrderExecService, where it is marked abstract, so it will have to be implemented by every broker / exchange specific subclass.

The broker / exchange specific SimpleOrderExecService will create the broker / exchange specific order, assign an intId if none has been assigned yet and send the order to the broker / exchange.

After sending the Order to the broker / exchange, the order object is propagated to the AlgoTrader Server Esper service instance (running inside the AlgoTrader Server) as well as to the Esper service instance of the corresponding strategy (where potential actions like cancel order or modify order can be executed).

Open orders are kept in an internal order book until their full execution or cancellation. Completed orders remain in the book and are accessible through OrderService until evicted. Algotrader evicts completed orders at 24:00 local time daily by default. One can also manually evict orders by calling OrderService#evictExecutedOrders() method.

The actual exchange an Order is sent to will be retrieved from the associated Security/SecurityFamily. Alternatively it is possible to assign an Exchange to an Order Entity or Order Value Object directly.

Even though the Order Entity already contains commonly used properties like side, quantity, time-in-force, etc. it is possible to attach additional arbitrary properties to an Order. Order properties have a name, a value and a type.

Order properties of type INTERNAL are kept inside the system and are not propagated to external brokers.

If the type of an Order property is FIX it is assigned to an outgoing Fix order as an additional fix tag. It is therefore mandatory that the name of the order property is a number (representing the fix tag).

If the type of an Order property is IB the system will try to find an IB order field corresponding to the IB order property name. In case no matching field is found the order property is added as an AlgoParams)

An internal order property can be attached to an order as follows:

order.addProperty("test", "XYZ", OrderPropertyType.INTERNAL);

An Fix order property can be attached to an order as follows:

order.addProperty("4000", "XYZ", OrderPropertyType.FIX);

An IB order property can be attached to an order as follows:

order.addProperty("faGroup", "group1", OrderPropertyType.IB);

Note

OrderProperties are only supported on Order Entities but not on Order value objects.

Whenever order status events and fills are received back from the broker / exchange, OrderStatus and Fill objects / events are created and propagated to the AlgoTrader Server Esper service Instance.

The Fill events trigger the createTransaction method of the TransactionService which will create a Transaction object (a persistent Record in the database) based on the Fill. In addition the Fill and corresponding Transactions are also propagated to the strategy, where actions can be taken upon.

Like Fills and Transactions the OrderStatus event will also be propagated to the corresponding strategy.

The statement LOG_TRANSACTION_SUMMARY of the module-trades.epl is responsible for collecting all OrderStatus events for an order and produce one combined log statement.

The internal order book is updated upon every OrderStatus event (e.g. increase filledQuantity & reduce remainingQuantity). Once the Order is fully executed, it is evicted from the order book.

If an order does not receive either an Acknowledgment or Fill within a configurable time period (default: 1 sec) after sending the Order, an Exception is thrown, as there might be a problem with the broker / exchange connection. This is enforced by the NOTIFY_MISSING_ORDER_REPLY statement which can be turned of by the following VM argument:

-Dstatement.notifyMissingOrderReply=false

Once all fills corresponding to an Order are fully persisted an OrderCompletionVO event is generated and propagated to the Strategy. By the time an OrderStatus event is received by the strategy, corresponding database activity might not have been completed yet. However by the time an OrderCompletionVO event is received, it is guaranteed that all database activity has been completed. It is therefore save to invoke any sort of the database lookup at this time. For further details see Section 11.4.8, “Callbacks”.

intId is the internally assigned order identifier whereas extId is the id assigned by the external broker / exchange.

In general the internal order identifier has the following format:

Example: lmax1.1

By default AlgoTrader automatically assigns an IntId value to all outgoing orders. Open and executed orders can be identified and looked up by their IntId.

Especially when using a Section 11.4.8.2, “Trade callback” it is necessary to generate and assign an IntId value to the order prior to submitting it to the order service. The OrderService#getNextOrderId() method can be used to generate a unique IntId value per session associated with an Account record.

String orderId = getOrderService().getNextOrderId(order.getClass(), accountId);


order.setIntId(orderId);
engine.addTradeCallback(Collections.singleton(orderId), (strategyName, orderStati) -> {
    ...
});
getOrderService().sendOrders(orders);

Note

Please note that care must be taken when using OrderService#getNextOrderId() with the IB order service. The IB native interface expects orders to be sent with their order ids in ascending order. The Class IBOrderIdSynchronizer is responsible to make sure order ids are actually in ascending order. In case an order id is skipped the IBOrderIdSynchronizer will wait for up to maxOrderSyncTime milliseconds for the order with the correct order id to arrive.

In the electronic trading domain there are different ways to identify a security, some of which are:

Different Brokers employ different types of Symbology to identify a security. For this purpose AlgoTrader provides the notion of SymbologyResolver which is responsible for assigning appropriate information to outgoing broker communication. These SymbologyResolvers can be extended on a per broker basis.