private void SessionOnDomChanged(OEC.API.Contract contract)
		{
			var dom = contract.DOM;

			var bids = new List<QuoteChange>();
			var asks = new List<QuoteChange>();

			for (var i = 0; i < dom.BidExchanges.Length; i++)
				bids.Add(new QuoteChange(Sides.Buy, contract.Cast(dom.BidLevels[i]) ?? 0, dom.BidSizes[i]) { BoardCode = GetBoardCode(dom.BidExchanges[i], contract, null) });

			for (var i = 0; i < dom.AskExchanges.Length; i++)
				asks.Add(new QuoteChange(Sides.Sell, contract.Cast(dom.AskLevels[i]) ?? 0, dom.AskSizes[i]) { BoardCode = GetBoardCode(dom.AskExchanges[i], contract, null) });

			SendOutMessage(new QuoteChangeMessage
			{
				SecurityId = new SecurityId
				{
					SecurityCode = contract.Symbol,
					BoardCode = AssociatedBoardCode
				},
				ServerTime = dom.LastUpdate.ApplyTimeZone(TimeHelper.Est),
				Bids = bids,
				Asks = asks,
			});
		}
		private void SessionOnDomChanged(OEC.API.Contract contract)
		{
			ProcessContract(contract, 0);

			var dom = contract.DOM;

			var bids = new List<QuoteChange>();
			var asks = new List<QuoteChange>();

			var hasExchange = false;

			for (var i = 0; i < dom.BidExchanges.Length; i++)
			{
				var boardCode = GetBoardCode(dom.BidExchanges[i], contract, null);

				if (!hasExchange)
					hasExchange = !boardCode.IsEmpty() && boardCode != contract.Exchange.Name;

				bids.Add(new QuoteChange(Sides.Buy, contract.Cast(dom.BidLevels[i]) ?? 0, dom.BidSizes[i]) { BoardCode = boardCode });
			}

			for (var i = 0; i < dom.AskExchanges.Length; i++)
			{
				var boardCode = GetBoardCode(dom.AskExchanges[i], contract, null);

				if (!hasExchange)
					hasExchange = !boardCode.IsEmpty() && boardCode != contract.Exchange.Name;

				asks.Add(new QuoteChange(Sides.Sell, contract.Cast(dom.AskLevels[i]) ?? 0, dom.AskSizes[i]) { BoardCode = boardCode });
			}

			SendOutMessage(new QuoteChangeMessage
			{
				SecurityId = new SecurityId
				{
					SecurityCode = contract.Symbol,
					BoardCode = hasExchange ? AssociatedBoardCode : contract.Exchange.Name ?? AssociatedBoardCode
				},
				ServerTime = dom.LastUpdate.ApplyTimeZone(TimeHelper.Est),
				Bids = bids,
				Asks = asks,
			});
		}
		private void ProcessContract(OEC.API.Contract contract, Price currentPrice, long originalTransactionId)
		{
			var secId = contract.ToSecurityId();
			
			SendOutMessage(new SecurityMessage
			{
				SecurityId = secId,
				Name = contract.Name,
				UnderlyingSecurityCode = contract.BaseSymbol,
				Currency = contract.Currency.Name.ToCurrency(),
				Strike = contract.Strike.ToDecimal(),
				ExpiryDate = contract.HasExpiration ? contract.ExpirationDate.ApplyTimeZone(TimeHelper.Est) : (DateTimeOffset?)null,
				PriceStep = contract.TickSize.ToDecimal(),
				Decimals = contract.PriceFormat > 0 ? contract.PriceFormat : (int?)null,
				OptionType = contract.IsOption ? (contract.Put ? OptionTypes.Put : OptionTypes.Call) : (OptionTypes?)null,
				SecurityType = contract.GetSecurityType(),
				OriginalTransactionId = originalTransactionId,
			});

			if (currentPrice == null)
				return;

			SendOutMessage(new Level1ChangeMessage
			{
				SecurityId = secId,
				ServerTime = currentPrice.LastDateTime.ApplyTimeZone(TimeHelper.Est),
			}
			.TryAdd(Level1Fields.LastTradePrice, contract.Cast(currentPrice.LastPrice))
			.TryAdd(Level1Fields.BestAskPrice, contract.Cast(currentPrice.AskPrice))
			.TryAdd(Level1Fields.BestAskVolume, (decimal)currentPrice.AskVol)
			.TryAdd(Level1Fields.BestBidPrice, contract.Cast(currentPrice.BidPrice))
			.TryAdd(Level1Fields.BestBidVolume, (decimal)currentPrice.BidVol)
			.TryAdd(Level1Fields.Change, contract.Cast(currentPrice.Change))
			.TryAdd(Level1Fields.OpenInterest, (decimal)currentPrice.OpenInterest)
			.TryAdd(Level1Fields.OpenPrice, contract.Cast(currentPrice.OpenPrice))
			.TryAdd(Level1Fields.HighPrice, contract.Cast(currentPrice.HighPrice))
			.TryAdd(Level1Fields.LowPrice, contract.Cast(currentPrice.LowPrice))
			.TryAdd(Level1Fields.LastTradeVolume, (decimal)currentPrice.LastVol)
			.TryAdd(Level1Fields.SettlementPrice, contract.Cast(currentPrice.Settlement))
			.TryAdd(Level1Fields.Volume, (decimal)currentPrice.TotalVol)
			.TryAdd(Level1Fields.StepPrice, (decimal)contract.ContractSize)
			.Add(Level1Fields.State, contract.GetSecurityState()));
		}
		private void ProcessContract(OEC.API.Contract contract, Price currentPrice, long originalTransactionId)
		{
			ProcessContract(contract, originalTransactionId);

			if (currentPrice == null)
				return;

			SendOutMessage(new Level1ChangeMessage
			{
				SecurityId = contract.ToSecurityId(),
				ServerTime = currentPrice.LastDateTime.ApplyTimeZone(TimeHelper.Est),
			}
			.TryAdd(Level1Fields.LastTradePrice, contract.Cast(currentPrice.LastPrice))
			.TryAdd(Level1Fields.BestAskPrice, contract.Cast(currentPrice.AskPrice))
			.TryAdd(Level1Fields.BestAskVolume, (decimal)currentPrice.AskVol)
			.TryAdd(Level1Fields.BestBidPrice, contract.Cast(currentPrice.BidPrice))
			.TryAdd(Level1Fields.BestBidVolume, (decimal)currentPrice.BidVol)
			.TryAdd(Level1Fields.Change, contract.Cast(currentPrice.Change))
			.TryAdd(Level1Fields.OpenInterest, (decimal)currentPrice.OpenInterest)
			.TryAdd(Level1Fields.OpenPrice, contract.Cast(currentPrice.OpenPrice))
			.TryAdd(Level1Fields.HighPrice, contract.Cast(currentPrice.HighPrice))
			.TryAdd(Level1Fields.LowPrice, contract.Cast(currentPrice.LowPrice))
			.TryAdd(Level1Fields.LastTradeVolume, (decimal)currentPrice.LastVol)
			.TryAdd(Level1Fields.SettlementPrice, contract.Cast(currentPrice.Settlement))
			.TryAdd(Level1Fields.Volume, (decimal)currentPrice.TotalVol)
			.TryAdd(Level1Fields.StepPrice, (decimal)contract.ContractSize)
			.Add(Level1Fields.State, contract.GetSecurityState()));
		}