9 Specialized trade orders

Several specialized order types are supported by IBMatlab, each of which has dedicated parameters for configuration. These order types include VWAP (best effort), TWAP, bracket orders, automated orders, combo orders, and options exercise/lapse.

9.1 VWAP (best-effort) orders

When the order Type is ‘VWAP’ (the best-effort type, since the guaranteed type has Type='GuaranteedVWAP'), IB treats the order as a Market order with a VWAP algo strategy.94 IBMatlab enables specifying the algo strategy’s properties, as follows:

Parameter

Data type

Default

Description

Type

String

'LMT'

Set to 'VWAP' for this IBAlgo type

MaxPctVol

number

0.1=10%

Percent of participation of average daily volume up to 0.5 (=50%).

StartTime

String

'9:00:00 EST'

Format: 'YYYYMMDD hh:mm:ss TMZ' (TMZ is optional)

EndTime

String

'16:00:00 EST'

(same as StartTime above)

AllowPastEndTime

integer or logical flag

1=true

If true, allow the algo to continue to work past the specified EndTime if the full quantity has not been filled.

NoTakeLiq

integer or logical flag

0=false

If true, discourage the VWAP algo from hitting the bid or lifting the offer if possible.

SpeedUp

integer or logical flag

0=false

If true, compensates for the decreased fill rate due to presence of limit price.

MonetaryValue

number

0

Cash quantity

Here is an example for specifying a best-effort VWAP trade order:

orderId = IBMatlab('action','SELL','symbol','GOOG','quantity',10,...
'type','VWAP','limitPrice',600,'MaxPctVol',0.3,...
'StartTime','20120215 10:30:00 EST', ...
'EndTime', '10:45:00 EST', ...
'AllowPastEndTime',false, ...
'NoTakeLiq',true);

When we run the command above in Matlab, we see the following in IB’s TWS:

TWS VWAP

Note that IB automatically routes the trade to its internal servers (IBALGO) rather than directly to the relevant exchange as it would do in most other cases. Also note that the VWAP order is NOT guaranteed to execute. Best-effort VWAP algo orders result in lower commissions than the Guaranteed VWAP, but the order may not fully execute and is not guaranteed, so if you need to ensure this, use Guaranteed VWAP.

StartTime and EndTime dictate when the VWAP algo will begin/end working, regardless of whether or not the entire quantity has been filled. EndTime supersedes the TIF (time in force) parameter. Note that the order will automatically be cancelled at the designated EndTime regardless of whether the entire quantity has filled unless AllowPastEndTime=1. If an EndTime is specified, then set AllowPastEndTime=1 (or true) to allow the VWAP algo to continue to work past the specified EndTime if the full quantity has not been filled.

Note: If you specify and StartTime and EndTime, TWS confirms the validity of the time period using yesterday’s trading volume. If the time period you define is too short, you will receive a message with recommended time adjustments.

In the example above, note the optional date (20120215) in StartTime. In the EndTime parameter no date was specified so today’s date will be used, at 10:45 EST.

The time-zone part is also optional, but we strongly recommend specifying it, to prevent ambiguities. Only a few major time zones are accepted; you can always convert a time to one of these time zones. The list of IB-supported time-zones is given below:95

Time zone supported by IB

Description

GMT

Greenwich Mean Time

EST

Eastern Standard Time

MST

Mountain Standard Time

PST

Pacific Standard Time

AST

Atlantic Standard Time

JST

Japan Standard Time

AET

Australian Eastern Standard Time

Setting the NoTakeLiq parameter value to true (or 1) may help to avoid liquidity-taker fees, and could result in liquidity-adding rebates. But it may also result in greater deviations from the benchmark and partial fills, since the posted bid/offer may not always get hit as the price moves up/down. IB will use best efforts not to take liquidity, however, there will be times that it cannot be avoided.

VWAP orders are treated as LMT orders so the LimitPrice parameter is mandatory.96

Note: IB only enables VWAP algo orders for US equities on live accounts (i.e., not on paper-trading accounts97).

9.2 TWAP (best-effort) orders

When the order Type is ‘TWAP’, IB treats the order as a Limit order with a TWAP algo strategy.98 IBMatlab enables specifying the algo strategy’s properties, as follows:

Parameter

Data type

Default

Description

Type

string

'LMT'

Set to 'TWAP' for this IBAlgo type

StrategyType

string

'Marketable'

One of:

'Marketable' (default)

'Matching Midpoint'

'Matching Same Side'

'Matching Last'

StartTime

string

'9:00:00 EST'

Format: 'YYYYMMDD hh:mm:ss TMZ' (TMZ is optional)

EndTime

string

'16:00:00 EST'

(same as StartTime above)

AllowPastEndTime

integer or logical flag

1=true

If true, allow the algo to continue to work past the specified EndTime if the full quantity has not been filled.

Note: StartTime, EndTime and AllowPastEndTime were described in §9.1.

Here is an example for specifying a TWAP trade order:

orderId = IBMatlab('action','SELL', 'symbol','GOOG', 'quantity',10,...
'type','TWAP', 'limitPrice',600, ...
'StrategyType','Matching Last', ...
'StartTime','20120215 10:30:00 EST', ...
'EndTime', '10:45:00 EST', ...
'AllowPastEndTime',false);

Note that, as with VWAP, IB automatically routes the trade to its internal servers (IBALGO) rather than directly to the relevant exchange as it would do in most other cases. Also note that the TWAP order is NOT guaranteed to execute. The order will trade if and when the StrategyType criterion is met.

Note: IB only enables TWAP algo orders for US equities.

9.3 Bracket (child) orders

Bracket orders are trades which aim to limit losses while locking-in profits, by sending two opposite-side child orders to offset a parent order.99 This mechanism ensures that the child orders are made active only when the parent order executes.

Both of the bracket child orders have the same amount as the parent order, and belong to the same OCA (One-Cancels-All) group, so that if one of the child orders is triggered and gets executed, the opposing order is automatically cancelled. Similarly, canceling the parent order will automatically cancel all its child orders.

Buy orders are bracketed by a high-side sell Limit (Type='LMT') order and a low-side sell Stop (Type='STP') order; Sell orders are bracketed by a high-side buy Stop order and a low side buy Limit order.

In IB-Matlab, brackets can only be assigned to parent Buy or Sell orders having Type='LMT' or 'STPLMT'. Specifying bracket orders is very simple, using the BracketDelta parameter. This parameter (default=[] = empty) accepts a single number value or an array of two numeric values, which specify the offset from the parent order’s LimitPrice:

If BracketDelta is a 2-value array [lowerDelta,upperDelta], then lowerDelta is used as the offset for the lower child, and upperDelta is used for the upper child. The corresponding child order limits will be set to LimitPrice-lowerDelta and LimitPrice+upperDelta, respectively.

If BracketDelta is a single (scalar) value, then this value is used as offset for both child orders: LimitPrice-offset and LimitPrice+offset, respectively.

IBMatlab returns the orderId of the parent order; the child orders have order IDs that are orderId+1 and orderId+2, respectively.

For example, the following trade order:

parentOrderId = IBMatlab('action','BUY', 'symbol','GOOG', ...
'quantity',100, 'type','LMT', ...
'limitPrice',600, 'BracketDelta',[20,50]);

Will result in the following situation in IB:

TWS bracket order

In this screenshot, notice that the parent order is shown as active (blue; IB status: “Order is being held and monitored”) at the bottom. This order has a Last-Key value of “4” and is a simple Buy at Limit 600 order.

The child orders are shown above their parent as inactive (red; IB status: “Waiting for parent order to fill”). These orders have type=LMT (for the 650 take-profit order) and STP (for the 580 stop-loss order). Note that the child orders have a Last-Key value that derives from their parent (4.2, 4.1 respectively) and the same OCA group name, which is automatically generated based on the order timestamp.

It is possible to specify child bracket orders of different types than the default LMT and STP. This can be done using the BracketTypes parameter. For example, to set an upper bracket of type MIT (Market-If-Touched) rather than LMT for the preceding example, we could do as follows:

parentOrderId = IBMatlab('action','BUY', 'symbol','GOOG', ...
'quantity',100, 'type','LMT', ...
'limitPrice',600, 'BracketDelta',[20,50], ...
'BracketTypes',{'STP','MIT'});

TWS bracket order2

Another method to achieve this modification would be to use the relevant child order ID (which is parentOrderId+2 for the upper child) and modify its type from LMT to MIT (see §10.2 below for details).

The following parameters specifically affect bracket orders:

Parameter

Data type

Default

Description

BracketDelta

number

[]=empty

Price offset for stop-loss and take-profit bracket child orders.

Note: BracketDelta may be a single value or a [lowerDelta,upperDelta] pair of values

Note: value(s) must be positive:
- low bracket will use limitPrice – lowerDelta
- high bracket will use limitPrice + upperDelta

BracketTypes

cell array of 2 strings

Buy: {'STP', 'LMT'}

Sell: {'LMT', 'STP'}

Types of child bracket orders.

The first string in the cell array defines the order type for the lower bracket; the second string defines the order type for the upper bracket.

See related BracketDelta parameter above.

As an alternative to using IBMatlab’s BracketDelta and BracketTypes, users can also create child orders directly, thereby creating non-standard bracket setups, using the ParentId, OCAType and OCAGroup parameters. The Transmit parameter (§9.6) is also typically used, to ensure that the parent order is not transmitted before the child orders are attached.

For example, the following code snippet creates a parent order with 3 child orders: a take-profit order, a stop-loss order, and an end-of-day exit order:100

% First create (but do not transmit) the parent order
parentId = IBMatlab('action','BUY', 'symbol','GOOG', ...
'quantity',100, 'type','LMT', ...
'LimitPrice',600, 'transmit',false);

% Attach a take-profit child order
takeProfitId = IBMatlab('action','SELL', 'symbol','GOOG', ...
'quantity',100, 'type','MIT', 'AuxPrice',650,...
'ParentId'
, parentId, ...
'OCAType',3 ,'OCAGroup','abc #123');

% Attach a stop-loss child order
stopLossId = IBMatlab('action','SELL', 'symbol','GOOG', ...
'quantity',100, 'type','STP', 'AuxPrice',580,...
'ParentId'
, parentId, ...
'OCAType',3 ,'OCAGroup','abc #123');

% Attach an end-of-day exit child order
eodExitId = IBMatlab('action','SELL', 'symbol','GOOG', ...
'quantity',100, 'type','MOC', ...
'ParentId', parentId, ...
'OCAType',3 ,'OCAGroup','abc #123');

% Pause a bit to enable IB time to process the orders
pause(0.5);

% Transmit the modified parent order
IBMatlab('action','BUY', 'orderId',parentId, 'transmit',true, ...
'symbol','GOOG', 'quantity',100, ...
'type','LMT', 'LimitPrice',600);

???

9.4 Automated orders

Automated orders are similar to orders of types REL and TRAIL. The idea is to modify a Limit order’s LimitPrice based on instantaneous market bid and ask quotes plus (or minus) a certain number of security tick value. At a certain point in time, the order, if not fulfilled or cancelled by then, can automatically be transformed from LMT to some other type (e.g., MKT).

IBMatlab implements automated orders using a timer that periodically checks the latest bid/ask quotes for the specified security and modifies the order’s LimitPrice (and possibly the order Type) accordingly.

Unlike IB’s REL and TRAIL order types (and their variants, e.g., TRAIL MIT etc.), which update the LimitPrice continuously, IBMatlab’s automated orders are only updated periodically. This could be problematic for highly-volatile securities: in such cases users should use IB’s standard REL and TRAIL. However, for low-volatility securities, the flexibility offered by IBMatlab’s automated orders could be useful.

The following parameters affect automated orders in IBMatlab:

Parameter

Data type

Default

Description

LimitBasis

string

(none)

Either 'BID' or 'ASK'. LimitBasis cannot be used together with LimitPrice.

LimitDelta

integer

0

Units of the security’s minimal tick value

LimitBounds

[number, number]

[0,inf]

The LimitPrice will only fluctuate between the specified lower & upper bounds

LimitRepeatEvery

number

0

Update timer period in seconds

LimitPause

number

0

Update timer suspend time in seconds

LimitUpdateMode

number

0

Mode of the periodic LimitPrice update:

0: LimitPrice increases or decreases based on the latest market bid/ask price

1: LimitPrice only increases; if market price decreases, LimitPrice remains as-is

-1: LimitPrice only decreases; if the price increases, LimitPrice remains as-is

LimitChangeTime

string

(now+
10 hrs
)

Time at which to change the order Type automatically, if it was not fulfilled or cancelled by then. Format: 'YYYYMMDD hh:mm:ss' local time

LimitChangeType

string

'MKT'

The new order type to be used at LimitChangeTime

Tick

number

0

Override the security’s reported tick value, used by LimitDelta. This is useful for securities/exchanges that do not report a valid tick value in market queries (see §5.1).

IBMatlab uses Matlab timers for the implementation of automated orders having LimitRepeatEvery > 0. These timers invoke their callback function once every LimitRepeatEvery seconds. In each invocation, the current market data for the security is checked against the specifications (LimitUpdateMode, LimitBounds etc.). If it is determined that the trade order should be modified, then an update command is sent to the IB server with the new LimitPrice (see §10.2 below). This process could take some time and therefore it is strongly suggested to use a LimitRepeatEvery value larger than 5 or 10 [secs], otherwise Matlab might use a large percent of its CPU time in these timer callbacks. Each automated order uses an independent timer, so having multiple concurrent automated orders would only exasperate the situation. Therefore, the more such concurrent orders you have, the longer LimitRepeatEvery should be.

Note: using IBMatlab’s automated orders, implied by setting a non-empty LimitBasis parameter value, automatically sets the order type to LMT, regardless of the order Type requested by the user. LimitPrice cannot be used together with LimitBasis.

For example, the tick value for GOOG is 0.01. To send a Limit BUY order, which is updated to BID – 2 ticks (i.e., BID – 0.02) every 15 seconds, run the following:

orderId=IBMatlab('action','BUY', 'symbol','GOOG', 'quantity',100,...
'type','LMT', 'LimitBasis','BID',...
'LimitDelta',-2, 'LimitRepeatEvery',15);

When trying to use the automated orders feature, you may discover that the limit price is not updated although the market price moves up or down. In most likelihood, this is due to the tick price not being available for some reason, and the simple solution is to specify it directly using the Tick parameter:

orderId=IBMatlab('action','BUY', 'symbol','GOOG', 'quantity',100,...
'type','LMT', 'LimitBasis','BID', 'tick',0.01,...
'LimitDelta',-2, 'LimitRepeatEvery',15);

The LimitPause parameter enables a suspension of the order for the specified duration between each timer invocation. At the beginning of each suspension, the order is cancelled. At the end of each suspension, the order is resubmitted with updated LimitPrice and Quantity (depending on the number of executed Quantity until that time). For example, if LimitRepeatEvery=15 and LimitPause=3, then the order will be active between t=0 and t=15, then again between t=18 and t=33, then again between t=36 and t=51, and so on.

High frequency traders often game REL and various types of pegged orders, e.g., by temporarily causing price to move up or down such that these orders trigger at less than optimal prices. Order delays reduce this possibility, as temporary price movements may revert before the order is re-released. The regular periodic update feature (LimitRepeatEvery) helps in this regard, but using LimitPause would increase the possibility of price improvement (e.g., for a buy order the price could drop below the original bid).

9.5 Combo orders

IB enables traders to trade a spread of securities as a single atomic combination (combo) order. For example, a trader might trade a calendar spread of some security options or futures, e.g. Sell November, Buy December. Each of these securities (legs) is treated separately, but the combination is treated as a single entity. Combo-orders typically improve trading certainty, reduce risk of partial or mis-executions, and reduce the trading costs significantly compared to trading the securities separately.

To use combo-trades in IBMatlab, specify the leg parameters (Symbol, LocalSymbol, SecType, Exchange, Currency, Multiplier, Expiry, Strike, and Right) in a cell array wherever the different legs have different values. In addition, you must specify the ComboActions parameter:

orderId = IBMatlab('action','buy', 'exchange','CFE', 'quantity',1, ...
'SecType','FUT', 'LocalSymbol',{'VXZ2','VXX2'}, ...
'ComboActions',{'Buy','Sell'})

Alternatively, you could use cell arrays also for the fields that are the same for all legs. The following is equivalent to the command above:

orderId = IBMatlab('action','buy', 'exchange',{'CFE','CFE'}, ...
'quantity',1, 'SecType',{'FUT','FUT'}, ...
'LocalSymbol',{'VXZ2','VXX2'}, ...
'ComboActions',{'Buy','Sell'})

The same syntax can be used for querying the market data of a specific combo:

data = IBMatlab('action','query', 'exchange','GLOBEX', ...
'secType','FUT', 'localSymbol',{'ESZ2','ESH3'}, ...
'ComboActions',{'Sell','Buy'}

Note that querying market data for a combo might well return negative prices. For example, in the specific query example above, the following data was received:

data =
reqId: 230455081

reqTime: '26-Oct-2012 04:24:22'

dataTime: '26-Oct-2012 04:24:23'

dataTimestamp: 7.3517e+05

ticker: ''

bidPrice: -6.8500

askPrice: -6.7500

bidSize: 748

askSize: 287

open: -1

close: -1

low: -1

high: -1

lastPrice: -1

volume: -1

tick: 0.2500

contract: [1x1 struct]
contractDetails: [1x2 struct]

Only instantaneous market bid/ask data is reliably returned for combo queries – the open, close, low, high, lastPrice and volume fields are often returned empty (-1).

IB may rejects combo requests (query/trade), due to a variety of possible reasons:

IB only supports combos for a small subset of securities – generally speaking, US options and futures. For example, Forex is NOT supported as of 2016.

IB will reject a combo that has been incorrectly configured (see details below)

IB will reject a combo if you are not subscribed for real-time quotes for any of its legs.

IB does not support combos on the demo account, only on live and paper-trade accounts.101 The availability of combo functionality may depend on your IB account’s subscription plan and the specific combo that you try to use.

Some combo queries can only be received using streaming quotes (§7.1), but not snapshot quotes (§5.1), due to an IB server bug/limitation. A workaround for this limitation is included in IB-Matlab since version 1.97.

In all such cases, query requests will return -1 data in all data fields, including bidPrice/askPrice; trade order commands will simply be ignored by IB.

Unfortunately, IB does not report an informative error message when a combo trade order or market query is rejected. We are left guessing as to the reason: perhaps one or more legs is incorrectly configured or not supported or not subscribed for real-time data; perhaps the market is closed; etc. Contact IB to check your specific case.

When specifying combo legs, you can specify the optional ComboRatios parameter, as an array of positive values that shall be used to determine the relative weights of the legs. IBMatlab uses default ratios of [1,1], i.e. the same ratio for all legs.102

When specifying combo legs, we need to be aware of exchange limitations. In general combos use the default ratio of 1:1, but in some cases some other ratio is needed. For example, the ComboRatios for the ZN/ZT spread (10-vs-2-year US Treasury-Notes) must be set to 1:2 since the ECBOT exchange does not currently (1/1/2016) support any other ratio. This ratio changes over time: the ratio was 1:2 in early 2013, then changed to 3:5, then 1:2 again.103 If you specify an incorrect ratio, or when the market is closed, IB will send an ICS (Inter-Commodity Spread) error message. For example:

[API.msg2] Invalid ICS spread {360280114, 318}

In cases where you cannot figure out the exact set of parameters for a combo, it might help to try to create the combo directly in TWS: If the combo is supported by TWS then it might also be available to the API (and IBMatlab). But if the combo is not supported by TWS then it will also certainly not work in IBMatlab.

The combo legs must all use the same exchange and generally also the same currency. However, combo legs do not need to have the same underlying security Symbol. If you wish to use a combo spread of two securities with a different symbol, you could use the internal symbol for the spread using the ComboBagSymbol parameter. For example, the ZN/ZT spread has the internal symbol ‘TUT’:104

IBMatlab('action','query', 'SecType','FUT', 'exchange','ECBOT', ...
'ComboBagSymbol','TUT', ... % the spread's symbol is TUT
'LocalSymbol',{'ZN MAR 16','ZT MAR 16'}, ...
'ComboActions',{'Sell','Buy'}, 'ComboRatios',[1,2])

ans = 
              reqId: 576662704
            reqTime: '24-Dec-2015 05:18:49'
           dataTime: '24-Dec-2015 05:18:53'
      dataTimestamp: 7.3632e+05
      lastEventTime: 7.3632e+05
             ticker: ''
           bidPrice: -0.0078
           askPrice: 0.0078
               open: -1
              close: 0
                low: 0.0078
               high: 0.0078
          lastPrice: 0.0078
             volume: -1
             halted: 0
               tick: 0.0078
           contract: [1x1 struct] <= Note: legs info in comboLegs field
    contractDetails: [1x2 struct] <= Note: contractDetails for 2 legs
            bidSize: 592
            askSize: 25
           lastSize: 2
      lastTimestamp: '1450947638'

Sometimes IB fails to return snapshot query data for combos (as for TUT above), due to IB server limitations/bugs. In such cases, using streaming quotes (see Chapter 7) may be a good workaround:

IBMatlab('action','query', 'SecType','FUT', 'exchange','ECBOT', ...
'ComboBagSymbol','TUT', ... % the spread's symbol is TUT
'LocalSymbol',{'ZN MAR 13','ZT MAR 13'}, ...
'ComboActions',{'Sell','Buy'}, 'ComboRatios',[1,2], ...
'QuotesNumber',2);

pause(1.5); % wait a bit for data to be received from IB server

data = IBMatlab('action','query', 'QuotesNumber',-1, ...
'LocalSymbol',{'ZN MAR 13','ZT MAR 13'});

When specifying the spread’s LocalSymbol, be careful to enter all the spaces. For example, the ZN LocalSymbol has 4 spaces between “ZN” and “MAR”. IB is very sensitive about this: if you specify a LocalSymbol that is even slightly incorrect, IB will complain that it cannot find the specified contract. See §14.2 for additional details.

To complete the picture, here’s an example order to purchase a bear spread for 9/2018 E-mini S&P 500 Future Options (SecType='FOP'; note the negative LimitPrice):

orderId = IBMatlab('action','buy', 'exchange','GLOBEX', 'quantity',1,...
'SecType','FOP', 'type','LMT', 'limitPrice',-4, ...
'symbol','ES', 'expiry',201809, 'right','Call', ...
'strike',[2720,2730], 'ComboActions',{'Sell','Buy'})

or alternatively:

orderId = IBMatlab('action','buy', 'exchange','GLOBEX', 'quantity',1,...
'SecType','FOP', 'type','LMT', 'limitPrice',-4, ...
'localSymbol', {'ESU8 C2720', 'ESU8 C2730'}, ...
'ComboActions',{'Sell','Buy'})

The following parameters affect combo orders in IBMatlab:

Parameter

Data type

Default

Description

Symbol

string or cell-array of strings

(none)

The symbol(s) of the underlying leg assets.

LocalSymbol

string or cell-array of strings

''

The local exchange symbol of the underlying leg asset. If left empty, IB tries to infer it from the other parameters.

SecType

string or cell-array of strings

'STK'

One of: 'STK', 'OPT', 'FUT', 'IND', 'FOP' (but not 'CASH' or 'BAG') for the legs.

Exchange

string or cell-array of strings

'SMART'

The exchange that should process the request for the corresponding legs.

Currency

string or cell-array of strings

'USD'

The currency for the corresponding legs.

Multiplier

number

[]

The contract multiplier (for options)

Expiry

string or cell-array of strings

''

'YYYYMM' or 'YYYYMMDD' format, for each of the combo legs.

Strike

number or numeric array

0.0

The strike price (for options) of the corresponding legs.

Right

string or cell-array of strings

''

One of: ‘P’, ‘PUT’, ‘C’, ‘CALL’ for each of the combo legs.

ComboActions

cell-array of strings

{}

Array of corresponding leg actions. For example: {'Sell', 'Buy'}

ComboRatios

numeric array of positive numbers

[1,1]

Array of corresponding leg weights. Any number is accepted – only the relative values matter, so [1,1.5]=[2,3]=[4,6].

ComboBag
Symbol

string

''

The exchange symbol of the combo-bag spread. When left empty, IBMatlab will use the last leg’s LocalSymbol and Symbol for the parent bag contract.

9.6 Setting special order attributes

Most of the important order parameters that are supported by IB are also supported as IBMatlab parameters. However, IB also supports additional properties that in some cases may be important.

For example, we may wish to specify the security identifier (via the contract object’s secIDType and secId properties105), or to specify the All-or-None flag (via the order object’s allOrNone property106).

These properties are not available as IBMatlab parameters, but they can still be specified using the ibConnector Java object returned by IBMatlab as a second output value, as explained in §15 below. The contract and order objects can be created and updated in two alternative ways:

We can use ibConnector to create the initial contract and order Java objects, modify their requested properties, then use ibConnector again to send the order to IB. §15.3 shows a usage example of this.

We can use IBMatlab’s Hold parameter (see §8.1) to prepare the contract and order Java objects, modify their properties, then use ibConnector to send the order to IB. The difference vs. the previous method is that we don’t need to create the contract/order objects – IBMatlab takes care of this for us.

In all cases, we would use the ibConnector.placeOrder function to send the updated contract and order objects to IB for execution. Here is a usage example:107

% Prepare initial contract and order objects using the Hold mechanism
[orderId, ibConnector, contract, order] = ...
IBMatlab(
'action','BUY', 'Hold',true, ...);

% Modify some contract properties
contract.m_secIdType = 'ISIN';
contract.m_secId =
'US0378331005'; % =Apple Inc.
contract.m_multiplier = '100'; % only relevant for option/future

% Modify some order properties
order.m_clearingIntent = 'Away'; % Possible values: IB, Away, PTA
order.m_settlingFirm =
'CSBLO'; % =Credit Suisse Securities Europe
order.m_allOrNone =
true; % set the order to be All-or-None
order.m_sweepToFill = true; % set the order to be Sweep-to-Fill
order.m_orderRef =
'my trading algo'; % user-specified trading note

% Send the modified order to IB
ibConnector.placeOrder(orderId, contract, order);

Note: the order object is only returned from IBMatlab for trading orders (i.e., Action = 'Buy', 'Sell', 'SShort' or 'SLong'), but not other IBMatlab actions.

Some additional order fields that can be set in this manner include:

m_hidden – true for a hidden order routed via the INet (Island) exchange108

m_displaySize –integer >0 for an Iceberg order109

m_volatility – value >0 for specifying option limit price in terms of volatility [percent], typically used together with m_volatilityType [1=daily, 2=annual]

additional contract and order fields are listed in IB’s API documentation110

Note: field names of IB’s Java objects (e.g. contract, order) have a m_ prefix (e.g. contract.m_secId, order.m_orderRef). IB-Matlab v2.19 onward reports such objects as Matlab structs without the m_ prefix (e.g. contract.secId, order.orderRef) when returning data (see §5), but whenever we use the Java objects we need to add the m_ prefix to the field names. In the example above, contract and order are Java objects, so we must use the m_ prefix of field names to modify the Java field values.

When changing an order immediately following creation, IB might reject the request. In such cases, adding a short pause(0.5) normally solves the problem:

[API.msg2] Unable to modify this order as it is still being processed

The Hold and Transmit parameters should not be confused: Hold delays the order in IB-Matlab (you will not see it in TWS); Transmit delays the order within TWS:

hold vs

Using Transmit, orders can be sent to TWS and delayed (not sent for execution), until the user clicks the <Transmit> (or <Cancel>) button. Prepare such orders as follows:

IBMatlab('action','BUY', 'Transmit',false, ...);

This will create the order in TWS without transmitting it. You will see the order in TWS’s API tab with a button to transmit:

???

Right-clicking anywhere in the row will present a menu with additional options:

???

While the order is waiting in TWS for transmission, its attributes can be modified, either directly in TWS, or programmatically (see §10).

9.7 Exercising and lapsing options

To exercise or lapse an option, use Action='exercise' or 'lapse' (respectively). You must specify the quantity of contracts and the exchange (IB’s SMART exchange cannot be used).111 You can also indicate whether to override IB’s default handling action (exercise in-the-money options only). For example:

orderId = IBMatlab('action','exercise', 'symbol','GOOG', ...
'secType','OPT', 'expiry','201509', ...
'multiplier',100, 'strike',600, 'right','C', ...
'quantity',5, 'exchange','AMEX', 'override',true)

Assuming that the information is correct and that I have 5 unlapsed GOOG 9/2015 Call-600 options in my portfolio, then these 5 options will be exercised and turn into 500 shares (5 options * 100 multiplier) of the underlying GOOG, at USD 600 each.

At the time of this writing, GOOG trades at USD 542.34, so the exercise is not in the money and would be rejected if I had not stated Override=true. Because of the override the exercise order is executed at a nominal loss of USD 57.66 (=600-542.34) per share (excluding commissions).

If the option is not in-the-money and you try to exercise without specifying the Override parameter (or if you set the Override value to the default=false), you will receive an error from IB:

[API.msg2] Error processing request: Exercise ignored because option is not in-the-money. {498825899, 322}

If the options do not exist in your portfolio you will receive a different error message:

[API.msg2] Error processing request: No unlapsed position exists in this option in account DU123456. {498752361, 322}

If you have several IB accounts, then the AccountName parameter must be specified, otherwise you will receive yet a different error message:

[API.msg2] Error validating request:-'kd': cause - The account code is required for this operation. {498752362, 321}

You can only lapse an option on its last trading day. If you try to lapse it on a different date, you will receive two separate error messages from IB:

[API.msg2] Order rejected - reason: trade date must match last trade date of the contract {498825901, 201}

[API.msg2] Error processing request: Exercise/Lapse failed due to server rejection {498825901, 322}

Finally, as of the time of this writing, IB only supports exercising/lapsing options, not FOP (future-on-option) or warrants. Customers wishing to exercise or lapse such contracts must submit a manual request ticket to IB.

The following parameters affect exercising/lapsing options in IBMatlab:

Parameter

Data type

Default

Description

Action

string

(none)

Either 'exercise' or 'lapse'.

Symbol

string

(none)

The symbol of the underlying asset.

LocalSymbol

string

''

The local exchange symbol of the option contract. When left empty, IB infers it from Symbol and the other properties.

SecType

string

(none)

Needs to be 'OPT'. IB does not currently allow exercising any other SecType.

Exchange

string

(none)

The exchange that should process the request – cannot be set to 'SMART'.

Currency

string

'USD'

The currency for the option contract.

Multiplier

number

[]

The option contract multiplier.

Expiry

string

''

'YYYYMM' or 'YYYYMMDD' format.

Strike

number

0.0

The strike price of the option contract.

Right

string

''

One of: ‘P’, ‘PUT’, ‘C’, ‘CALL’.

Quantity

integer

0

Number of contracts to exercise or lapse.

Override

integer or logical flag

0=false

0 or false: use default action (exercise in-the-money options only)

1 or true: override the default action

AccountName

string

''

The specific IB account ID to use.
Useful when you handle multiple IB accounts, otherwise leave empty.

9.8 Algorithmic trading orders

In addition to VWAP (§9.1) and TWAP (§9.2), IB-Matlab supports multiple algo-trading strategies, provided by both IB (“IBAlgo”) and 3rd-parties. Some important IBAlgos (Arrival Price,112 Close Price,113 Dark Ice,114 Percentage of Volume,115 Balance Impact/Risk,116 Minimize Impact117) have dedicated IBMatlab convenience parameters; numerous other algos can be specified using a pair of generic parameters.

Algo properties are specified in IBMatlab as follows (Kind: D=dedicated; G=generic):

Parameter

Kind

Data type

Default

Description

Type

D

string

'LMT'

Set to one of the following:

'VWAP' (see §9.1)

'TWAP' (see §9.2)

'ArrivalPx'

'ClosePx'

'DarkIce'

'PctVol'

'BalanceImpactRisk'

'MinImpact'

MaxPctVol

D

number

0.1=10%

Max % participation of average daily volume up to 0.5 (=50%).

PctVol

D

number

0.1=10%

Target % participation of avg daily volume up to 0.5 (=50%).

StartTime

D

string

'9:00:00 EST'

Format: 'YYYYMMDD hh:mm:ss TMZ' (TMZ optional)

EndTime

D

string

'16:00:00 EST'

(same as StartTime above)

AllowPastEndTime

D

integer or logical flag

1=true

If true, allow the algo to continue to work past the specified EndTime if the full quantity has not been filled.

NoTakeLiq

D

integer or logical flag

0=false

If true, avoid hitting the bid or lifting the offer, if possible.

SpeedUp

D

integer or logical flag

0=false

If true, compensate for decreased fill rate due to a limit price.
Only relevant for VWAP algo.

RiskAversion

D

string

‘Neutral’

One of:

'Neutral' (default)

'Get Done'

'Aggressive'

'Passive'

ForceCompletion

D

integer or logical flag

0=false

If true, attempt completion by end of day.

DisplaySize

D

integer

1

The order quantity (size) you want to display to the market. The algo will randomize the size by 50% on either side. Only relevant for DarkIce algo.

MonetaryValue

D

number

0

Cash quantity

AlgoStrategy

G

string

''

Any algo name listed in https://interactivebrokers.github.io/tws-api/algos.html

AlgoParams

G

cell-array

{}

Cell array of name,value pairs. Example: {'MaxPctVol',0.25, 'RiskAversion','Aggressive'}

Note: StartTime, EndTime, AllowPastEndTime, NoTakeLiq, SpeedUp and MonetaryValue were described in §9.1.

Only a few important IBAlgos have dedicated IB-Matlab parameters, listed above. All other strategies/algos are supported by using the AlgoStrategy and AlgoParams parameters, which cover the dedicated convenience parameters as well as many others.

Here is an example for an Arrival Price order using dedicated convenience parameters:

orderId = IBMatlab('action','BUY', 'symbol','GOOG', 'quantity',10, ...
'TIF','Day', 'limitPrice',600, 'type','ArrivalPx',...
'MaxPctVol',0.01, 'RiskAversion','Passive', ...
'StartTime','20120215 10:30:00 EST', ...
'EndTime', '10:45:00 EST', ...
'ForceCompletion',true, 'AllowPastEndTime',false);

And the same Arrival Price order using the generic AlgoStrategy and AlgoParams:

algoParams = {'maxPctVol',0.01, 'riskAversion','Passive', ...
'startTime','20120215 10:30:00 EST', ...
'endTime', '10:45:00 EST', ...
'forceCompletion',true, 'allowPastEndTime',false};
orderId = IBMatlab(
'action','BUY', 'symbol','GOOG', 'quantity',10,...
'TIF','Day', 'limitPrice',600, ...
'algoStrategy','ArrivalPx', 'algoParams',algoParams);

IB regularly adds/modifies algo strategies and their corresponding parameters. Some algo properties (parameters) are only relevant to some algos but not others, and this list is also dynamic. For an up to date listing of the available algos and parameters, visit https://interactivebrokers.github.io/tws-api/algos.html.

IB only enables algo strategy orders for a subset of security types and exchanges. For example, as of December 2019 IBAlgos are limited to US stocks, while QBAlgos are limited to futures. Refer to the specific algo’s documentation for details.

IB supports some algos only in TWS, not via the API. For example, as of December 2019, IB officially supports Fox River algos only in TWS, not the API.118 If you specify such algos in IBMatlab, IB may possibly reject the requested order. When IB adds any new algo provider, algo strategy and/or algo parameter, you can immediately use them in IBMatlab via the AlgoStrategy, AlgoParams parameters.

As with VWAP and TWAP, IB automatically routes all IBAlgo trades to its internal servers (IBALGO), ignoring the specified Exchange. In contrast, all 3rd-party (non-IB) algos require routing the order through the corresponding 3rd-party algo servers: CSFB (Credit-Suisse First Boston) algos119 require setting Exchange='CSFBALGO'; Jefferies algos120 require Exchange='JEFFALGO'; and QB (Quantitative Brokers)121 algos require Exchange='QBALGO'. Here is an example of a CSFB 'Inline' algo order:

algoParams = {'StartTime','20120215 10:30:00 EST', ...
'EndTime', '10:45:00 EST', ...
'ExecStyle','Patient', 'Auction','Default',...
'MinPercent',10, 'MaxPercent',20, 'DisplaySize',100,...
'BlockFinder',false, 'BlockPrice',40,
'MinBlockSize',100, 'MaxBlockSize',100, 'IWouldPrice',35};
orderId = IBMatlab(
'action','BUY', 'symbol','GOOG', 'quantity',10,...
'Exchange','CSFBALGO', ... % note the Exchange
'algoStrategy','Inline', 'algoParams',algoParams);

Additional notes:

As with standard LMT orders, some algo orders are not guaranteed to execute.

Many algos are only available in the live account, and cannot be tested in a paper-trading account. None of the algos are available in IB’s Demo account.

IBAlgo orders cannot use the default TIF value of 'GTC' – use 'Day' instead.

IBAlgo orders are treated as LMT orders, so you must specify the LimitPrice parameter in all IBAlgo orders.122 For better control over the order, avoid using the dedicated convenience algo parameters; use AlgoStrategy and AlgoParams instead. These do not override any order or contract parameter, so you can set (for example) Type='MKT' if you wish.


94 http://interactivebrokers.github.io/tws-api/ibalgos.html#vwap, http://interactivebrokers.com/en/software/tws/usersguidebook/algos/vwap.htm

95 Some additional timezones are also supported, e.g. HKT for Hong-Kong Time. Such timezones are not officially supported and IB may possibly stop accepting them at some point. Also note that the timezone must be specified using a 3-letter acronym, not other notations such as US/Eastern or America/New_York etc. as may be reported by the contract details query (§5.4).

96 IB-Matlab versions prior to 1.92 (July 14, 2017) used MKT orders for the VWAP algo

97 https://ibkrguides.com/clientportal/aboutpapertradingaccounts.htm

98 http://interactivebrokers.github.io/tws-api/ibalgos.html#twap, http://interactivebrokers.com/en/software/tws/usersguidebook/algos/twap.htm

99 http://interactivebrokers.com/en/trading/orders/bracket.php, http://ibkb.interactivebrokers.com/node/1043

100 In this example, OCAType=3 because this is the only OCA type that IB permits with a MOC child order (without the MOC child, you can also use OCA types 1 or 2).

101 https://quant.stackexchange.com/questions/8744/what-is-the-difference-between-the-interactive-brokers-demo-account-and-a-personal-paper-trader-account; https://ibkrguides.com/clientportal/aboutpapertradingaccounts.htm

102 Discussion of combo ratios and limit prices: https://groups.io/g/twsapi/topic/77368761#45604

103 The latest spread ratios on CME can be found here: http://cmegroup.com/trading/interest-rates/intercommodity-spread.html

104 Other similar predefined CME spreads can be found in http://cmegroup.com/trading/interest-rates/intercommodity-spread.html and http://cmegroup.com/trading/interest-rates/files/TreasurySwap_SpreadOverview.pdf

105 https://interactivebrokers.com/php/whiteLabel/Interoperability/Socket_Client_Java/java_properties.htm

106 https://interactivebrokers.com/php/whiteLabel/Interoperability/Socket_Client_Java/java_properties.htm

107 Note that many properties can also be set via direct IBMatlab parameters e.g. SecId, SecIdType, Multiplier, OrderRef.

108 http://interactivebrokers.com/en/trading/orders/hidden.php

109 http://interactivebrokers.com/en/trading/orders/iceberg.php

110 http://interactivebrokers.com/php/whiteLabel/Interoperability/Socket_Client_Java/java_properties.htm

111 http://interactivebrokers.github.io/tws-api/classIBApi_1_1EClient.html#aad70a7b82ad3b5e7ae3e9f0b98dc2a5b

112 http://interactivebrokers.github.io/tws-api/ibalgos.html#arrivalprice, http://interactivebrokers.com/en/index.php?f=1122, http://interactivebrokers.com/en/software/tws/usersguidebook/algos/arrival_price.htm

113 http://interactivebrokers.github.io/tws-api/ibalgos.html#closepx, http://interactivebrokers.com/en/software/tws/usersguidebook/algos/closeprice.htm

114 http://interactivebrokers.github.io/tws-api/ibalgos.html#darkice, http://interactivebrokers.com/en/software/tws/usersguidebook/algos/dark_ice.htm

115 http://interactivebrokers.github.io/tws-api/ibalgos.html#pctvol, http://interactivebrokers.com/en/software/tws/usersguidebook/algos/percentage_of_volume_strategy.htm

116 http://interactivebrokers.github.io/tws-api/ibalgos.html#balanceimpact, http://interactivebrokers.com/en/software/tws/usersguidebook/algos/balance_impact_and_risk.htm

117 http://interactivebrokers.github.io/tws-api/ibalgos.html#minimpact, http://interactivebrokers.com/en/software/tws/usersguidebook/algos/minimize_impact.htm

118 https://interactivebrokers.com/en/software/tws/twsguide.htm#algostop.htm%3FTocPath%3DAlgos%7C_____0; https://interactivebrokers.com/en/index.php?f=4985#thirdy-party-algos

119 https://interactivebrokers.github.io/tws-api/csfb.html

120 https://interactivebrokers.github.io/tws-api/jefferies.html

121 https://interactivebrokers.github.io/tws-api/qbalgos.html

122 IB-Matlab versions prior to 1.92 (July 14, 2017) used MKT orders for the VWAP algo