OK, here is some trivialized psuedo-code for what I have in mind. It ignores a lot of details:
Code:
IMarketDataHandler mdh = new DebugMarketDataHandler();
//Alternatively...
//IMarketDataHandler mdh = new JMSMarketDataHandler();
IMarketDataProvider mdp = new IBAdaptor(mdh);
//Alternatively...
//IMarketDataProvider mdp = new OpenTickAdaptor(mdh)
mdp.connect();
mdp.subscribe(...);
mdp.unsubscribe(...);
mdp.disconnect();
Obviously this is very simplistic. However, I hope the
concept and essence is clear:
1) An interface IMarketDataHandler which hypothetically has methods like onQuote(), onTrade(), onError() etc.
It is the responsibility of the adaptor to translate their native callback handlers into the normalized methods of the IMarketDataHandler interface.
Using an interface for handlers allows people to provide different implementations e.g. a debug handler that simply dumps the information. A JMS producer which posts the data to various topics. The handler could even be the entry point to someone's custom ATS.
2) An interface IMarketDataProvider which hypothetically has methods like connect(), subscribe() etc.
It is the responsibility of the adaptor to translate these methods into the relevant native calls.
Now, there are a multitude of problems with this idealized arrangement but I don't see the problems as being insurmountable.
The immediate problems I have are the following:
1) Dealing with connection/authentication parameters. For example, the IB adaptor connects to a port. The OpenTick adaptor connects to a server(s) with authentication parameters. Obviously some kind of factory seems warranted here so any ideas on the matter much appreciated.
2) Dealing with unsupported functionality or dealing with lowest common denominator functionality. I'm looking for ideas on how best to deal with the different capabilities of different providers. Perhaps throwing unsupported runtime exceptions for those providers with less capabilities etc. Again, ideas please!
3) Dealing with errors. Connection errors etc. My thoughts are give the responsibility of the adaptor to package native errors into a normalized format which then get's propogated. The question then becomes, propogate the error via exception mechanisms or via IMarketDataHandler interface onError() method and leave it to the implementation of the handler to decide how to deal with the error.
4) Subscribing, unsubscribing etc. normalization of instrument/symbols etc. If normalized, normalized to what? Is the QuantDeveloper approach of being FIX-oriented worth pursuing? Should it be left to the adaptor to convert the normalized instrument/symbol/contract to a native format? etc. Thoughts/ideas on this matter please!
5) The most annoying problem for me has been to deal with the fact that IB and others are
both data providers and broker interfaces. Therefore, one would want to re-use the existing connection when it comes to instantiating a broker interface. However, things can get more complicated than that:
You may want to have market data from one source and execute via another. You may have a system that executes some trades via TWS on one port, and another system that executes some trades via TWS on another port or even another IP address etc.
So lots of things to think about. I'm really trying to keep posts as short as possible without omitting pertinent information but it's a little tricky.
I've just downloaded StarUML to see what it's like and hopefully communicate ideas via diagrams in future. I'll have to get back up to speed on UML. It's all been a very long time...!