private void ProcessOrderRegisterMessage(OrderRegisterMessage message)
		{
			var condition = (OandaOrderCondition)message.Condition;

			string type;

			if (condition == null)
				type = message.Price == 0 ? "market" : "limit";
			else
				type = condition.IsMarket ? _orderImit : "stop";

			var response = _restClient.CreateOrder(GetAccountId(message.PortfolioName),
				message.SecurityId.ToOanda(), (int)message.Volume, message.Side.To<string>().ToLowerInvariant(),
				type,
				GetExpiryTime(message),
				message.Price,
				condition?.LowerBound,
				condition?.UpperBound,
				condition?.StopLossOffset,
				condition?.TakeProfitOffset,
				condition?.TrailingStopLossOffset);

			var execMsg = new ExecutionMessage
			{
				OriginalTransactionId = message.TransactionId,
				ServerTime = response.Time.FromOanda(),
				ExecutionType = ExecutionTypes.Transaction,
				PortfolioName = message.PortfolioName,
				HasOrderInfo = true,
			};

			var tradeData = response.TradeOpened;

			if (tradeData != null)
			{
				execMsg.OrderState = OrderStates.Done;
				execMsg.OrderId = tradeData.Id;
			}
			else
			{
				execMsg.OrderState = OrderStates.Active;
				execMsg.OrderId = response.OrderOpened.Id;
			}

			SendOutMessage(execMsg);

			if (tradeData != null)
			{
				SendOutMessage(new ExecutionMessage
				{
					OriginalTransactionId = message.TransactionId,
					ExecutionType = ExecutionTypes.Transaction,
					TradePrice = (decimal)tradeData.Price,
					TradeVolume = tradeData.Units,
					ServerTime = tradeData.Time.FromOanda(),
					TradeId = tradeData.Id,
					HasTradeInfo = true,
				});
			}
		}
Example #2
0
		/// <summary>
		/// Рассчитать комиссию.
		/// </summary>
		/// <param name="message">Сообщение, содержащее информацию по заявке или собственной сделке.</param>
		/// <returns>Комиссия. Если комиссию рассчитать невозможно, то будет возвращено <see langword="null"/>.</returns>
		public decimal? ProcessExecution(ExecutionMessage message)
		{
			var commission = OnProcessExecution(message);

			if (commission != null)
				Commission += commission.Value;

			return commission;
		}
Example #3
0
		/// <summary>
		/// Initializes a new instance of the <see cref="PnLInfo"/>.
		/// </summary>
		/// <param name="trade">Own trade.</param>
		/// <param name="closedVolume">The volume of position, which was closed by own trade.</param>
		/// <param name="pnL">The profit, realized by this trade.</param>
		public PnLInfo(ExecutionMessage trade, decimal closedVolume, decimal pnL)
		{
			if (trade == null)
				throw new ArgumentNullException(nameof(trade));

			if (closedVolume < 0)
				throw new ArgumentOutOfRangeException(nameof(closedVolume), closedVolume, LocalizedStrings.Str946);

			Trade = trade;
			ClosedVolume = closedVolume;
			PnL = pnL;
		}
		/// <summary>
		/// To calculate commission.
		/// </summary>
		/// <param name="message">The message containing the information about the order or own trade.</param>
		/// <returns>The commission. If the commission can not be calculated then <see langword="null" /> will be returned.</returns>
		public virtual decimal? ProcessExecution(ExecutionMessage message)
		{
			if (_rules.Count == 0)
				return null;

			var commission = _rules.Cache.Sum(rule => rule.ProcessExecution(message));

			if (commission != null)
				Commission += commission.Value;

			return commission;
		}
Example #5
0
		/// <summary>
		/// Рассчитать прибыльность сделки. Если сделка уже ранее была обработана, то возвращается предыдущая информация.
		/// </summary>
		/// <param name="trade">Сделка.</param>
		/// <returns>Информация о новой сделке.</returns>
		public virtual PnLInfo ProcessMyTrade(ExecutionMessage trade)
		{
			if (trade == null)
				throw new ArgumentNullException("trade");

			lock (_portfolioManagers.SyncRoot)
			{
				var manager = _portfolioManagers.SafeAdd(trade.PortfolioName, pf => new PortfolioPnLManager(pf));
				
				PnLInfo info;

				if (manager.ProcessMyTrade(trade, out info))
					_realizedPnL += info.PnL;

				return info;
			}
		}
		/// <summary>
		/// To calculate trade profitability. If the trade was already processed earlier, previous information returns.
		/// </summary>
		/// <param name="trade">Trade.</param>
		/// <param name="info">Information on new trade.</param>
		/// <returns><see langword="true" />, if new trade received, otherwise, <see langword="false" />.</returns>
		public bool ProcessMyTrade(ExecutionMessage trade, out PnLInfo info)
		{
			if (trade == null)
				throw new ArgumentNullException(nameof(trade));

			var tradeId = trade.GetTradeId();

			if (_tradeInfos.TryGetValue(tradeId, out info))
				return false;

			var queue = _securityPnLs.SafeAdd(trade.SecurityId, security => new PnLQueue(security));

			info = queue.Process(trade);

			_tradeInfos.Add(tradeId, info);
			_realizedPnL += info.PnL;

			return true;
		}
		/// <summary>
		/// Callback of the order (re)registration.
		/// </summary>
		/// <param name="transId">Transaction ID.</param>
		/// <param name="data">(Re)registration result.</param>
		/// <param name="ex">(Re)registration error.</param>
		private void ClientOnOrderRegisterResult(long transId, PlaceEquityOrderResponse2 data, Exception ex)
		{
			if (ex != null)
			{
				this.AddWarningLog("RegisterOrder: {0}", ex);
				SendOutMessage(new ExecutionMessage
				{
					OriginalTransactionId = transId,
					OrderState = OrderStates.Failed,
					Error = new InvalidOperationException(LocalizedStrings.Str2258Params.Put(transId, ex)),
					OrderStatus = OrderStatus.RejectedBySystem,
					ExecutionType = ExecutionTypes.Transaction,
					HasOrderInfo = true,
				});
				return;
			}

			var msg = new ExecutionMessage
			{
				SecurityId = new SecurityId { SecurityCode = data.symbol, BoardCode = AssociatedBoardCode },
				PortfolioName = data.accountId.To<string>(),
				Side = data.orderAction.ETradeActionToSide(),
				OriginalTransactionId = transId,
				OrderState = OrderStates.Active,
				OrderId = data.orderNum,
				ExecutionType = ExecutionTypes.Transaction,
				ServerTime = ETradeUtil.ETradeTimestampToUTC(data.orderTime),
				HasOrderInfo = true,
			};

			SaveOrder(transId, msg.OrderId ?? 0);

			if (data.messageList != null)
			{
				foreach (var m in data.messageList)
					this.AddDebugLog("ord #{0}: ({1}) {2}", data.orderNum, m.msgCode, m.msgDesc);
			}

			SendOutMessage(msg);
		}
Example #8
0
		public Tuple<Order, bool, bool> ProcessOrderMessage(Security security, ExecutionMessage message)
		{
			if (security == null)
				throw new ArgumentNullException(nameof(security));

			if (message == null)
				throw new ArgumentNullException(nameof(message));

			if (message.Error != null)
				throw new ArgumentException(LocalizedStrings.Str714Params.PutEx(message));

			bool isNew;

			var transactionId = message.TransactionId;

			if (transactionId == 0)
			{
				// ExecMsg.OriginalTransactionId == OrderStatMsg.TransactionId when orders info requested by OrderStatMsg
				transactionId = _orderStatusTransactions.Contains(message.OriginalTransactionId) ? 0 : message.OriginalTransactionId;
			}

			var securityData = GetData(security);

			var orderInfo = GetOrderInfo(securityData, message.OrderType, transactionId, message.OrderId, message.OrderStringId, trId =>
			{
				var o = EntityFactory.CreateOrder(security, message.OrderType, trId);

				o.Time = message.ServerTime;
				o.Price = message.OrderPrice;
				o.Volume = message.OrderVolume ?? 0;
				o.Direction = message.Side;
				o.Comment = message.Comment;
				o.ExpiryDate = message.ExpiryDate;
				o.Condition = message.Condition;
				o.UserOrderId = message.UserOrderId;
				o.Portfolio = message.PortfolioName.IsEmpty()
					? _portfolios.FirstOrDefault().Value
					: ProcessPortfolio(message.PortfolioName).Item1;
				o.ClientCode = message.ClientCode;

				return o;
			}, out isNew, true);

			if (orderInfo == null)
				return null;

			var order = orderInfo.Item1;
			var isCancelled = orderInfo.Item2;
			//var isReReregisterCancelled = orderInfo.Item3;
			var raiseNewOrder = orderInfo.Item3;

			var isPending = order.State == OrderStates.Pending;
			//var isPrevIdSet = (order.Id != null || !order.StringId.IsEmpty());

			bool isChanged;

			if (order.State == OrderStates.Done)
			{
				// данные о заявке могут приходить из маркет-дата и транзакционного адаптеров
				isChanged = false;
				//throw new InvalidOperationException("Изменение заявки в состоянии Done невозможно.");
			}
			else
			{
				if (message.OrderId != null)
					order.Id = message.OrderId.Value;

				if (!message.OrderStringId.IsEmpty())
					order.StringId = message.OrderStringId;

				if (!message.OrderBoardId.IsEmpty())
					order.BoardId = message.OrderBoardId;

				//// некоторые коннекторы не транслируют при отмене отмененный объем
				//// esper. при перерегистрации заявок необходимо обновлять баланс
				//if (message.Balance > 0 || !isCancelled || isReReregisterCancelled)
				//{
				//	// BTCE коннектор не транслирует баланс заявки
				//	if (!(message.OrderState == OrderStates.Active && message.Balance == 0))
				//		order.Balance = message.Balance;
				//}

				if (message.Balance != null)
					order.Balance = message.Balance.Value;

				// IB коннектор не транслирует состояние заявки в одном из своих сообщений
				if (message.OrderState != null)
					order.State = message.OrderState.Value;

				if (order.Time == DateTimeOffset.MinValue)
					order.Time = message.ServerTime;

				// для новых заявок используем серверное время, 
				// т.к. заявка получена первый раз и не менялась
				// ServerTime для заявки - это время регистрации
				order.LastChangeTime = isNew ? message.ServerTime : message.LocalTime;
				order.LocalTime = message.LocalTime;

				//нулевой объем может быть при перерегистрации
				if (order.Volume == 0 && message.OrderVolume != null)
					order.Volume = message.OrderVolume.Value;

				if (message.Commission != null)
					order.Commission = message.Commission;

				if (message.TimeInForce != null)
					order.TimeInForce = message.TimeInForce.Value;

				if (isPending)
				{
					if (order.State != OrderStates.Pending && message.Latency != null)
						order.LatencyRegistration = message.Latency.Value;
				}
				else if (isCancelled && order.State == OrderStates.Done)
				{
					if (message.Latency != null)
						order.LatencyCancellation = message.Latency.Value;
				}

				isChanged = true;
			}

			//if (isNew || (!isPrevIdSet && (order.Id != null || !order.StringId.IsEmpty())))
			//{

			// так как биржевые идентифиаторы могут повторяться, то переписываем старые заявки новыми как наиболее актуальными
					
			if (order.Id != null)
			{
				securityData.OrdersById[order.Id.Value] = order;
				_allOrdersById[order.Id.Value] = order;
			}
				
			if (!order.StringId.IsEmpty())
			{
				securityData.OrdersByStringId[order.StringId] = order;
				_allOrdersByStringId[order.StringId] = order;
			}

			//}

			//if (message.OrderType == OrderTypes.Conditional && (message.DerivedOrderId != null || !message.DerivedOrderStringId.IsEmpty()))
			//{
			//	var derivedOrder = GetOrder(security, 0L, message.DerivedOrderId ?? 0, message.DerivedOrderStringId);

			//	if (order == null)
			//		_orderStopOrderAssociations.Add(Tuple.Create(message.DerivedOrderId ?? 0, message.DerivedOrderStringId), new RefPair<Order, Action<Order, Order>>(order, (s, o) => s.DerivedOrder = o));
			//	else
			//		order.DerivedOrder = derivedOrder;
			//}

			message.CopyExtensionInfo(order);

			return Tuple.Create(order, raiseNewOrder, isChanged);
		}
		private void ReadOrderStatus(IBSocket socket, ServerVersions version)
		{
			var id = socket.ReadInt();

			var status = socket.ReadOrderStatus();
			/* filled */
			socket.ReadInt();
			var balance = socket.ReadDecimal();
			var avgPrice = socket.ReadDecimal();
			var permId = version >= ServerVersions.V2 ? socket.ReadInt() : (int?)null;
			var parentId = version >= ServerVersions.V3 ? socket.ReadInt() : (int?)null;
			var lastTradePrice = version >= ServerVersions.V4 ? socket.ReadDecimal() : (decimal?)null;
			var clientId = version >= ServerVersions.V5 ? socket.ReadInt() : (int?)null;
			var whyHeld = version >= ServerVersions.V6 ? socket.ReadStr() : null;

			var execMsg = new ExecutionMessage
			{
				ExecutionType = ExecutionTypes.Transaction,
				OriginalTransactionId = id,
				Balance = balance,
				OrderStatus = status,
				OrderState = status.ToOrderState(),
				HasOrderInfo = true,
			};

			execMsg.SetAveragePrice(avgPrice);

			if (permId != null)
				execMsg.SetPermId(permId.Value);

			if (parentId != null)
				execMsg.Condition = new IBOrderCondition { ParentId = parentId.Value };

			if (lastTradePrice != null)
				execMsg.SetLastTradePrice(lastTradePrice.Value);

			if (clientId != null)
				execMsg.SetClientId(clientId.Value);

			if (whyHeld != null)
				execMsg.SetWhyHeld(whyHeld);

			SendOutMessage(execMsg);
		}
Example #10
0
			protected override void WriterFixOrderCondition(IFixWriter writer, ExecutionMessage message)
			{
				writer.WriteOrderCondition((QuikOrderCondition)message.Condition, TransactionSession.DateTimeFormat);
			}
Example #11
0
		private void SendOutErrorExecution(ExecutionMessage execMsg, Exception ex)
		{
			execMsg.ServerTime = CurrentTime;
			execMsg.Error = ex;
			execMsg.OrderState = OrderStates.Failed;
			SendOutMessage(execMsg);
		}
Example #12
0
		/// <summary>
		/// Process message.
		/// </summary>
		/// <param name="message">Message.</param>
		/// <returns>The result of processing. If <see langword="null" /> is returned, then generator has no sufficient data to generate new message.</returns>
		protected override Message OnProcess(Message message)
		{
			DateTimeOffset time;

			switch (message.Type)
			{
				case MessageTypes.Board:
					return null;
				case MessageTypes.Level1Change:
				{
					var l1Msg = (Level1ChangeMessage)message;

					var value = l1Msg.Changes.TryGetValue(Level1Fields.LastTradePrice);

					if (value != null)
						_lastTradePrice = (decimal)value;

					time = l1Msg.ServerTime;

					break;
				}
				case MessageTypes.Execution:
				{
					var execMsg = (ExecutionMessage)message;

					switch (execMsg.ExecutionType)
					{
						case ExecutionTypes.Tick:
						case ExecutionTypes.Trade:
							_lastTradePrice = execMsg.TradePrice.Value;
							break;
						case ExecutionTypes.OrderLog:
							if (execMsg.TradePrice != null)
								_lastTradePrice = execMsg.TradePrice.Value;
							break;
						default:
							return null;
					}

					time = execMsg.ServerTime;

					break;
				}
				case MessageTypes.Time:
				{
					var timeMsg = (TimeMessage)message;

					time = timeMsg.ServerTime;

					break;
				}
				default:
					return null;
			}

			if (!IsTimeToGenerate(time))
				return null;

			var trade = new ExecutionMessage
			{
				SecurityId = SecurityId,
				TradeId = IdGenerator.GetNextId(),
				ServerTime = time,
				LocalTime = time.LocalDateTime,
				OriginSide = GenerateDirection ? RandomGen.GetEnum<Sides>() : (Sides?)null,
				Volume = Volumes.Next(),
				ExecutionType = ExecutionTypes.Tick
			};

			var priceStep = SecurityDefinition.PriceStep ?? 0.01m;

			_lastTradePrice += RandomGen.GetInt(-MaxPriceStepCount, MaxPriceStepCount) * priceStep;

			if (_lastTradePrice <= 0)
				_lastTradePrice = priceStep;

			trade.TradePrice = _lastTradePrice;

			LastGenerationTime = time;

			return trade;
		}
Example #13
0
		/// <summary>
		/// Create a copy of <see cref="ExecutionMessage"/>.
		/// </summary>
		/// <returns>Copy.</returns>
		public override Message Clone()
		{
			var clone = new ExecutionMessage
			{
				Balance = Balance,
				Comment = Comment,
				Condition = Condition.CloneNullable(),
				ClientCode = ClientCode,
				Currency = Currency,
				ServerTime = ServerTime,
				DepoName = DepoName,
				Error = Error,
				ExpiryDate = ExpiryDate,
				IsSystem = IsSystem,
				LocalTime = LocalTime,
				OpenInterest = OpenInterest,
				OrderId = OrderId,
				OrderStringId = OrderStringId,
				OrderBoardId = OrderBoardId,
				ExecutionType = ExecutionType,
				IsCancelled = IsCancelled,
				//Action = Action,
				OrderState = OrderState,
				OrderStatus = OrderStatus,
				OrderType = OrderType,
				OriginSide = OriginSide,
				PortfolioName = PortfolioName,
				Price = Price,
				SecurityId = SecurityId,
				Side = Side,
				SystemComment = SystemComment,
				TimeInForce = TimeInForce,
				TradeId = TradeId,
				TradeStringId = TradeStringId,
				TradePrice = TradePrice,
				TradeStatus = TradeStatus,
				TransactionId = TransactionId,
				OriginalTransactionId = OriginalTransactionId,
				Volume = Volume,
				//IsFinished = IsFinished,
				VisibleVolume = VisibleVolume,
				IsUpTick = IsUpTick,
				Commission = Commission,
				Latency = Latency,
				Slippage = Slippage,
				UserOrderId = UserOrderId,

				DerivedOrderId = DerivedOrderId,
				DerivedOrderStringId = DerivedOrderStringId,
			};

			this.CopyExtensionInfo(clone);

			return clone;
		}
		private void SessionOnStiQuoteSnap(ref structSTIQuoteSnap structQuoteSnap)
		{
			var l1CngMsg = new Level1ChangeMessage
			{
				SecurityId = new SecurityId
				{
					SecurityCode = structQuoteSnap.bstrSymbol,
					BoardCode = structQuoteSnap.bstrExch
				},
				ServerTime = structQuoteSnap.bstrUpdateTime.StrToTime(),
			};

			if (structQuoteSnap.bAskPrice != 0)
				l1CngMsg.TryAdd(Level1Fields.BestAskPrice, (decimal)structQuoteSnap.fAskPrice);

			if (structQuoteSnap.bBidPrice != 0)
				l1CngMsg.TryAdd(Level1Fields.BestBidPrice, (decimal)structQuoteSnap.fBidPrice);

			l1CngMsg.TryAdd(Level1Fields.BestAskVolume, (decimal)structQuoteSnap.nAskSize);
			l1CngMsg.TryAdd(Level1Fields.BestBidVolume, (decimal)structQuoteSnap.nBidSize);

			if (structQuoteSnap.bOpenPrice != 0)
				l1CngMsg.TryAdd(Level1Fields.OpenPrice, (decimal)structQuoteSnap.fOpenPrice);

			if (structQuoteSnap.bHighPrice != 0)
				l1CngMsg.TryAdd(Level1Fields.HighPrice, (decimal)structQuoteSnap.fHighPrice);

			if (structQuoteSnap.bLowPrice != 0)
				l1CngMsg.TryAdd(Level1Fields.LowPrice, (decimal)structQuoteSnap.fLowPrice);

			if (structQuoteSnap.bLastPrice != 0)
				l1CngMsg.TryAdd(Level1Fields.LastTradePrice, (decimal)structQuoteSnap.fLastPrice);

			l1CngMsg.TryAdd(Level1Fields.LastTradeVolume, (decimal)structQuoteSnap.nLastSize);

			l1CngMsg.TryAdd(Level1Fields.OpenInterest, (decimal)structQuoteSnap.nOpenInterest);
			l1CngMsg.TryAdd(Level1Fields.Volume, (decimal)structQuoteSnap.nCumVolume);
			l1CngMsg.TryAdd(Level1Fields.VWAP, (decimal)structQuoteSnap.fVwap);

			l1CngMsg.TryAdd(Level1Fields.ClosePrice, (decimal)structQuoteSnap.fClosePrice); // öåíà çàêðûòèÿ ïðîøëîãî äíÿ.

			SendOutMessage(l1CngMsg);

			if (_subscribedSecuritiesToTrade.Cache.Contains(structQuoteSnap.bstrSymbol) && structQuoteSnap.fLastPrice != 0)
			{
				var tickMsg= new ExecutionMessage
				{
					ExecutionType = ExecutionTypes.Tick,
					SecurityId = new SecurityId{SecurityCode = structQuoteSnap.bstrSymbol,BoardCode = structQuoteSnap.bstrExch},
					//TradeId = structQuoteSnap.,
					TradePrice = (decimal)structQuoteSnap.fLastPrice,
					TradeVolume = structQuoteSnap.nLastSize,
					//OriginSide = action.ToSide(),
					ServerTime = structQuoteSnap.bstrUpdateTime.StrToTime()
				};

				SendOutMessage(tickMsg);
			}
		}
Example #15
0
        QuoteChangeMessage IOrderLogMarketDepthBuilder.Update(ExecutionMessage item)
        {
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }

            if (item.ExecutionType != ExecutionTypes.OrderLog)
            {
                throw new ArgumentException(nameof(item));
            }

            if (item.OrderPrice == 0)
            {
                return(null);
            }

            _depth.ServerTime = item.ServerTime;
            _depth.LocalTime  = item.LocalTime;

            QuoteChange?changedQuote = null;

            var quotes = item.Side == Sides.Buy ? _bids : _asks;

            if (item.IsOrderLogRegistered())
            {
                if (item.OrderVolume != null)
                {
                    QuoteChange ProcessRegister <T>(T id, Dictionary <T, decimal> orders)
                    {
                        var quote = quotes.SafeAdd(item.OrderPrice, key => new QuoteChange(key, 0));

                        var volume = item.OrderVolume.Value;

                        if (orders.TryGetValue(id, out var prevVolume))
                        {
                            quote.Volume += (volume - prevVolume);
                            orders[id]    = volume;
                        }
                        else
                        {
                            quote.Volume += volume;
                            orders.Add(id, volume);
                        }

                        quotes[item.OrderPrice] = quote;
                        return(quote);
                    }

                    if (item.OrderId != null)
                    {
                        changedQuote = ProcessRegister(item.OrderId.Value, _ordersByNum);
                    }
                    else if (!item.OrderStringId.IsEmpty())
                    {
                        changedQuote = ProcessRegister(item.OrderStringId, _ordersByString);
                    }
                }
            }
            else if (item.IsOrderLogMatched())
            {
                var volume = item.TradeVolume ?? item.OrderVolume;

                if (volume != null)
                {
                    QuoteChange?ProcessMatched <T>(T id, Dictionary <T, decimal> orders)
                    {
                        if (orders.TryGetValue(id, out var prevVolume))
                        {
                            orders[id] = prevVolume - volume.Value;

                            if (quotes.TryGetValue(item.OrderPrice, out var quote))
                            {
                                quote.Volume -= volume.Value;

                                if (quote.Volume <= 0)
                                {
                                    quotes.Remove(item.OrderPrice);
                                }

                                quotes[item.OrderPrice] = quote;
                                return(quote);
                            }
                        }

                        return(null);
                    }

                    if (item.OrderId != null)
                    {
                        changedQuote = ProcessMatched(item.OrderId.Value, _ordersByNum);
                    }
                    else if (!item.OrderStringId.IsEmpty())
                    {
                        changedQuote = ProcessMatched(item.OrderStringId, _ordersByString);
                    }
                }
            }
            else if (item.IsOrderLogCanceled())
            {
                QuoteChange?ProcessCanceled <T>(T id, Dictionary <T, decimal> orders)
                {
                    if (orders.TryGetAndRemove(id, out var prevVolume))
                    {
                        if (quotes.TryGetValue(item.OrderPrice, out var quote))
                        {
                            quote.Volume -= prevVolume;

                            if (quote.Volume <= 0)
                            {
                                quotes.Remove(item.OrderPrice);
                            }

                            quotes[item.OrderPrice] = quote;
                            return(quote);
                        }
                    }

                    return(null);
                }

                if (item.OrderId != null)
                {
                    changedQuote = ProcessCanceled(item.OrderId.Value, _ordersByNum);
                }
                else if (!item.OrderStringId.IsEmpty())
                {
                    changedQuote = ProcessCanceled(item.OrderStringId, _ordersByString);
                }
            }

            if (changedQuote == null)
            {
                return(null);
            }

            var increment = new QuoteChangeMessage
            {
                ServerTime = item.ServerTime,
                LocalTime  = item.LocalTime,
                SecurityId = _depth.SecurityId,
                State      = QuoteChangeStates.Increment,
            };

            var q = changedQuote.Value;

            if (item.Side == Sides.Buy)
            {
                increment.Bids = new[] { q }
            }
            ;
            else
            {
                increment.Asks = new[] { q }
            };

            return(increment);
        }
    }
Example #16
0
		public Tuple<MyTrade, bool> ProcessMyTradeMessage(Security security, ExecutionMessage message)
		{
			if (security == null)
				throw new ArgumentNullException(nameof(security));

			if (message == null)
				throw new ArgumentNullException(nameof(message));

			var originalTransactionId = _orderStatusTransactions.Contains(message.OriginalTransactionId)
				? 0 : message.OriginalTransactionId;

			if (originalTransactionId == 0 && message.OrderId == null && message.OrderStringId.IsEmpty())
				throw new ArgumentOutOfRangeException(nameof(message), originalTransactionId, LocalizedStrings.Str715);

			var securityData = GetData(security);

			var myTrade = securityData.MyTrades.TryGetValue(Tuple.Create(originalTransactionId, message.TradeId ?? 0));

			if (myTrade != null)
				return Tuple.Create(myTrade, false);

			var order = GetOrder(security, originalTransactionId, message.OrderId, message.OrderStringId);

			if (order == null)
				return null;

			var trade = message.ToTrade(EntityFactory.CreateTrade(security, message.TradeId, message.TradeStringId));

			var isNew = false;

			myTrade = securityData.MyTrades.SafeAdd(Tuple.Create(order.TransactionId, trade.Id), key =>
			{
				isNew = true;

				var t = EntityFactory.CreateMyTrade(order, trade);

				if (t.ExtensionInfo == null)
					t.ExtensionInfo = new Dictionary<object, object>();

				if (message.Commission != null)
					t.Commission = message.Commission;

				if (message.Slippage != null)
					t.Slippage = message.Slippage;

				message.CopyExtensionInfo(t);

				//trades.Add(t);
				_myTrades.Add(t);

				return t;
			});

			return Tuple.Create(myTrade, isNew);

			// mika
			// http://stocksharp.com/forum/yaf_postst1072_Probliemy-so-sdielkami--pozitsiiami.aspx
			// из-за того, что сделки по заявке иногда приходит быстрее события NewOrders, неправильно расчитывается поза по стратегиям

			//var raiseOrderChanged = false;

			//trades.SyncDo(d =>
			//{
			//    var newBalance = order.Volume - d.Sum(t => t.Trade.Volume);

			//    if (order.Balance > newBalance)
			//    {
			//        raiseOrderChanged = true;

			//        order.Balance = newBalance;

			//        if (order.Balance == 0)
			//            order.State = OrderStates.Done;
			//    }
			//});

			//if (raiseOrderChanged)
			//    RaiseOrderChanged(order);
		}
Example #17
0
        /// <summary>
        /// Create a copy of <see cref="ExecutionMessage"/>.
        /// </summary>
        /// <returns>Copy.</returns>
        public override Message Clone()
        {
            var clone = new ExecutionMessage
            {
                Balance       = Balance,
                Comment       = Comment,
                Condition     = Condition?.Clone(),
                ClientCode    = ClientCode,
                BrokerCode    = BrokerCode,
                Currency      = Currency,
                ServerTime    = ServerTime,
                DepoName      = DepoName,
                Error         = Error,
                ExpiryDate    = ExpiryDate,
                IsSystem      = IsSystem,
                OpenInterest  = OpenInterest,
                OrderId       = OrderId,
                OrderStringId = OrderStringId,
                OrderBoardId  = OrderBoardId,
                ExecutionType = ExecutionType,
                IsCancelled   = IsCancelled,
                //Action = Action,
                OrderState    = OrderState,
                OrderStatus   = OrderStatus,
                OrderType     = OrderType,
                OriginSide    = OriginSide,
                PortfolioName = PortfolioName,
                OrderPrice    = OrderPrice,
                SecurityId    = SecurityId,
                Side          = Side,
                SystemComment = SystemComment,
                TimeInForce   = TimeInForce,
                TradeId       = TradeId,
                TradeStringId = TradeStringId,
                TradePrice    = TradePrice,
                TradeStatus   = TradeStatus,
                TransactionId = TransactionId,
                OrderVolume   = OrderVolume,
                TradeVolume   = TradeVolume,
                //IsFinished = IsFinished,
                VisibleVolume = VisibleVolume,
                IsUpTick      = IsUpTick,
                Commission    = Commission,
                Latency       = Latency,
                Slippage      = Slippage,
                UserOrderId   = UserOrderId,

                //DerivedOrderId = DerivedOrderId,
                //DerivedOrderStringId = DerivedOrderStringId,

                PnL      = PnL,
                Position = Position,

                HasTradeInfo = HasTradeInfo,
                HasOrderInfo = HasOrderInfo,

                IsMarketMaker = IsMarketMaker,
                IsMargin      = IsMargin,
                IsManual      = IsManual,

                CommissionCurrency = CommissionCurrency,

                AveragePrice = AveragePrice,
                Yield        = Yield,
                MinVolume    = MinVolume,

                SubscriptionId  = SubscriptionId,
                SubscriptionIds = SubscriptionIds?.ToArray()
            };

            CopyTo(clone);

            return(clone);
        }
Example #18
0
        bool IOrderLogMarketDepthBuilder.Update(ExecutionMessage item)
        {
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }

            if (item.ExecutionType != ExecutionTypes.OrderLog)
            {
                throw new ArgumentException(nameof(item));
            }

            if (item.OrderPrice == 0)
            {
                return(false);
            }

            var changed = false;

            var quotes = item.Side == Sides.Buy ? _bids : _asks;

            try
            {
                if (item.IsOrderLogRegistered())
                {
                    if (item.OrderId != null)
                    {
                        var quote = quotes.SafeAdd(item.OrderPrice, key => new QuoteChange(item.Side, key, 0));
                        var id    = item.OrderId.Value;

                        if (item.OrderVolume != null)
                        {
                            var volume = item.OrderVolume.Value;

                            if (_orders.TryGetValue(id, out var prevVolume))
                            {
                                quote.Volume += (volume - prevVolume);
                                _orders[id]   = volume;
                            }
                            else
                            {
                                quote.Volume += volume;
                                _orders.Add(id, volume);
                            }

                            changed = true;
                        }
                    }
                }
                else if (item.IsOrderLogMatched())
                {
                    if (item.OrderId != null)
                    {
                        var id     = item.OrderId.Value;
                        var volume = item.TradeVolume ?? item.OrderVolume;

                        if (volume != null)
                        {
                            if (_orders.TryGetValue(id, out var prevVolume))
                            {
                                var quote = quotes.TryGetValue(item.OrderPrice);

                                if (quote != null)
                                {
                                    quote.Volume -= volume.Value;

                                    if (quote.Volume <= 0)
                                    {
                                        quotes.Remove(item.OrderPrice);
                                    }
                                }

                                _orders[id] = prevVolume - volume.Value;
                                changed     = true;
                            }
                        }
                    }
                }
                else if (item.IsOrderLogCanceled())
                {
                    if (item.OrderId != null)
                    {
                        var id = item.OrderId.Value;

                        if (_orders.TryGetValue(id, out var prevVolume))
                        {
                            var quote = quotes.TryGetValue(item.OrderPrice);

                            if (quote != null)
                            {
                                quote.Volume -= prevVolume;

                                if (quote.Volume <= 0)
                                {
                                    quotes.Remove(item.OrderPrice);
                                }
                            }

                            _orders.Remove(id);
                            changed = true;
                        }
                    }
                }
            }
            finally
            {
                if (changed)
                {
                    _depth.ServerTime = item.ServerTime;
                    _depth.LocalTime  = item.LocalTime;

                    _depth.Bids = _bids.Values.ToArray();
                    _depth.Asks = _asks.Values.ToArray();
                }
            }

            return(changed);
        }
		private void OnProcessOrders(string[] data)
		{
			var f = Wrapper.FieldsOrders;

			if (data.Length > 0)
				this.AddLog(LogLevels.Debug, () => "OnProcessOrders:\n" + data.Join("\n"));

			foreach (var str in data)
			{
				var cols = str.ToColumns();

				// 83487901|41469-000|42550|M|B|8356|1|1|0:00:00||FORTS|0|
				// ...
				// 83487901|41469-000|42550|M|B|8356|1|0|12.12.2011 16:31:41|2198931532|FORTS|0|
				// NOTE: когда в первый раз приходит апдейт по заявке в нем нет ни времени, ни комментария.

				// 84352688|41469-000|12910|M|S|80.13|10|0|22.12.2011 17:16:58||MICEX_SHR|0|0|
				// 84352688|41469-000|12910|M|S|80.13|10|0|22.12.2011 17:16:58|2968835969|MICEX_SHR|0|80.408|
				// NOTE: на ММВБ заявка сперва приходит с пустым комментарием!

				var orderId = f.OrdNo.GetValue(cols);
				var transId = f.Comments.GetValue(cols);

				if (transId == 0)
				{
					var alfaTransactionId = _alfaIds.TryGetKey(orderId);
					transId = _localIds.TryGetKey(alfaTransactionId);

					if (transId == 0)
					{
						this.AddWarningLog("transaction id for order #{0} not found. creating new one.", orderId);
						transId = TransactionIdGenerator.GetNextId();
						if (alfaTransactionId == 0)
						{
							alfaTransactionId = --_lastFakeAlfaTransactionId;
							_alfaIds.Add(alfaTransactionId, orderId);
						}
						_localIds.Add(transId, alfaTransactionId);
					}
				}

				var msg = new ExecutionMessage
				{
					SecurityId = new SecurityId { Native = f.PaperNo.GetValue(cols) },
					PortfolioName = GetPortfolioName(f.AccCode.GetValue(cols), this.GetBoardCode(f.PlaceCode.GetValue(cols))),
					Side = f.BuySellStr.GetValue(cols),
					OrderPrice = f.Price.GetValue(cols),
					Volume = f.Qty.GetValue(cols),
					Balance = f.Rest.GetValue(cols),
					OriginalTransactionId = transId,
					OrderId = orderId,
					ExecutionType = ExecutionTypes.Order,
				};

				var orderTime = f.TsTime.GetValue(cols);
				if (orderTime.TimeOfDay != TimeSpan.Zero)
					msg.ServerTime = orderTime.ApplyTimeZone(TimeHelper.Moscow);

				var stopPrice = f.StopPrice.GetValue(cols);
				var orderType = f.Blank.GetValue(cols);

				switch (orderType)
				{
					case "S":
					{
						var updateToPrice = f.UpdateNewPrice.GetValue(cols);

						if (updateToPrice != 0) // Stop + TargetProfit
						{
							var updGrowPrice = f.UpdateGrowPrice.GetValue(cols);
							var updDownPrice = f.UpdateDownPrice.GetValue(cols);

							msg.Condition = new AlfaOrderCondition
							{
								StopPrice = stopPrice,
								TargetPrice = msg.OrderPrice,
								Slippage = msg.Side == Sides.Buy
											   ? updateToPrice - updGrowPrice
											   : updDownPrice - updateToPrice
							};
						}
						else // Stop
						{
							msg.Condition = new AlfaOrderCondition
							{
								StopPrice = stopPrice,
								Slippage = stopPrice == 0
											   ? 0
											   : msg.Side == Sides.Buy
													 ? msg.OrderPrice - stopPrice
													 : stopPrice - msg.OrderPrice
							};
						}

						msg.OrderType = OrderTypes.Conditional;

						break;
					}
					case "T":
					{
						var level = f.TrailingLevel.GetValue(cols);
						var slippage = f.TrailingSlippage.GetValue(cols);

						msg.Condition = new AlfaOrderCondition
						{
							Level = level,
							Slippage = slippage,
							StopPrice = stopPrice
						};

						msg.OrderType = OrderTypes.Conditional;

						break;
					}
					case "L":
						msg.OrderType = OrderTypes.Limit;
						break;
					default:
						this.AddWarningLog("Unknown order type '{0}' (id={1})", orderType, orderId);
						break;
				}

				var status = f.OrderStatus.GetValue(cols);
				switch (status)
				{
					case "O": // активная
					case "G": // с условием
						msg.OrderState = OrderStates.Active;
						break;

					case "M": // исполнена
						msg.OrderState = msg.Balance != 0 ? OrderStates.Active : OrderStates.Done;
						break;

					case "W": // удалена
						msg.OrderState = OrderStates.Done;
						break;

					case "N": // принята сервером АД, но пока не на бирже
						msg.OrderState = OrderStates.Pending;
						break;

					default:
						this.AddInfoLog("Order status {0} is not taken into account", status);
						break;
				}

				SendOutMessage(msg);
			}
		}
Example #20
0
		/// <summary>
		/// To calculate commission.
		/// </summary>
		/// <param name="message">The message containing the information about the order or own trade.</param>
		/// <returns>The commission. If the commission can not be calculated then <see langword="null" /> will be returned.</returns>
		protected override decimal? OnProcessExecution(ExecutionMessage message)
		{
			if (message.ExecutionType == ExecutionTypes.Order)
				return (decimal)Value;
			
			return null;
		}
Example #21
0
        /// <summary>
        /// Create a copy of <see cref="ExecutionMessage"/>.
        /// </summary>
        /// <returns>Copy.</returns>
        public override Message Clone()
        {
            var clone = new ExecutionMessage
            {
                Balance       = Balance,
                Comment       = Comment,
                Condition     = Condition.CloneNullable(),
                ClientCode    = ClientCode,
                BrokerCode    = BrokerCode,
                Currency      = Currency,
                ServerTime    = ServerTime,
                DepoName      = DepoName,
                Error         = Error,
                ExpiryDate    = ExpiryDate,
                IsSystem      = IsSystem,
                LocalTime     = LocalTime,
                OpenInterest  = OpenInterest,
                OrderId       = OrderId,
                OrderStringId = OrderStringId,
                OrderBoardId  = OrderBoardId,
                ExecutionType = ExecutionType,
                IsCancelled   = IsCancelled,
                //Action = Action,
                OrderState            = OrderState,
                OrderStatus           = OrderStatus,
                OrderType             = OrderType,
                OriginSide            = OriginSide,
                PortfolioName         = PortfolioName,
                OrderPrice            = OrderPrice,
                SecurityId            = SecurityId,
                Side                  = Side,
                SystemComment         = SystemComment,
                TimeInForce           = TimeInForce,
                TradeId               = TradeId,
                TradeStringId         = TradeStringId,
                TradePrice            = TradePrice,
                TradeStatus           = TradeStatus,
                TransactionId         = TransactionId,
                OriginalTransactionId = OriginalTransactionId,
                OrderVolume           = OrderVolume,
                TradeVolume           = TradeVolume,
                //IsFinished = IsFinished,
                VisibleVolume = VisibleVolume,
                IsUpTick      = IsUpTick,
                Commission    = Commission,
                Latency       = Latency,
                Slippage      = Slippage,
                UserOrderId   = UserOrderId,

                DerivedOrderId       = DerivedOrderId,
                DerivedOrderStringId = DerivedOrderStringId,

                PnL      = PnL,
                Position = Position,

                HasTradeInfo = HasTradeInfo,
                HasOrderInfo = HasOrderInfo
            };

            this.CopyExtensionInfo(clone);

            return(clone);
        }
Example #22
0
		/// <summary>
		/// To calculate commission.
		/// </summary>
		/// <param name="message">The message containing the information about the order or own trade.</param>
		/// <returns>The commission. If the commission can not be calculated then <see langword="null" /> will be returned.</returns>
		protected override decimal? OnProcessExecution(ExecutionMessage message)
		{
			if (message.ExecutionType != ExecutionTypes.Trade)
				return null;

			if (++_currentCount < Count)
				return null;

			_currentCount = 0;
			return (decimal)Value;
		}
Example #23
0
			protected override void WriterFixOrderCondition(IFixWriter writer, ExecutionMessage message)
			{
				writer.WriteOrderCondition((QuikOrderCondition)message.Condition);
			}
Example #24
0
		/// <summary>
		/// To calculate commission.
		/// </summary>
		/// <param name="message">The message containing the information about the order or own trade.</param>
		/// <returns>The commission. If the commission can not be calculated then <see langword="null" /> will be returned.</returns>
		protected override decimal? OnProcessExecution(ExecutionMessage message)
		{
			if (message.ExecutionType == ExecutionTypes.Trade)
				return (decimal)(message.TradePrice * message.Volume * Value);
			
			return null;
		}
		/// <summary>
		/// Send message.
		/// </summary>
		/// <param name="message">Message.</param>
		protected override void OnSendInMessage(Message message)
		{
			switch (message.Type)
			{
				case MessageTypes.Reset:
				{
					if (_client != null)
					{
						DisposeClient();
					}

					try
					{
						Connection.Close();
						Connection.ClearCache();
					}
					catch (Exception ex)
					{
						SendOutError(ex);
					}

					Connection.StatusChange -= ConnectionOnStatusChange;

					SendOutMessage(new ResetMessage());

					break;
				}

				case MessageTypes.Connect:
				{
					if (_client != null)
						throw new InvalidOperationException(LocalizedStrings.Str3378);

					var doc = XDocument.Load("http://www.ddfplus.com/getusersettings.php?username={0}&password={1}".Put(Login, Password.To<string>()));

					var loginElem = doc.Element("usersettings").Elements("login").First();

					if (loginElem.GetAttributeValue<string>("status") != "ok")
						throw new InvalidOperationException(LocalizedStrings.UnknownServerError);

					if (loginElem.GetAttributeValue<string>("credentials") != "ok")
						throw new InvalidOperationException(LocalizedStrings.Str3350);

					foreach (var elem in doc.Element("usersettings").Element("servers").Elements())
					{
						switch (elem.GetAttributeValue<string>("type"))
						{
							case "stream":
								_streamAddress = elem.GetAttributeValue<string>("primary");
								break;

							case "historicalv2":
								_historicalAddress = elem.GetAttributeValue<string>("primary");
								break;

							case "extras":
								_extrasAddress = elem.GetAttributeValue<string>("primary");
								break;

							case "news":
								_newsAddress = elem.GetAttributeValue<string>("primary");
								break;
						}
					}

					SendOutMessage(new ConnectMessage());

					Connection.StatusChange += ConnectionOnStatusChange;
					Connection.Properties["streamingversion"] = "3";

					_client = new Client();

					_client.Error += ClientOnError;
					_client.NewBookQuote += ClientOnNewBookQuote;
					_client.NewOHLCQuote += ClientOnNewOhlcQuote;
					_client.NewQuote += ClientOnNewQuote;

					Connection.Username = Login;
					Connection.Password = Password.To<string>();
					Connection.Mode = ConnectionMode.TCPClient;

					break;
				}

				case MessageTypes.Disconnect:
				{
					if (_client == null)
						throw new InvalidOperationException(LocalizedStrings.Str1856);

					DisposeClient();
					Connection.Close();

					break;
				}

				case MessageTypes.SecurityLookup:
				{
					var lookupMsg = (SecurityLookupMessage)message;

					XDocument doc = null;

					if (!lookupMsg.SecurityId.SecurityCode.IsEmpty())
					{
						doc = XDocument.Load("{0}/instruments/?lookup={1}".Put(_extrasAddress, lookupMsg.SecurityId.SecurityCode));
					}
					else if (!lookupMsg.SecurityId.BoardCode.IsEmpty())
					{
						doc = XDocument.Load("{0}/instruments/?exchange={1}".Put(_extrasAddress, lookupMsg.SecurityId.BoardCode));
					}

					if (doc != null)
					{
						foreach (var element in doc.Element("instruments").Elements())
						{
							SendOutMessage(new SecurityMessage
							{
								SecurityId = new SecurityId
								{
									SecurityCode = element.GetAttributeValue<string>("guid"),
									BoardCode = element.GetAttributeValue<string>("exchange"),
								},
								Name = element.GetAttributeValue<string>("symbol_description"),
								OriginalTransactionId = lookupMsg.TransactionId,
								SecurityType = TraderHelper.FromIso10962(element.GetAttributeValue<string>("symbol_cfi")),
								PriceStep = element.GetAttributeValue<decimal?>("tick_increment"),
								Multiplier = element.GetAttributeValue<decimal?>("point_value"),
								Currency = element.GetAttributeValue<CurrencyTypes?>("currency")
							});
						}
					}

					SendOutMessage(new SecurityLookupResultMessage
					{
						OriginalTransactionId = lookupMsg.TransactionId,
					});

					break;
				}

				case MessageTypes.MarketData:
				{
					var mdMsg = (MarketDataMessage)message;

					switch (mdMsg.DataType)
					{
						case MarketDataTypes.Level1:
							break;
						case MarketDataTypes.MarketDepth:
							break;
						case MarketDataTypes.Trades:
						{
							if (mdMsg.Count != null || mdMsg.From != null || mdMsg.To != null)
							{
								var url = new Url("{0}/queryticks.ashx".Put(_historicalAddress));

								url.QueryString
									.Append("username", Login)
									.Append("password", Password.To<string>())
									.Append("symbol", mdMsg.SecurityId.SecurityCode)
									.Append("order", "asc");

								if (mdMsg.Count != null)
									url.QueryString.Append("maxrecords", mdMsg.Count.Value);

								if (mdMsg.From != null)
									url.QueryString.Append("start", mdMsg.From.Value.FromDateTimeOffset(_defaultTimeFormatRequest));

								if (mdMsg.To != null)
									url.QueryString.Append("end", mdMsg.To.Value.FromDateTimeOffset(_defaultTimeFormatRequest));

								using (var client = new WebClient())
								{
									var lines = client.DownloadString(url)
										.Split("\n")
										.Where(l => l != "\r")
										.ToArray();

									var i = 0;
									foreach (var line in lines)
									{
										var columns = line.Split(',');

										try
										{
											var msg = new ExecutionMessage
											{
												SecurityId = mdMsg.SecurityId,
												OriginalTransactionId = mdMsg.TransactionId,
												ExecutionType = ExecutionTypes.Tick,
												ServerTime = columns[0].ToDateTime("yyyy-MM-dd HH:mm:ss.fff"),
												TradePrice = columns[3].To<decimal>(),
												Volume = columns[4].To<decimal>(),
											};

											msg.AddValue("IsFinished", ++i == lines.Length);

											SendOutMessage(msg);
										}
										catch (Exception ex)
										{
											throw new InvalidOperationException(LocalizedStrings.Str2141Params.Put(line), ex);
										}
									}
								}
							}

							break;
						}
						case MarketDataTypes.News:
							break;
						case MarketDataTypes.CandleTimeFrame:
						{
							var tf = (TimeSpan)mdMsg.Arg;

							string serviceName;
							string timeFormatRequest = _defaultTimeFormatRequest;
							string timeFormatResponse = "yyyy-MM-dd";

							if (tf == TimeSpan.FromMinutes(1))
							{
								serviceName = "queryminutes";
								timeFormatResponse = "yyyy-MM-dd HH:mm";
							}
							else if (tf == TimeSpan.FromDays(1))
							{
								serviceName = "queryeod";
								timeFormatRequest = "yyyyMMdd";
							}
							else
								throw new InvalidOperationException(LocalizedStrings.Str2102);

							var url = new Url("{0}/{1}.ashx".Put(_historicalAddress, serviceName));

							url.QueryString
								.Append("username", Login)
								.Append("password", Password.To<string>())
								.Append("symbol", mdMsg.SecurityId.SecurityCode)
								.Append("order", "asc");

							if (mdMsg.Count != null)
								url.QueryString.Append("maxrecords", mdMsg.Count.Value);

							if (mdMsg.From != null)
								url.QueryString.Append("start", mdMsg.From.Value.FromDateTimeOffset(timeFormatRequest));

							if (mdMsg.To != null)
								url.QueryString.Append("end", mdMsg.To.Value.FromDateTimeOffset(timeFormatRequest));

							using (var client = new WebClient())
							{
								var lines = client.DownloadString(url)
										.Split("\n")
										.Where(l => l != "\r")
										.ToArray();

								var i = 0;
								foreach (var line in lines)
								{
									var columns = line.Split(',');

									try
									{
										SendOutMessage(new TimeFrameCandleMessage
										{
											SecurityId = mdMsg.SecurityId,
											OriginalTransactionId = mdMsg.TransactionId,
											OpenTime = columns[tf == TimeSpan.FromMinutes(1) ? 0 : 1].ToDateTime(timeFormatResponse).ApplyTimeZone(TimeHelper.Est),
											OpenPrice = columns[2].To<decimal>(),
											HighPrice = columns[3].To<decimal>(),
											LowPrice = columns[4].To<decimal>(),
											ClosePrice = columns[5].To<decimal>(),
											TotalVolume = columns[6].To<decimal>(),
											OpenInterest = columns.Length > 7 ? columns[7].To<decimal>() : (decimal?)null,
											IsFinished = ++i == lines.Length
										});
									}
									catch (Exception ex)
									{
										throw new InvalidOperationException(LocalizedStrings.Str2141Params.Put(line), ex);
									}
								}
							}

							break;
						}
						default:
						{
							SendOutMarketDataNotSupported(mdMsg.TransactionId);
							return;
						}
					}

					SendOutMessage(new MarketDataMessage { OriginalTransactionId = mdMsg.TransactionId });
					break;
				}
			}
		}
Example #26
0
		/// <summary>
		/// To calculate commission.
		/// </summary>
		/// <param name="message">The message containing the information about the order or own trade.</param>
		/// <returns>The commission. If the commission can not be calculated then <see langword="null" /> will be returned.</returns>
		protected override decimal? OnProcessExecution(ExecutionMessage message)
		{
			if (message.ExecutionType == ExecutionTypes.Trade && message.SecurityId.SecurityType == SecurityType)
				return (decimal)Value;
			
			return null;
		}
		private void ReadMyTrade(IBSocket socket, ServerVersions version)
		{
			/* requestId */
			if (version >= ServerVersions.V7)
				socket.ReadInt();

			// http://www.interactivebrokers.com/en/software/api/apiguide/java/execution.htm

			var transactionId = socket.ReadInt();

			//Handle the 2^31-1 == 0 bug
			if (transactionId == int.MaxValue)
				transactionId = 0;

			//Read Contract Fields
			var contractId = version >= ServerVersions.V5 ? socket.ReadInt() : -1;

			var secName = socket.ReadStr();
			var type = socket.ReadSecurityType();
			var expiryDate = socket.ReadExpiry();
			var strike = socket.ReadDecimal();
			var optionType = socket.ReadOptionType();
			var multiplier = version >= ServerVersions.V9 ? socket.ReadMultiplier() : null;
			var boardCode = socket.ReadBoardCode();
			var currency = socket.ReadCurrency();
			var secCode = socket.ReadLocalCode(secName);
			var secClass = (version >= ServerVersions.V10) ? socket.ReadStr() : null;

			var tradeId = socket.ReadStr();
			var time = socket.ReadDateTime("yyyyMMdd  HH:mm:ss");
			var portfolio = socket.ReadStr();
			/* exchange */
			socket.ReadStr();
			var side = socket.ReadTradeSide();
			var volume = socket.ReadDecimal();
			var price = socket.ReadDecimal();
			var permId = version >= ServerVersions.V2 ? socket.ReadInt() : (int?)null;
			var clientId = version >= ServerVersions.V3 ? socket.ReadInt() : (int?)null;
			var liquidation = version >= ServerVersions.V4 ? socket.ReadInt() : (int?)null;
			var cumulativeQuantity = version >= ServerVersions.V6 ? socket.ReadInt() : (int?)null;
			var averagePrice = version >= ServerVersions.V6 ? socket.ReadDecimal() : (decimal?)null;
			var orderRef = version >= ServerVersions.V8 ? socket.ReadStr() : null;
			var evRule = version >= ServerVersions.V9 ? socket.ReadStr() : null;
			var evMultiplier = version >= ServerVersions.V9 ? socket.ReadDecimal() : (decimal?)null;

			var secId = new SecurityId
			{
				SecurityCode = secCode,
				BoardCode = GetBoardCode(boardCode),
				InteractiveBrokers = contractId,
			};

			SendOutMessage(new SecurityMessage
			{
				SecurityId = secId,
				Name = secName,
				SecurityType = type,
				ExpiryDate = expiryDate,
				Strike = strike,
				OptionType = optionType,
				Currency = currency,
				Multiplier = multiplier ?? 0,
				Class = secClass
			});

			// заявка была создана руками
			if (transactionId == 0)
				return;

			_secIdByTradeIds[tradeId] = secId;

			var execMsg = new ExecutionMessage
			{
				ExecutionType = ExecutionTypes.Transaction,
				OriginalTransactionId = transactionId,
				TradeStringId = tradeId,
				OriginSide = side,
				TradePrice = price,
				TradeVolume = volume,
				PortfolioName = portfolio,
				ServerTime = time,
				SecurityId = secId,
				HasTradeInfo = true,
			};

			if (permId != null)
				execMsg.SetPermId(permId.Value);

			if (clientId != null)
				execMsg.SetClientId(clientId.Value);

			if (liquidation != null)
				execMsg.SetLiquidation(liquidation.Value);

			if (cumulativeQuantity != null)
				execMsg.SetCumulativeQuantity(cumulativeQuantity.Value);

			if (averagePrice != null)
				execMsg.SetAveragePrice(averagePrice.Value);

			if (orderRef != null)
				execMsg.SetOrderRef(orderRef);

			if (evRule != null)
				execMsg.SetEvRule(evRule);

			if (evMultiplier != null)
				execMsg.SetEvMultiplier(evMultiplier.Value);

			SendOutMessage(execMsg);
		}
Example #28
0
		/// <summary>
		/// To calculate commission.
		/// </summary>
		/// <param name="message">The message containing the information about the order or own trade.</param>
		/// <returns>The commission. If the commission can not be calculated then <see langword="null" /> will be returned.</returns>
		protected override decimal? OnProcessExecution(ExecutionMessage message)
		{
			if (message.ExecutionType == ExecutionTypes.Trade && message.SecurityId.BoardCode.CompareIgnoreCase(BoardCode))
				return (decimal)Value;
			
			return null;
		}
		private void ReadOpenOrder(IBSocket socket, ServerVersions version)
		{
			var transactionId = socket.ReadInt();

			var contractId = version >= ServerVersions.V17 ? socket.ReadInt() : -1;

			var secCode = socket.ReadStr();
			var type = socket.ReadSecurityType();
			var expiryDate = socket.ReadExpiry();
			var strike = socket.ReadDecimal();
			var optionType = socket.ReadOptionType();
			var multiplier = version >= ServerVersions.V32 ? socket.ReadMultiplier() : null;
			var boardCode = socket.ReadBoardCode();
			var currency = socket.ReadCurrency();
			secCode = version >= ServerVersions.V2 ? socket.ReadLocalCode(secCode) : null;
			var secClass = (version >= ServerVersions.V32) ? socket.ReadStr() : null;

			var ibCon = new IBOrderCondition();

			// read order fields
			var direction = socket.ReadOrderSide();
			var volume = socket.ReadDecimal();

			OrderTypes orderType;
			IBOrderCondition.ExtendedOrderTypes? extendedType;
			socket.ReadOrderType(out orderType, out extendedType);
			ibCon.ExtendedType = extendedType;

			var price = socket.ReadDecimal();
			ibCon.StopPrice = socket.ReadDecimal();
			var expiration = socket.ReadStr();
			ibCon.Oca.Group = socket.ReadStr();
			var portfolio = socket.ReadStr();
			ibCon.IsOpenOrClose = socket.ReadStr() == "O";
			ibCon.Origin = (IBOrderCondition.OrderOrigins)socket.ReadInt();
			var comment = socket.ReadStr();

			var clientId = version >= ServerVersions.V3 ? socket.ReadInt() : (int?)null;
			int? permId = null;

			if (version >= ServerVersions.V4)
			{
				permId = socket.ReadInt();

				if (version < ServerVersions.V18)
				{
					// will never happen
					/* order.m_ignoreRth = */
					socket.ReadBool();
				}
				else
					ibCon.OutsideRth = socket.ReadBool();

				ibCon.Hidden = socket.ReadBool();
				ibCon.SmartRouting.DiscretionaryAmount = socket.ReadDecimal();
			}

			if (version >= ServerVersions.V5)
				ibCon.GoodAfterTime = socket.ReadNullDateTime(IBSocketHelper.TimeFormat);

			if (version >= ServerVersions.V6)
			{
				// skip deprecated sharesAllocation field
				socket.ReadStr();
			}

			if (version >= ServerVersions.V7)
			{
				ibCon.FinancialAdvisor.Group = socket.ReadStr();
				ibCon.FinancialAdvisor.Allocation = socket.ReadFinancialAdvisor();
				ibCon.FinancialAdvisor.Percentage = socket.ReadStr();
				ibCon.FinancialAdvisor.Profile = socket.ReadStr();
			}

			var orderExpiryDate = version >= ServerVersions.V8 ? socket.ReadNullDateTime(IBSocketHelper.TimeFormat) : null;
			var visibleVolume = volume;

			if (version >= ServerVersions.V9)
			{
				ibCon.Agent = socket.ReadAgent();
				ibCon.PercentOffset = socket.ReadDecimal();
				ibCon.Clearing.SettlingFirm = socket.ReadStr();
				ibCon.ShortSale.Slot = (IBOrderCondition.ShortSaleSlots)socket.ReadInt();
				ibCon.ShortSale.Location = socket.ReadStr();

				if (socket.ServerVersion == ServerVersions.V51)
					socket.ReadInt(); //exempt code
				else if (version >= ServerVersions.V23)
					ibCon.ShortSale.ExemptCode = socket.ReadInt();

				ibCon.AuctionStrategy = (IBOrderCondition.AuctionStrategies)socket.ReadInt();
				ibCon.StartingPrice = socket.ReadDecimal();
				ibCon.StockRefPrice = socket.ReadDecimal();
				ibCon.Delta = socket.ReadDecimal();
				ibCon.StockRangeLower = socket.ReadDecimal();
				ibCon.StockRangeUpper = socket.ReadDecimal();
				visibleVolume = socket.ReadInt();

				if (version < ServerVersions.V18)
				{
					// will never happen
					/* order.m_rthOnly = */
					socket.ReadBool();
				}

				ibCon.BlockOrder = socket.ReadBool();
				ibCon.SweepToFill = socket.ReadBool();
				ibCon.AllOrNone = socket.ReadBool();
				ibCon.MinVolume = socket.ReadInt();
				ibCon.Oca.Type = (IBOrderCondition.OcaTypes)socket.ReadInt();
				ibCon.SmartRouting.ETradeOnly = socket.ReadBool();
				ibCon.SmartRouting.FirmQuoteOnly = socket.ReadBool();
				ibCon.SmartRouting.NbboPriceCap = socket.ReadDecimal();
			}

			if (version >= ServerVersions.V10)
			{
				ibCon.ParentId = socket.ReadInt();
				ibCon.TriggerMethod = (IBOrderCondition.TriggerMethods)socket.ReadInt();
			}

			if (version >= ServerVersions.V11)
			{
				ibCon.Volatility.Volatility = socket.ReadDecimal();
				ibCon.Volatility.VolatilityTimeFrame = socket.ReadVolatilityType();

				if (version == ServerVersions.V11)
				{
					if (!socket.ReadBool())
						ibCon.Volatility.ExtendedOrderType = IBOrderCondition.ExtendedOrderTypes.Empty;
					else
						ibCon.Volatility.OrderType = OrderTypes.Market;
				}
				else
				{
					OrderTypes volOrdertype;
					IBOrderCondition.ExtendedOrderTypes? volExtendedType;
					socket.ReadOrderType(out volOrdertype, out volExtendedType);
					ibCon.Volatility.OrderType = volOrdertype;
					ibCon.Volatility.ExtendedOrderType = volExtendedType;

					ibCon.Volatility.StopPrice = socket.ReadDecimal();

					if (volExtendedType != IBOrderCondition.ExtendedOrderTypes.Empty)
					{
						if (version >= ServerVersions.V27)
						{
							ibCon.Volatility.ConId = socket.ReadInt();
							ibCon.Volatility.SettlingFirm = socket.ReadStr();

							var portfolioName = socket.ReadStr();
							if (!portfolioName.IsEmpty())
								ibCon.Volatility.ClearingPortfolio = portfolioName;

							ibCon.Volatility.ClearingIntent = socket.ReadStr();
						}

						if (version >= ServerVersions.V31)
						{
							var isOpenOrCloseStr = socket.ReadStr();
							ibCon.Volatility.ShortSale.IsOpenOrClose = isOpenOrCloseStr == "?" ? (bool?)null : isOpenOrCloseStr.To<int>() == 1;
							ibCon.Volatility.IsShortSale = socket.ReadBool();
							ibCon.Volatility.ShortSale.Slot = (IBOrderCondition.ShortSaleSlots)socket.ReadInt();
							ibCon.Volatility.ShortSale.Location = socket.ReadStr();
						}
					}
				}

				ibCon.Volatility.ContinuousUpdate = socket.ReadBool();

				if (socket.ServerVersion == ServerVersions.V26)
				{
					ibCon.StockRangeLower = socket.ReadDecimal();
					ibCon.StockRangeUpper = socket.ReadDecimal();
				}

				ibCon.Volatility.IsAverageBestPrice = socket.ReadBool();
			}

			if (version >= ServerVersions.V13)
				ibCon.TrailStopPrice = socket.ReadDecimal();

			if (version >= ServerVersions.V30)
				ibCon.TrailStopVolumePercentage = socket.ReadNullDecimal();

			if (version >= ServerVersions.V14)
			{
				ibCon.Combo.BasisPoints = socket.ReadDecimal();
				ibCon.Combo.BasisPointsType = socket.ReadInt();
				ibCon.Combo.LegsDescription = socket.ReadStr();
			}

			if (version >= ServerVersions.V29)
			{
				var comboLegsCount = socket.ReadInt();
				if (comboLegsCount > 0)
				{
					//contract.m_comboLegs = new Vector(comboLegsCount);
					for (var i = 0; i < comboLegsCount; ++i)
					{
						//int conId = 
						socket.ReadInt();
						//int ratio = 
						socket.ReadInt();
						//String action = 
						socket.ReadStr();
						//String exchange = 
						socket.ReadStr();
						//int openClose = 
						socket.ReadInt();
						//int shortSaleSlot = 
						socket.ReadInt();
						//String designatedLocation = 
						socket.ReadStr();
						//int exemptCode = 
						socket.ReadInt();

						//ComboLeg comboLeg = new ComboLeg(conId, ratio, action, exchange, openClose,
						//		shortSaleSlot, designatedLocation, exemptCode);
						//contract.m_comboLegs.add(comboLeg);
					}
				}

				var orderComboLegsCount = socket.ReadInt();
				if (orderComboLegsCount > 0)
				{
					//order.m_orderComboLegs = new Vector(orderComboLegsCount);
					for (var i = 0; i < orderComboLegsCount; ++i)
					{
						//var comboPrice = 
						socket.ReadNullDecimal();
						//OrderComboLeg orderComboLeg = new OrderComboLeg(comboPrice);
						//order.m_orderComboLegs.add(orderComboLeg);
					}
				}
			}

			if (version >= ServerVersions.V26)
			{
				var smartComboRoutingParamsCount = socket.ReadInt();
				if (smartComboRoutingParamsCount > 0)
				{
					var @params = new List<Tuple<string, string>>();

					for (var i = 0; i < smartComboRoutingParamsCount; ++i)
						@params.Add(Tuple.Create(socket.ReadStr(), socket.ReadStr()));

					ibCon.SmartRouting.ComboParams = @params;
				}
			}

			if (version >= ServerVersions.V15)
			{
				if (version >= ServerVersions.V20)
				{
					ibCon.Scale.InitLevelSize = socket.ReadNullInt();
					ibCon.Scale.SubsLevelSize = socket.ReadNullInt();
				}
				else
				{
					/* int notSuppScaleNumComponents = */
					socket.ReadNullInt();
					ibCon.Scale.InitLevelSize = socket.ReadNullInt();
				}

				ibCon.Scale.PriceIncrement = socket.ReadNullDecimal();
			}

			if (version >= ServerVersions.V28 && ibCon.Scale.PriceIncrement > 0)
			{
				ibCon.Scale.PriceAdjustValue = socket.ReadNullDecimal();
				ibCon.Scale.PriceAdjustInterval = socket.ReadInt();
				ibCon.Scale.ProfitOffset = socket.ReadNullDecimal();
				ibCon.Scale.AutoReset = socket.ReadBool();
				ibCon.Scale.InitPosition = socket.ReadNullInt();
				ibCon.Scale.InitFillQty = socket.ReadNullInt();
				ibCon.Scale.RandomPercent = socket.ReadBool();
			}

			if (version >= ServerVersions.V24)
				socket.ReadHedge(ibCon);

			if (version >= ServerVersions.V25)
				ibCon.SmartRouting.OptOutSmartRouting = socket.ReadBool();

			if (version >= ServerVersions.V19)
			{
				var portfolioName = socket.ReadStr();

				if (!portfolioName.IsEmpty())
					ibCon.Clearing.ClearingPortfolio = portfolioName;

				ibCon.Clearing.Intent = socket.ReadIntent();
			}

			if (version >= ServerVersions.V22)
				ibCon.SmartRouting.NotHeld = socket.ReadBool();

			if (version >= ServerVersions.V20)
			{
				if (socket.ReadBool())
				{
					//UnderlyingComponent underComp = new UnderlyingComponent();
					//underComp.ContractId = 
					socket.ReadInt();
					//underComp.Delta = 
					socket.ReadDecimal();
					//underComp.Price = 
					socket.ReadDecimal();
					//contract.UnderlyingComponent = underComp;
				}
			}

			if (version >= ServerVersions.V21)
			{
				ibCon.Algo.Strategy = socket.ReadStr();

				if (!ibCon.Algo.Strategy.IsEmpty())
				{
					var algoParamsCount = socket.ReadInt();

					if (algoParamsCount > 0)
					{
						var algoParams = new List<Tuple<string, string>>();

						for (var i = 0; i < algoParamsCount; i++)
							algoParams.Add(Tuple.Create(socket.ReadStr(), socket.ReadStr()));

						ibCon.Algo.Params = algoParams;
					}
				}
			}

			//OrderState orderState = new OrderState();

			OrderStatus? status = null;

			if (version >= ServerVersions.V16)
			{
				socket.ReadStr();
				//order.WhatIf = !(string.IsNullOrEmpty(rstr) || rstr == "0");

				status = socket.ReadOrderStatus();
				//orderState.InitMargin = 
				socket.ReadStr();
				//orderState.MaintMargin = 
				socket.ReadStr();
				//orderState.EquityWithLoan = 
				socket.ReadStr();
				//orderState.IbCommission = 
				socket.ReadNullDecimal();
				//orderState.MinCommission = 
				socket.ReadNullDecimal();
				//orderState.MaxCommission = 
				socket.ReadNullDecimal();
				//orderState.CommissionCurrency = 
				socket.ReadStr();
				//orderState.WarningText = 
				socket.ReadStr();
			}

			var secId = new SecurityId
			{
				SecurityCode = secCode,
				BoardCode = GetBoardCode(boardCode),
				InteractiveBrokers = contractId,
			};

			SendOutMessage(new SecurityMessage
			{
				SecurityId = secId,
				ExpiryDate = expiryDate,
				Strike = strike,
				OptionType = optionType,
				Class = secClass,
				SecurityType = type,
				Currency = currency,
				Multiplier = multiplier ?? 0,
			});

			var orderMsg = new ExecutionMessage
			{
				ExecutionType = ExecutionTypes.Transaction,
				SecurityId = secId,
				OriginalTransactionId = transactionId,
				OrderType = orderType,
				Side = direction,
				OrderVolume = volume,
				OrderPrice = price,
				Condition = ibCon,
				ExpiryDate = orderExpiryDate,
				VisibleVolume = visibleVolume,
				PortfolioName = portfolio,
				Comment = comment,
				OrderStatus = status,
				OrderState = status?.ToOrderState(),
				HasOrderInfo = true,
			};

			if (orderMsg.OrderState == OrderStates.Active || orderMsg.OrderState == OrderStates.Done)
				orderMsg.OrderId = transactionId;

			switch (expiration)
			{
				case "DAY":
					orderMsg.TimeInForce = TimeInForce.PutInQueue;
					break;
				case "GTC":
					//orderMsg.ExpiryDate = DateTimeOffset.MaxValue;
					break;
				case "IOC":
					orderMsg.TimeInForce = TimeInForce.CancelBalance;
					break;
				case "FOK":
					orderMsg.TimeInForce = TimeInForce.MatchOrCancel;
					break;
				case "GTD":
					break;
				case "OPG":
					ibCon.IsMarketOnOpen = true;
					break;
				default:
					throw new InvalidOperationException(LocalizedStrings.Str2515Params.Put(expiration));
			}

			if (clientId != null)
				orderMsg.SetClientId(clientId.Value);

			if (permId != null)
				orderMsg.SetPermId(permId.Value);

			SendOutMessage(orderMsg);
		}
Example #30
0
		/// <summary>
		/// To calculate commission.
		/// </summary>
		/// <param name="message">The message containing the information about the order or own trade.</param>
		/// <returns>The commission. If the commission can not be calculated then <see langword="null" /> will be returned.</returns>
		protected override decimal? OnProcessExecution(ExecutionMessage message)
		{
			if (message.ExecutionType != ExecutionTypes.Trade)
				return null;

			_currentTurnOver += message.GetTradePrice() * message.SafeGetVolume();

			if (_currentTurnOver < TurnOver)
				return null;

			return (decimal)Value;
		}
Example #31
0
		public Tuple<OrderFail, bool> ProcessOrderFailMessage(Security security, ExecutionMessage message)
		{
			if (security == null)
				throw new ArgumentNullException(nameof(security));

			if (message == null)
				throw new ArgumentNullException(nameof(message));

			var data = GetData(security);

			Order order = null;

			if (!message.OrderStringId.IsEmpty())
				order = data.OrdersByStringId.TryGetValue(message.OrderStringId);

			bool isCancelled;

			if (order == null)
			{
				if (message.OriginalTransactionId == 0)
					throw new ArgumentOutOfRangeException(nameof(message), message.OriginalTransactionId, LocalizedStrings.Str715);

				var orders = data.Orders;

				order = (Order)orders.TryGetValue(CreateOrderKey(message.OrderType, message.OriginalTransactionId, true));

				if (order != null && order.Id == message.OrderId)
					isCancelled = true;
				else
				{
					order = (Order)orders.TryGetValue(CreateOrderKey(message.OrderType, message.OriginalTransactionId, false));
					isCancelled = false;
				}

				if (order == null)
					return null;
			}
			else
			{
				var pair = data.Orders.LastOrDefault(p => p.Value.Order == order);
				isCancelled = pair.Key.Item3;
			}

			// ServerTime для заявки - это время регистрации
			order.LastChangeTime = message.LocalTime;
			order.LocalTime = message.LocalTime;

			if (message.OrderStatus != null)
				order.Status = message.OrderStatus;

			//для ошибок снятия не надо менять состояние заявки
			if (!isCancelled)
				order.State = OrderStates.Failed;

			if (message.Commission != null)
				order.Commission = message.Commission;

			message.CopyExtensionInfo(order);

			var error = message.Error ?? new InvalidOperationException(
				isCancelled ? LocalizedStrings.Str716 : LocalizedStrings.Str717);

			var fail = EntityFactory.CreateOrderFail(order, error);
			fail.ServerTime = message.ServerTime;
			fail.LocalTime = message.LocalTime;
			return Tuple.Create(fail, isCancelled);
		}
Example #32
0
		/// <summary>
		/// To calculate commission.
		/// </summary>
		/// <param name="message">The message containing the information about the order or own trade.</param>
		/// <returns>The commission. If the commission can not be calculated then <see langword="null" /> will be returned.</returns>
		protected abstract decimal? OnProcessExecution(ExecutionMessage message);
Example #33
0
		public Tuple<Trade, bool> ProcessTradeMessage(Security security, ExecutionMessage message)
		{
			if (security == null)
				throw new ArgumentNullException(nameof(security));

			if (message == null)
				throw new ArgumentNullException(nameof(message));

			var trade = GetTrade(security, message.TradeId, message.TradeStringId, (id, stringId) =>
			{
				var t = message.ToTrade(EntityFactory.CreateTrade(security, id, stringId));
				t.LocalTime = message.LocalTime;
				t.Time = message.ServerTime;
				message.CopyExtensionInfo(t);
				return t;
			});

			return trade;
		}
		private void OnSessionOrderChanged(LmaxOrder lmaxOrder)
		{
			var transactionId = TryParseTransactionId(lmaxOrder.InstructionId);

			if (transactionId == null)
				return;

			LmaxOrderCondition condition = null;
			decimal price = 0;
			OrderTypes orderType;

			switch (lmaxOrder.OrderType)
			{
				case OrderType.MARKET:
					orderType = OrderTypes.Market;
					break;
				case OrderType.LIMIT:
					orderType = OrderTypes.Limit;

					if (lmaxOrder.LimitPrice == null)
						throw new ArgumentException(LocalizedStrings.Str3394Params.Put(transactionId), nameof(lmaxOrder));

					price = (decimal)lmaxOrder.LimitPrice;
					break;
				case OrderType.STOP_ORDER:
				case OrderType.STOP_LOSS_MARKET_ORDER:
				case OrderType.STOP_PROFIT_LIMIT_ORDER:
					orderType = OrderTypes.Conditional;

					if (lmaxOrder.StopPrice == null)
						throw new ArgumentException(LocalizedStrings.Str3395Params.Put(transactionId), nameof(lmaxOrder));

					price = (decimal)lmaxOrder.StopPrice;

					condition = new LmaxOrderCondition
					{
						StopLossOffset = lmaxOrder.StopLossOffset,
						TakeProfitOffset = lmaxOrder.StopProfitOffset,
					};
					break;
				case OrderType.CLOSE_OUT_ORDER_POSITION:
				case OrderType.CLOSE_OUT_POSITION:
				case OrderType.SETTLEMENT_ORDER:
				case OrderType.OFF_ORDERBOOK:
				case OrderType.REVERSAL:
				case OrderType.UNKNOWN:
					orderType = OrderTypes.Execute;
					break;
				default:
					throw new ArgumentOutOfRangeException();
			}

			DateTimeOffset? expiryDate = null;
			var tif = StockSharpTimeInForce.PutInQueue;

			switch (lmaxOrder.TimeInForce)
			{
				case LmaxTimeInForce.FillOrKill:
					tif = StockSharpTimeInForce.MatchOrCancel;
					break;
				case LmaxTimeInForce.ImmediateOrCancel:
					tif = StockSharpTimeInForce.CancelBalance;
					break;
				case LmaxTimeInForce.GoodForDay:
					expiryDate = DateTime.Today.ApplyTimeZone(TimeZoneInfo.Utc);
					break;
				case LmaxTimeInForce.GoodTilCancelled:
					break;
				case LmaxTimeInForce.Unknown:
					throw new NotSupportedException(LocalizedStrings.Str3396Params.Put(lmaxOrder.TimeInForce, transactionId.Value, lmaxOrder.OrderId));
				default:
					throw new InvalidOperationException(LocalizedStrings.Str3397Params.Put(lmaxOrder.TimeInForce, transactionId.Value, lmaxOrder.OrderId));
			}

			var msg = new ExecutionMessage
			{
				SecurityId = new SecurityId { Native = lmaxOrder.InstrumentId },
				OriginalTransactionId = transactionId.Value,
				OrderType = orderType,
				OrderPrice = price,
				Condition = condition,
				OrderVolume = lmaxOrder.Quantity.Abs(),
				Side = lmaxOrder.Quantity > 0 ? Sides.Buy : Sides.Sell,
				Balance = lmaxOrder.Quantity - lmaxOrder.FilledQuantity,
				PortfolioName = lmaxOrder.AccountId.To<string>(),
				TimeInForce = tif,
				ExpiryDate = expiryDate,
				OrderStringId = lmaxOrder.OrderId,
				ExecutionType = ExecutionTypes.Transaction,
				Commission = lmaxOrder.Commission,
				ServerTime = CurrentTime.Convert(TimeZoneInfo.Utc)
			};

			msg.OrderState = lmaxOrder.CancelledQuantity > 0
								? OrderStates.Done
								: (msg.Balance == 0 ? OrderStates.Done : OrderStates.Active);

			//msg.Action = lmaxOrder.CancelledQuantity > 0
			//				 ? ExecutionActions.Canceled
			//				 : (lmaxOrder.FilledQuantity == 0 ? ExecutionActions.Registered : ExecutionActions.Matched);

			SendOutMessage(msg);
		}