Example #1
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;
		}
Example #2
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 #3
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);
		}
Example #4
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 #5
0
		public IEnumerable<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);

			var orders = new List<Tuple<Order, bool>>();

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

			var o = (Order)data.Orders.TryGetValue(CreateOrderKey(message.OrderType, message.OriginalTransactionId, true));

			if (o != null /*&& order.Id == message.OrderId*/)
			{
				orders.Add(Tuple.Create(o, true));

				// if replace
				var replaced = (Order)data.Orders.TryGetValue(CreateOrderKey(message.OrderType, message.OriginalTransactionId, false));

				if (replaced != null)
					orders.Add(Tuple.Create(replaced, false));
			}
			else
			{
				o = (Order)data.Orders.TryGetValue(CreateOrderKey(message.OrderType, message.OriginalTransactionId, false));
				orders.Add(Tuple.Create(o, false));
			}

			if (o == null)
			{
				if (!message.OrderStringId.IsEmpty())
				{
					o = data.OrdersByStringId.TryGetValue(message.OrderStringId);

					if (o != null)
					{
						var pair = data.Orders.LastOrDefault(p => p.Value.Order == o);

						if (pair.Key != null)
							orders.Add(Tuple.Create(pair.Value.Order, pair.Key.Item3));
					}
				}
			}

			if (orders.Count == 0)
				return Enumerable.Empty<Tuple<OrderFail, bool>>();

			return orders.Select(t =>
			{
				var order = t.Item1;
				var isCancelled = t.Item2;

				order.LastChangeTime = message.ServerTime;
				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);
			});
		}