Date: Fri, 29 Mar 2024 01:32:49 -0700 (PDT) Message-ID: <887332908.415.1711701169353@aries> Subject: Exported From Confluence MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_Part_414_1425570438.1711701169353" ------=_Part_414_1425570438.1711701169353 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Content-Location: file:///C:/exported.html
When connecting the Marketcetera Automated Trading Platform to a= n external data source, like a market data provider
org.marketcetera.marketdata.c=
ore.provider.MarketDataProvider
There, wasn't that easy? Like all things in life worth getting, though, = the devil is in the details. Let's take a closer look.
You can just create a class that implements MarketDataProvide=
r
, however, it's probably going to be easier to create a class that =
extends org.marketcetera.marketdata.core.provider.AbstractMarket=
DataProvider
(which itself implements the necessary interface) inste=
ad. So, do that. Then, implement the following abstract methods:
Just like it sounds! Implement the steps necessary to start the adapter.= This usually includes doing some initialization on libraries from the prov= ider, opening sockets, etc. The details differ depending on the external so= urce.
Like doStart, but the opposite. Shut it all down.
Execute a market data request from the provider. You're going to be hand=
ed two objects: MarketDataRequestAtom
and Mark=
etDataRequest
. The request atom is a symbol/content tuple, like "top=
-of-the-book for IBM", e.g. Just make data flow from the provider for that.=
This method will be invoked for each atom generated from a request. The co=
mplete request is provided for context as well, but just generate data for =
the atom.
Almost all market data providers are asynchronous and streaming. So, ret= urn from this method as soon as the request is made, don't wait for market = data to start arriving. More on that later. The superclass takes care of re= ference counting, etc, so you don't have to.
Cancel a market data request subscription for the given atom.
And that's (almost) it!
There are two more pieces of information you need:
Before your adapter can return events, it needs to call A=
bstractMarketDataProvider.addSymbolMapping
. This method maps the sym=
bol in an atom to a subclass of org.marketcetera.trade.Instrument, as in:
addSymbo= lMapping("IBM",new Equity("IBM"));
This allows the parent class to associate the atom to a particular= instrument.
AbstractMarketDataProvider.publishEve=
nts
using the org.marketcetera.event.Content
from =
the atom that generated the request and the org.marketcetera.tra=
de.Instrument
you associated the atom with above.The easiest way to add your provider to the application context is to ad=
d a bean to strategyengine.xml
like this:
<bean = id=3D"myFeed" class=3D"com.marketcetera.marketdata.myfeed.MyFeed"> <property name=3D"providerRegistry" ref=3D"marketDataManager"/> </bean>
The providerRegistry
points to the existing MarketDataManager
implementation, which is how Marketcetera knows a=
bout your provider. You can also set other properties you might need here, =
like hostname, port, username, password, etc. Just add matching getters/set=
ters to the class and additional property elements.
That really is it!
To make it easy to resolve symbols to instruments, use the symbol resolv= er built into Marketcetera. To make it show up in your provider, add this t= o your bean:
<bean= id=3D"myFeed" class=3D"com.marketcetera.marketdata.myfeed.MyFeed"> <property name=3D"providerRegistry" ref=3D"marketDataManager"/> <property name=3D"symbolResolver" ref=3D"symbolResolverService"/> </bean>
and this to your feed class:
public = void setSymbolResolver(SymbolResolverService inService) { symbolResolverService =3D inService; } public SymbolResolverService getSymbolResolverService() { return symbolResolverService; } private SymbolResolverService symbolResolverService;
To use it:
protecte= d void doMarketDataRequest(MarketDataRequest inCompleteRequest, MarketDataR= equestAtom inRequestAtom) { Instrument resolvedInstrument =3D symbolResolverService.resolveSymbol(i= nRequestAtom.getSymbol); addSymbolMapping(inRequestAtom.getSymbol(), resolvedInstrument); // do whatever to make the data flow - remember the instrument above, y= ou'll need it }
You can adapt the behavior of the SymbolResolverService
if =
you want. Look at application.xml
for the bean that defines it=
. You can add your own symbol resolvers if you want.