10 Accessing and cancelling open trade orders
10.1 Retrieving the list of open orders
To retrieve the list of open IB orders use Action='orders' or 'open' as follows:
>> data = IBMatlab('action','orders')
data =
1x3 struct array with fields:
orderId
contract
order
orderState
status
filled
remaining
avgFillPrice
permId
parentId
lastFillPrice
clientId
whyHeld
message
This returns a Matlab struct array, where each array element represents a different open order. In this particular case, we see the parent order and two open bracket child-orders from §9.3 above.
You can access any of the orders using the standard Matlab dot notation:
>> data(1)
ans =
orderId: 154410310
contract: [1x1 struct]
order: [1x1 struct]
orderState: [1x1 struct]
status: 'Submitted'
filled: 0
remaining: 100
avgFillPrice: 0
permId: 989560927
parentId: 0
lastFillPrice: 0
clientId: 8981
whyHeld: []
message: [1x162 char]
>> data(2)
ans =
orderId: 154410311
contract: [1x1 struct]
order: [1x1 struct]
orderState: [1x1 struct]
status: 'PreSubmitted'
filled: 0
remaining: 100
avgFillPrice: 0
permId: 989560928
parentId: 154410310
lastFillPrice: 0
clientId: 8981
whyHeld: 'child,trigger'
message: [1x182 char]
Each of the order structs contains the following data fields:123
orderId – this is the ID returned by IBMatlab when you successfully submit a trade order. It is the ID that is used by IB to uniquely identify the trade.
contract – this is a struct object that contains the contract information, including all the relevant information about the affected security
order – this is another struct object that contains information about the specific trade order’s parameters
orderState – this is another struct object that contains information about the current status of the open order. An order can be open with several possible states, and this is reported in this struct’s fields.124
status – indicates the order status e.g., ‘Submitted’, ‘PreSubmitted’, etc.
filled – indicates the number of shares that have been executed in the order
remaining – number of shares remaining to be executed in the order
avgFillPrice – average price of the filled (executed) shares; 0 if no fills
permId – the permanent ID used to store the order in the IB server
parentId – the order ID of the order’s parent order; 0 if no parent
lastFillPrice – last price at which shares in the order were executed
clientId – ID of the client used for sending the order (see §13 below)
whyHeld – specific reasons for holding the order in an open state
message – a detailed message string stating the order’s state. This is basically just a string that contains all the fields above and their values.
For example:
>> data(2).contract
ans =
conId: 30351181
symbol: 'GOOG'
secType: 'STK'
expiry: []
strike: 0
right: '?'
multiplier: []
exchange: 'SMART'
currency: 'USD'
localSymbol: 'GOOG'
primaryExch: []
includeExpired: 0
secIdType: []
secId: []
comboLegsDescrip: []
comboLegs: []
underComp: []
>> data(1).order
ans =
CUSTOMER: 0
FIRM: 1
OPT_UNKNOWN: '?'
OPT_BROKER_DEALER: 'b'
OPT_CUSTOMER: 'c'
OPT_FIRM: 'f'
OPT_ISEMM: 'm'
OPT_FARMM: 'n'
OPT_SPECIALIST: 'y'
AUCTION_MATCH: 1
AUCTION_IMPROVEMENT: 2
AUCTION_TRANSPARENT: 3
EMPTY_STR: ''
orderId: 154410311
clientId: 8981
permId: 989560928
action: 'SELL'
totalQuantity: 100
orderType: 'STP'
lmtPrice: 580
auxPrice: 0
tif: 'GTC'
ocaGroup: '989560927'
ocaType: 3
transmit: 1
parentId: 154410310
(plus many more internal order properties...)
>> data(1).orderState
ans =
status: 'Submitted'
initMargin: Inf
maintMargin: Inf
equityWithLoan: Inf
commission: Inf
minCommission: Inf
maxCommission: Inf
commissionCurrency: 'USD'
warningText: []
Note: in IB-Matlab v2.19 (11/2022) and newer, values of Inf indicate an undefined/uninitialized value; in IB-Matlab v2.18 and older such values were reported as 1.79769313486232e+308 (realmax) or 2147483647 (intmax).
Note: IB warns125 that “It is possible that orderStatus() may return duplicate messages. It is essential that you filter the message accordingly.”
We can filter the results based on a specific OrderId and/or Symbol. For example:
% Filter by order ID
>> data = IBMatlab('action','orders', 'OrderId',154410310)
data =
orderId: 154410310
contract: [1x1 struct]
order: [1x1 struct]
orderState: [1x1 struct]
(etc.)
% Filter by symbol: note that symbol filtering is case insensitive
>> data = IBMatlab('action','orders', 'symbol','goog')
Of course, it is possible that there are no open orders that match the filtering criteria:
>> data = IBMatlab('action','orders', 'symbol','xyz')
data =
[]
We can use the returned data to filter the results by any of the order/contract fields:
data = IBMatlab('action','orders', 'symbol','goog');
for idx = length(data):-1:1 % only report orders having lmtPrice<600
if data(idx).order.lmtPrice>=600, data(idx)=[]; end
end
Note that you can only retrieve (and modify) open orders that were originally sent by your IB-Matlab ClientID. Trades placed directly in TWS, or via another API client that connects to TWS, or by another IB-Matlab connection session with a different ClientID, are not normally accessible. If this limitation affects your work, use a static ClientID of 0, thereby enabling access to all open orders placed by any IB-Matlab session (since they will all have the same ClientID=0) as well as directly on TWS (which uses the same ClientID=0).126 See §13 for additional details on ClientID.
10.2 Modifying open orders
To modify parameters of open orders, we need to first ensure they are really open (duh!). This sounds trivial, but one would be surprised at how common a mistake is to try to update an order that has already been filled or cancelled.
When we are certain that the order is open, we can resend the order with modified parameters, along with the OrderId parameter. The OrderId parameter tells IBMatlab (and IB) to modify that specific order, rather than to create a new order:
[orderId, ibConnector] = IBMatlab('action','BUY','symbol','GOOG',...
'quantity',100,'type','LMT','limitPrice',600);
% Let some time pass...
% If the requested order is still open
if ~isempty(IBMatlab('action','orders', 'OrderId',orderId))
% Send the trade with modified parameters
IBMatlab('action','BUY', 'symbol','GOOG', 'quantity',50, ...
'type','MKT', 'OrderID',orderId);
end
Note: orders placed manually via TWS all have an OrderId of 0, unless we run the following command in Matlab. TWS orders placed from then on will get unique IDs. Naturally, we also need to set ClientId=0 to access the TWS orders (see §10.1):
ibConnector.reqAutoOpenOrders(true); % see §15 for details
10.3 Cancelling open orders
To cancel open orders, we need (as above) to first ensure that they are really open (again, duh!), although in this case it does not really matter so much if we are trying to cancel a non-existing order. The only side-effect will be a harmless message sent to the Matlab command window, no real harm done.
To cancel the trade, simply use Action='cancel' with the specific order ID:
% If the requested order is still open
if ~isempty(IBMatlab('action','orders', 'OrderId',orderId))
% Cancel the requested order
data = IBMatlab('action','cancel', 'OrderID',orderId);
end
To cancel ALL open orders simply discard the OrderId parameter from the command:
data = IBMatlab('action','cancel'); % cancel ALL open orders
In both cases, the returned data is an array of structs corresponding to the cancelled order(s), as described in §10.1 above.
Alternatively, we can use the Java connector object for this (see §15 for details):
% Place an order, return the orderId and the Java connector object
[orderId, ibConnector] = IBMatlab('action','BUY', ...);
% Cancel the order using the underlying Java connector object
ibConnector.cancelOrder(orderId);