Limitations of the MATLAB COM Interface
This tutorial is one in a series that discusses Using CQG From Within MATLAB.
Some of the limitations of the MATLAB COM interface are discussed – and specifically those limitations that apply to calling CQG through COM. Note that none of the limitations to be discussed here are show stoppers. Rather they are issues that need to be understood to write workable code for interfacing CQG and MATLAB.
The specific issues discussed here are,
- Handling Asynchronous Events
- Working with Collections
- Exception Handling
- The Date Data Type
- The IsReady Method
It is assumed that the reader has some understanding of both the CQG API and MATLAB, although a detailed knowledge of neither is required.
Handling Asynchronous Events
As of R2012a MATLAB does not officially support asynchronous events arriving through its COM interface. This is a significant issue for using CQG from within MATLAB as CQG relies almost exclusively on firing events asynchonously to tell a listener that new data is available or an error has occured.
For example, several of the common events fired from CQG are:
- CELStarted – when the connection to CQG from MATLAB is started.
- DataConnectionStatusChanged – when the connection status has changed, e.g. it has been lost or regained.
- DataError – when a discrepancy between data sent and recieved is detected.
Although the asynchonous nature of the above events can typically be handled quite easily, an example where asynchonous events can cause problems is the following: Consider the TimedBars interface, which allows information such as Open, High, Low, and Close data to be loaded into MATLAB. The TimedBars will typically cover a user specified, possibly sliding, window of time.
Figure 1 shows how such TimedBars data may be displaying in MATLAB as a scrolling candlestick plot. (See the An Example Obtaining TimedBars tutorial for an example of how to obtain TimedBars data similar to that used to generate Figure 1.)
After starting the CQG connection, when the first set of TimedBars is available, CQG will (asynchonously) fire a TimedBarsResolved event. The (user written) event handler is then used to initialize anything in MATLAB that will subsequently be used to display the data – such as the graphics components used to display the candlestick in Figure 1.
Subsequent to the TimedBarsResolved event, CQG may (asynchronously) fire the events
- TimedBarsAdded – when data with a new timestamp outside the current time range is available.
- TimedBarsUpdated – when the data for an existing timestamp has changed.
- TimedBarsInserted – when data with a new timestamp within the current time range is available.
- TimedBarsRemoved – when data for a given timestamp is dropped (i.e. slides out of the current time range).
However a problem arises when the TimedBarsResolved event has not been completely handled before one or more of the above events occur. For instance, if a TimedBarsUpdated event occurs and tries to update an existing candlestick before the TimedBarsResolved event handler has completed initializing the candlestick plot then an error can easily occur.
When using MATLAB there is no guaranteed way around this asynchronous event firing problem. (There are several ways around the problem when using the CQG interface to other languages, e.g. VBA, C# and C++, and they are touched upon briefly in the The IsReady Method section.)
From MATLAB the only approach is to ensure that as much of the initialization as possible gets performed before data begins to get received. For the candlestick example this means creating all of the graphics components using dummy data prior to starting the upload of real data. Then the newly arrived data simply has to update the candlesticks rather than create them from scratch, which provides a considerable time saving.
Working with Collections
The MATLAB documentation (for at least R2012a and prior releases) states that MATLAB only supports indexed Collections. However that is not strictly correct.
What the documentation means is that looping over the elements of a collection is difficult if the collection does not have a method to extract its elements based on an index. This is a consequence of MATLAB not having a For...Each syntax construct (such as those in VBA and C#) allowing non-indexed collections to be looped over.
The CQG object model contains various collections that do not have an appropriate indexing method for MATLAB to use when looping. One of these is the CQGQuotes collection.
However, there are (sometimes) ways around this limitation. One of them is shown in the An Example Obtaining Tick Data tutorial, where a CQGQuotes collection is passed to the InstrumentChanged event handler. The CQGQuotes collection is non-indexed, however it does have an Item method that allows items to be extracted from the collection via an enumeration. (The InstrumentChanged event is fired when a particular instument that has been subsribed to changes – for instance when the last Bid, Ask or Trade of an instrument changes – and the enumeration represents whether it was a change in the Bid, Ask, Trade or one of many other properties that forced the InstrumentChanged event to be fired.)
The workaround involves knowing two things: how many items are in a particular CQGQuotes collection; and all possible enumerations that can be used to access the elements via the available Item method.
Errors/exceptions must not be thrown inside event handlers. If they are, then there is a very high probability that MATLAB will close instantanously – no warning; no opportunity to save files or data; the MATLAB process will just die. (Sometimes MATLAB will indcate that a segmentation fault has occured, thus providing the opportunity to save before exiting.)
This means that any event handler where an error can possibly occur must use Try...Catch constructs to catch errors and deal with them. Unfortunately wrapping the event handler in a Try...Catch is not enough. The error handling must be done inside the event handler.
This limitation makes the bubbling up of errors to higher level exception handlers difficult, and can sometimes also cause problems just in general debugging. Fortunately neither of these problems are insurmountable.
The Date Data Type
Unlike many programming languages MATLAB does not have a Date data type. Rather dates are stored either as datenum or character strings. A date represented as a number stores the amount of time that has elapsed from a specified universal start date, which in MATLAB is 1-Jan-0000, while a string representation looks like ‘31-12-2000 10:47:05 PM’. (Note that this is just one of many different formats that the date as a string can be represented using.)
With the CQG-MATLAB API the problem arises when a CQG method requires its input to be a Date data type. In these cases the MATLAB representation of the date must be converted to a COM Date using the COM.Date method before being passed to the CQG API.
The IsReady Method
The CQG API documentation describes the IsReady method as being a method specifically written for use with Microsoft Excel to tell CQG whether Excel is ready to receive events. The assumption here is that sometimes Excel needs to tell CQG to delay firing new events until it has finished processing a previously fired event, i.e. until it is ready to receive them.
This would be an ideal approach to use to overcome the asynchronous events limitation discussed earlier in this tutorial. (The documentation indicates that IsReady may also be used in other applications, not just Excel.) The problem is that the input to IsReady is passed (in VBA) ByRef, and MATLAB does not support passing data by reference (or as pointers).
Hence there is no mechanism in the CQG-MATLAB API for MATLAB to tell CQG to delay firing the next event.