AlgoTraderAlgoTrader Documentation

Chapter 25. Execution Algos

25.1. Existing Execution Algos
25.2. Development of Execution Algos

AlgoTrader provides several built-in Execution Algos.

SlicingOrder

Splits an order into several slices, where the quantity of each slice is randomized between minVolPct and maxVolPct of the current volume offered at the exchange. In addition minQuantity and maxQuantity restriction can be imposed. If maxVolPct is zero, then the current market volume will not be considered when sizing the order. If maxQuantity is zero, then no maximum quantity will be enforced on top of the market volume restriction. The SlicingOrder will make sure that the remainingQty for the next slice is greater than minQuantity. Maximum quantity rules have precedence over minimum quantity rules

Each order will stay in the market for minDuration to maxDuration seconds (if it is not filled before that). Between each slice there will be a random delay of minDelay to maxDelay seconds. In addition, the SlicingOrder has a sophisticated pricing logic. For a BUY order the first slice will be place 1 tick below the Ask. For a SELL order the first tick will be placed one tick above the Bid. Depending on whether a slice gets filled, the price of the next slice is adjusted. If a slice gets filled, the price of the next slice will be reduced by one tick (for BUY orders) but it will always be at least one tick above the Bid. If the slice does not get filled, the price of the next slice is increased by one tick (for BUY orders) but it will never be higher than the ask. A SlicingOrder can be created and sent as follows :

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);

Alternatively OrderPreferences can be used to create a SlicingOrder.

VWAPOrder

The VWAPOrder seeks to achieve the Volume-Weighted Average price (VWAP). VWAP is a trading benchmark used by many institutional investors. VWAP is calculated by adding up the market value traded for every transaction (price multiplied by number of contracts traded) and then dividing by the total contract traded.

The VWAPOrder retrieves historical prices for the number of days specified in the lookbackPeriod parameter and splits the trading day into buckets with a length in minutes according to the bucketSize parameter. Child orders will be time sliced between minInterval to maxInterval seconds. Optionally startTime (default value: now) and endTime (default value: end of trading day) can be specified. In addition a quantityRandomFactor can be applied to randomize quantities of child orders. The VWAPOrder accepts a maximum participation rate of 50% of the historical volume.

When a VWAPOrder is either fully-executed or cancelled a message containing the average price, the benchmark price as well as the execution duration is logged to the console. A VWAPOrder can be created and sent as follows :

VWAPOrder order = new VWAPOrder();
order.setStrategy(strategy);
order.setAccount(account);
order.setSecurity(security);
order.setQuantity(orderQuantity);
order.setSide(Side.BUY);
order.setStartTime(startTime);
order.setEndTime(endTime);
order.setBucketSize(Duration.MIN_10);
order.setLookbackPeriod(10);
order.setMaxInterval(60);
order.setMinInterval(30);
order.setQtyRandomFactor(0.3);

getOrderService().sendOrder(order);

Alternatively OrderPreferences can be used to create a VWAPOrder.

TargetPositionOrder

The TargetPositionOrder seeks to bring the actual position to an intended target quantity. The TargetPositionOrder starts off by looking up the actual position quantity, calculating the delta between the actual and target quantity and issuing a market order to fill the difference. In many cases the TargetPositionOrder differs little from sending a simple market order. Orders can take some time to fully execute. In the meantime the target position may change. The target quantity of a TargetPositionOrder can be altered at any point of time which will cause the order to re-evaluate its actual state and cancel or modify currently pending order and issue a new order if necessary to match the expected target position. The order also reacts intelligently to stray fills that can occur.

By default TargetPositionOrder is considered to be fully executed once its target position has been reached. The order is then removed from the order book. Often however strategies might want to maintain a particular position over a longer period of time. TargetPositionOrder can be issued with keepAlive attribute set to true to make the order active until explicitly canceled. The order will transition into Status#TARGET_REACHED state once fully executed and will stay there until the target is adjusted or the order is canceled. A TargetPositionOrder can be created and sent as follows :

TargetPositionOrder order = new TargetPositionOrder();
order.setStrategy(strategy);
order.setAccount(account);
order.setSecurity(security);
order.setQuantity(orderQuantity);
order.setSide(Side.BUY);
order.setKeepAlive(true);
order.setTarget(BigDecimal.valueOf(111.1));

getOrderService().sendOrder(order);

Alternatively OrderPreferences can be used to create a TargetPositionOrder.

TrailingLimitOrder

A TrailingLimitOrder submits an order directly to the exchange with a limit price set a fixed distance away from the current market price. The limit price is adjusted relative to the market price when the market moves in favor of the order. The TrailingLimitOrder is typically used when entering a position on an instrument with a Bullish view.

For a BUY order the limit price will be set a specific amount (defined by the trailingAmount parameter) below the current market price. In case the market price rises, the limit price is increased once the specified minimum amount (defined by the increment parameter) is exceeded. If the market price falls, the limit price stays untouched. If the market price falls below the limit price the order will get filled by the exchange (depending on adequate liquidity).

For a SELL order the limit price will be set a specific amount (defined by the trailingAmount parameter) above the current market price. In case the market price falls, the limit price is decreased once the specified minimum amount (defined by the increment parameter) is exceeded. If the market price rises, the limit price stays untouched. If the market price rises above the limit price the order will get filled by the exchange (depending on adequate liquidity).

A TrailingLimitOrder can be created and sent as follows :

TrailingLimitOrder order = new TrailingLimitOrder();
order.setStrategy(strategy);
order.setAccount(account);
order.setSecurity(security);
order.setQuantity(orderQuantity);
order.setSide(Side.BUY);
order.setTrailingAmount(BigDecimal.valueOf(0.5));
order.setIncrement(BigDecimal.valueOf(0.1));

Alternatively OrderPreferences can be used to create a TrailingLimitOrder.

TickwiseIncrementalOrder

Sends the entire Order as one Slice. The price of the order is set according to the current market price. The order is first set at startOffsetTicks ticks above the market (for BUY orders). If the order is not filled within a defined period of time, the price of the order is increased by one tick up to a maximum of endOffsetTicks ticks below the other side of the market.

VariableIncrementalOrder

Sends the entire Order as one Slice. The price of the order is set according to the current market price. The order is first set at startOffsetPct (% of the spread) above the market (for BUY orders). If the order is not filled within a defined period of time, the price of the order is increased by increment (%of the spread) up to a maximum of endOffsetPct (% of the spread) below the other side of the market.

Additional Execution Algos can be added to the system with minimal effort. Execution Algos consist of the following artifacts

  • a subclass of AlgoOrder. See chapter Section 8.1.4, “Order”. An AlgoOrder should be a plain old Java bean and contain no execution logic.

  • an object that represents the state of an algo order execution which needs to subclass AlgoOrderStateVO. Please note that if state objects contains elements that are potentially threading unsafe, access to those elements must be synchronized!

  • an esper module (optional). This module can optionally provide statements to cancel a child order, modify a child order, send the next child order, etc.

  • an implementation of AlgoOrderExecService interface. It is generally recommended to subclass AbstractAlgoOrderExecService and implement its protected methods that represent various algo specific handling logic. The #handleValidateOrder method must implement algo specific order validation logic. The #handleSendOrder, #handleModifyOrder and #handleCancelOrder method must implement algo specific order execution, modification and cancellation logic respectively.

  • a corresponding entry in the ch.algotrader.enumeration.OrderType class.

  • a Spring wiring within ch.algotrader.wiring.core.ServiceWiring.

    Custom AbstractAlgoOrderExecService implementation can also tap into event streams pertaining to the algo order execution. The #handleChildFill and #handleChildOrderStatus methods can used to provide custom handling of fills and status events for child orders executed by the algo and to update its internal state. The #handleOrderStatus method can be used to update the internal state in response to transition of the algo order from one execution phase to another

    In addition the class can implement any additional logic needed in conjunction with custom Esper statements.

    Note

    It is important that AlgoOrderExecService implementations are built to be state-less. They must store all details pertaining to execution of algo orders in their respective state objects.

The OrderService is aware of all AlgoOrderExecService instances declared in the Spring application context of the server process. Custom AlgoOrderExecService implementations also get automatically recognized as long as they are declared in the same application context. The OrderService delegates handling of individual orders to their respective algo service based on the order type. It is important for classes implementing AlgoOrderExecService to correctly implement its #getAlgoOrderType method.