IB-Matlab is a commercial application that connects Matlab with Interactive-Brokers (IB).
IB-Matlab provides a Matlab wrapper interface to IB’s API Java connector. This enables quantitative traders and algo traders to easily leverage Matlab’s superior analysis and visualization capabilities, with InteractiveBrokers no-nonsense low-cost trading platform for stocks, ETFs, mutual funds, bonds, options, futures, commodities and FOREX (foreign currency exchange).
The need
While IB’s Java connector, which is provided by IB, 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.
Other applications that solve these problems are either expensive, limited in functionality, or limited in deployment (for example, ActiveX solutions will only work on 32-bit Windows systems). matlab2ib quant2ib
Main features of IB-Matlab
IB-Matlab is an inexpensive application that solves the connectivity problem by enabling simple Matlab access to the entire IB API functionality. Users can activate IB’s API by simple Matlab commands, without any need to know Java.
Active trading actions (buy, sell, short and cancel) and query actions (market, streaming quotes, open orders, historical, account and portfolio data) are available using simple one-line Matlab code (see usage examples below). Additional trading features (the full range of IB API) can be accessed using internal objects exposed by IB-Matlab.
Users can easily attach Matlab code (callbacks) to IB events. For example, 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.
IB-Matlab also provides functionality that is not available in the basic IB API: the ability to specify automated trading, automatically changing unfulfilled limits based on the momentary bid/ask prices, and changing order types at a certain time.
IB-Matlab is up-to-date with the latest IB API (9.66, from Nov 2011), and the latest IB clients – both the Trading WorkStation (TWS) and the IB Gateway. It works on Matlab 7.1 and above (support for older versions can be provided upon demand). It is compatible with all platforms on which TWS (or the IB Gateway) and Matlab run: Windows (both 32 and 64 bits), Macs, Linux/Unix.
Free trial version
A fully-functional free trial version is available upon request – please email me and I will be happy to send you a no-obligations copy and to help you install it on your system.
Documentation
- Quick-reference help
- Full User Guide (PDF)
- Syntax details and usage examples
- Two reviews of IB-Matlab were published in the prestigious AutomatedTrader magazine (2011, 2012). The full reviews (PDF) are available for download here (2011, 2012).
- IB’s online API Guide
Pricing and support
The license for a single computer for the first year costs $349. This includes installation support, fixing bugs, and any fixes that may be required due to IB API changes.
Annual renewal (including license, support and maintenance) for each following year costs $99.
To purchase the software license ($349), click here.
To purchase the annual renewal ($99), click here.
Please email me if you require volume license pricing or custom development.
A fully-functional free trial version is available upon request – please email me.
I pride myself on providing top-quality software and support. Customer satisfaction is a top priority for me.
Usage syntax
General syntax (quick help reference; detailed user guide (PDF)):
[orderId,ibConnectionObject] = IBMatlab(varargin)
Possible inputs parameters:
- varargin = Matlab struct or fieldname/value pairs with the following optional fields:
- General: LogFileName, MsgDisplayLevel
- Connection: ClientId, Host, Port
- Action: (one of Buy, Sell, SShort, Query, Cancel, Account_Data, History_Data, or Portfolio_Data)
- Order type: (one of MKT, MKTCLS, LMT, LMTCLS, PEGMKT, STP, STPLMT, MIT, TRAIL, REL, VWAP, GuarranteedVWAP, TRAILLIMIT, OPEN, etc. – see full list here and detailed explanations here; note that IB does not allow some combinations of orders and securities)
- Order data: Action, Quantity, TIF, LimitPrice, AuxPrice, OCAGroup, ParentId, TrailStopPrice, GoodAfterTime, GoodTillDate, BracketDelta, BracketTypes, AccountName, FAProfile, TriggerMethod, OutsideRTH, OrderId
- VWAP order data: MaxPctVol, StartTime, EndTime, AllowPastEndTime, NoTakeLiq
- Automated order data: LimitBasis, LimitDelta, LimitRepeatEvery, LimitChangeTime, LimitChangeType, Tick
- Contract data: Symbol, SecType, Exchange, Currency, LocalSymbol, Expiry, Strike, Right
- Historical data: EndDateTime, DurationValue, DurationUnits, BarSize, WhatToShow, UseRTH, FormatDate (note IB’s pace limitations)
- Streaming quotes data: QuotesNumber, QuotesBufferSize, GenericTickList
- Event callbacks: CallbackFunction, CallbackAccountDownloadEnd, CallbackBondContractDetails, CallbackConnectionClosed, CallbackContractDetails, CallbackContractDetailsEnd, CallbackCurrentTime, CallbackDeltaNeutralValidation, CallbackExecDetails, CallbackExecDetailsEnd, CallbackFundamentalData, CallbackHistoricalData, CallbackManagedAccounts, CallbackMessage, CallbackNextValidId, CallbackOpenOrder, CallbackOpenOrderEnd, CallbackOrderStatus, CallbackTickPrice, CallbackTickSize, CallbackTickString, CallbackTickGeneric, CallbackTickEFP, CallbackTickOptionComputation, CallbackTickSnapshotEnd, CallbackRealtimeBar, CallbackReceiveFA, CallbackScannerData, CallbackScannerDataEnd, CallbackScannerParameters, CallbackUpdateAccountTime, CallbackUpdateAccountValue, CallbackUpdateMktDepth, CallbackUpdateMktDepthL2, CallbackUpdateNewsBulletin, CallbackUpdatePortfolio
Outputs:
- orderId = -1 if unsuccessful, otherwise the ID of the placed order, or data for ‘QUERY’ actions
- ibConnectionObject = reference of Java object that interfaces with IB
Usage examples
1) Buy stock
Note the two alternative manners in which the parameters can be specified (you can use whichever is more convenient to you):
% Matlab struct alternative: paramsStruct = []; paramsStruct.action = 'BUY'; paramsStruct.symbol = 'GOOG'; paramsStruct.quantity = 100; paramsStruct.limitPrice = 600; orderId = IBMatlab(paramsStruct); % Name/value pairs alternative: orderId = IBMatlab('action','BUY', 'symbol','GOOG', 'quantity',100, 'limitPrice',600);
2) Sell stock
orderId = IBMatlab('action','SELL', 'symbol','GOOG', 'quantity',100, 'limitPrice',600);
3) Get market data for a particular stock
>> data = IBMatlab('action','QUERY', 'symbol','GOOG') data = reqId: 22209874 reqTime: '02-Dec-2010 00:47:23' dataTime: '02-Dec-2010 00:47:23' 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
4) Get portfolio data
>> data = IBMatlab('action','PORTFOLIO_DATA') data = 1x12 struct array with fields: symbol localSymbol exchange secType currency right expiry strike position marketValue marketPrice averageCost >> data(1) ans = symbol: 'AMZN' localSymbol: 'AMZN' exchange: 'NASDAQ' secType: 'STK' currency: 'USD' right: '0' expiry: '' strike: 0 position: 9200 marketValue: 1715800 marketPrice: 186.5 averageCost: 169.03183335
5) Get historical data
Supported Historical data parameters (explanations here): EndDateTime, DurationValue, DurationUnits, BarSize, WhatToShow, UseRTH, FormatDate. Note IB’s pace limitations for historical data.
>> data = IBMatlab('action','HISTORY_DATA', 'symbol','IBM', 'barSize','1 hour', 'useRTH',1) data = dateTime: {1x7 cell} open: [161.08 160.95 161.66 161.17 161.57 161.75 162.07] high: [161.35 161.65 161.70 161.60 161.98 162.09 162.34] low: [160.86 160.89 161.00 161.13 161.53 161.61 161.89] close: [160.93 161.65 161.18 161.60 161.74 162.07 162.29] 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 162.14] hasGaps: [0 0 0 0 0 0 0] >> data.dateTime ans = '20110225 16:30:00' '20110225 17:00:00' '20110225 18:00:00' '20110225 19:00:00' '20110225 20:00:00' '20110225 21:00:00' '20110225 22:00:00'
6) Get account data
>> 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 CorporateBondValue: 0 Currency: 'USD' Cushion: 0.361508 DayTradesRemaining: -1 DayTradesRemainingT_plus_1: -1 DayTradesRemainingT_plus_2: -1 DayTradesRemainingT_plus_3: -1 DayTradesRemainingT_plus_4: -1 EquityWithLoanValue: 723913.41 ExcessLiquidity: 261700.68 ExchangeRate: 1 FullAvailableFunds: 261700.68 FullExcessLiquidity: 261700.68 FullInitMarginReq: 462212.73 FullMaintMarginReq: 462212.73 FundValue: 0 FutureOptionValue: 0 FuturesPNL: 0 FxCashBalance: 0 GrossPositionValue: 1540709.11 IndianStockHaircut: 0 InitMarginReq: 462212.73 Leverage: 2.13 LookAheadAvailableFunds: 261700.68 LookAheadExcessLiquidity: 261700.68 LookAheadInitMarginReq: 462212.73 LookAheadMaintMarginReq: 462212.73 LookAheadNextChange: 0 MaintMarginReq: 462212.73 MoneyMarketFundValue: 0 MutualFundValue: 0 NetDividend: 0 NetLiquidation: 723913.41 NetLiquidationByCurrency: 714852.34 OptionMarketValue: 0 PASharesValue: 0 PNL: 'true' PreviousDayEquityWithLoanValue: 696109.82 RealizedPnL: 0 RegTEquity: 723913.41 RegTMargin: 770354.56 SMA: 78512.41 StockMarketValue: 1540709.11 TBillValue: 0 TBondValue: 0 TotalCashBalance: -825400.37 TotalCashValue: -816339.3 TradingType: 'STKNOPT' UnalteredInitMarginReq: -1 UnalteredMaintMarginReq: -1 UnrealizedPnL: -40731.17 WarrantValue: 0 WhatIfPMEnabled: 'true'
7) Get streaming quotes data
The initial request to send streaming quotes:
>> reqId = IBMatlab('action','QUERY', 'symbol','EUR', 'localsymbol','EUR.USD', ... 'currency','USD', 'sectype','cash', 'exchange','idealpro', 'QuotesNumber',100) reqId = 147898050
Subsequent requests to retrieve the latest accumulated QuotesBuffer data return a dataStruct that looks like this:
>> dataStruct = IBMatlab('action','QUERY', 'symbol','EUR', '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]
Note that you only need to specify the Symbol/LocalSymbol and the QuotesNumber in the subsequent requests, all other parameters are unnecessary since the system already knows about this symbol’s parameters from the initial streaming request.
To get the actual data, simply read the data field of this dataStruct:
>> dataStruct.data ans = dataTimestamp: 734892.764653854 high: 1.3061 highTimestamp: 734892.762143183 low: 1.29545 lowTimestamp: 734892.762143183 close: 1.30155 closeTimestamp: 734892.762143183 bidPrice: 1.2986 bidPriceTimestamp: 734892.764653854 bidSize: 1000000 bidSizeTimestamp: 734892.764653854 askPrice: 1.29865 askPriceTimestamp: 734892.764499421 askSize: 18533000 askSizeTimestamp: 734892.764653854
Note that each data item has an associated timestamp, because different data items are sent separately from the IB server. You can convert the timestamps into human-readable string by using Matlab’s datestr function, as follows:
>> datestr(dataStruct.data.dataTimestamp) ans = 24-Jan-2012 23:56:32
If instead of using QuotesBufferSize=1 (which is the default value), I had used QuotesBufferSize=4, then I would see not the latest quote but the latest 4 quotes:
>> reqId = IBMatlab('action','QUERY', 'symbol','EUR', 'localsymbol', 'EUR.USD', 'currency','USD', ... 'sectype','cash', 'exchange','idealpro', 'QuotesNumber',10, 'QuotesBufferSize',4); % now at any following point in time run the following command to get the latest 4 quotes: >> dataStruct = IBMatlab('action','QUERY', 'localsymbol','EUR.USD', 'QuotesNumber',-1); >> dataStruct.data ans = dataTimestamp: [734892.99760235 734892.99760235 734892.99760235 734892.997756076] high: 1.3061 highTimestamp: 734892.99740162 low: 1.29545 lowTimestamp: 734892.99740162 bidPrice: [1.3035 1.30355 1.3035 1.30345] bidPriceTimestamp: [734892.99760235 734892.99760235 734892.99760235 734892.997756076] bidSize: [3000000 2000000 4000000 4000000] bidSizeTimestamp: [734892.997743958 734892.997756076 734892.997756076 734892.997756076] askPrice: [1.3036 1.30355 1.3036 1.30355] askPriceTimestamp: [734892.997523681 734892.997667824 734892.997667824 734892.997756076] askSize: [2153000 3153000 2153000 4153000] askSizeTimestamp: [734892.997756076 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 the IB server.
8) Specify event callback – ExecDetails
Attach a user callback function to ExecDetails events (that occur upon any order execution – more details here):
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):
% See: http://www.interactivebrokers.com/php/apiUsersGuide/apiguide/java/execdetails.htm % http://www.interactivebrokers.com/php/apiguide/interoperability/activex_other/activexevents.htm#execDetails function IBMatlab_CallbackExecDetails(hObject, eventData, varargin) % Extract the basic event data components contractData = eventData.contract; executionData = eventData.execution; % Example of extracting data from the contract object: % See: http://www.interactivebrokers.com/php/apiUsersGuide/apiguide/java/contract.htm symbol = char(eventData.contract.m_symbol); secType = char(eventData.contract.m_secType); % ... and several other contract data available - see the above webpage % Example of extracting data from the execution object: % http://www.interactivebrokers.com/php/apiUsersGuide/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; % ... and several other contract data available - see the above webpage % Now do something useful with all this information... end % IBMatlab_CallbackExecDetails
9) Specify event callback – TickGeneric
Attach a user callback function to TickGeneric events in order to check whether a security is shortable
Note: according to IB, “Generic Tick Tags cannot be specified if you elect to use the Snapshot market data subscription“, and therefore we need to use the streaming-quotes mechanism, so QuotesNumber>1:
orderId = IBMatlab('action','Query', 'symbol','GOOG', 'GenericTicklist','236', 'QuotesNumber',2, ... 'CallbackTickGeneric',@IBMatlab_CallbackTickGeneric);
where the function IBMatlab_CallbackTickGeneric is defined as follows:
% See: http://www.interactivebrokers.com/php/apiUsersGuide/apiguide/java/tickgeneric.htm % http://www.interactivebrokers.com/php/apiguide/interoperability/activex_other/activexevents.htm#tickGeneric function IBMatlab_CallbackTickGeneric(hObject,eventData,varargin) % Only check the shortable tick type =46, according to % http://www.interactivebrokers.com/php/apiUsersGuide/apiguide.htm#apiguide/api/tick_values.htm%23XREF_tick_values_generic_tick if eventData.field == 46 % 46=Shortable % Get this event's tickerId (=orderId as returned from the original IBMatlab command) tickerId = eventData.tickerId; % Get the corresponding shortable value shortableValue = eventData.generic; % Now check whether the security is shortable or not title = sprintf('Shortable info for request %d', tickerId); if (shortableValue > 2.5) % 3.0 msgbox('There are at least 1000 shares available for a short sale', title, 'help'); elseif (shortableValue > 1.5) % 2.0 msgbox('This contract will be available for short sale if shares can be located', title, 'warn'); elseif (shortableValue > 0.5) % 1.0 msgbox('Not available for short sale', title, 'warn'); else msgbox(sprintf('Unknown shortable value: %g',shortableValue), title, 'error'); end end % if shortable tickType end % IBMatlab_CallbackTickGeneric
10) Using the underlying Java connection object
Cancel an open order (one example of the many possible actions that can be done via ibConnectionObject):
% 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); % Alternatively, cancel the order using the Matlab wrapper: IBMatlab('action','CANCEL', 'orderId',orderId);
Legal disclaimer:
THIS 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 NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
