Market Data OEC Application Programming Interface

We need to get some data to make a trading decision. OECAPI can give us quotes, DOMs, bars, ticks and histograms. All we need to do is to hook to some event, send a request to subscribe to data updates and/or just load a piece of data

This topic contains the following sections:

Quotes

Quotes is the simplest kind of market data. Let's enhance our example to write down to console output all quotes for the symbol that found out via symbol lookup

C#
		static void Main(string[] args)
		{
			...
			oecapi.OnPriceTick += new OEC.API.OnPriceChangedEvent(oecapi_OnPriceTick);
			...
		}
		
		static void oecapi_OnSymbolLookupReceived(OEC.API.SymbolLookupCriteria symbolLookup, OEC.API.ContractList contracts)
		{
			if (esh3SymbolLookupRequest != null && symbolLookup.ID == esh3SymbolLookupRequest.ID)
			{
				Console.WriteLine("Symbol lookup request for ESH3 found {0} contracts", contracts.Count);
				foreach (var contract in contracts)
				{
					DisplayContract(contract);
					oecapi.Subscribe(contract); // Subscribe for quotes
				}
			}
			...
		}
		
		static void oecapi_OnPriceTick(OEC.API.Contract contract, OEC.API.Price price)
		{
			Console.WriteLine("{0} {1} O:{2} H:{3} L:{4} Last:{5}, Bid:{6} Ask:{7} TotalVol:{8}",
					contract.Symbol, price.LastDateTime,
					contract.PriceToString(price.OpenPrice), contract.PriceToString(price.HighPrice),
					contract.PriceToString(price.LowPrice),  contract.PriceToString(price.LastPrice),
					contract.PriceToString(price.BidPrice),  contract.PriceToString(price.AskPrice),
					price.TotalVol);
		}

As a variant, we could use CurrentPrice inside this event (or in any other place of application)

Want to trottle updates down? Just replace OnPriceTick to OnPriceChanged: OnPriceChanged raised with cumulative quote not more often than one time in EventBatchInterval msec

To unsubscribe quotes just call Unsubscribe(Contract). You need to make sure you called the same number of times of Subscribe and Unsubscribe for a contract to avoid "subscription" leaks. Number of subscriptions is a limited resource.

DOM

Subscribe to DOM is not quite harder:

C#
		static void Main(string[] args)
		{
			...
			oecapi.OnDOMChanged += new OEC.API.OnDOMChangedEvent(oecapi_OnDOMChanged);
			...
		}
		
		static void oecapi_OnSymbolLookupReceived(OEC.API.SymbolLookupCriteria symbolLookup, OEC.API.ContractList contracts)
		{
			...
					oecapi.Subscribe(contract); // Subscribe for quotes
					oecapi.SubscribeDOM(contract); // Subscribe DOM
			...
		}
		
		static void oecapi_OnDOMChanged(OEC.API.Contract contract)
		{
			OEC.API.DOM dom = contract.DOM;
			Console.WriteLine("DOM {0} {1} Bids: {2} Asks: {3} Best Bid: {4} Best Ask: {5}",
					contract.Symbol, dom.LastUpdate,
					dom.BidLevels.Length, dom.AskLevels.Length,
					dom.BidLevels.Length > 0 ? dom.BidSizes[0].ToString() + "@" + contract.PriceToString(dom.BidLevels[0]) : "-",
					dom.AskLevels.Length > 0 ? dom.AskSizes[0].ToString() + "@" + contract.PriceToString(dom.AskLevels[0]) : "-");
		}

Unsubscribe pair for DOM is UnsubscribeDOM(Contract)

Bars

Loading bars needs more input parameters than DOMs and quotes. Moreover, we can either load just a bunch of historical bars, either load some historical bars up to now and then get updates via a subscription. OEC.API.OECClient.RequestBars is supposed for one time loading, OEC.API.SubscribeBars - for updatable subscriptions

C#
		static void Main(string[] args)
		{			
			...
			oecapi.OnBarsReceived += new OEC.API.OnBarsReceivedEvent(oecapi_OnBarsReceived);			
			...
		}
		
		static void oecapi_OnSymbolLookupReceived(OEC.API.SymbolLookupCriteria symbolLookup, OEC.API.ContractList contracts)
		{
			...
					oecapi.Subscribe(contract); // Subscribe for quotes
					oecapi.SubscribeDOM(contract); // Subscribe DOM
					oecapi.SubscribeBars(contract, DateTime.UtcNow.AddDays(-3), OEC.Data.SubscriptionType.Bar, 10); // Subscribe 10-min bars and loads previous 3 days of historical bars
			...
		}
		
		static void oecapi_OnBarsReceived(OEC.API.Subscription subscription, OEC.API.Bar[] bars)
		{
			Console.WriteLine("{0} bars received for {1} {2} {3}", bars.Length, subscription.Contract.Symbol, subscription.Type, subscription.IntInterval);
			foreach (OEC.API.Bar bar in bars)
				DisplayBar(subscription.Contract, bar);
		}

		static void DisplayBar(OEC.API.Contract contract, OEC.API.Bar bar)
		{
			Console.WriteLine("{0} {1} O:{2} H:{3} L:{4} C:{5} Vol:{6} Ticks:{7} UpVol:{8} DownVol:{9}",
					contract.Symbol, bar.Timestamp.ToLocalTime(),
					contract.PriceToString(bar.Open), contract.PriceToString(bar.High),
					contract.PriceToString(bar.Low), contract.PriceToString(bar.Close),
					bar.Volume, bar.Ticks,
					bar.UpVolume, bar.DownVolume);
		}

OECAPI provides a good choice of bar types: second, minute, range, momentum, tick and volume bars with custom size, daily, weekly, monthly bars

Unsubscribe pair for SubscribeBars is CancelSubscription(Subscription). RequestBars requests don't need to be unsubscribed.

Ticks

Subsribing and loading of tick are almost the same as bars:

C#
		static void Main(string[] args)
		{			
			...
			oecapi.OnTicksReceived += new OEC.API.OnTicksReceivedEvent(oecapi_OnTicksReceived);
			...
		}
		
		static void oecapi_OnSymbolLookupReceived(OEC.API.SymbolLookupCriteria symbolLookup, OEC.API.ContractList contracts)
		{
			...
					oecapi.SubscribeBars(contract, DateTime.UtcNow.AddDays(-3), OEC.Data.SubscriptionType.Bar, 10); // Subscribe 10-min bars and loads previous 3 days of historical bars
					oecapi.RequestTicks(contract, DateTime.UtcNow.AddHours(-1), DateTime.UtcNow); // Request ticks for the last hour without further updates
			...
		}
		
		static void oecapi_OnTicksReceived(OEC.API.Subscription subscription, OEC.API.Ticks ticks)
		{
			Console.WriteLine("{0} ticks received for {1}", ticks.PriceList.Length, subscription.Contract.Symbol);
			for (int i = 0; i < ticks.PriceList.Length; ++i)
				Console.WriteLine("{0} {1}@{2}\tBid:{3} Ask:{4}", ticks.TimestampList[i].ToLocalTime(), ticks.VolumeList[i], ticks.PriceList[i], ticks.BidPriceList[i], ticks.AskPriceList[i]);
		}

Unsubscribe pair for SubscribeTicks is CancelSubscription(Subscription). RequestTicks requests don't need to be unsubscribed.

Subscription Limits

As mentioned above, subscriptions are a limited resource in OECAPI. Don't need a subscription anymore - unsubscribe it. If you reached the limit, subscription request will be declined by OEC server. Let's output to console window our current status of subscriptions.

C#
		static System.Windows.Forms.Timer statusTimer = null;
		static void Main(string[] args)
		{
			...
			statusTimer = new System.Windows.Forms.Timer();
			statusTimer.Tick += new EventHandler(statusTimer_Tick);
			statusTimer.Interval = 1000;
			statusTimer.Start();
			Console.WriteLine("Press Ctrl-C to exit");
			System.Windows.Forms.Application.Run();
		}

		static void statusTimer_Tick(object sender, EventArgs e)
		{
			if(oecapi.CompleteConnected)
				ShowCurrentSubscriptionStatus();
		}

		static void ShowCurrentSubscriptionStatus()
		{
			Console.WriteLine("Quotes: {0}/{1}; DOMs: {2}/{3}; bars: {4}/{5}; ticks: {6}/{7}",
					GetQuotesSubscriptions(), oecapi.Properties["Quotes"],
					GetDOMsSubscriptions(), oecapi.Properties["DOMs"],
					GetBarsSubscriptions(), oecapi.Properties["MaxBars"],
					GetTicksSubscriptions(), oecapi.Properties["MaxTicks"]);

		}
		
		static IEnumerable<OEC.API.Subscription> GetUpdatableSubscriptions(params OEC.Data.SubscriptionType [] subscriptionTypes)
		{
			return oecapi.Subscriptions.Where(subscription => subscription.Updatable && subscriptionTypes.Contains(subscription.Type));
		}

		static int GetQuotesSubscriptions()
		{
			return GetUpdatableSubscriptions(OEC.Data.SubscriptionType.Price).Count(subscription => !subscription.Contract.IsForex && !subscription.Contract.IsEquityAsset);
		}

		static int GetDOMsSubscriptions()
		{
			return GetUpdatableSubscriptions(OEC.Data.SubscriptionType.DOM).Count();
		}

		static int GetBarsSubscriptions()
		{
			return GetUpdatableSubscriptions(OEC.Data.SubscriptionType.Bar, 
						OEC.Data.SubscriptionType.DayBar, 
						OEC.Data.SubscriptionType.WeeklyBar, 
						OEC.Data.SubscriptionType.MonthlyBar,
						OEC.Data.SubscriptionType.SecondBar, 
						OEC.Data.SubscriptionType.RangeBar, OEC.Data.SubscriptionType.MomentumBar,
						OEC.Data.SubscriptionType.TickBar, OEC.Data.SubscriptionType.VolumeBar).Count();
		}

		static int GetTicksSubscriptions()
		{
			return GetUpdatableSubscriptions(OEC.Data.SubscriptionType.Tick, OEC.Data.SubscriptionType.Histogram).Count();
		}

Currently, OEC has the next limits:

  • DOMs - number of DOM subscriptions

  • MaxBars - number of bar subscriptions

  • MaxTicks - tick subscriptions

  • Quotes - futures-related quote subscriptions

  • QuotesEquity - equity-related quote subscriptions (if you have equity account)

  • QuotesFX - FX quote subscriptions (if you have forex account)

Since bar and tick requests are more expensive resource that quotes and DOMs, they have additional limitations. These limits are OEC-wide and can be changed any time:

  • MaxBars = 8192: Maximum amount of bars which returns back to a client per one request

  • MaxDayBarDays = 365: Maximum allowed days to load for day and day-based bars

  • MaxIntraBarDays = 90: Maximum allowed days to load for intraday bars

  • MaxPerGroup = 4096: Maximum items per group which returns back to a client

  • MaxTickBasedBarDays = 10: Maximum allowed days to load for tick-based bars

  • MaxTickDays = 3: Maximum allowed days to load for ticks

  • MaxTicks = 65536: Maximum amount of ticks which returns back to a client per one request