softwarespartan / IB4m

Interactive Brokers API for Matlab
GNU General Public License v2.0
62 stars 21 forks source link

Learning on how to expose additional TWS API Events #39

Open Benvaulter opened 5 years ago

Benvaulter commented 5 years ago

Hi Abel,

as mentioned in one of my previous posts, it would be great if you could let us know the process on how to expose additional events (i.e. so that we can initialize buffers in Matlab and catch the data there). You already mentioned that it's not really a complicated process and that it requires adding something in Java and the recompiling the code.

I mosty use the IB API Gateway which offers a direct view into the logs and tested several IB methods from the eClientSocket from within Matlab and it all works perfectly (i.e. I can see in the log that the TWS returns data for the request), hence it would be awesome to be able to access this data in Matlab as well using the established "buffer-method".

Would be great if you find the time to quickly write that done - would be happy to help with this process as well to expose new events :)

softwarespartan commented 5 years ago

Hi Ben

Added market rule events in latest commit for IB4m. Also, added new repository for all the src and IntelliJ build files for the IB4m jar file.

https://github.com/softwarespartan/TWS973

In general, on the Java side, you need to update com.tws.Handler to respond to the event. There are many example so just follow the pattern. The generic steps are

1.add listener map 2.add methods for add/remove listener 3.create event class (object that is passed to matlab)

  1. overload TWS API callback to process response and publish event to listeners

    private final Set marketRuleListeners = Collections.newSetFromMap(new ConcurrentHashMap<NotificationListener,Boolean>());

    public void addMarketRuleListener (NotificationListener listener) { System.out.println("market rule listener has been added"); this.marketRuleListeners.add(listener); }

    public void removeMarketRuleListener (NotificationListener listener) { System.out.println("market rule listener has been removed"); this.marketRuleListeners.remove(listener); }

    @Override public void marketRule(int marketRuleId, PriceIncrement[] priceIncrements) { this.processEvent( new MarketRuleEvent(this, Arrays.asList(priceIncrements)), this.marketRuleListeners ); }

    public final class MarketRuleEvent extends Event<List>{ public MarketRuleEvent(Object source, List data) { super(source, data); } }

From the matlab side, need to modify the following (e.g. for MarketRule)

+TWS/+EventData/MarketRule.m +TWS/Events.m +TWS/processNotification.m

The new class +TWS/+EventData/MarketRule.m is just a generic matlab event class. It just needs to exist of Matlab can create event objects. If you look at +TWS/+EventData they are all the same except for their Class names. Technically, these are called 'marker' classes.

Then need to update +TWS/Events.m with 'constant' tag for the new event as well as add it to the 'events' properties.

Finally, update +TWS/processNotification for the new event object coming from com.tws.Handler. In the case of market rule the new event is 'com.tws.Handler$MarketRuleEvent' which matches the class created on the Java side:

public final class MarketRuleEvent extends Event<List<PriceIncrement>>{
    public MarketRuleEvent(Object source, List<PriceIncrement> data) { super(source, data); }
}

When building the jar file need to add

/Applications/MATLAB_R2016b.app/java/jar/jmi.jar

which is the backend java/matlab interface. I am currently using java compiler 1.8.0_101 and compiling at language level 7. This is important since if does not match language level of the matlab runtime java then will not be able to import jar file. When fail jar import there is no warning, nothing -- matlab just silently fails. So if build own jar file and then can't find the classes after import in matlab, first thing to check is compiler version and language level. I had to modify a bit of the TWS API codes to get them to compile at language level 7 (that's an old language level).

Give that a try and see if that is enough details to get you going.