Skip to main content

Trading

Order execution simulation

Our test environment simulates multiple real life scenarios to facilitate debugging.

  • Orders with a symbol that start with “AA” will be fully filled. Limit orders execute at the price specified on the order, market orders execute at $50.00
  • Orders with a symbol not starting with the letters “AA” will remain open and would be available to cancel replace later.
  • Orders with a symbol starting with “PAR” will be partially filled to half of the requested quantity.
  • Orders with a symbol starting with the letters “BUST” will be filled and then the fill will be immediately busted.
  • Orders with a symbol starting with “CORRECTP” in them will be filled and then corrected with the price of +$1.00 of the initial fill price.
  • Orders with a symbol starting with “CORRECTQ” will be filled and then corrected with the filled quantity to -10 of the initially filled quantity.

Sending new equity orders

The method to send equity orders

public async Task IClient.PlaceAsync(
long orderId,
int quantity,
long price,
Side side,
string symbol,
string route,
OrderOptions options)

Relevant callback events

void ICallback.OnOrderAck(long eventId, long orderId, long limeOrderId,
AckOptions options);

void ICallback.OnOrderReject(long eventId, long orderId, string reason);

void ICallback.OnFill(long eventId, long orderId, Side side, int liquidity,
long fillPrice, int quantityFilled, int quantityLeft,
DateTime transactTime, string symbol, FillOptions options)

Use PlaceAsync method to create a new equity order.

parameterdescription
long orderIda unique id generated by client. Uniqueness must be maintained within the trading day. An order with duplicate id will be rejected.
int quantityquantity of the order
long priceorder limit price scaled to 1/100 of a cent. For example, value of $40.52 should be represented as 405200. The value of 0 indicates a Market order.
Side sideBuy, Sell, SellShort or BuyToCover
string symbolsecurity Symbol
string routeroute name known to Lime

As soon as Lime Trading Server receives the order it assigns a lime order id and sends an acknowledge event back to the client. OnOrderAck method on your ICallback instance receives both orderId and limeOrderId. If the acknowledge has never been called the client can assume that the order has never been received by Lime. Otherwise, in case of any errors the client receives an OnOrderReject. After the acknowledgement the order becomes active and can receive one or more OnFill events.

Sending new option orders

// Generating a unique order id as unix timestamp.
// Note that this does not necessarily guarantee uniqueness if you send more than one order per millisecond
var orderId = (long)(DateTime.Now - new DateTime(1970, 1, 1)).TotalMilliseconds;

// Create an option Call on underlying symbol PAR, expiring tomorrow, strike price $170.00
// The strike price is scaled to 1/1000 of a dollar.
var option = USOptionsSymbol.Call("PAR", DateTime.Now.AddDays(1), 170000);

// Buy to open 50 contracts at $120.00
await client.PlaceUSOptionsAsync(orderId, 50, 1200000, Side.Buy, PositionEffect.Open,
option, "ARCP");

Relevant callback events

void ICallback.OnOrderAck(long eventId, long orderId, long limeOrderId,
AckOptions options);

void ICallback.OnOrderReject(long eventId, long orderId, string reason);

void ICallback.OnUSOptionsFill(long eventId, long orderId, Side side,
int liquidity, long fillPrice, int quantityFilled, int quantityLeft,
DateTime transactTime, USOptionsSymbol symbol, FillOptions options)

To create an option order, use PlaceUSOptionsAsync. The general behaviour and parameters are essentially the same as for equity order

parameterdescription
long orderIda unique id generated by client. Uniqueness must be maintained within the trading day. An order with duplicate id will be rejected.
int quantitynumber of contracts
long priceorder limit price scaled to 1/100 of a cent. For example, value of $40.52 should be represented as 405200. The value of 0 indicates a Market order.
Side sideBuy, Sell. Note that SellShort and BuyToCover sides are not applicable to options.
PositionEffect positionEffectOpen or Close. The client is expected to track the positions and send Open when buying or selling to open, or Close when selling or buying to close an existing position
USOptionsSymbol symbola USOptionsSymbol structure describing an options contract.
- string underlying - is the root symbol of the option
- DateTime expiration - the contract expiration date
- int strike - contract strike price. Unlike the limit price where the value is scaled to 1/10000 of a dollar, the strike price is scaled to 1/1000 of a dollar
- USOptionType type - Put or Call
string routeroute name known to Lime

Cancelling orders

await client.CancelAsync(id);
await client.CancelAllAsync(id);

Related callback events

void ICallback.OnCancelAck(long eventId, long orderId);
void ICallback.OnCancelReject(long eventId, long orderId, string reason);

There are multiple ways to cancel an order.

You need to call CancelAsync method passing its id to cancel a specific order. On successul cancellation, callback receives an OnCancelAck event. In case of an error the callback receives an OnCancelReject including a human-readable message explaining he reason. The most common reason is that requested order is no longer active. It is either cancelled or filled by the time the cancellation is requested. Another common mistake is a wrong order id so that lime trading server can't find the requested order at all.

There is also CancelAllAsync that allows cancel all active orders at once. The client receives cancellation acknowledgment events on each of the cancelled orders. In case if no orders have been active the client receives nothing.

Anoher common practice is to instruct Lime to cancel all orders in case of connectivity issue. To do that, the client has to specify cancelOnDisconnect parameter on ConnectAsync.

Replacing orders

You can cancel an order and replace it with a new order in one call. On most exchanges this is equivalent to actually cancelling the order and sending a new one. It gives the order a new position on the execution queue at exchanges's matching engine. The exception is when order quantity is decreased with same limit price, in this case exchanges amend the order without losing its place on the queue.

public async Task ReplaceAsync(
long originalOrderId, long orderId, int newQuantity, long newPrice, ReplaceOptions options);
long originalOrderId

Required. An existing open order to be replaced.

long orderId

Required. The new order id.

int newQuantity

Required. The new quantity of the order.

long newPrice

Required. The new limit price of the order. Market orders can not be replaced.

ReplaceOptions options

Optional information for a replace request

ReplaceOptions structure

OptionDescription
int ShortSaleAffirmLongQuantityThis option is required for certain accounts and affirms that the client has the given long position in the security being traded. This option can only be set for orders which are short-sales. The value must be greater than zero.
int MinQuantityMinimum quantity of an order to be executed, only valid for specific destinations.
int MinimumTriggerVolMinimum Trigger Volume tag, valid for specific destinations and order types.

On succesful replace, callback receives OnReplaceAck with the new order id. The previous order is considered Cancelled. Otherwise, OnReplaceReject is called with rejection reason and the previous order stays unaffected. One of the most common reasons of rejecting a replace request is when the original order has already been filled or cancelled.

void ICallback.OnReplaceAck(long eventId, long origOrderId, long orderId,
long limeOrderId, AckOptions options);

void ICallback.OnReplaceReject(long eventId, long origOrderId, long orderId,
string reason);

Busted and corrected orders

There is a rare case when an exchange would need to handle an error and correct a previously executed fill. They can either bust the fill and after that send a new execution event, or they can send a correction event amending executed price or quantity. The trade to bust or correct is identified by its FillOptions.ExecId.

void ICallback.OnBust(long eventId, long orderId, Side reversedSide,
long bustedPrice, int quantityBusted, int quantityLeft,
DateTime transactTime, string symbol, FillOptions options);

void ICallback.OnUSOptionsBust(long eventId, long orderId, Side reversedSide,
long bustedPrice, int quantityBusted, int quantityLeft,
DateTime transactTime, USOptionsSymbol symbol, FillOptions options);

void ICallback.OnCorrect(long eventId, long orderId, Side side,
long newFillPrice, int newFilledQuantity, int quantityLeft,
DateTime transactTime, string symbol, FillOptions options);

void ICallback.OnUSOptionsCorrect(long eventId, long orderId, Side side,
long newFillPrice, int newFilledQuantity, int quantityLeft,
DateTime transactTime, USOptionsSymbol symbol, FillOptions options);