IB-Matlab User Guide
IB-Matlab User Guide
Version 1.42 November 27, 2013 Fully compatible with IB version 9.69
Undocumented Matlab
unbelievable features; unbelievable quality; unbelievable cost effectiveness; unbelievable service
Table of Contents
DISCLAIMER ............................................................................................. 3 1 Introduction ............................................................................................... 4 2 Installation................................................................................................. 6 3 Using IBMatlab ......................................................................................... 9 4 Querying account and portfolio data....................................................... 15
4.1 Account information ..................................................................................................... 15 4.2 Portfolio data ............................................................................................................... 16
13 Forcing connection parameters ............................................................. 74 14 Messages and general error handling .................................................... 79 15 Using the Java connector object ........................................................... 82
15.1 Using the connector object ......................................................................................... 82 15.2 Programming interface .............................................................................................. 83 15.3 Usage example ........................................................................................................... 89
DISCLAIMER THIS IB-MATLAB SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO, THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND/OR NONINFRINGEMENT. MUCH EFFORT WAS INVESTED TO ENSURE THE CORRECTNESS, ACCURACY AND USEFULLNESS OF THE INFORMATION PRESENTED IN THIS DOCUMENT AND THE SOFTWARE. HOWEVER, THERE IS NEITHER GUARANTEE THAT THE INFORMATION IS COMPLETE OR ERROR-FREE, NOR THAT IT MEETS THE USERS NEEDS. THE AUTHOR AND COPYRIGHT HOLDERS TAKE ABSOLUTELY NO RESPONSIBILITY FOR POSSIBLE CONSEQUENCES DUE TO THIS DOCUMENT OR USE OF THE SOFTWARE. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, LOSS, OR OTHER LIABILITY, WHETHER IN ACTION OF CONTRACT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE, REGARDLESS OF FORM OF CLAIM OR WHETHER THE AUTHORS WERE ADVISED OF SUCH LIABILITIES. WHEN USING THIS DOCUMENT AND SOFTWARE, USERS MUST VERIFY THE BEHAVIOR CAREFULLY ON THEIR SYSTEM BEFORE USING THE SAME FUNCTIONALITY FOR LIVE TRADES. USERS SHOULD EITHER USE THIS DOCUMENT AND SOFTWARE AT THEIR OWN RISK, OR NOT AT ALL. ALL TRADING SYMBOLS AND TRADING ORDERS DISPLAYED IN THE DOCUMENTATION ARE FOR ILLUSTRATIVE PURPOSES ONLY AND ARE NOT INTENDED TO PORTRAY A TRADING RECOMMENDATION.
1 Introduction InteractiveBrokers (IB, www.interactivebrokers.com) provides brokerage and financial data-feed services. IB customers can use its services using specialized applications (so-called clients) that can be installed on the users computer. These client applications provide a user-interface that enables the user to view portfolio and market information, as well as to issue orders to the IB server. The most widely-used IB client application is TWS (Trader Work Station).1 In addition to TWS, IB provides other means of communicating with its server. A lightweight client application called IB Gateway is installed together with TWS. IB Gateway has no fancy GUI like TWS but provides exactly the same API functionality as TWS, while using fewer system resources and running more efficiently.2 IB also publishes an interface (Application Programming Interface, or API) that enables user applications to connect to the IB server using one of its client applications (either IB Gateway or TWS). This API enables user trading models to interact with IB: send trade orders, receive market and portfolio information, process execution and tick events etc. IB provides its API for three target platforms: Windows, Mac and Linux (Mac and Linux actually use the same API installation).3 The API has several variants, including C++, Java, DDE, and ActiveX (DDE and ActiveX only on Windows). Matlab is a programming development platform that is widely-used in the financial sector. Matlab enables users to quickly analyze data, display results in graphs or interactive user interfaces, and to develop automated, semi-automated and decisionsupport trading models. Unfortunately, IB does not provide an official Matlab API connector. While IBs Java connector can be used directly in Matlab, setting up the event callbacks and data conversions between Matlab and the connector is definitely not easy. You need to be familiar with both Matlab and Java, at least to some degree. This is the role of IB-Matlab (http://UndocumentedMatlab.com/IB-Matlab). IBMatlab uses IBs Java API to connect Matlab to IB, providing a seamless interface within Matlab to the entire set of Java API functionality. Users can activate IBs API by simple Matlab commands, without any need to know Java. In fact, Javas cross-platform compatibility means that exactly the same IB-Matlab code runs on all platforms supported by both IB and Matlab, namely Windows (both 32 and 64 bit), Macs and Linux/Unix.
1 2 3
IB-Matlab consists of two parts that provide different ways of interacting with IB: 1. A Java package (IBMatlab.jar) that connects to the TWS/Gateway and provides full access to IB's Java API functionality. Matlab users can use a special connector object in Matlab to invoke the Java API functions directly from within Matlab. 2. A Matlab wrapper (IBMatlab.p4) that does not provide 100% of the functionality, only the 20% that is used 80% of the time. This wrapper is a pure Matlab implementation that enables Matlab users to access the most important IB functionalities without needing to know anything about Java. Active trading actions (buy, sell, short and cancel) and query actions (market, streaming quotes, open orders, historical, account and portfolio data) can be initiated with simple one-line Matlab code that uses the Matlab wrapper (IBMatlab.p). Additional trading features (the full range of IBs Java API) can be accessed using the connector object exposed by IB-Matlab. Users can easily attach Matlab code (callbacks) to IB events. This enables special operations (e.g., adding an entry in an Excel file, sending an email or SMS) whenever an order is fully or partially executed, or a specified price is reached, for example. Reviews of IB-Matlabs Matlab wrapper were published in 20115 and 20126 in Automated Trader magazine and can be downloaded from IB-Matlabs web page.7 This document explains how to install and use IB-Matlab. Depending on the date that you have installed IB-Matlab, your version may be missing some features discussed in this document. However, as part of your annual license renewal you will receive the latest IB-Matlab version, including all the functionality detailed here.
4
In IB-Matlab releases prior to February 15, 2012, this wrapper was named IB_trade, not IBMatlab. IB_trade has exactly the same interface and functionality as IBMatlab, except for features that were added since 2/2012. In the vast majority of cases, any use of IBMatlab in this document can be substituted with IB_trade without any further change. http://www.automatedtrader.net/articles/software-review/84091/the-virtue-of-simplicity http://www.automatedtrader.net/articles/software-review/107768/mashup http://undocumentedmatlab.com/files/IB-Matlab_Review.pdf, http://undocumentedmatlab.com/files/IB-Matlab_Review2.pdf
5 6 7
2 Installation IB-Matlab requires the following in order to run: 1. An active account at IB Use of IBs Demo account is not recommended: it is limited in comparison with the functionalities of a live account. To test IB-Matlab, we recommend using the paper-trade (simulated trading) account that IB assigns when you register to IB. Paper-trade accounts resemble your live account more closely than the Demo account. 2. An installation of TWS and/or the IB Gateway (normally installed together) 3. An installation of Matlab 7.1 (R14 SP3) or a newer release If you have an earlier release of Matlab, some API functionality may still be available on your system. Contact Yair ([email protected]) for details. The installation procedure for IB-Matlab is as follows: 1. Ensure that you have read and accepted the license agreement. This is required even for the trial version of IB-Matlab. If you do not accept the license agreement then you cannot use IB-Matlab. 2. Place the IB-Matlab files (esp. IBMatlab.jar, IBMatlab.p, and IBMatlab.m) in a dedicated folder (for example: C:\IB-Matlab\). Do not place the files in one of Matlabs installation folders. 3. Add the new IB-Matlab folder to your Matlab path using the path tool (in Matlabs Desktop menu, run File / Set path and save). The IB-Matlab folder needs to be in your Matlab path whenever you run IBMatlab. 4. Type the following in your Matlab command prompt:
>> edit('classpath.txt');
This will open the classpath.txt file for editing in the Matlab editor. This file includes the Java static classpath that is used in Matlab and is typically located in the %matlabroot%/toolbox/local/ folder (e.g., C:\Program Files\MATLAB\ R2011b\toolbox\local\). 5. Add the full path to the IBMatlab.jar file into the classpath.txt file (you may need to repeat this step whenever you install a new Matlab release on your computer). For example, on a Windows computer if the IB-Matlab files are in C:\IB-Matlab\, then the new line in the classpath.txt file should be as follows: C:\IB-Matlab\IBMatlab.jar You must use the full absolute filepath. So on MacOS, for example, enter /Users/Yair/IB-Matlab/IBMatlab.jar rather than ~/IB-Matlab/IBMatlab.jar. Similarly, you cannot use something like $matlabroot/../../IB-Matlab.jar.
When trying to save the classpath.txt file, you might get an error message saying the file is read-only. To solve this, enable write-access to this file: In Linux/Unix, run chmod a+w classpath.txt. In Windows, open Windows Explorer, right-click the classpath.txt file, select Properties, and unselect the Read-only attribute. In Windows 7/8 you need to run Matlab as Administrator (right click the Matlab icon and select Run as Administrator) in order to be able to save the file, even when it is not read-only. If you cannot get administrator access to modify classpath.txt, place a copy of it in your Matlab startup folder. This is the folder used when you start Matlab type the following command at the Matlab command prompt to get it:
>> pwd
Note that placing the modified classpath.txt file in your Matlab startup folder enabled you to run IB-Matlab whenever you use this startup folder so if you ever use a different Matlab startup folder then you will need to copy the classpath.txt file to the new startup folder. Also note that the classpath.txt file depends on the Matlab release it will only work on your current release of Matlab if you try to use a different Matlab release with this same startup folder, then Matlab itself (not just IB-Matlab) may fail to load. For these reasons, a much safer approach is to update the classpath.txt file in Matlabs default location, namely the %matlabroot%/toolbox/local/ folder. 6. Restart Matlab (no need to restart the computer or to run as administrator) 7. If you are running the Production version of IB-Matlab, then you will need to activate your license at this point. When you purchase your license you will be given specific instructions how to do this. 8. Ensure that either TWS or IB Gateway is working and logged-in to IB. 9. In TWS, go to the main menus Edit / Global Configuration / API / Settings and make the following changes:8 a. enable the Enable ActiveX and Socket Clients checkbox b. add 127.0.0.1 (=localhost, i.e. the current computer) and 0:0:0:0:0:0:0:1 (the IPv6 loopback address, used by IB-Gateway) to the list of Trusted IP Addresses. If you wish to use IB-Matlab on a different computer than the one that runs TWS, add IB-Matlab machines IP address to the list of trusted IP addresses. c. validate the Socket port used by TWS for API communication. This should normally be 7496. It can be changed to some other value, but then you will need to specify the Port parameter when you use IBMatlab for the first time after each Matlab restart.9
8
If you do not make these changes, then IB-Matlab will either not be able to connect to IB, or will require popup confirmation upon each request by IB-Matlab. See 13 below for more details
d. elect whether to specify a Master Client ID (positive integer number), that will provide access to all orders created by any API client. You can then use this in IBMatlab by specifying the ClientId parameter.10
e. If you have recently upgraded from a 32-bit system (e.g., Windows XP) to 64 bits (e.g., Windows 7), then if you encounter some problems running IB-Matlab, this could be due to a 32-64 bit mixup in TWS.11 10. If you plan to use the IB Gateway, then the configuration is very similar: Go to the Gateways main menu Configure / Settings / API / Settings and modify the configuration as for TWS above. The only difference is that the Enable ActiveX and Socket Clients checkbox is not available in the Gateways configuration, because it is always enabled for trusted IPs (which is good).12 11. You can now run IBMatlab within Matlab. To verify that IB-Matlab is properly installed, retrieve your current IB account information, using the following commands (which are explained in 4 below):
>> data = IBMatlab('action','account_data') >> data = IBMatlab('action','portfolio')
12. If you get an error IBMatlab.jar not found in static Java classpath. Please add IBMatlab.jar to classpath.txt, then repeat step #5 above carefully, restart Matlab and retry step #11. If you still get the error, please contact Yair.
10
See 13 below for more details. Note: It has been reported that setting a value in this field may limit the ability to concurrently access multiple IB accounts, as may be the case for Financial Advisors or if you have child IB accounts. See http://www.elitetrader.com/vb/showthread.php?threadid=175081 for details on how to solve this. If you forget to add the localhost IP to the list of trusted IP addresses, IBMatlab will complain that it cannot connect to IB
11 12
3 Using IBMatlab IB-Matlab uses the IB client (either TWS or IB Gateway) to connect to the IB server. Therefore, to use IB-Matlab, you must first ensure that either TWS or Gateway is active. If an active IB client is not detected, IB-Matlab will automatically attempt to start TWS and to connect to it. Note that this may not work for some TWS installations. You can always start TWS or IB Gateway manually, before running IBMatlab. In any case, if an IB connection is unsuccessful, IB-Matlab will error. IB-Matlabs Matlab wrapper function is called IBMatlab. This function is contained within the IBMatlab.p file. Its accompanying IBMatlab.m file provides online documentation using standard Matlab syntax, e.g.:
>> help IBMatlab >> doc IBMatlab
The IBMatlab function accepts a variable number of parameters, and returns two objects: a data object (that contains the returned query data, or the order ID of a sent trade order), and a connector object that provides full access to the Java API.13 IBMatlab can accept input parameters in either of two formats: As name-value pairs for example:
>> data = IBMatlab('action','account, 'AccountName','DU12345');
These input formats are equivalent. You can use whichever format you feel more comfortable with. Note that if you choose to use the struct format and then to reuse this struct for different IBMatlab commands (by altering a few of the parameters), then the entire set of struct parameters is used, possibly including some leftover parameters from previous IBMatlab commands, that may lead to unexpected results. For example:
% 1st IBMatlab command buy 10 GOOG at limit $600.00 >> params = []; % initialize >> params.Action = 'buy'; >> params.Symbol = 'GOOG'; >> params.Quantity = 10; >> params.Type = 'LMT'; >> params.LimitPrice = 600.00; >> orderId1 = IBMatlab(params);
13
IB-Matlab User Guide % 2nd IBMatlab command sell 10 GOOG at limit $625.00 >> params.Action = 'sell'; % reuse the existing params struct >> params.LimitPrice = 625.00; >> orderId1 = IBMatlab(params);
10
The second IBMatlab command will sell all 10 units of GOOG, even if the user meant to sell just a single unit. This is because the params struct still contains the Quantity=10 field from the first IBMatlab command. To avoid unexpected results, I therefore advise to re-initialize the params struct (=[]) for each IBMatlab command. IBMatlab is quite tolerant of user input: parameter names are case-insensitive (whereas most IB values are case-sensitive), parameter order does not matter, and in some cases the inputs can be shortened. For example, the following are all equivalent:
>> >> >> >> >> >> data data data data data data = = = = = = IBMatlab('action','account', 'AccountName','DU12345'); IBMatlab('action','account_data', 'accountname','DU12345'); IBMatlab('action','account_data', 'AccountName','DU12345'); IBMatlab('Action','Account_Data', 'AccountName','DU12345'); IBMatlab('ACTION','ACCOUNT_DATA', 'AccountName','DU12345'); IBMatlab('AccountName','DU12345', 'action','account_data');
The full list of acceptable input parameters is listed in the sections below, grouped by usage classification. When using IBMatlab, there is no need to worry about connecting or disconnecting from TWS/Gateway IBMatlab handles these activities automatically, without requiring user intervention. The user only needs to ensure that TWS/Gateway is active and logged-in when the IBMatlab command is invoked in Matlab. Much of IBMatlabs functionality relates to a specific security that you choose to query or trade. IB is not very forgiving if you do not provide the exact security specifications (a.k.a. Contract) that it expects: in such a situation, data is not returned, and an often-cryptic error message is displayed in Matlabs Command Window:14
>> data = IBMatlab('action','query', 'symbol','EUR') [API.msg2] No security definition has been found for the request {153745243, 200} data = reqId: 153745243 reqTime: '13-Feb-2012 21:25:42' dataTime: '' dataTimestamp: -1 ticker: 'EUR' bidPrice: -1 askPrice: -1 open: -1 close: -1
14
The error messages can be suppressed using the MsgDisplayLevel parameter, and can also be trapped and processed using the CallbackMessage parameter see 14 below for more details
11
Unfortunately, IB is not very informative about what exactly was wrong with our request, we need to discover this ourselves. It turns out that in this specific case, we need to specify a few additional parameters, since the defaults (localSymbol=symbol, secType='STK', exchange='SMART') are invalid for this security:
>> data = IBMatlab('action','query', 'symbol','EUR', ... 'localSymbol','EUR.USD', 'secType','cash', ... 'exchange','idealpro') data = reqId: 153745244 reqTime: '13-Feb-2012 21:28:51' dataTime: '13-Feb-2012 21:28:52' dataTimestamp: 734912.895051898 ticker: 'EUR' bidPrice: 1.32565 askPrice: 1.32575 open: -1 close: 1.3197 low: 1.32075 high: 1.32835 lastPrice: -1 volume: -1 tick: 5e-005 bidSize: 26000000 askSize: 20521000
In other cases, we may also need to explicitly specify the Currency (default='USD'). For example, the Russell 2000 index (RUT) is listed on the Toronto Stock Exchange (TSE) and uses CAD Currency. For options/future we also need to specify the Expiry, Strike and Right parameters. In one particular case that we encountered, it was not even sufficient to specify the Expiry in YYYYMM format because a particular underlying security had two separate futures expiring in the same month:
>> data = IBMatlab('action','query','symbol','TNA','secType','opt',... 'expiry','201202','strike',47,'right','CALL') [API.msg2] The contract description specified for TNA is ambiguous; you must specify the multiplier. {149386474, 200}
The solution in this particular case was simply to specify the exact Expiry in YYYYMMDD format (i.e., specifying the full date rather than just the month).
12
If you are uncertain about a securitys contract details, try to test different parameter combinations. Alternately, use your TWS paper-trade (simulated trading) account to buy a virtual unit of the security, right-click the ticker in TWS and select Contract Info / Description:
This specific example shows that the LocalSymbol for the IBM OCT12 PUT option is IBM 121020P001000000 (Symbol remains IBM). Note that this LocalSymbol has multiple spaces. For this reason it is better to copy-paste the value directly from the window, rather than to copy it manually. Alternately, buy a virtual unit of the security as above, then use IB-Matlab to read the portfolio (see 4 below) and check the reported contract data. For example:
>> data = IBMatlab('action','portfolio'); >> data(3) ans = symbol: 'EUR' localSymbol: 'EUR.USD' exchange: 'IDEALPRO' secType: 'CASH' currency: 'USD' right: '0' ...
13
As a last resort, contact IBs API customer support help-desk (see Appendix A.1 below) to request the necessary parameters for a particular security. Here are some examples of IB symbols:15 Symbol CO GE VOD-LSE ESM1-GLOBEX-FUT QQQFJ-CBOE-OPT SPX-CBOE-IND INDU-NYSE-IND YM JUN 11-ECBOT-FUT Type Stock Stock Stock Future Option Index Index Future Description Cisco Corporation, NASDAQ General Electric, NYSE Vodafone Group, London Stock Exch. Emini ES Jun 2011 futures, Globex Jun 2004, 36.0 CALL option QQQFJ S&P-500 Index, CBOE Dow Jones Industrials Index, NYSE YM Jun 2011 future, ECBOT Note: 3 spaces between the symbol and month,1 space between month and year QM (Crude) June 2005 future contract, NYMEX German Dec 2011 Bund future
Future Future
Commodity London Gold Spot Cash Forex EURUSD currency pair, IDEAL
EUR.USD-IDEALPRO-CASH Cash Forex EURUSD currency pair, IDEALPRO Traders who wish to see the full option chain list, are referred to 11.4 below. While it is not possible to receive the entire list of option prices in a single command (each market price requires a separate request with a specific LocalSymbol), it is possible to extract the full list of option LocalSymbols in a single command.
15
14
Here is the full list of Contract properties supported by IBMatlab:16 Parameter Data type Default Description string (none) The symbol of the underlying asset Symbol '' The local exchange symbol of the underlying LocalSymbol string asset. When left empty, IB sometimes tries to infer it from Symbol and the other properties. string 'STK' One of: SecType 'STK' stocks (default) 'OPT' options 'FUT' futures 'IND' indexes 'FOP' options on futures 'CASH' - Forex 'BAG' string 'SMART' The exchange that should process the request. Exchange SMART uses IBs SmartRouting to optimize order execution time and cost.17 string 'USD' The currency to be used. Possible ambiguities Currency may mean that this field must be specified. For example, when Exchange='SMART' and Symbol='IBM', then Currency must be explicitly specified since IBM can trade in either GBP or USD. Because of these potential ambiguities, it is a good idea to always specify Currency. string '' 'YYYYMM' or 'YYYYMMDD' format Expiry number 0.0 The strike price (for options) Strike string '' One of: 'P', 'PUT', 'C', 'CALL' Right Important: Numbers should not be enclosed with quote marks when specifying parameter values. Therefore, we should specify IBMatlab(..., 'Strike',5.20) and not IBMatlab(..., 'Strike','5.20'). Otherwise, Matlab might get confused when trying to interpret the string '5.20' as a number, and very odd results might happen.
16
This list closely mirrors IBs Java API list of Contract details. Some of the Java API properties mentioned in the online lis t (http://www.interactivebrokers.com/en/software/api/apiguide/java/contract.htm) are not supported by IBMatlab, but they can still be accessed via IB-Matlabs Java connector object, as described in 15 below. http://www.interactivebrokers.com/en/p.php?f=smartRouting
17
15
4 Querying account and portfolio data 4.1 Account information IB user accounts have numerous internal properties/parameters, ranging from the account currency to cash balance, margin information etc. You can retrieve this information in Matlab using the following simple command:
>> data = IBMatlab('action','account_data') data = AccountCode: 'DU12345' currency: [] accountName: 'DU12345' AccountReady: 'true' AccountType: 'INDIVIDUAL' AccruedCash: -456.4 AccruedDividend: 0 AvailableFunds: 261700.68 Billable: 0 BuyingPower: 779656.96 CashBalance: -825400.37 (and so on ... dozens of different account parameters)
As can be seen, the returned data object is a simple Matlab struct, whose fields match the IB account properties. To access a specific field use standard Matlab dot notation:
>> myBuyingPower = data.BuyingPower; %=779656.96 in this specific case
Some account data fields have several variants. For example, different values may be returned by IB server for NetLiquidation, NetLiquidation_C and NetLiquidation_S. Until you trade a commodity, NetLiquidation_C=0 and NetLiquidation_S= NetLiquidation. After trading a commodity, NetLiquidation_C holds the value for commodities, NetLiquidation_S for securities, and NetLiquidation for the total. Several other fields also have these _S and _C variants.18 If your TWS account is linked to more than one IB account (as is common for Financial Advisors, for example), then you should specify the AccountName input parameter, so that IB would know which IB account to access:19
>> data = IBMatlab('action','account_data', 'AccountName','DU12345');
To get the account information for all accounts in a consolidated manner, set AccountName to 'All':20
>> data = IBMatlab('action','account_data', 'AccountName','All');
18
IB-Matlab versions prior to 5/5/2012 did not make a distinction between Field, Field_S and Field_C, and so the reported value in Field might be any of the three possibilities. If you dont specify the AccountName, you will get stale or empty account data. Note: The TWS/IB-Gateway API setting "Master API Client ID" may need to be empty (even if correct) for this to work (see installation step 9d in 2 above)
19 20
16
4.2 Portfolio data To retrieve an IB accounts portfolio (list of held securities), run a similar command in Matlab, with a 'portfolio' (or 'portfolio_data') action:
>> data = IBMatlab('action','portfolio') data = 1x12 struct array with fields: symbol localSymbol exchange secType currency right expiry strike position marketValue marketPrice averageCost contract
This returns a Matlab array of structs, where each struct element in the array represents a different security held in the IB account. For example:
>> data(2) ans = symbol: localSymbol: exchange: secType: currency: right: expiry: strike: position: marketValue: marketPrice: averageCost: contract:
'AMZN' 'AMZN' 'NASDAQ' 'STK' 'USD' '0' '' 0 9200 1715800 186.5 169.03183335 [1x1 struct]
17
In some cases, IB might return empty data in response to account/portfolio requests. Two workarounds have been found for this, although they might not cover all cases.21 The workarounds are to simply re-request the information, and to force a programmatic reconnection to IB (more on the Java connector in 15 below):
data = IBMatlab('action','portfolio'); if isempty(data) % empty data try to re-request the same data [data, ibConnectionObject] = IBMatlab('action','portfolio'); end if isempty(data) % still empty data try to disconnect/reconnect ibConnectionObject.disconnectFromTWS; % disconnect from IB pause(1); % let IB cool down a bit data = IBMatlab('action','portfolio'); % will automatically reconnect end
As in the case of retrieving the account data, when requesting portfolio data we need to ensure that we are requesting the data for the correct account, if we have more than a single IB account connected to our IB login. Many frustrations can be avoided by specifically stating the requested AccountName parameter whenever we use IBMatlab in multi-account environments. If you are unsure of the account name, you can use AccountName='All'. A suggested practice for safe/robust programming is to compare the sum of the noncash portfolio marketValues versus the accounts StockMarketValue, as reported by the IBMatlab('action','account_data') command. Be careful to sum only non-cash securities (i.e., ~strcmpi(data.secType,'cash')). Shorted securities will appear with a negative marketValue in the portfolio struct array, while long securities will have a positive value. The sum of these values, which should be equal to the accounts StockMarketValue, may be positive or negative, indicating whether the overall portfolio is long or short. If you are only interested in the total monetary amount of the security positions (i.e., their absolute marketValues), then the sum in this case should equal the accounts GrossPositionValue. Note that small differences between the portfolio marketValue sums and the account StockMarketValue or GrossPositionValue, due to market changes that occurred between the time that the account data was collected, compared to the time that the portfolio data was requested. If you run these requests immediately one after another, then in the vast majority of the cases the data will match exactly.
21
For example, the IB API has a known limitation that it does not return the portfolio position if the clearing house is not IB
18
5 Querying current market data 5.1 Single-quote data Let us start with a simple example where we retrieve the current market information for Google Inc., which trades using the GOOG symbol on IBs SMART exchange (the default exchange), with USD currency (the default currency):
>> data = IBMatlab('action','query', 'symbol','GOOG') data = reqId: 22209874 reqTime: '02-Dec-2010 00:47:23' dataTime: '02-Dec-2010 00:47:24' dataTimestamp: 734474.032914491 ticker: 'GOOG' bidPrice: 563.68 askPrice: 564.47 open: 562.82 close: 555.71 low: 562.4 high: 571.57 lastPrice: -1 volume: 36891 tick: 0.01 bidSize: 3 askSize: 3 lastSize: 0 contract: [1x1 struct] contractDetails: [1x1 struct]
As can be seen, the returned data object is a Matlab struct whose fields are selfexplanatory. To access any specific field, use the standard Matlab notation:
>> price = data.bidPrice; %=563.68 in this specific case
Note: the reqTime, dataTime and dataTimestamp fields reflect the local time. If the lastPrice field is returned with valid data (not -1) then it is usually accompanied by a lastTimestamp field that reflects the server time in Java units (seconds since midnight 1/1/197022 as a string, for example: '1348563149'). We can convert lastTimestamp into Matlab format by converting the string into a number and using datenum:23
>> datestr(datenum([1970 1 1 0 0 str2num(data.lastTimestamp)])) ans = 25-Sep-2012 08:52:29
To retrieve the current market data, three pre-conditions must be met: 1. The IB account is subscribed to the information service for the stated security 2. The specified security can be found on the specified exchange using the specified classification properties (a.k.a. Contract) 3. The security is currently traded (i.e., its market is currently open)
22 23
19
If any of these conditions is not met, the information returned by IB will be empty/invalid (the data fields will have a value of -1 or []). If condition 3 is not met, then the empty data will not be accompanied by any error message; if condition 1 and/or 2 (but not 3) is not met, an error message will be displayed in the Matlab command window,24 as the following examples illustrate:
>> data = IBMatlab('action','query', 'symbol','GOOG'); [API.msg2] Requested market data is not subscribed.Error&BEST/STK/Top {153745220, 354} data = dateTime: {1x0 cell} open: [] high: [] low: [] close: [] volume: [] count: [] WAP: [] hasGaps: []
This illustrates a situation where we are not subscribed to data for this specific security type and/or exchange. A similar yet different message is returned when we try to get historical data for an unsubscribed security type/exchange:
>> data = IBMatlab('action','history', 'symbol','GOOG'); [API.msg2] Historical Market Data Service error message: No market data permissions for NASDAQ STK {153745241, 162}
If we specify an incorrect security name or classification properties, then the data is similarly not returned, and an error message is displayed (see discussion in 3). Additional market data about a security can be retrieved using IBs Generic Tick List mechanism, which is accessed via the GenericTickList parameter. This parameter is a string (default='' =empty) that accepts comma-separated integers such as '100,101' or '236'.25 Note that the value should be a string ('236'), not a number (236).
>> data = IBMatlab('action','query', 'symbol','GOOG', ... 'GenericTickList','100'); % Note: '100', not 100
One of the useful tick-types is 236, which returns information about whether or not the specified security is shortable. Only some securities and exchanges support this feature (mainly US stocks), and only for streaming quotes26 (not for regular market queries). When the feature is supported, an additional shortable field is returned with basic information about the securitys shortability.27
24
The error messages can be suppressed using the MsgDisplayLevel parameter, and can also be trapped and processed using the CallbackMessage parameter see 14 below for more details http://www.interactivebrokers.com/en/software/api/apiguide/tables/generic_tick_types.htm See 7 for details on streaming quotes See 11.3 for details about the shortable mechanism, with a full working example that uses callbacks
25 26 27
20
5.2 Scanner data Scanner data returns a list of securities that match the specified scan criteria. IB includes a long list of predefined scanners,28 including MOST_ACTIVE, TOP_PERC_GAIN, HOT_BY_VOLUME, HOT_BY_PRICE etc. The scan can be limited to security type and trading location,29 as well as to a variety of criteria on the security attributes (price, volume, maturity date, market cap, Moody/S&P rating, coupon rate etc.).30 This is an extensive list, which covers much of the demand. Note: IB scanners are only limited to the predefined scanner types and options above. We cannot define a generic scan criteria based on attributes that are not on the predefined list. In such cases, we would need to use other means to scan the markets. To use market scanners in IB-Matlab, set the Action parameter to 'Scanner', and either use the default criteria values (see table below) or override them. For example, to return the currently most active stock in NASDAQ (the default criteria):
>> data = IBMatlab('action','scanner') data = EventName: 'scannerData' reqId: 349661732 rank: 0 contractDetails: [1x1 struct] distance: [] benchmark: [] projection: [] legsStr: [] symbol: 'QQQ' localSymbol: 'QQQ' contract: [1x1 struct]
Additional information about the returned security (QQQ in this case) can be seen in the contract and contractDetails fields of the returned data structure. By default, IB-Matlab only returns the top single security matching the scan criteria. We can change this using the NumberOfRows parameter. IB limits the amount of returned data, so it is quite possible that we will receive fewer results than requested:
>> data = IBMatlab('action','scanner', 'NumberOfRows',100) data = 1x23 struct array with fields: EventName reqId rank contractDetails distance benchmark projection
28 29 30
IB-Matlab User Guide legsStr symbol localSymbol contract >> data(end) ans = EventName: reqId: rank: contractDetails: distance: benchmark: projection: legsStr: symbol: localSymbol: contract:
21
Note: the IB documentation about the possible scanner parameter values is quite limited and incomplete. If you are unsure of the parameter values that are required for a specific scan, contact IBs customer service and ask them for the specific set of API ScannerSubscription parameters that are required for your requested scan. One feature that could help in determining the possible parameter values is an XML document that the IB server provides which describes the possible combinations. We can retrieve this document by specifying Type='parameters' in IB-Matlab:
>> xmlStr = IBMatlab('action','scanner', 'Type','parameters') xmlStr = <?xml version="1.0" encoding="UTF-8"?> <ScanParameterResponse> <InstrumentList varName="instrumentList"> <Instrument> <name>US Stocks</name> <type>STK</type> <filters>PRICE,PRICE_USD,VOLUME,VOLUME_USD,AVGVOL UME,AVGVOLUME_USD,HALTED,...,FIRSTTRADEDATE,HASOP TIONS</filters> <group>STK.GLOBAL</group> <shortName>US</shortName> </Instrument> <Instrument> <name>US Futures</name> <type>FUT.US</type> <secType>FUT</secType> <filters>PRICE,PRICE_USD,VOLUME,VOLUME_USD,PRODCA T,LEADFUT,CHANGEPERC,CHANGEOPENPERC,OPENGAPPERC,P RICERANGE,TRADERATE</filters> <group>FUT.GLOBAL</group> <shortName>US</shortName> </Instrument> ... (~20K additional lines!)
22
This XML string is quite long (~1MB, ~20K lines). We can store it in a *.xml file and open this file in an XML reader (for example, a browser). Alternatively, we can ask IB-Matlab to parse this XML and present us with a more manageable Matlab struct that we can then process in Matlab. This is done by setting ParametersType='struct'. Note that this XML parsing could take a long time (a full minute or even longer):
>> params = IBMatlab('action','scanner', 'type','parameters', ... 'ParametersType','struct') %may take a long time! params = Name: 'ScanParameterResponse' InstrumentList: [1x1 struct] LocationTree: [1x1 struct] ScanTypeList: [1x2 struct] SettingList: [1x1 struct] FilterList: [1x2 struct] ScannerLayoutList: [1x1 struct] InstrumentGroupList: [1x1 struct] SimilarProductsDefaults: [1x1 struct] MainScreenDefaultTickers: [1x1 struct] ColumnSets: [1x1 struct] SidecarScannerDefaults: [1x1 struct] >> params.InstrumentList ans = Name: 'InstrumentList' Attributes: [1x1 struct] Instrument: [1x23 struct] >> params.InstrumentList.Instrument(2) ans = Name: 'Instrument' name: 'US Futures' type: 'FUT.US' filters: [1x108 char] group: 'FUT.GLOBAL' shortName: 'US' secType: 'FUT' nscanSecType: [] permSecType: [] >> params.InstrumentList.Instrument(2).filters ans = PRICE,PRICE_USD,VOLUME,VOLUME_USD,PRODCAT,LEADFUT,CHANGEPERC,CHANGEOPEN PERC,OPENGAPPERC,PRICERANGE,TRADERATE
23
The parameters that affect scanner data retrieval closely mirror those expected by the Java API:31 Parameter Type Data type string Default 'Scan' Description One of: 'Scan' scanner data (default) 'Parameters' possible scanner param values One of: 'XML' (default) 'Struct' Matlab struct Filter out contracts with a price lower than this value Filter out contracts with a volume lower than this value Filter out contracts with avg. options volume lower than this Filter out contracts with a price higher than this value Filter out contracts with a coupon rate lower than this Filter out contracts with a coupon rate higher than this Filter out convertible bonds
ParametersType
string
'XML'
AbovePrice AboveVolume
number integer
AverageOptionVolume integer Above number BelowPrice CouponRateAbove CouponRateBelow ExcludeConvertible Instrument LocationCode MarketCapAbove MarketCapBelow MaturityDateAbove MaturityDateBelow number number string
'' (empty string) string 'STK' Defines the instrument type32 string 'STK.NASDAQ' Defines the scanned markets33 number 0.0 Filter out contracts with a market cap lower than this number Inf Filter out contracts with a market cap above this value string '' Filter out contracts with a (empty string) maturity date earlier than this string '' Filter out contracts with a (empty string) maturity date later than this
31 32
http://www.interactivebrokers.com/en/software/api/apiguide/java/scannersubscription.htm http://www.interactivebrokers.com/en/software/api/apiguide/tables/instruments_and_location_codes_for_market_scanners.htm (note: this is only a partial list!) http://www.interactivebrokers.com/en/software/api/apiguide/tables/instruments_and_location_codes_for_market_scanners.htm (note: this is only a partial list!)
33
24
Description
Filter out contracts with a Moody rating below this value Filter out contracts with a Moody rating above this value The number of rows of data to return for the query 'MOST_ACTIVE' A long list.. see the API doc34 '' For example, a pairing 'Annual, (empty string) true' used on the Top Option Implied Vol % Gainers scan returns annualized volatilities '' Filter out contracts with an (empty string) S&P rating below this value '' Filter out contracts with an (empty string) S&P rating above this value 'ALL' One of: 'ALL' (default) 'CORP' 'ADR' 'ETF' 'REIT' 'CEF'
34
http://www.interactivebrokers.com/en/software/api/apiguide/tables/available_market_scanners.htm
25
6 Querying historical data Historical data can be retrieved from IB, subject to your accounts subscription rights, and IBs lengthy list of pacing violation limitations.35 Note that these are IB server limitations, not IB-Matlab limitations. As of July 2013, these limitations include: 1. Historical data is limited to 2000 results (data bars) if more than that is requested, the entire request is dropped. 2. Historical data can by default only be requested for the past year. If you have purchased additional concurrent real-time market data-lines from IB, then you can ask for historical data up to 4 years back. If you request data older than your allowed limit, the entire request is dropped. 3. Historical data requests that use a bar size of 30 seconds or less can only go back six months. If older data is requested, the entire request is dropped. 4. Requesting identical historical data requests within 15 seconds is prohibited. IB-Matlab will automatically return the previous results in such a case. 5. Requesting 6+ historical data requests for the same Contract, Exchange and Tick Type within 2 seconds is prohibited the entire request will be dropped. 6. Requesting 60+ historical data requests of any type within 10-minutes is prohibited the entire request will be dropped. 7. Only certain combinations of bar Duration and Size are supported: Bar Size 1 day 1 day 1 day 1 day, 1 hour 1 day, 1 hour, 30 mins, 15 mins 1 hour, 30 mins, 15 mins, 3 mins, 2 mins, 1 min 1 hour, 30 mins, 15 mins, 5 mins, 3 mins, 2 mins, 1 min, 30 secs 1 hour, 30 mins, 15 mins, 5 mins, 3 mins, 2 mins, 1 min, 30 secs, 14400 S (4 hours) 15 secs 1 hour, 30 mins, 15 mins, 5 mins, 3 mins, 2 mins, 1 min, 30 secs, 7200 S (2 hours) 15 secs, 5 secs 3600 S (1 hour) 15 mins, 5 mins, 3 mins, 2 mins, 1 min, 30 secs, 15 secs, 5 secs 15 mins, 5 mins, 3 mins, 2 mins, 1 min, 30 secs, 15 secs, 5 secs, 1800 S (30 mins) 1 sec 960 S (15 mins) 5 mins, 3 mins, 2 mins, 1 min, 30 secs, 15 secs, 5 secs, 1 sec 3 mins, 2 mins, 1 min, 30 secs, 15 secs, 5 secs, 1 sec 300 S (5 mins) 30 secs, 15 secs, 5 secs, 1 sec 60 S (1 min) Duration 1Y 6M 3M 1M 1W 2D 1D
35
http://www.interactivebrokers.com/en/software/api/apiguide/api/historical_data_limitations.htm
26
Other Duration values (that are not specified in the table) are sometimes, but not always, accepted by IB. For example, 60D (=60 days) is accepted, but 61D is not. In such cases, you can always find a valid alternative (3M instead of 61D, for example). Note that IB-Matlab does not prevent you from entering invalid Durations and Bar Sizes it is up to you to verify that your specified parameters are accepted by IB. If they are not, then IB will report an error message that will be displayed in the Matlab command window. Subject to these limitations, retrieval of information in IB-Matlab is quite simple. For example, to return the 1-hour bars from the past day:
>> data = IBMatlab('action','history', 'symbol','IBM', ... 'barSize','1 hour', 'useRTH',1) data = dateNum: [1x7 double] dateTime: {1x7 cell} open: [161.08 160.95 161.66 161.17 161.57 161.75 high: [161.35 161.65 161.70 161.60 161.98 162.09 low: [160.86 160.89 161.00 161.13 161.53 161.61 close: [160.93 161.65 161.18 161.60 161.74 162.07 volume: [5384 6332 4580 2963 4728 4465 10173] count: [2776 4387 2990 1921 2949 2981 6187] WAP: [161.07 161.25 161.35 161.31 161.79 161.92 hasGaps: [0 0 0 0 0 0 0]
As can be seen, the returned data object is a Matlab struct whose fields are:36 dateNum a numeric array of date/time values in Matlabs numeric format37 dateTime a cell-array of date strings, or a numeric array of date values in IB format (see the FormatDate parameter, explained below) open the bars opening price high the high price during the time covered by the bar low the low price during the time covered by the bar close the bars closing price volume the trading volume during the time covered by the bar count number of trades that occurred during the time covered by the bar Note: only valid when WhatToShow='Trades' (see below) WAP the weighted average price during the time covered by the bar hasGaps whether or not there are gaps (unreported bars) in the data
36 37
http://www.interactivebrokers.com/en/software/api/apiguide/java/historicaldata.htm#HT_historicalDataw http://www.mathworks.com/help/matlab/ref/datenum.html
27
The fields are Matlab data arrays (numeric arrays for the data and cell-arrays for the timestamps). To access any specific field, use the standard Matlab notation:
>> data.dateTime ans = '20110225 16:30:00' '20110225 19:00:00' '20110225 22:00:00'
'20110225 '20110225
17:00:00' 20:00:00'
'20110225 '20110225
18:00:00' 21:00:00'
As noted above, if any of the limitations for historical data requests is not met, then an error message is displayed in the Matlab command prompt and no data is returned. Unfortunately, IBs error messages are not always very descriptive in their explanation of what was actually wrong with the request. The parameters that affect historical data retrieval closely mirror those expected by the Java API:38 Parameter EndDateTime Data type string Default Description '' Use the format 'YYYYMMDD (empty string), hh:mm:ss TMZ' (the TMZ time zone is meaning now optional39) 1 Together with DurationUnits this parameter specifies the historical data duration, subject to the limitations on possible Duration/BarSize 'D' One of: 'S' (seconds) 'D' (days default) 'W' (weeks) 'M' (months) 'Y' (years) Specifies the size of the bars that will be returned (within IB/TWS limits). Valid values include:
38 39
DurationValue
integer
DurationUnits
string
BarSize
string
'1 min'
28
Default 'Trades'
Description Determines the nature of data being extracted. Valid values include: Trades (default; invalid for Forex) Midpoint Bid Ask Bid_Ask Historical_Volatility Option_Implied_Volatility Determines whether to return all data available during the requested time span, or only data that falls within Regular Trading Hours. Valid values include: 0 or false (default): all data is returned even where the market in question was outside of its regular trading hours
UseRTH
0 = false
FormatDate
integer
1 or true: only data within the regular trading hours is returned, even if the requested time span falls partially or completely outside of the RTH. Determines the date format applied to returned bars. Valid values include: 1) dates applying to bars returned in the format: 'yyyymmdd hh:mm:dd' (the time part is omitted if barSize>=1d) 2) dates are returned as a long integer (# of seconds since 1/1/1970 GMT) Maximal number of seconds to wait for an IB response to a request (note: the timeout is ignored in some cases, e.g. after partial data has been received etc.)
Timeout
number
Inf = unlimited
Note that some securities and exchanges do not support certain historical parameter combinations. For example, FOREX (currency) historical data requests on the IDEALPRO exchange do not support WhatToShow='Trades' but only 'Midpoint'. IB displays a very cryptic error message in such cases, and we are only left with the option of guessing what parameter value to modify, or ask IBs customer support.
29
Also note that some exchanges, while returning the requested historical data, may not provide all of the historical data fields listed above. For example, in the case of FOREX on IDEALPRO again, the Volume, Count and WAP fields are not returned, and appear as arrays of -1 when returned to the user in the data struct:
>> data = IBMatlab('action','history', 'symbol','EUR', ... 'localSymbol','EUR.USD', 'secType','cash', ... 'exchange','idealpro', 'barSize','1 day', ... 'DurationValue',3, 'WhatToShow','midpoint') data = datenum: [734909 734910 734913] dateTime: {'20120210' '20120211' '20120214'} open: [1.32605 1.3286 1.32095] high: [1.3321 1.329075 1.328425] low: [1.321625 1.315575 1.320275] close: [1.328575 1.319825 1.325975] volume: [-1 -1 -1] count: [-1 -1 -1] WAP: [-1 -1 -1] hasGaps: [0 0 0]
Note that in this specific example, historical daily (BarSize = '1 day') data from the past 3 days have been requested on 2012-02-13 (Monday). However, the received data was for 2012-02-09 (Thursday), 2012-02-10 (Friday) and 2012-02-13 (Monday). Data was not received for 2012-02-11 and 2012-02-12 because the specified security was not traded during the weekend. Another oddity is that the dates were reported with an offset of 1 (2012-02-10 instead of 2012-02-09 etc.). The reason is that the information is collected on a daily basis and reported as of the first second after midnight, i.e., on the following date. This is indeed confusing, so if you rely on the reported historical data dates in your analysis, then you should take this into consideration. In some cases, users may be tempted to use the historical data mechanism in order to retrieve real-time data. This is actually relatively easy to set-up. For example, implement an endless loop in Matlab that sleeps for 60 seconds, requests the latest historical data for the past minute and goes to sleep again (more advanced Matlab users would probably implement a recurring timer object that wakes up every minute). In such cases, the user should consider using the streaming quotes or realtime bars mechanisms, rather than historical quotes. Streaming data is the subject of the following section.
30
7 Streaming data Streaming data is a near-real-time mechanism, where IB sends ongoing information to IB-Matlab about quote ticks (bids and asks) and aggregated real-time bars. 7.1 Streaming quotes The streaming quotes mechanism has two distinct parts: 1. Request IB to start sending the stream of quotes for a specified security. This is done by using Action='query' and QuotesNumber with a positive >1 value. 2. Later, whenever you wish to read the latest quote(s), simply use Action='query' and QuotesNumber= -1 (minus one). This will return the latest information without stopping the background streaming. For example, lets request 100 streaming quotes for EUR.USD:
>> reqId = IBMatlab('action','query', 'symbol','EUR', ... 'localSymbol','EUR.USD', 'currency','USD', ... 'secType','cash', 'exchange','idealpro', ... 'QuotesNumber',100) reqId = 147898050
This causes IB to start sending quotes to IB-Matlab in the background, up to the specified QuotesNumber, without affecting normal Matlab processing. This means that you can continue to work with Matlab, process/display information etc. QuotesNumber can be any number higher than 1 for streaming to work (a value of 1 is the standard market-query request described in 5). To collect the streaming quotes endlessly, simply set QuotesNumber to the value inf. Note that in Matlab, inf is a number not a string so do not enclose it in quotes ('inf') when submitting requests. Also note that the request to start streaming quotes returns the request ID, not data. The quotes are collected into an internal data buffer in IB-Matlab. A different buffer is maintained for each localSymbol. The buffer size can be controlled using the QuotesBufferSize parameter, which has a default value of 1. This means that by default only the latest streaming quote of each type (bid/ask) is stored, along with high/low/close data. If you set a higher value for QuotesBufferSize,40 then up to the specified number of latest bid quotes will be stored (note: only bid quotes are counted here):
>> reqId = IBMatlab('action','query', 'symbol','GOOG', ... 'QuotesNumber',100, 'QuotesBufferSize',500)
40
QuotesBufferSize is a numeric parameter like QuotesNumber, so dont enclose the parameter value within string quotes ()
31
Note that using a large QuotesBufferSize increases memory usage, which could have an adverse effect if you use a very large buffer size (many thousands) and/or streaming for a large number of different securities.41 Subsequent requests to retrieve the latest accumulated quotes buffer data, without stopping the background streaming, should use QuotesNumber = -1 (minus one). These requests return a data struct that looks like this:
>> dataStruct = IBMatlab('action','query', ... 'localSymbol','EUR.USD', ... 'QuotesNumber',-1) dataStruct = reqId: 147898050 symbol: 'EUR' localSymbol: 'EUR.USD' isActive: 1 quotesReceived: 6 quotesToReceive: 10 quotesBufferSize: 1 genericTickList: '' data: [1x1 struct] contract: [1x1 com.ib.client.Contract]
Streaming quotes are stored using a combination of the LocalSymbol, SecType, and Expiry date values that were specified in the initial request for the streaming quotes. In most cases (as in the example above), we only need to specify the Symbol/LocalSymbol and the QuotesNumber in the subsequent requests.42 Specifying all the other parameters is normally unnecessary, since IB-Matlab already knows about this symbols parameters from the initial streaming request. We would only need to specify the SecType and possibly also the Expiry when there is a potential conflict between distinct streaming quotes (e.g., streaming quotes of both the underlying asset and some Futures index of it). This is useful and easy to use, but also means that you cannot have two simultaneous streams for the same combination of LocalSymbol, SecType and Expiry, even if using different other parameters. In the returned dataStruct, we can see the following fields:
41
this is the request ID for the original streaming request, the same ID that was returned by IBMatlab when we sent our initial request
reqId symbol, localSymbol
Quotes use about 1.5KB of Matlab memory. So, if QuotesBufferSize=1500, then for 20 symbols IB-Matlab would need 20*1500*1.5KB = 45MB of Matlab memory when all 20 buffers become full (which could take a while). IB-Matlab versions since 2012-01-15 only need to use LocalSymbol; earlier versions of IB-Matlab used Symbol to store the streaming data. This means that the earlier versions cannot stream EUR.USD and EUR.JPY simultaneously, since they both have the same symbol (EUR). In practice, for most stocks, Symbol = LocalSymbol so this distinction does not really matter.
42
32
a logical flag indicating whether quotes are currently being streamed for the security. When QuotesNumber bid quotes have been received, this flag is set to false (0).
isActive quotesReceived
total number of streaming bid quotes requested for the security (=QuotesNumber parameter). When quotesReceived >= quotesToReceive, streaming quotes are turned off and isActive is set to false (0). Note that it is possible that quotesReceived > quotesToReceive, since it takes a short time for the streaming quotes cancellation request to reach IB, and during this time it is possible that new real-time quotes have arrived.
quotesToReceive quotesBufferSize genericTickList
any GenericTickList requested in the initial request will be kept here for possible reuse upon resubscribing to the streaming quotes (see the ReconnectEvery parameter described below). a Java object that holds the definition of the security, for possible reuse upon resubscribing to the streaming quotes.
contract data
To get the actual quotes data, simply read the data field of this dataStruct:
>> dataStruct.data ans = dataTimestamp: high: highTimestamp: low: lowTimestamp: close: closeTimestamp: bidPrice: bidPriceTimestamp: bidSize: bidSizeTimestamp: askPrice: askPriceTimestamp: askSize: askSizeTimestamp: 734892.764653854 1.3061 734892.762143183 1.29545 734892.762143183 1.30155 734892.762143183 1.2986 734892.764653854 1000000 734892.764653854 1.29865 734892.764499421 18533000 734892.764653854
Note that each data item has an associated timestamp, because different data items are sent separately and independently from IB server. You can convert the timestamps into human-readable string by using Matlabs datestr function, as follows:
>> datestr(dataStruct.data.dataTimestamp) ans = 24-Jan-2012 23:56:32
33
The dataTimestamp field currently holds the same information as bidPriceTimestamp. Future versions of IB-Matlab may modify this to indicate the latest timestamp of any received quote, not necessarily a bid quote. If instead of using QuotesBufferSize=1 (which is the default value), we had used QuotesBufferSize=3, then we would see not the latest quote but the latest 3 quotes:
>> reqId = IBMatlab('action','query', 'symbol','EUR', ... 'localSymbol','EUR.USD', 'currency','USD', ... 'secType','cash', 'exchange','idealpro', ... 'QuotesNumber',10, 'QuotesBufferSize',3); % now at any following point in time run the following command to get the latest 3 quotes: >> dataStruct = IBMatlab('action','query', ... 'localSymbol','EUR.USD', ... 'QuotesNumber',-1); >> dataStruct.data ans = dataTimestamp: [734892.99760235 734892.99760235 734892.997756076] high: 1.3061 highTimestamp: 734892.99740162 low: 1.29545 lowTimestamp: 734892.99740162 bidPrice: [1.30355 1.3035 1.30345] bidPriceTimestamp: [734892.99760235 734892.99760235 734892.997756076] bidSize: [2000000 4000000 4000000] bidSizeTimestamp: [734892.997756076 734892.997756076 734892.997756076] askPrice: [1.30355 1.3036 1.30355] askPriceTimestamp: [734892.997667824 734892.997667824 734892.997756076] askSize: [3153000 2153000 4153000] askSizeTimestamp: [734892.997756076 734892.997756076 734892.997756076] close: 1.30155 closeTimestamp: 734892.997407037
Note that the high, low and close fields are only sent once by the IB server, as we would expect. Only the bid and ask information is sent as a continuous stream of data from IB. Also note how each of the quote values has an associated timestamp. To stop collecting streaming quotes for a security, simply send the request again, this time with QuotesNumber=0. The request will return the dataStruct with the latest data that was accumulated up to that time. Another parameter that can be used for streaming quotes in IB-Matlab attempts to bypass a problem that sometimes occurs with high-frequency streams. In such cases, it has been reported that after several thousand quotes, IB stops sending streaming quotes data, without any reported error message. The ReconnectEvery numeric parameter (default=2000) controls the number of quotes (total of all streaming securities) before IB-trade automatically reconnects to IB and re-subscribes to the streaming quotes. You can specify any positive numeric value, or inf to accept streaming quotes without any automated reconnection.
34
Here is a summary of the IBMatlab parameters that directly affect streaming quotes: Parameter QuotesNumber Data type Default Description integer 1 One of: inf continuous endless streaming quotes for the specified security N>1 stream only N quotes 1 get only a single quote (i.e., nonstreaming snapshot) (default) 0 stop streaming quotes -1 return the latest accumulated quotes data while continuing to stream new quotes data integer 1 Controls the number of streaming quotes QuotesBufferSize stored in a cyclic buffer. Once this number of quotes has been received, the oldest quote is discarded whenever a new quote arrives. string '' Used to request additional (non-default) GenericTickList information: volume, last trade info, etc.43 integer 2000 Number of quotes (total of all securities) ReconnectEvery before automated reconnection to IB and resubscription to the streaming quotes. inf accept streaming quotes without automated reconnection N>0 automatically reconnect and re-subscribe to streaming quotes after N quotes are received. string '' Used to identify and store streamed quotes. LocalSymbol SecType Expiry string string 'STK' Used to identify and store streamed quotes. '' Used to identify and store streamed quotes.
Notes: IB does not send flat ticks (quotes where price does not change). Also, IB streaming data is NOT tick-by-tick, but rather snapshots of the market (every 5ms for Forex, 10ms for Options, and 250ms for all other security types). By default, IB limits the streaming to 100 concurrent requests (contracts). Users can purchase additional 100-contract blocks from IB. The messages rate is not limited by IB, but a practical processing limit is ~100 quote events per second. This rate is ok for several dozen highly-traded stocks, but not the entire S&P nor heavily-traded Forex.
43
https://www.interactivebrokers.com/en/software/api/apiguide/tables/generic_tick_types.htm
35
7.2 Realtime bars The realtime bars mechanism is similar to streaming quotes in the sense that it enables the user to receive information about a security every several seconds, until the specified QuotesNumber of bars have been received. The mechanism is also similar to historical data in the sense that the bars information is aggregated. Each bar contains the OHLCV information just as for historical data bars (see 6 for details). Similarly to streaming quotes, the realtime bars mechanism has two distinct parts: 1. Request IB to start sending the stream of bars for a specified security. This is done by using Action='realtime_bars' and QuotesNumber with a positive (>0) value. If QuotesNumber=1 (the default value), then the data for the single bar is returned immediately; Otherwise, only the request ID is returned. 2. Later, whenever you wish to read the latest bar(s) data, simply use Action='realtime_bars' and QuotesNumber= -1 (minus one). This will return the latest information without stopping the background streaming. Like streaming quotes, the streamed bars are stored based on a unique combination of their LocalSymbol, SecType and Expiry. Unlike streaming quotes, there is no automatic reconnection for realtime bars. Note that IB currently limits the realtime bars to 5-second bars only.44 Also, only some combinations of securities, exchanges and data types (the WhatToShow parameter) are supported. If you have doubts about whether a specific combination is supported, ask IB customer service (the limitation is on the IB server, not IBMatlab). Users can process realtime bars in one of two ways: use a Matlab timer to query the latest accumulated bars data (via QuotesNumber = -1), or: use the CallbackRealtimeBars parameter to set a dedicated Matlab callback function that will be invoked whenever a new bar is received (every 5 secs).45 Here is a simple example of using realtime bars for a single (snapshot) bar (QuotesNumber = 1), representing the previous 5 seconds:
>> data = IBMatlab('action','realtime', 'symbol','IBM') data = dateNum: 735551.017997685 dateTime: {'13-Nov-2013 00:25:55'} open: 183 high: 183 low: 183 close: 183 volume: 0 WAP: 183 count: 0
44 45
36
And here is a slightly more complex example, with QuotesNumber=3. The data struct that is returned in this case is correspondently more complex:
>> reqId = IBMatlab('action','realtime', 'symbol','AMZN', ... 'QuotesNumber',3, 'QuotesBufferSize',10); reqId = 345327051 (now wait 15 seconds or more for the 3 bars to be received) >> dataStruct = IBMatlab('action','realtime', 'symbol','AMZN', 'QuotesNumber',-1); dataStruct = reqId: 345327051 symbol: 'AMZN' localSymbol: '' isActive: 0 quotesReceived: 3 quotesToReceive: 3 quotesBufferSize: 10 genericTickList: '' data: [1x1 struct] contract: [1x1 com.ib.client.Contract] >> dataStruct.data ans = dateNum: [735551.008912037 735551.008969907 735551.009027778] dateTime: {1x3 cell} open: [349.97 349.97 349.97] high: [349.97 349.97 349.97] low: [349.97 349.97 349.97] close: [349.97 349.97 349.97] volume: [0 0 0] WAP: [349.97 349.97 349.97] count: [0 0 0] >> dataStruct.data.dateTime ans = '13-Nov-2013 00:12:50' '13-Nov-2013 00:12:55'
'13-Nov-2013 00:13:00'
These messages can safely be ignored. They represent harmless requests by IBMatlab to IB, to cancel realtime bar requests that were already cancelled on the IB server. Realtime bar requests are subject to both historical data pacing limitations (see 6 for details) and streaming data pacing limitations (7.1). You may be able to loosen the limitations by purchasing additional data slots from IB. Discuss your alternatives with IB customer service, if you encounter pacing violation messages:
[API.msg2] Invalid Real-time Query: Historical data request pacing violation {8314, 420}
37
Here is a summary of the IBMatlab parameters that directly affect realtime bars: Parameter Data type Default Description string '' Needs to be 'realtime_bars' for this feature Action integer 1 One of: QuotesNumber inf continuous endless streaming bars for the specified security N>1 stream only N bars 1 get only a single bar (i.e., nonstreaming snapshot) (default) 0 stop streaming quotes -1 return the latest accumulated bars data while continuing to stream new data 1 Controls the number of streaming bars QuotesBufferSize integer stored in a cyclic buffer. Once this number of bars has been received, the oldest bar is discarded whenever a new bar arrives. string '' Used to request additional (non-default) GenericTickList information: volume, last trade info, etc.46 string '' Used to identify and store streamed bars. LocalSymbol SecType Expiry WhatToShow string string 'STK' Used to identify and store streamed bars. '' Used to identify and store streamed bars.
UseRTH
string (case 'Trades' Determines the nature of data being insensitive) extracted. Valid values include: Trades (default) Midpoint Bid Ask integer or 0 = Determines whether to return all data logical flag false available during the requested time span, or only data that falls within Regular Trading Hours. Valid values include: 0 or false (default): all data is returned even where the market in question was outside of its regular trading hours 1 or true: only data within the regular trading hours is returned, even if the requested time span falls partially or completely outside of the RTH.
46
https://www.interactivebrokers.com/en/software/api/apiguide/tables/generic_tick_types.htm
38
8 Sending trade orders Three classes of trade orders are supported in IB-Matlab: Buy, Sell, and Short. These are implemented in IBMatlab using the corresponding values for the Action parameter: 'Buy', 'Sell', and 'SShort'. Several additional IBMatlab parameters affect trade orders. The most widely-used properties are Type (default='LMT'), Quantity, and LimitPrice. Additional properties are explained below. Here is a simple example for buying and selling a security:
orderId = IBMatlab('action','BUY','symbol','GOOG','quantity',100,... 'type','LMT', 'limitPrice',600); orderId = IBMatlab('action','SELL','symbol','GOOG','quantity',100,... 'type','LMT', 'limitPrice',600);
In this example, we have sent an order to Buy/Sell 100 shares of GOOG on the SMART exchange, using an order type Limit and limit price of USD 600. IBMatlab returns the corresponding orderId assigned by IB we can use this orderID later to modify open orders, cancel open orders, or follow-up in TWS or in the trade logs. IBs API supports a long list of order types. Unfortunately, many of these may not be available on your TWS and/or for the requested exchange and security type.47 You need to carefully ensure that the order type is accepted by IB before using it in IBMatlab. Here is the list of order types supported by IBMatlab, which is a subset of the list in IBs documentation:48 Class Order type Order type Description full name abbreviation Limit LMT Buy or sell a security at a specified price or better. Market-toMTL A Market-To-Limit order is sent as a Market order to Limit execute at the current best price. If the entire order does not immediately execute at the market price, the remainder of the order is re-submitted as a Limit order with the limit price set to the price at which the Limit market order portion of the order executed. risk Market with MKT PRT A Market With Protection order is sent as a Market Protection order to execute at the current best price. If the entire order does not immediately execute at the market price, the remainder of the order is re-submitted as a Limit order with the limit price set by Globex to a price slightly higher/lower than the current best price
47 48
http://www.interactivebrokers.com/en/index.php?f=4985 http://www.interactivebrokers.com/en/software/api/apiguide/tables/supported_order_types.htm
39
Order type Order type Description full name abbreviation Stop STP A Stop order becomes a Market order to buy (sell) once market price rises (drops) to the specified trigger price (the AuxPrice parameter) Stop Limit STP LMT A Stop Limit order becomes a Limit order to buy (sell) once the market price rises (drops) to the specified trigger price (the AuxPrice parameter) Trailing TRAIL LIT A Trailing Limit-If-Touched sell order sets the Limit if trigger price at a fixed amount (or %) above the Touched market price. If the market price falls, the trigger price falls by the same amount; if the market price rises, the trigger price remains unchanged. If the price rises all the way to the trigger price, the order is submitted as a Limit order. (and vice versa for buy orders) Trailing TRAIL MIT A Trailing Market-If-Touched sell order sets a Market If trigger price at a fixed amount (or %) above the Touched market price. If the market price falls, the trigger price falls by the same amount; if the market price Limit rises, the trigger price remains unchanged. If the risk price rises all the way to the trigger price, the order is submitted as a Market order. (and vice versa for buy orders) Trailing TRAIL A Trailing Stop sell order sets the stop trigger price Stop at a fixed amount (or %) below the market price. If the market price rises, the stop trigger price rises by the same amount; if the market price falls, the trigger price remains unchanged. If price falls all the way to trigger price, the order is submitted as a Market order (and vice versa for buy orders) Trailing TRAIL A Trailing Stop Limit sell order sets the stop trigger Stop Limit LIMIT price at a fixed amount (or %) below the market price. If the market price rises, the stop trigger price rises by the same amount; if the market price falls, the trigger price remains un-changed. If the price falls all the way to the trigger price, the order is submitted as a Limit order. (and vice versa for buy orders) Market MKT An order to buy (sell) a security at the offer (bid) Execut price currently available in the marketplace. There is ion no guarantee that the order will fully or even speed partially execute at any specific price. Class
40
Class
Order type Order type Description full name abbreviation Market-ifMIT A Market-if-Touched order becomes a Market order Touched to buy (sell) once the market price drops (rises) to the specified trigger price. Market-onMOC Market-on-Close will execute as a Market order Close during the market close time, as close to the closing price as possible. Pegged-to- PEG MKT A Limit order whose price adjusts automatically Market relative to market price, using specified offset amount Relative REL An order whose price is dynamically derived from the current best bid (offer) in the marketplace. For a buy order, the price is calculated by adding the specified offset (or %) to the best bid. A limit price may optionally be entered to specify a cap for the amount you are willing to pay. (and vice versa for sell orders) Box Top BOX TOP A Market order that is automatically changed to Limit order if it does not execute immediately at market price Limit-onLOC Limit-on-close will execute at the market close time, Close at the closing price, if the closing price is at or better than the limit price, according to the exchange rules; Otherwise the order will be cancelled. Limit if LIT A Limit-if-Touched order becomes a Limit order to Touched buy (sell) once the market price drops (rises) to the specified trigger price. Pegged-to- PEG MID A Limit order whose price adjusts automatically Midpoint relative to midpoint price using specified offset amt TWAP TWAP Achieves the Time-Weighted Average Price on a best efforts best-effort basis (see details in 9.2 below). VWAP VWAP Achieves the Volume-Weighted Average Price on a best efforts best-effort basis (see details in 9.1 below). VWAP - Guarrante- The VWAP for a stock is calculated by adding the guaranteed edVWAP dollars traded for every transaction in that stock ("price" x "number of shares traded") and dividing the total shares traded. By default, a VWAP order is computed from the open of the market to the market close, and is calculated by volume weighting all transactions during this time period. TWS allows you to modify the cut-off, expiration times using Time in Force and Expiration Date fields respectively
41
In addition to specifying the order Type, Quantity and LimitPrice, several other parameters may need to be specified to fully describe the order. Here is a summary of the parameters that directly affect trade orders in IBMatlab:49 Parameter Action Data type Default Description String (none) One of: 'Buy', 'Sell', or 'SShort' (note the double-S in SShort) Integer 0 Number of requested shares Quantity String 'LMT' Refer to the order-types table above Type Number 0 Limit price used in Limit order types LimitPrice Number 0 Extra numeric data used by some order types AuxPrice (e.g., STP uses AuxPrice, not LimitPrice) 0 The stop price used when Type='TrailLimit' TrailStopPrice Number String 'GTC' Time-in-Force. Not all TIFs are available for TIF all orders. Can be one of: 'Day' Good until end of trading day 'DTC' Day Till Cancelled 'GTC' Good Till Cancelled (default) 'GTD' Good Till Date (uses the GoodTillDate parameter below) 50 'GAT' Good After Time/date (uses GoodAfterTime parameter below) 51 'IOC' Immediate or Cancel 'FOK' Fill or Kill52 'OPG' Open Price Guarantee53 'AUC' Auction, submitted at the Calculated Opening Price54
49 50
Also see the corresponding API documentation: http://www.interactivebrokers.com/en/software/api/apiguide/java/order.htm GTD requires enabling Advanced Time In Force Attributes in the Preferences page of TWS / IB Gateway (http://www.interactivebrokers.com/en/software/webtraderguide/webtrader.htm#webtrader/orders/advanced_time_in_force_att ributes.htm) GAT requires enabling Advanced Time In Force Attributes in the Preferences page of TWS / IB Gateway (http://www.interactivebrokers.com/en/software/webtraderguide/webtrader.htm#webtrader/orders/advanced_time_in_force_att ributes.htm). For additional information on GAT see http://www.interactivebrokers.com/en/software/tws/usersguidebook/ordertypes/good_after_time.htm FOK is not officially supported, according to IBs API documentation (http://www.interactivebrokers.com/en/software/api/apiguide/tables/supported_order_types.htm). FOK requires the entire order to be filled, as opposed to IOC that allows a partial fill. For additional information on FOK see http://www.interactivebrokers.com/en/software/tws/usersguidebook/ordertypes/fill_or_kill.htm OPG is not officially supported, according to IBs API documentation (http://www.interactivebrokers.com/en/software/api/apiguide/tables/supported_order_types.htm). An OPG is used with a Limit order to indicate a Limit-on-Open order, or with a Market order to indicate a Market-on-Open order (http://www.interactivebrokers.com/en/software/webtraderguide/webtrader/orders/creating_an_order.htm) AUC is not officially supported, according to IBs API documentation (http://www.interactivebrokers.com/en/software/api/apiguide/tables/supported_order_types.htm). For additional information on AUC see http://www.interactivebrokers.com/en/software/tws/usersguidebook/ordertypes/auction.htm
51
52
53
54
42
Parameter GoodTillDate
Data type Default Description string '' Format: 'YYYYMMDD hh:mm:ss TMZ' (TMZ is optional55) '' Format: 'YYYYMMDD hh:mm:ss TMZ' GoodAfterTime string (TMZ is optional56) integer or 0=false 0 or false: order should not execute OutsideRTH logical outside regular trading hours flag 1 or true: order can execute outside regular trading hours if required string '' The specific IB account used for this trade. AccountName Useful when you handle multiple IB accounts, otherwise leave empty. string '' The Financial Advisor allocation profile to FAProfile which trades will be allocated. Only relevant for Financial Advisor accounts, otherwise leave empty. string '' One-Cancels-All group name. This can be OCAGroup specified for several trade orders so that whenever one of them gets cancelled or filled, the others get cancelled automatically. 0 One of:57 TriggerMethod integer 0=Default 1=Double-Bid-Ask 2=Last 3=Double-Last 4=Bid-Ask 7=Last-or-Bid-Ask 8=Mid-point
55 56 57
The list of time zones accepted by IB is listed in 9.1 below The list of time zones accepted by IB is listed in 9.1 below http://www.interactivebrokers.com/en/software/tws/usersguidebook/configuretws/modify_the_stop_trigger_method.htm
43
Parameter BracketDelta
Data type Default Description number []=empty Price offset for stop-loss and take-profit bracket child orders (see 9.3 below). 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 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, and 9.3 below for additional details.
BracketTypes
ParentId
OrderId
Hold
Sell: {'LMT', 'STP'} integer 0 Useful for setting child orders of a parent order: these orders are only active when their parent OrderId is active or gets triggered. This is normally used in bracket orders (see 9.3 below), but can also be used otherwise. integer (auto- If specified, and if the specified OrderId is assigned) still open, then the specified order data will be updated, rather than creating a new order. This enables users to modify the order Type, LimitPrice and other important parameters of existing open orders (see 10 below). integer or 0=false 0 or false: order will be sent to IB logical immediately flag 1 or true: order will be prepared but not sent to IB. The user can them modify the order properties before sending to IB. See 9.6 below for additional details.
44
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 and combo orders. 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.58 IBMatlab enables specifying the algo strategys properties, as follows: Parameter MaxPctVol Description Percent of participation of average daily volume up to 0.5 (=50%). string '9:00:00 EST' Format: 'YYYYMMDD hh:mm:ss StartTime TMZ' (TMZ is optional) string '16:00:00 EST' (same as StartTime above) EndTime 1=true If true, allow the algo to continue to AllowPastEndTime integer or logical flag work past the specified end time if the full quantity has not been filled. integer or 0=false If true, discourage the VWAP algo NoTakeLiq logical flag from hitting the bid or lifting the offer if possible. This 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. 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);
Default 0.1=10%
58
http://www.interactivebrokers.com/en/trading/orders/vwapAlgo.php; http://www.interactivebrokers.com/en/software/tws/usersguidebook/algos/vwap.htm
45
When we run the command above in Matlab, we see the following in IBs TWS:
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. The End Time 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 AllowTradingPastEndTime=1. If an EndTime is specified, then set AllowTradingPastEndTime=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 that acceptability of the time period using yesterdays 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 todays date will be used, at 10:45:00 EST. The time-zone part is also optional, but we strongly recommend specifying it, to prevent ambiguities. Not all of the worlds time zones are accepted, but some of the major ones are, and you can always convert a time to one of these time zones. The full list of time-zones supported by IB is given below: 59 Time zone supported by IB GMT EST MST PST AST JST AET Description Greenwich Mean Time Eastern Standard Time Mountain Standard Time Pacific Standard Time Atlantic Standard Time Japan Standard Time Australian Standard Time
http://www.interactivebrokers.com/en/software/api/apiguide/tables/supported_time_zones.htm
46
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.60 IBMatlab enables specifying the algo strategys properties, as follows: Parameter StrategyType Default Description 'Marketable' One of: 'Marketable' (default) 'Matching Midpoint' 'Matching Same Side' 'Matching Last' string '9:00:00 EST' Format: 'YYYYMMDD hh:mm:ss StartTime TMZ' (TMZ is optional) string '16:00:00 EST' (same as StartTime above) EndTime 1=true If true, allow the algo to continue to AllowPastEndTime integer or logical flag work past the specified end time 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. IB only enables TWAP algo orders for US equities.
60
http://www.interactivebrokers.com/en/trading/orders/twapAlgo.php; http://www.interactivebrokers.com/en/software/tws/usersguidebook/algos/twap.htm
47
9.3 Bracket 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.61 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 orders LimitPrice. If BracketDelta is 2-value array [lowerDelta,upperDelta], then lowerDelta is used as the offset for the lower child, and upperDelta is used for the upper child; if BracketDelta is a single number, then this offset is used for both child orders. The corresponding child order limits will be set to LimitPrice-lowerDelta and LimitPrice+upperDelta, 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]);
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.
61
http://www.interactivebrokers.com/en/trading/orders/bracket.php, http://ibkb.interactivebrokers.com/node/1043
48
The child orders are shown above their parent as inactive (red; IB status: Waiting for parent order to fill). These orders are of 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.1, 4.2 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'});
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).
49
9.4 Automated orders Automated orders are similar to orders of types REL and TRAIL. The idea is to modify a Limit orders 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 orders LimitPrice (and possibly the order Type) accordingly. Unlike IBs REL and TRAIL order types (and their variants, e.g., TRAIL MIT etc.), which update the LimitPrice continuously, IBMatlabs automated orders are only updated periodically. This could be problematic in highly-volatile securities in such cases users should use IBs standard REL and TRAIL. However, for low-volatility securities, the flexibility offered by IBMatlabs automated orders could be beneficial. The parameters that affect automated orders in IBMatlab are the following: Parameter LimitBasis LimitDelta LimitRepeatEvery LimitUpdateMode Data type string Description One of: 'BID', 'ASK'. LimitBasis cannot be used together with LimitPrice. integer 0 Units of the securitys minimal tick value number 0 Update timer period in seconds number 0 Mode of the periodic limit update: 0: limit increases or decreases based on the latest market bid/ask price 1: limit can only increase; if market price decreases, limit remains as-is -1: limit can only decrease; if the price increases, limit remains as-is 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 string 'MKT' The new order type to be used at LimitChangeTime number 0 Override the securitys 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 above). Default (none)
LimitChangeTime
LimitChangeType Tick
50
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 etc.). If it is determined that the trade order should be modified, then an update command is sent to the IB server (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 IBMatlabs 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);
51
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, Expiry, Strike, and Right) in a cell array wherever the different legs have different values. In addition, you must specify the ComboActions parameter. You can also specify the ComboRatios parameter, but this is optional:62
orderId = IBMatlab('action','buy', 'exchange','CFE', 'quantity',1, ... 'SecType','FUT', 'LocalSymbol',{'VXZ2','VXX2'}, ... 'ComboActions',{'Buy','Sell'}, 'AccountName','D123')
Alternately, 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'}, 'AccountName','D123')
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: reqTime: dataTime: dataTimestamp: ticker: bidPrice: askPrice: bidSize: askSize: open: close: low:
62
230455081 '26-Oct-2012 04:24:22' '26-Oct-2012 04:24:23' 7.3517e+05 '' -6.8500 -6.7500 748 287 -1 -1 -1
By default, IBMatlab uses ratios of [1,1], i.e. the same ratio for all legs. You can specify any array of positive values that shall be used to determine the relative weights of the legs.
IB-Matlab User Guide high: lastPrice: volume: tick: contract: contractDetails: -1 -1 -1 0.2500 [1x1 struct] [1x1 struct]
52
Note that only instantaneous market bid/ask data is returned the open, close, low, high, volume and lastPrice information are not returned. IB only supports combo trades for a small subset of securities (generally speaking, US options and futures). FOREX, for example, is currently NOT supported. 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 we specified one or more of the legs incorrectly; or maybe we are not subscribed for realtime data for any of the legs; or perhaps IB does not support the combo for the specific legs that we requested. 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:
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',[3,5])
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 instance, in the above example, the ComboRatios for the ZT/ZN spread was set to 3:5 since the ECBOT exchange does not support any other ratio. Note that this ratio may change from time to time: the ZT/ZN spread ratio was 1:2 in early 2013, and changed to 3:5 later that year. When specifying the spreads LocalSymbol, be careful to enter all the spaces in there. For example, the ZN LocalSymbol has 4 spaces between ZN and MAR. IB is super sensitive about this and if you specify a LocalSymbol that is even slightly incorrect then IB will complain that it cannot find the specified contract.
53
The parameters that affect combo orders in IBMatlab are the following: Parameter Symbol Data type Default Description String or cell- (none) The symbol(s) of the underlying leg array of strings assets. String or cell'' The local exchange symbol of the LocalSymbol array of strings underlying leg asset. When left empty, IB sometimes tries to infer it from Symbol and the other properties. String or cell'STK' One of: 'STK', 'OPT', 'FUT', 'IND', 'FOP' SecType array of strings (but not 'CASH' or 'BAG') for the legs. String or cell- 'SMART' The exchange that should process the Exchange array of strings request for the corresponding legs. String or cell'USD' The currency for the corresponding legs. Currency array of strings String or cell'' 'YYYYMM' or 'YYYYMMDD' format, Expiry array of strings for each of the combo legs. Number or 0.0 The strike price (for options) of the Strike numeric array corresponding legs. String or cell'' One of: 'P', 'PUT', 'C', 'CALL' for each of Right array of strings the combo legs. {} Array of corresponding leg actions. For ComboActions Cell-array of strings example: {'Sell', 'Buy'} [1,1] Array of corresponding leg weights. Any ComboRatios Numeric array of positive number is accepted it is the relative numbers values that matter. String '' The exchange symbol of the combo-bag ComboBag spread. When left empty, IBMatlab will Symbol use the last legs Symbol and LocalSymbol for the parent bag contract.
54
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 objects m_secIDType and m_secId properties63), or to specify the All-or-None flag (via the order objects m_allOrNone property64). These properties are not available as IBMatlab parameters, but they can still be specified in IB-Matlab using the ibConnectionObject Java object returned by IBMatlab as a second output value, as explained in 15 below. There are several ways in which we can create and update the contract: We can use ibConnectionObject to create the initial contract and order objects, modify their requested properties, then use ibConnectionObject again to send the order to IB. 15.3 shows a usage example of this. We can use IBMatlabs Hold parameter (see 8) to prepare the contract and order object, then modify them with the extra properties, and finally use ibConnectionObject to send the order to IB. The difference vs. the previous method is that we dont need to create the contract and order objects IBMatlab takes care of this for us.
In all cases, we would use the ibConnectionObject.placeOrder function to send the updated contract and order to IB for processing. Here is a typical usage example:
% Prepare initial contract and order objects using the Hold mechanism [orderId, ibConnectionObject, contract, order] = ... IBMatlab('action','BUY', 'Hold',true, ...); % Modify some contract properties contract.m_secIdType = 'ISIN'; contract.m_secId = 'US0378331005'; % Modify some order properties order.m_clearingIntent = 'Away'; order.m_settlingFirm = 'CSBLO'; order.m_allOrNone = true; % Send the modified order to IB ibConnectionObject.placeOrder(orderId, contract, order);
% =Apple Inc.
Note that the contract and order objects are only returned from IBMatlab for trading orders (i.e., Action = 'Buy', 'Sell' or 'SShort'), but not for other IBMatlab actions.
63 64
http://www.interactivebrokers.com/en/software/api/apiguide/java/contract.htm http://www.interactivebrokers.com/en/software/api/apiguide/java/order.htm
55
The Hold mechanism can be used to programmatically prepare an order for later manual approval and transmission in TWS:
% Prepare initial contract and order objects using the Hold mechanism [orderId, ibConnectionObject, contract, order] = ... IBMatlab('action','BUY', 'Hold',true, ...); % Modify the order to NOT transmit immediately from TWS to IB server order.m_transmit = false; % Send the modified order to IB ibConnectionObject.placeOrder(orderId, contract, order);
This will create the order in TWS without transmitting it. You will see the order in TWSs API tab with a button to transmit:
Right-clicking anywhere in the row will present a menu with additional options:
56
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='query' and Type='open' as follows:
>> data = IBMatlab('action','query', 'type','open') 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 three open bracket orders from 9.3 above. You can access any of the orders using the standard Matlab dot notation:
>> data(1) ans = orderId: contract: order: orderState: status: filled: remaining: avgFillPrice: permId: parentId: lastFillPrice: clientId: whyHeld: message: 154410310 [1x1 struct] [1x1 struct] [1x1 struct] 'Submitted' 0 100 0 989560927 0 0 8981 [] [1x162 char]
IB-Matlab User Guide >> data(2) ans = orderId: contract: order: orderState: status: filled: remaining: avgFillPrice: permId: parentId: lastFillPrice: clientId: whyHeld: message: 154410311 [1x1 struct] [1x1 struct] [1x1 struct] 'PreSubmitted' 0 100 0 989560928 154410310 0 8981 'child,trigger' [1x182 char]
57
Each of the order structs contains the following data fields:65 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.
orderId
this is a struct object that contains the Contract information, including all the relevant information about the affected security
contract order
this is another struct object that contains information about the specific trade orders parameters 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 structs fields.
orderState status filled
indicates the order status e.g., Submitted, PreSubmitted, etc. indicates the number of shares that have been executed in the order number of shares remaining to be executed in the order average price of the filled (executed) shares; 0 if no fills
remaining
avgFillPrice permId
the permanent ID used to store the order in the IB server the order ID of the orders parent order; 0 if no parent last price at which shares in the order were executed ID of the client used for sending the order (see 13 below)
parentId
a detailed message string stating the orders state. This is basically just a string that contains all the fields above and their values.
65
http://www.interactivebrokers.com/en/software/api/apiguide/java/orderstatus.htm
58
For example:
>> data(2).contract ans = m_conId: m_symbol: m_secType: m_expiry: m_strike: m_right: m_multiplier: m_exchange: m_currency: m_localSymbol: m_primaryExch: m_includeExpired: m_secIdType: m_secId: m_comboLegsDescrip: m_comboLegs: m_underComp: >> data(1).order ans = CUSTOMER: FIRM: OPT_UNKNOWN: OPT_BROKER_DEALER: OPT_CUSTOMER: OPT_FIRM: OPT_ISEMM: OPT_FARMM: OPT_SPECIALIST: AUCTION_MATCH: AUCTION_IMPROVEMENT: AUCTION_TRANSPARENT: EMPTY_STR: m_orderId: m_clientId: m_permId: m_action: m_totalQuantity: m_orderType: m_lmtPrice: m_auxPrice: m_tif: m_ocaGroup: m_ocaType: m_transmit: m_parentId: 0 1 '?' 'b' 'c' 'f' 'm' 'n' 'y' 1 2 3 '' 154410311 8981 989560928 'SELL' 100 'STP' 580 0 'GTC' '989560927' 3 1 154410310
IB-Matlab User Guide >> data(1).orderState ans = m_status: m_initMargin: m_maintMargin: m_equityWithLoan: m_commission: m_minCommission: m_maxCommission: m_commissionCurrency: m_warningText:
59
Dont let the number 1.79769313486232e+308 alarm you this is simply IBs way of specifying uninitialized data. Note: IB warns66 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 Symbol and/or OrderId. For example:
>> data = IBMatlab('action','query','type','open','OrderId',154410310) data = orderId: 154410310 contract: [1x1 struct] order: [1x1 struct] orderState: [1x1 struct] (etc.)
Of course, it is possible that there are no open orders that match the filtering criteria:
>> data = IBMatlab('action','query', 'type','open', 'symbol','xyz') data = []
Note that you can only retrieve (and modify) open orders that were originally sent by your IB-Matlab ClientID. Trades that were placed directly in TWS, or via another API client that connects to TWS, or by another IB-Matlab connection session with a different ClientID, will not be accessible to you. If this limitation affects your work, you could try to 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). See 13 below for additional details on ClientID.
66
http://www.interactivebrokers.com/en/software/api/apiguide/java/orderstatus.htm
60
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 = 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','query','type','open','OrderId',orderId)) % Send the trade with modified parameters IBMatlab('action','BUY', 'symbol','GOOG', 'quantity',50, ... 'type','MKT', 'orderID',orderId); end
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','query','type','open','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. Alternately, 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, ibConnectionObject] = IBMatlab('action','BUY', ...); % Cancel the order using the underlying Java connector object ibConnectionObject.cancelOrder(orderId);
61
11 Processing IB events 11.1 Processing events in IB-Matlab IB uses an asynchronous event-based mechanism for sending information to clients. This means that we do not simply send a request to IB and wait for the answer. Instead, we send a request, and when IB is ready it will send us one or more (or zero) events in response. These events carry data, and by analyzing the stored event data we (hopefully) receive the answer that we were waiting for. These callbacks are constantly being fired (i.e., invoked) by asynchronous messages from IB, ranging from temporary market connection losses/reconnections, to error messages and responses to market queries. Some of the events are triggered by user actions (market or portfolio queries, for example), while others are triggered by IB (e.g., disconnection notifications). The full list of IB events (and their data) is documented in the online API documentation.67 Matlab has built-in support for asynchronous events, called Callbacks in Matlab jargon.68 Whereas Matlab callbacks are normally used in conjunction with Graphical User Interfaces (GUI), they can also be used with IB-Matlab, which automatically converts all the Java events received from IB into Matlab callbacks. There are two types of callbacks that you can use in IB-Matlab: Generic callback this is a catch-all callback function that is triggered upon any IB event. Within this callback, you would need to write some code to distinguish between the different event types in order to process the events data. A skeleton for this is given below. The parameter controlling this callback in IBMatlab is called CallbackFunction. Specific callback this is a callback function that is only triggered when the specific event type is received from IB. Since the event type is known, you can process its event data more easily than in the generic callback case. However, you would need to specify a different specific callback for each of the event types that you wish to process.
The parameters controlling the specific callbacks in IBMatlab are called CallbackXXX, where XXX is the name of the IB event (the only exception to this rule is CallbackMessage, which handles the IB error event the reason is that this event sends informational messages in addition to errors,69 so IBs event name is misleading in this specific case).
67 68 69
62
When you specify any callback function to IBMatlab, either the generic kind (CallbackFunction) or a specific kind (CallbackXXX), the command action does not even need to be related to the callback (for example, you can set CallbackExecDetails together with Action='query').
data = IBMatlab('action','query', ..., ... 'CallbackExecDetails',@IBMatlab_CallbackExecDetails);
where IBMatlab_CallbackExecDetails() is a Matlab function created by you that accepts two input parameters:
hObject
the Java connector object that is described in 15 below a Matlab struct that contains the events data in separate fields
eventData
You can pass external data to your callback functions using the callback cell-array format. For example, to pass two extra data values:70
callbackDetails = {@IBMatlab_CallbackExecDetails, 123, 'abc'}; IBMatlab('action','query',..., 'CallbackExecDetails',callbackDetails); function IBMatlab_CallbackExecDetails(ibConn,eventData,extra1,extra2) % do the callback processing here end
When you specify any callback function to IBMatlab, you only need to set it once, in any IBMatlab command. Unlike most IBMatlab parameters, which are not remembered across IBMatlab commands and need to be re-specified, callbacks do not need to be re-specified. They are remembered from the moment they are first set, until such time as Matlab exits or the callback parameter is changed.71 To reset a callback (i.e., remove the callback invocation), simply set the callback parameter value to [] (empty square brackets) or '' (empty string):
data = IBMatlab('action','query', ..., 'CallbackExecDetails','');
Matlab callbacks are invoked even if you use the Java connector object (see 15) for requesting data from IB. This is actually very useful: we can use the connector object to send a request to IB, and then process the results in a Matlab callback function.
70 71
http://www.mathworks.com/help/matlab/creating_guis/writing-code-for-callbacks.html#brqow8p It is not an error to re-specify the callbacks in each IBMatlab command, it is simply useless and makes the code less readable
63
Using Matlab callbacks with the Java connector object can be used, for example, to implement combo trades,72 as an alternative to the built-in mechanism described in 9.5 above. In this case, separate contracts are created for the separate combo legs, then submitted to IB via the Java connectors reqContractDetails() method, awaiting the returned IDs via the Matlab callback to the ContractDetails event (see CallbackContractDetails in the table below). Once the IDs for all the legs are received, com.ib.client.ComboLeg objects73 are created. The completed order can then be submitted to IB for trading via the Java connectors placeOrder() method. All this may appear a bit difficult to implement, but in fact can be achieved in only a few dozen lines of code. This example illustrates how Matlab callbacks can seamlessly interact with the underlying Java connectors methods. Here is the list of currently-supported callback events in IBMatlab (for additional information about any of the callbacks, follow the link in the IB Event column): IBMatlab parameter
CallbackAccountDownloadEnd
IB Event
accountDownloadEnd
Called when?
in response to account queries, after all UpdateAccount events were sent, to indicate end of data in response to calling reqAccountSummary() on the Java connector when all AccountSummary events have been sent, to indicate end of data in response to market queries; not really used in IBMatlab immediately after a trade execution, or when requesting executions (see 12.1 below) when IB-Matlab loses its connection (or reconnects) to TWS/Gateway in response to market queries; used in IBMatlab only to get the tick value when all ContractDetails events have been sent, to indicate end of data numerous times during regular work; returns the current server system time in response to a Delta-Neutral DN RFQ
CallbackAccountSummary
accountSummary
No
No Yes Yes
CallbackConnectionClosed
connectionClosed
Yes
CallbackContractDetails
contractDetails
Yes
CallbackContractDetailsEnd
contractDetailsEnd
Yes
CallbackCurrentTime
currentTime
Yes No
CallbackDeltaNeutralValidation deltaNeutralValidation
72 73
http://www.interactivebrokers.com/en/software/api/apiguide/java/placing_a_combination_order.htm http://www.interactivebrokers.com/en/software/api/apiguide/java/comboleg.htm#XREF_interoperability_socket66
64
IBMatlab parameter
IB Event
Called when?
whenever an order is partially or fully filled, or in response to reqExecutions() on the Java connector when all the ExecDetails events have been sent, to indicate end of data in response to calling reqFundamentalData() on the Java connector in response to a historical data request, for each of the result bars separately when a successful connection is made to a Financial Advisor account, or in response to calling reqManagedAccts ()on the Java connector when the market type is set to Frozen or RealTime, to announce the switch, or in response to calling reqMarketDataType() on the Java connector whenever IB wishes to send the user an error or informational message. See 14 below. after connecting to IB in response to a user query for open orders, for each open order after all OpenOrder events have been sent for a request, to indicate end of data in response to a user query for open orders (for each open order), or when an orders status changes in response to calling reqPositions() on the Java connector After all Position events have been sent for a request, to indicate end of data in response to a market query, for price fields (e.g., bid) in response to a market query, for size fields (e.g., bidSize)
CallbackExecDetails
execDetails
CallbackExecDetailsEnd
execDetailsEnd
Yes
CallbackFundamentalData
fundamentalData
No
CallbackHistoricalData
historicalData
Yes
CallbackManagedAccounts
managedAccounts
No
CallbackMarketDataType
marketDataType
No
CallbackOrderStatus
orderStatus
Yes
CallbackPosition
position
No
No Yes Yes
65
IBMatlab parameter
CallbackTickString CallbackTickGeneric CallbackTickEFP
IB Event
tickString tickGeneric tickEFP
Called when?
in response to a market query, for string fields (e.g., lastTimestamp) in response to a query with a GenericTickList param when the market data changes. Values are updated immediately with no delay. when the market of an option or its underlier moves. TWSs option model volatilities, prices, and deltas, along with the present value of dividends expected on that underlier are received when all events in response to a snapshot query request have been sent, to indicate end of data in response to a realtime bars request, for each of the result bars separately in response to calling requestFA() on the Java connector in response to a user query for scanner data, for each result row when the last scannerData event has been sent, to indicate end of data in response to a user query for scanner parameters XML together with the UpdateAccountValue callbacks, to report on the event time for every single property in the list of account properties, when the account data is requested (see 4) or updated when market depth has changed when the Level II market depth has changed for each new bulletin if the client has subscribed by calling reqNewsBulletins() on the Java connector when account updates are requested or occur
CallbackTickOptionComputation tickOptionComputation
No
CallbackTickSnapshotEnd
tickSnapshotEnd
Yes
CallbackRealtimeBar
realtimeBar
Yes
Yes No No
CallbackUpdateNewsBulletin
updateNewsBulletin
No
CallbackUpdatePortfolio
updatePortfolio
Yes
66
11.2 Example using CallbackExecDetails to track executions The execDetails event is triggered whenever an order is fully or partially executed. Let us trap this event and send the execution information into a CSV file for later use in Excel (also see 12 below):
orderId = IBMatlab('action','BUY', 'symbol','GOOG', 'quantity',1, ... 'limitPrice',600, ... 'CallbackExecDetails',@IBMatlab_CallbackExecDetails);
Where the function IBMatlab_CallbackExecDetails is defined as follows (for example, in a file called IBMatlab_CallbackExecDetails.m):74
function IBMatlab_CallbackExecDetails(ibConnector, eventData, varargin) % Extract the basic event data components contractData = eventData.contract; executionData = eventData.execution; % Example of extracting data from the contract object: % http://www.interactivebrokers.com/en/software/api/apiguide/java/contract.htm symbol = char(eventData.contract.m_symbol); secType = char(eventData.contract.m_secType); % ... several other contract data field available - see above webpage % Example of extracting data from the execution object: % http://www.interactivebrokers.com/en/software/api/apiguide/java/execution.htm orderId = eventData.execution.m_orderId; execId = char(eventData.execution.m_execId); time = char(eventData.execution.m_time); exchange = char(eventData.execution.m_exchange); side = char(eventData.execution.m_side); shares = eventData.execution.m_shares; price = eventData.execution.m_price; permId = eventData.execution.m_permId; liquidation = eventData.execution.m_liquidation; cumQty = eventData.execution.m_cumQty; avgPrice = eventData.execution.m_avgPrice; % ... several other execution data field available - see above webpage % Convert the data elements into a comma-separated string csvline = sprintf('%s,%d,%s,%d,%d,%f\n', time, orderId, symbol, ... shares, cumQty, price); % Now append this comma-separated string to the CSV file fid = fopen('executions.csv', 'at'); % 'at' = append text fprintf(fid, csvline); fclose(fid); end % IBMatlab_CallbackExecDetails
74
67
11.3 Example using CallbackTickGeneric to check if a security is shortable In this example, we attach a user callback function to tickGeneric events in order to check whether a security is shortable75 (also see 5 above). Note: according to IB,76 Generic Tick Tags cannot be specified if you elect to use the Snapshot market data subscription, and therefore we need to use the streamingquotes mechanism, so QuotesNumber>1:
orderId = IBMatlab('action','Query', 'symbol','GOOG', ... 'GenericTicklist','236', 'QuotesNumber',2, ... 'CallbackTickGeneric',@IBMatlab_CallbackTickGeneric);
Note that in this particular example we could also have simply used the streaming quotes data, instead of using the callback:
>> dataS = IBMatlab('action','query','symbol','GOOG','quotesNumber',-1); >> shortableValue = dataS.data.shortable; % =3 for GOOG
75 76 77
68
11.4 Example using CallbackContractDetails to get a contracts full options chain In this example, we attach a user callback function to contractDetails events in order to receive the full list of LocalSymbols and associated contract properties of an underlying securitys options chain. As noted in 3 above, it is not possible to receive the entire list of option prices in a single command each market price requires a separate request with a specific LocalSymbol. However, we can use the contractDetails event to extract the full list of option LocalSymbols in a single command. This relies on the fact that when the Right and Strike parameters of a contract are empty, IB returns the full list of contracts matching the other specifications. We first define our callback function for the event:
function IBCallbackContractDetails(ibConnector, eventData) contract = eventData.contractDetails.m_summary; fprintf([char(contract.m_localSymbol) char(contract.m_secType) char(contract.m_symbol) char(contract.m_expiry) char(contract.m_right) char(contract.m_multiplier) num2str(contract.m_strike) end % IBCallbackContractDetails '\t' ... '\t' ... '\t' ... '\t' ... '\t' ... '\t' ... '\n']);
Now we ask IB for the current market data of the contract with empty Right and Strike. We can safely ignore the IB warning about ambiguous or missing security definition:
>> data=IBMatlab('action','query', 'symbol','CL', 'secType','FOP',... 'exchange','NYMEX', 'currency','USD', ... 'expiry','201306', 'right','', 'strike',0.0, ... 'CallbackContractDetails',@IBCallbackContractDetails) [API.msg2] The contract description specified for CL is ambiguous; you must specify the multiplier. {286356018, 200} LOM3 P6650 FOP CL 20130516 LOM3 P8900 FOP CL 20130516 LOM3 P11150 FOP CL 20130516 LOM3 C6400 FOP CL 20130516 LOM3 C8650 FOP CL 20130516 LOM3 C10900 FOP CL 20130516 LOM3 C6650 FOP CL 20130516 LOM3 C8900 FOP CL 20130516 ... (over 400 different contracts) P P P C C C C C 1000 1000 1000 1000 1000 1000 1000 1000 66.5 89 111.5 64 86.5 109 66.5 89
69
The returned data struct will naturally contain empty market data, but its contractDetails field will contain useful data about the requested security:
>> data data = reqId: reqTime: dataTime: dataTimestamp: lastEventTime: ticker: bidPrice: askPrice: open: close: low: high: lastPrice: volume: tick: contract: contractDetails: 286356019 '30-Apr-2013 12:55:28' '30-Apr-2013 12:55:31' 735354.538562743 735354.538562743 'CL' -1 -1 -1 -1 -1 -1 -1 -1 0.01 [1x1 struct] [1x1 struct]
>> data.contract % these are the details for only one of the options ans = m_conId: 50318947 m_symbol: 'CL' m_secType: 'FOP' m_expiry: '20130516' m_strike: 111.5 m_right: 'P' m_multiplier: '1000' m_exchange: 'NYMEX' m_currency: 'USD' m_localSymbol: 'LOM3 P11150' ... >> data.contractDetails ans = m_summary: m_marketName: m_tradingClass: m_minTick: m_priceMagnifier: m_orderTypes: m_validExchanges: m_underConId: m_longName: m_contractMonth: m_industry: m_category: m_subcategory: m_timeZoneId: m_tradingHours: m_liquidHours: 1715,1800-2359' ...
[1x1 com.ib.client.Contract] 'LO' 'LO' 0.01 1 [1x205 char] 'NYMEX' 43635367 'Light Sweet Crude Oil' '201306' [] [] [] 'EST' '20130430:1800-1715;20130501:1800-1715' '20130430:0000-1715,1800-2359;20130501:0000-
70
12 Tracking trade executions IB-Matlab provides several distinct ways to programmatically track trade executions: 12.1 User requests To retrieve the list of trade executions done in the IB account today, use Action='query' and Type='executions' as follows (note the similarities to the request for open order, 10.1 above):
>> data = IBMatlab('action','query', 'type','executions') data = 1x3 struct array with fields: orderId execId time exchange side shares symbol price permId liquidation cumQty avgPrice contract execution
This returns a Matlab struct array, where each array element represents a different execution event. You can access any of the orders using the standard Matlab dot notation:
>> data(1) ans = orderId: execId: time: exchange: side: shares: symbol: price: permId: liquidation: cumQty: avgPrice: contract: execution: 154735358 '00018037.4ff27b0e.01.01' '20120216 18:50:14' 'ISLAND' 'BOT' 1 'GOOG' 602.82 300757703 0 1 602.82 [1x1 struct] [1x1 struct]
IB-Matlab User Guide >> data(2) ans = orderId: execId: time: exchange: side: shares: symbol: price: permId: liquidation: cumQty: avgPrice: contract: execution:
71
154737092 '00018037.4ff2a3b8.01.01' '20120216 18:58:57' 'BEX' 'SLD' 3 'GOOG' 605.19 300757711 0 3 605.19 [1x1 struct] [1x1 struct]
Each of the order structs contains the following data fields:78 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. TWS orders have a fixed order ID of zero (0).
orderId execId time
the unique ID assigned to this execution the exchange which executed the trade
indicates the time of execution (local user time, not IB server time) BOT (=buy) or SLD (=sell) the number of executed shares the securitys symbol (use the contract field to get the LocalSymbol) the permanent ID used to store the order in the IB server Identifies the position as one to be liquidated last should the
exchange side
permId
liquidation
need arise the cumulative quantity of shares filled in this trade (used for partial executions)
cumQty avgPrice contract
this is a struct object that contains the Contract information, including all the relevant information about the affected security this is another struct object that contains information about the specific executions parameters
execution
78
http://www.interactivebrokers.com/en/software/api/apiguide/java/orderstatus.htm
72
For example:
>> data(2).contract ans = m_conId: m_symbol: m_secType: m_expiry: m_strike: m_right: m_multiplier: m_exchange: m_currency: m_localSymbol: m_primaryExch: m_includeExpired: m_secIdType: m_secId: m_comboLegsDescrip: m_comboLegs: m_underComp: 30351181 'GOOG' 'STK' [] 0 [] [] 'BEX' 'USD' 'GOOG' [] 0 [] [] [] '[]' []
>> data(2).execution ans = m_orderId: 154737092 m_clientId: 8101 m_execId: '00018037.4ff2a3b8.01.01' m_time: '20120216 18:58:57' m_acctNumber: 'DU90912' m_exchange: 'BEX' m_side: 'SLD' m_shares: 3 m_price: 605.19 m_permId: 300757711 m_liquidation: 0 m_cumQty: 3 m_avgPrice: 605.19
We can filter the results based on a specific Symbol and/or OrderId. For example:
>> data = IBMatlab('action','query','type','executions','OrderId',154737092) data = orderId: 154737092 execId: '00018037.4ff2a3b8.01.01' (etc.)
Of course, it is possible that there are no executions that match the filtering criteria:
>> data = IBMatlab('action','query','type','executions','symbol','xyz') data = []
73
12.2 Automated log files IB-Matlab automatically stores two log files of trade executions. Both files have the same name, and different extensions. The default file name (<LogFileName>) for these files is IB_tradeslog_yyyymmdd, where yyyymmdd is the current date. For example, on 2012-02-15 the log files will be called IB_tradeslog_20120215.csv and IB_tradeslog_20120215.mat. <LogFileName> can be modified by setting the LogFileName parameter in IBMatlab (default = './IB_tradeslog_YYYYMMDD.csv'). Note the leading './' in the default value of LogFileName you can use any other folder path if you want to store the log files in a different folder than the current Matlab folder. A CSV (comma separated values) text file named <LogFileName>.csv. A separate line is stored for each execution event. This file can be opened in Excel as well as by any text editor. A MAT (Matlab compressed format) binary file named <LogFileName>.mat that stores the struct array explained in 12.1 above, excluding the sub-structs contract and execution.
It should be noted that using these log files, which is done by default, can have a significant performance impact in cases of rapid partial executions. For example, if we buy 1000 shares of a security whose normal ask size is 5 shares, then we should expect about 200 separate execution messages when the order is filled. This in turns translates into 200 separate file saves, for each of the two log files (CSV, MAT). This could cause MATLAB to appear frozen for quite a long time until all this I/O is done. To solve the performance issue in cases where the execution logs are not really needed, set the LogFileName parameter to the empty string ('') to prevent logging. 12.3 Using CallbackExecDetails You can set the CallbackExecDetails parameter to a user-defined Matlab function that will process each execution event at the moment that it is reported. 11.2 above contains a working example of such a function. As noted in 11.1, you only need to set CallbackExecDetails once (this is normally done in the same IBMatlab command that sends the trade order). You do not need to re-specify this callback in subsequent IBMatlab commands, unless you wish to override the parameter with a different function, or to cancel it (in which case you would set it to [] or '').
74
13 Forcing connection parameters IB-Matlab does not require any special configuration when connecting to IB. It uses a random client ID when first connecting to TWS or the IB Gateway, and this is perfectly fine for the vast majority of uses. However, in some specific cases, users may wish to control the connection properties. This is supported in IB-Matlab using the following input parameters: Parameter ClientId Host Port AccountName Data type integer string integer string Description A number that identifies IB-Matlab to (random) TWS/Gateway. 0 acts as another TWS. 'localhost' = IP address of the computer that runs '127.0.0.1' TWS/Gateway Port number used by TWS/Gateway for 7496 API communication The specific IB account used for queries or '' trades. Useful when you handle multiple IB accounts, otherwise leave empty. The Financial Advisor allocation profile to which trades will be allocated. Only '' relevant for Financial Advisor accounts, otherwise leave empty. Default
FAProfile
string
The ClientID, Host and Port properties should match the API configuration of the TWS/Gateway applications, as described in 2 above (installation steps #9-10). You can set a static Client ID in order to be able to modify open orders placed in a different IB-Matlab session (i.e., after the original IB-Matlab client has disconnected from IB and a new IB-Matlab has connected). IB normally prevents clients from modifying orders placed by other clients, but if all your clients use the same ID then this limitation will not affect you. Matlab-to-IB reconnections occur automatically when IB-Matlab needs to issue any request to IB and the connection is not live for whatever reason. This happens upon the initial IBMatlab request (when the initial connection needs to be established); after TWS or the IB Gateway were closed; after a call was made to ibConnectionObject.disconnectFromTWS (see below); after a Matlab restart; after a specified number of streaming quotes, and in a few other special cases.79 In reconnections of any kind, IB-Matlab automatically tries to reuse the same ClientID as in the previous connection. When a new ClientID is specified for any IBMatlab command, IBMatlab automatically disconnects the previous client ID and reconnects as the new ClientID.
79
75
In the IB Gateway, this will be seen as a dark-gray tab contents for the old ClientID and a light-gray tab contents for the connected ClientID:
data = IBMatlab('action','query', 'type','executions', 'ClientID',8103)
While specifying a new ClientID automatically disconnects and reconnects to IB, you can also force a disconnection/reconnection for the same ClientID, by using the Java connector object (discussed in 15 below). Following a disconnection from IB, IBMatlab will automatically reconnect to IB upon the very next use of IBMatlab:
[data, ibConnectionObject] = IBMatlab('action',...); ibConnectionObject.disconnectFromTWS; data = IBMatlab('action','portfolio'); % do whatever % disconnect from IB % will automatically reconnect
ClientID 0 is special: it simulates the TWS and enables IB-Matlab to receive, modify and cancel all the open orders that were interactively entered in TWS. Instead of ClientID 0, you can use any other value that you pre-configured as the Master API Client ID in the TWS/Gateways API configuration screen (see 2 installation step #9). Using a Master Client ID enables the IB-Matlab client to receive all open orders that were placed in the IB account using any Client ID, not just TWS. If you only connect IB-Matlab and no other API client to TWS, and if you only use the static ClientID 0, then you do not need to worry about the Master API Client ID setup. Another use is to connect IB-Matlab on one computer (which has Matlab installed) to TWS/Gateway on another computer, which may not necessarily have Matlab. In this case, simply set the Host and possibly also the Port parameters.
76
Note that TWS and the IB Gateway have a limitation that they can only be connected to a single IB-Matlab client at any time. Also, TWS and the IB Gateway cannot be logged-in at the same time to the same IB account. These IB limitations mean you cannot simultaneously connect multiple IB-Matlab instances to the same IB account.
Users computer TWS
Account DU123
IB Server
Users Application
IBMatlab
Not OK prevented by IB
TWS
MATLAB
Users Application
IBMatlab
IB Server
On the other hand, it is possible to control multiple IB accounts from the same TWS application, and in such a case IB-Matlab can access all of these accounts when it connects to TWS, using the AccountName parameter. Please refer to your TWS documentation (or IBs customer service) to set up your TWS accordingly.
Users computer MATLAB TWS
Users Application
IBMatlab
OK !
IB Server
77
It is also possible to run TWS with one IB account, and IB Gateway with another account, either on the same computer as IB-Matlab, or on another machine. You can then connect one or more IB-Matlab instances to these IB applications at the same time. Simply ensure that your Host, Port and AccountName parameters are OK for any IBMatlab command. IB-Matlab can maintain simultaneous connections to both TWS and IB Gateway, on different Ports, as long as they are both on the same Host.
Users computer MATLAB TWS
Account DU123
OK!
Port 7497
IB Gateway
Account DU124
IB Server
TWS & IB Gateway are on the same host (computer) and can be controlled by a single IB-Matlab
Users Application
IBMatlab
Account DU123
Users computer #2
TWS
Account DU124
IB Server
TWS & IB Gateway are on separate hosts (computers) and cannot be controlled by a single IB-Matlab
78
To control two or more TWS/Gateways, it is better to use distinct IB-Matlab instances, i.e., distinct Matlab sessions, each running its own IB-Matlab instance and connecting to a single IB client (TWS or Gateway). This helps prevent mix-ups in the AccountName or Port that might occur when IB-Matlab controls separate IB clients:
Users computer MATLAB TWS
Users Application
IBMatlab
Account DU123
OK!
MATLAB IB Gateway
Users Application
IBMatlab
Account DU124
IB Server
Users Application
IBMatlab
Account DU123
OK!
TWS IB Server
Users Application
IBMatlab
Account DU124
Note that if you wish to use IB-Matlab on separate computers, then you will need a separate IB-Matlab license for each computer.
79
14 Messages and general error handling IB constantly sends messages of various severity levels to IB-Matlab. These range from the mundane (e.g., Market data farm connection is OK:cashfarm {-1, 2104}) to the problematic (e.g., No security definition has been found for the request {153745227, 200}). All these messages arrive as regular events of type error, just like all the other information sent from IB (see 11 above for details). IB-Matlab automatically displays messages in the Matlab command window. The user can control the display of these messages using the MsgDisplayLevel parameter, which accepts the following possible values: -2 most verbose output, including all the information contained in all incoming IB events (not just messages) -1 display all messages as well as basic events information 0 (default) display all messages, but not other events 1 only display error messages, not informational messages 2 do not display any automated output onscreen (not even errors)
We can trap and process the message events just like any other IB events, using Matlab callbacks. Note that the parameter for message callback is CallbackMessage, although for some reason the IB event is called error:
data = IBMatlab('action','query', ..., 'MsgDisplayLevel',-1, ... 'CallbackMessage',@IBMatlab_CallbackMessage);
The information contained in the message events varies depending on message type.80 The three main variants appear to be events with one of the following data sets: Contents Description Displayed as message general error messages [API.msg1] message, id (data1), errors and informational [API.msg2] code (data2) messages message, severe IB errors [API.msg3] exception object (exceptions) Displayed onscreen if MsgDisplayLevel < 2 MsgDisplayLevel < 1 or: data2 < 200081 MsgDisplayLevel < 2
The full list of message codes (data2) for API.msg2 (which is the most common message type) is listed online.82 It is sub-divided into three groups: Error messages (data2 codes between 100-999) System messages (data2 codes between 1000-1999) Warning messages (data2 codes between 2000-2999)
80 81
http://www.interactivebrokers.com/en/software/api/apiguide/java/error.htm IB-Matlab versions prior to 2013-05-10 had a different implementation, in which MsgDisplayLevel=1 had an effect only on very few messages while most messages were displayed. This was fixed to be consistent with the original intention. http://www.interactivebrokers.com/en/software/api/apiguide/tables/api_message_codes.htm
82
80
As noted above, most of the messages are of type API.msg2, and contain two numeric fields: data2 contains the message code, and data1 contains message-specific data. For most message codes (e.g., Market data farm connection is OK:cashfarm =code 2104), there is no associated message-specific data, and in such cases data1 = -1. In some cases, however, data1 does contain relevant information. For example, No security definition has been found for the request {153745227, 200} tells us that this error (code=200) happened for the specific request ID 153745227. We can therefore correlate between the error and the trade order that triggered this error. As noted above, the API.msg2 messages reported by IB are often cryptic, and we sometimes need to use detective skills in order to track down the root cause of a problem.83 Several mechanisms can help us with this detective work: We could set IBMatlabs MsgDisplayLevel parameter to -1 or -2 (see above). We could set IBMatlabs Debug parameter (default=0) to 1. This will display in the Matlab Command Window a long list of parameters used by IBMatlab to prepare the request for IB. Check this list for any default values that should actually be set to some non-default values. We could set the API logging level to Detailed in the TWS/Gateway API configuration window.84 By default it is set to Error, and this can be changed at any time. This affects the amount of information (verbosity) logged in IBs log files, which are located in IBs installation folder (e.g., C:\Program Files\Jts).85 The log files are separated by the day of week, and have names such as: ibgateway.Thu.log, log.Wed.txt, api.8981.Tue.log. These refer, respectively, to the main Gateway log, the main TWS log,86 and a log of requests/responses for a specific ClientID. The api.*.log file reflects the contents of the corresponding tab in the Gateway application.87 Note that setting the logging level to Detail has a performance overhead and should be avoided except when debugging a specific issue. In other cases, you can set the level to Information, Warning or back to the default Error.
In addition to messages reported by IB, the users program must check for and handle cases of exceptions caused by IB-Matlab. In the vast majority of cases, these are due to invalid input parameters being passed to IBMatlab (for example, an invalid Action parameter value). However, an exception could also happen due to network problems, or even an occasional internal bug due to an unhandled edge-case situation.
83 84 85 86
See examples in 3 above See 2, installation step 9d http://www.interactivebrokers.com/en/software/api/apiguide/tables/api_logging.htm The list of IDs used in the ibgateway.*.log, log.*.txt log files when the logging level is Detailed, is described here: http://www.interactivebrokers.com/en/software/api/apiguide/api/api_request_server_response_message_identifiers.htm; information about the format of the extra log entries can be found in http://www.interactivebrokers.com/en/software/api/apiguide/api/api_logging.htm See the screenshot in 13 above
87
81
To trap and handle such programmatic exceptions, wrap your calls to IBMatlab within a try-catch block, as follows:
try data = IBMatlab('action','query', ... ); catch % process the exception here end
Try-catch blocks do not have any performance or memory overhead and are a very effective way to handle programmatic errors. We highly recommend that you use them very liberally within your user program, not just to wrap IBMatlab calls but also for any other processing tasks. I/O sections in particular (reading/writing to files) are prone to errors and are prime candidates for such exception handling. The same applies for processing blocks that handle user inputs (we can never really be too sure what invalid junk a user might enter in there, can we?). Very common causes of errors when using IB-Matlab are relying on default parameter values, and specifying numeric parameter values within string quotes (e.g., 1 rather than 1).88 Users of IB-Matlab should take extra precaution in their programs to ensure that these common mistakes do not occur. A different type of error occurs in user applications that rely on valid data being returned from the IB server in response to account, portfolio or market-data queries. Unfortunately, the IB server data feed (or perhaps only the interface) is not as reliable as it could be. IB sometimes returns empty or invalid data field values, typically -1. This issue, together with some workarounds, was discussed in 3 and 4 above. In general, user applications should implement sanity checks on the returned data, and retry to send the request until receiving valid data. Failing to do so may result in applicative errors, and might even lead to bad automated trading decisions, so please be extra careful about this. One final type of error may be due to out-of-memory errors, either directly in Matlab or in Java. Matlab out of memory errors might occur when receiving and storing a huge amount of streaming/historic data. They can be fixed by running IB-Matlab on a computer having more memory, or by reducing the amount of stored data.89 Java memory errors are recognized by the message java.lang.OutOfMemoryError: Java heap space. They can be solved by running Matlab with more allocated Java heap memory than the default value of 64 or 128MB (depending on Matlab release). This value can be increased in Matlabs preferences, or via a java.opts file.90
88 89 90
82
15 Using the Java connector object 15.1 Using the connector object Each call to IBMatlab returns two output values: data - generally contains the request ID or the requested query data ibConnectionObject a Java object reference In most cases, users do not need to use ibConnectionObject and so we can generally ignore the second output value and simply call IBMatlab with a single output:
data = IBMatlab('action','query', ... );
However, flexible and feature-rich as IBMatlab is, it does not contain the entire set of functionalities exposed by IBs Java API. In order to access these additional functionalities, we need to use ibConnectionObject:
[data, ibConnectionObject] = IBMatlab('action','query', ... ); ibConnectionObject
is a Java object of type IBMatlab.IBConnection. You can call its publicly-accessible methods (functions) just like any Matlab function. For example:
[data, ibConnectionObject] = IBMatlab('action','query', ... ); flag = ibConnectionObject.isConnected; % no input params, so no () ibConnectionObject.disconnectFromTWS(); % no real need for () here ibConnectionObject.cancelOrder(153745227);
There is an almost exact correlation between the methods in ibConnectionObject and the methods documented in IBs Java API (for both requests91 and responses92). This was done on purpose, to enable easy integration with IB. ibConnectionObject is in many respects an interface object to IBs Java API. Therefore, the full documentation of ibConnectionObject is really the official IB Java API documentation. When you call any of the request methods, you cannot really call the corresponding event methods to receive and process the data. For example, if you call ibConnectionObject.reqCurrentTime(), you cannot call the corresponding currentTime() method. Instead, currentTime() is automatically being called by the underlying Java engine as a new event. However, as noted in 11.1, all these events can be trapped and processed within Matlab callbacks. In this particular case, a currentTime event is raised and this can be trapped and processed in a user Matlab function specified by the CallbackCurrentTime parameter. Note: All trade (buy/sell/short) orders must be placed exclusively through either the ibConnectionObject interface (the placeOrder() method) or the IBMatlab name-value pair interface. Placing trade orders via both interfaces in a single IB-Matlab session will result in request ID mixup and failed trades: the IB server will reject trades that have duplicate or non-sequential IDs. Using duplicate and non-sequential IDs is not critical in many other IB requests, but is critical in the specific case of trade orders.
91 92
http://www.interactivebrokers.com/en/software/api/apiguide/java/java_eclientsocket_methods.htm http://www.interactivebrokers.com/en/software/api/apiguide/java/java_ewrapper_methods.htm
83
84
85
// Exercise options public void exerciseOptions(int tickerId, Contract contract, int exerciseAction, int exerciseQuantity, String account, int override) // Request Reuters global fundamental data. There must be a subscription to // Reuters Fundamental setup in Account Management before you can receive data public void reqFundamentalData(int id, Contract contract, String str) // Cancel request for Reuters global fundamental data public void cancelFundamentalData(int id) // Request the next available reqId public void reqNextValidId() // same as reqId() below public void reqId() // a single ID public void reqIds(int numIds) // multiple IDs // Market Data requests: // Calculate the implied volatility of a contract public void calculateImpliedVolatility(int tickerId, Contract contract, double optionPrice, double underPrice) // Cancel request to calculate the implied volatility of a contract public void cancelCalculateImpliedVolatility(int tickerId) // Calculate an option price public void calculateOptionPrice(int tickerId, Contract contract, double volatility, double underPrice) // Cancel request to calculate an option price public void cancelCalculateOptionPrice(int tickerId) // Cancel all open API orders - 9.65 public void reqGlobalCancel() // Request market data type - 9.66 // (1 for real-time streaming market data or 2 for frozen market data) public void reqMarketDataType(int marketDataType) // Request reception of the data from the TWS Account Window Summary tab - 9.69 public void reqAccountSummary(int reqId, String group, String tags) // Cancel request for TWS Account Window Summary data - 9.69 public void cancelAccountSummary(int reqId) // Request reception of real-time position data for an all accounts - 9.69 public void reqPositions() // Cancel request for real-time position data - 9.69 public void cancelPositions() // Set the level of API request and processing logging public void setServerLogLevel (int logLevel)
93
http://www.interactivebrokers.com/en/software/api/apiguide/java/reqrealtimebars.htm
86
/**************************** * IB Callbacks (invoked automatically should NOT be called directly!) ****************************/ // Receives public void public void public void error and informational messages error(String str) error(int data1, int data2, String str) error(Exception e)
// Receives indication that the TWS connection has closed public void connectionClosed() // Receives market data public void tickPrice(int tickerId, int field, double price, int canAutoExecute) public void tickSize(int tickerId, int field, int size) public void tickString(int tickerId, int field, String value) public void tickGeneric(int tickerId, int field, double generic) public void tickEFP(int tickerId, int field, double basisPoints, String formattedBasisPoints, double totalDividends, int holdDays, String futureExpiry, double dividendImpact, double dividendsToExpiry) public void tickOptionComputation(int tickerId, int field, double impliedVol, double delta, double modelPrice, double pvDividend) public void tickOptionComputation(int tickerId, int field, double impliedVol, double delta, double optPrice, double pvDividend, double gamma, double vega, double theta, double undPrice) public void tickSnapshotEnd(int reqId) // Receives execution report information public void execDetails(int orderId, Contract contract, Execution execution) // Receives historical data results public void historicalData(int reqId, String date, double open, double high, double low, double close, int volume, int count, double WAP, boolean hasGaps) // Receives the next valid order ID upon connection public void nextValidId(int orderId) // Receives data about open orders public void openOrder(int orderId, Contract contract, Order order) public void openOrder(int orderId, Contract contract, Order order, OrderState orderState) // Receives data about orders status public void orderStatus(int orderId, String status, int filled, int remaining, double avgFillPrice, int permId, int parentId, double lastFillPrice, int clientId)
87
88
89
15.3 Usage example Let us use the Java connector object to implement the Arrival Price algo example that is provided in the official IB Java API.94 This Arrival Price example shows how easy it is to convert Java code available in the official API or support forums (or even code supplied by IBs API customer support team) to Matlab using IB-Matlab: First, here is the original Java code:
import com.ib.client.TagValue; Contract m_contract = new Contract(); Order m_order = new Order(); Vector<TagValue> m_algoParams = new Vector<TagValue>(); /** Stocks */ m_contract.m_symbol = "MSFT"; m_contract.m_secType = "STK"; m_contract.m_exchange = "SMART"; m_contract.m_currency = "USD"; /** Arrival Price m_algoParams.add( m_algoParams.add( m_algoParams.add( m_algoParams.add( m_algoParams.add( m_algoParams.add( */ new new new new new new TagValue("maxPctVol","0.01") ); TagValue("riskAversion","Passive") ); TagValue("startTime","9:00:00 EST") ); TagValue("endTime","15:00:00 EST") ); TagValue("forceCompletion","0") ); TagValue("allowPastEndTime","1") );
m_order.m_action = "BUY"; m_order.m_totalQuantity = 1; m_order.m_orderType = "LMT"; m_order.m_lmtPrice = 0.14 m_order.m_algoStrategy = "ArrivalPx"; m_order.m_algoParams = m_algoParams; m_order.m_transmit = false; m_client.placeOrder(40, m_contract, m_order);
94
http://www.interactivebrokers.com/en/trading/orders/arrivalprice.php, http://www.interactivebrokers.com/en/software/api/apiguide/tables/ibalgo_parameters.htm
90
And now for the corresponding Matlab code (notice how closely it resembles the original Java code):95
import com.ib.client.TagValue; % First create the contract for the requested security m_contract = ibConnectionObject.createContract(... 'MSFT','STK','',0,'','SMART','USD','MSFT'); % Alternately, we could have done as follows: m_contract = ibConnectionObject.createContract(... '','','',0,'','','',''); m_contract.m_symbol = 'MSFT'; m_contract.m_secType = 'STK'; m_contract.m_exchange = 'SMART'; m_contract.m_currency = 'USD'; % Now set the Arrival Price algoParams m_algoParams = java.util.Vector; m_algoParams.add( TagValue('maxPctVol','0.01') ); m_algoParams.add( TagValue('riskAversion','Passive') ); m_algoParams.add( TagValue('startTime','9:00:00 EST') ); m_algoParams.add( TagValue('endTime','15:00:00 EST') ); m_algoParams.add( TagValue('forceCompletion','0') ); m_algoParams.add( TagValue('allowPastEndTime','1') ); % Now create the order, using algoParams m_order = ibConnectionObject.createOrder(... 'BUY', 1, 'LMT', 0.14, 0, '', ... '', 0, '', '', realmax, 0, false); m_order.m_algoStrategy = 'ArrivalPx'; m_order.m_algoParams = m_algoParams; m_order.m_transmit = false; % Finally, send the order to the IB server ibConnectionObject.placeOrder(40, m_contract, m_order);
95
91
16 Sample model using IB-Matlab Pairs Trading 16.1 Once a day - decide whether two securities are co-integrated
96
1. Download http://www.spatial-econometrics.com/ (jplv7.zip) and unzip into a new folder (this is a free alternative to Matlabs Econometrics Toolbox97). 2. Add the new toolbox function to your Matlab path. Naturally, use the actual folder name where youve unzipped the toolbox rather than my C:\... example:
addpath(genpath('C:\SpatialEconometricsToolbox'));
3. Use IB-Matlab to get last years daily history data for both securities:98
IBM_history = IBMatlab('action','history', 'Symbol','IBM', ... 'DurationValue',1,'DurationUnits','Y',... 'BarSize','1 day');
GOOG_history = IBMatlab('action','history', 'Symbol','GOOG', ... 'DurationValue',1,'DurationUnits','Y',... 'BarSize','1 day'); % Transform row vectors => column vectors for the adf,cadf tests IBM_close_prices = IBM_history.close'; % array of 252 values GOOG_close_prices = GOOG_history.close'; % array of 252 values
4. Ensure that both time series are not already stationary (do not have a unit root and tend to mean-revert). This is done with the adf (Augmented Dickey-Fuller test) function in the Spatial Econometrics Toolbox, which outputs a results struct that enables us to determine at varying confidence levels if this is in fact the case. ADF has the null hypothesis that the time series has a unit root and is non-stationary. To reject this, the absolute value of results.adf (the tstatistic) needs to be greater than the desired absolute value of results.crit a vector that contains 6 confidence level values, corresponding to 99%, 95%, 90%, 10%, 5% and 1% confidence. Only if the null hypothesis of a unit root and non-stationarity cannot be rejected for both time series in a possible pair, will it be worth proceeding to the cointegration test in step 5.
adfResults = adf(IBM_close_prices,0,1); if abs(adfResults.adf) < abs(adfResults.crit(3)) % failed test bail out end
and similarly test the second security (GOOG_close_prices here). Note that adf is a necessary but weak test: most securities will pass this test.
96
In practice, many traders do this test much more rarely, for practical reasons. However, they risk a chance that the pair of securities have stopped being cointegrated, so trading based on their cointegration assumption could prove to be very costly Also see MathWorks webinar Cointegration & Pairs Trading with Econometrics Toolbox: http://www.mathworks.com/wbnr55450; More cointegration examples using MathWorks Econometrics Toolbox: http://www.mathworks.com/help/econ/identify-cointegration.html See 6 for details
97
98
92
5. The cadf (Cointegrating Augmented Dickey-Fuller test) function in the Spatial Econometrics Toolbox tests for cointegration between a dependent time series (y) and an explanatory time series (x).99 The results struct output by cadf also includes a results.adf (t-statistic) value and six results.crit values. The null hypothesis here is that the time series are not cointegrated, so to reject this in favor of the pair possibly being cointegrated, the absolute value of results.adf needs to be greater than the desired results.crit value.
cadfResults = cadf(IBM_close_prices, GOOG_close_prices, 0,1); if abs(cadfResults.adf) < abs(cadfResults.crit(3)) % failed test bail out end
NOTES: There are numerous ways of calculating the beta of the relationship (and how frequently to adjust this) between the y and x time series (IBM and GOOG respectively in the example above) in order to determine the correct relative number of shares to buy/sell in each stock in a cointegrating pair.100 Also, the above tests do not indicate which stock informationally leads the other and which is the dependent/independent variable. Tests such as Granger Causality are intended for this purpose.101 6. If any of the securities failed any of the above tests, bail out 7. Compute the correlation factor between the time series (e.g., using ols):
res = ols(IBM_close_prices, GOOG_close_prices); % == res.beta
8. Store STD = std(Closesec1 *Closesec2) for later use in the runtime part below
modelData.std = std(IBM_close_prices res.beta*GOOG_close_prices);
In fact, cadf will test against a matrix of multiple explanatory variables but in the case of a pairs strategy only two vectors the two historic time series of prices x and y are required as inputs For more information on some of the possibilities see http://www.ljmu.ac.uk/Images_Everyone/Jozef_1st(1).pdf See http://maki.bme.ntu.edu.tw/codes/granger_tool/etc_granger.m See 7 for details See 11 for details
93
The simplistic code here assumes that the long-term mean spread between the securities is 0. In practice, the mean spread has to be calculated in run-time. One way of doing this is to use Bollinger Bands: simply check whether we are outside the second band for the overbought/oversold signal. Bollinger band functions are available in the Financial Toolbox ( bollinger function), or can be freely downloaded from: http://www.mathworks.co.uk/matlabcentral/fileexchange/10573-technical-analysis-tool
94
Appendix A resources A.1 Official IB resources API download page - http://www.interactivebrokers.com/en/software/ibapi.php All IB API guides http://individuals.interactivebrokers.com/en/software/api_guides.php API Online Reference Guide http://individuals.interactivebrokers.com/en/software/api/api.htm API Online Reference Guide Java http://www.interactivebrokers.com/en/software/api/apiguide/java/java.htm Java API Quick Reference (PDF) http://www.interactivebrokers.com/download/inst/JavaAPIQuickReference.pdf Full API Reference Guide (PDF) http://www.interactivebrokers.com/download/newMark/PDFs/APIprintable.pdf Getting Started with the TWS Java API (PDF) http://www.interactivebrokers.com/download/JavaAPIGettingStarted.pdf Getting Started with the TWS Java API for Advisors (PDF) http://www.interactivebrokers.com/download/GettingStartedJavaAPIAdvisors.pdf IB Gateway Users Guide (PDF) http://individuals.interactivebrokers.com/download/newMark/PDFs/gateway.pdf Java API Samples for the Getting Started Guide (ZIP) http://www.interactivebrokers.com/download/JavaAPIExamples.zip API Webinars http://www.interactivebrokers.com/en/general/education/webinars.php?p=a&ib_entity=llc IB discussion forum - http://www.interactivebrokers.com/smf/ API chat-room - http://chatsrv1.interactivebrokers.com/fchat/chat/flashchat.php API customer service and technical support - [email protected] (please let them know that you are using IB-Matlab, which in turn uses IBs Java API) Yahoo!s IB discussion forum (not an official IB resource) http://finance.groups.yahoo.com/group/twsapi/
95
A.2 MathWorks webinars Real-time trading in MATLAB http://www.youtube.com/watch?v=e4bdKcFl4GA This is a recording of a presentation that I gave at the MATLAB Computational Finance Virtual Conference in September 2013, explaining IB-Matlab and showing how it can be used for real-time trading using a demo trading application. Also available: presentation slides and the demo application source-code. MathWorks algorithmic-trading portal http://www.mathworks.com/discovery/algorithmic-trading.html, http://www.mathworks.com/financial-services/algorithmic-trading.html (includes the webinar Real-Time Trading System in MATLAB that features IB-Matlab) Algorithmic trading with MATLAB for financial applications http://www.mathworks.com/wbnr52491 Cointegration and Pairs Trading with the Econometrics Toolbox http://www.mathworks.com/wbnr55450 Energy trading & risk management with MATLAB http://www.mathworks.com/wbnr50145 Automated Trading with MATLAB http://www.mathworks.com/wbnr68672 Commodities Trading with MATLAB http://www.mathworks.com/wbnr78374
A.3 Additional open-source Matlab resources Quantitative Finance Matlab Code Library http://www.quantcentral.com/quantitative-finance-matlab-code-library/ (click one of the Matlab Code options in the websites main toolbar) Spatial Econometrics Toolbox for Matlab http://www.spatial-econometrics.com/ Algorithmic trading code in the Matlab File Exchange http://www.mathworks.com/matlabcentral/fileexchange/?term=trading
96
Appendix B change log The following table lists changes done to this document. Depending on the date that you have installed IB-Matlab, your version may be missing some features discussed in this document. Whenever you renew your annual license, you will receive the latest IB-Matlab version, including all the functionality detailed here. Version Date Section(s) Description 1.09 2012-04-16 Baseline version for this change-log Some account-data fields have several variants 4 starting with this IB-Matlab version 1.10 2012-05-05 Clarification about mixing Matlab and Java trade 15.1 orders 16 Major overhaul of the Pairs Trading sample model 1.11 2012-05-27 Added this new section with references to online A.2 MathWorks webinars Added note about compatibility with the IB API Cover version 9.67 1.12 2012-05-30 Added Java method interfaces commissionReport(), 15.2 marketDataType(), reqMarketDataType() Added currency usage example (RUTCAD); 3 added explanation how to retrieve contract info in TWS via Contract Info / Description menu Clarified what happens if any of the pre-conditions 5 1.13 2012-06-15 for querying market data are not met 11.1 Clarified to follow the hyperlinks in the table 12.1 Fixed usage example code: open executions 14 Typo fix: code=2000 code=200) Clarified about requesting portfolio information 4 (multi-accounts, safe programming, shorts, sums) Added references to the AuxPrice parameter where 1.14 2012-06-19 relevant; added TWAP order type; rearranged the 8 parameters in the order-params table; clarified TIF =GTD usage; clarified ParentID usage Clarified that LimitBasis cannot be used with 9.4 LimitPrice; fixed the code snippet accordingly 1.15 2012-06-28 14 Added discussion data errors leading to -1 values Added reference link to the MathWorks 16.1 Econometrics Toolbox Added usage example of the Java connector object 11.1 for implementing combo-trades 1.16 2012-07-18 14 Added discussion of out-of-memory errors 1.17 2012-08-07 9.3 Fixed LMTSTP STPLMT
97
Version
Date
1.18
2012-09-13
1.22
2012-06-10
1.23
2012-10-25
1.24
2012-11-19
1.25
2012-11-27
Section(s) Description Disclaimer Changed paragraph ordering (no change in text) Expanded the explanation how to retrieve contract 3 info in TWS via Contract Info / Description menu Added the contract field in the portfolio-query 4 results struct; fix in code snippet (sleeppause) Clarified that if any of the pre-conditions for 5 querying market data are not met, the returned info can be empty or error 9.5 Clarified on using the ibConnectionObject Clarified about telling IB support that IB-Matlab A.1 uses the Java API when contacting them Clarified that all time-stamp fields except 5 lastTimestamp reflect the local (not server) time. 11.1, 14, Updated some reference links following changes on 16.1 the www.mathworks.com website 2 Clarified on setting the path in classpath.txt 3 Clarified on reusing the struct input format Split 4 into 4.1 (account information) and 4.2 4 (portfolio information) Added resource: added reference to Automated A.2 Trading online webinar Cover Updated IB API compatibility: 9.67 9.68 Clarified that on a multi-account, not specifying the 4.1 AccountName parameter can lead to stale or empty account data The returned contract field in the portfolio query results struct is now a Matlab struct, not a Java 4.2 object; clarification that AccountName =all can be used on a multi-account Added the contractDetails field in the market-query 5 results struct 9.6 New section and functionality (ComboActions, (now: 9.5) ComboRatios params) for combo-orders Clarified (item 9e) about upgrades in Windows 322 bit to 64-bit 9.6 Switched usage example from ECBOT to GLOBEX (now: 9.5) exchange 9.5, 9.6 Switched the relative order of these sections Clarified that the Java connector object can be used 11.1 to implement combo trades as an alternative to the built-in mechanism (9.5)
98
Version 1.26
1.27
1.31
1.32
1.33
1.34
1.35
1.36
Description Added ComboBagSymbol parameter; added usage example of ComboBagSymbol; 2012-12-22 9.5 clarifications regarding combo legs limitations (need to use same exchange/currency, default ratio) Replaced Booleanboolean in Java method interfaces; added methods reqNextValidId(), reqId(), reqIds(), calculateImpliedVolatility(), 2013-01-10 15.2 cancelCalculateImpliedVolatility(), calculateOptionPrice(), cancelCalculateOptionPrice() 2013-02-08 (formatting changes only; no change in text) 2013-02-10 A.2, A.3 Added a few online resources 2013-03-08 2 Clarified editing the classpath.txt file Fixed description for Hold parameter (refer to 9.6, 8 not 9.5) 2013-04-11 Added usage example for preparing an order for 9.6 manual approval/transmission B Added this change log in a new Appendix B Cover Updated IB API compatibility: 9.68 9.69 1, A.1 Updated IB links, following changes on IB website Added new methods supported by 9.69: 2013-04-19 reqAccountSummary(), cancelAccountSummary(), 15.2 reqPositions(), cancelPositions(), accountSummary(), accountSummaryEnd(), position(), positionEnd() 3 Clarified usage of Symbol and SecType options 2013-04-30 8 Added additional supported TIF options 11 Added new sub-section 11.4; updated section titles 7 Clarified streaming quotes limitations 14 Clarified behavior of MsgDisplayLevel=1 2013-05-10 Added references for IB API chat-room and Yahoo! A.1 forum; updated IBs forum web-address Clarified that IBs paper-trade account is the 2, 3 simulated trading account Added the dateNum field in the historical-data 2013-06-21 6 query results struct; clarified that the time part is omitted in the dateTime field when barSize>=1d Clarified setting LogFileName='', to prevent real12.2 time execution logging, for improved performance 5, 9.5, 11.4 Addition of contract field to market query results 2013-07-15 6 Updated historical data limitations imposed by IB
Date
Section(s)
99
Version
1.37
1.38
1.39
1.40
1.41
Description Added callbacks for IBs AccountSummary, 11.1 AccountSummaryEnd, CommissionReport, MarketDataType, Position and PositionEnd events. 15.2 Clarified the function interface of reqRealTimeBars() 2013-09-11 A.2 Added MathWorks Commodities Trading webinar Fixed online IB references (the IB server modified (all) the URLs of its online API documentation) Added the LimitUpdateMode parameter; 9.4 Added clarification about the Tick value 2013-09-27 Added Real-time trading in MATLAB webinar/ A.2 presentation (+demo application source code) 6 Added the Timeout parameter 9.4 Added clarification about LimitRepeatEvery value 2013-10-10 Added clarifications about ComboRatios volatility 9.5 and LocalSymbol sensitivity Clarified the Disclaimer text e.g., clarified that any Disclaimer mention of a trading symbol or trading order does not constitute a recommendation by the author etc. 1 Replaced outline image with a clearer version Clarified that an IB client (TWS or Gateway) needs to be active in order for IB-Matlab to work; 2013-10-23 3 Added: IB-Matlab will automatically start TWS if an IB client (TWS or IB Gateway) is not active 8 Fixed reference URL to IBs order-types webpage Added screenshot of my Real-time Trading webinar; A.2 Added reference to MathWorks Algorithmic Trading portal that features a webinar on using IB-Matlab Added clarification about using GenericTickTypes 7.1 parameter to get extra info in streaming quotes 7.2 Added this section on the new realtime bars feature Indicated that the realtimeBars event is triggered by 11.1 IB-Matlab, accessible via CallbackRealtimeBars Clarified that the returned data structure only 2013-11-19 11.4 contains contract info for a single option contract Clarified the options of multi-client connection(s); 13 Minor clarification on use of ClientID parameter A.3 Added reference to Spatial Econometrics Toolbox Clarified that you will get the latest IB-Matlab B version whenever you renew your annual license
Date
Section(s)
100
Version
1.42
Section(s) Description 5.2 Added this section on the new scanner data feature Added minor clarification about not enclosing numeric parameters in Matlab string quotes (); 7.1 2013-11-27 Clarified that streaming quote fields are independent of each other Indicated that the scanner* events are triggered by 11.1 IB-Matlab, in response to user scanner requests
Date