private void ProcessOrderRegister(OrderRegisterMessage regMsg)
		{
			var reply = _client.MakeOrder(
				regMsg.SecurityId.SecurityCode.Replace('/', '_').ToLowerInvariant(),
				regMsg.Side.ToBtce(),
				regMsg.Price,
				regMsg.Volume
			);

			_orderInfo.Add(reply.Command.OrderId, RefTuple.Create(regMsg.TransactionId, regMsg.Volume));

			SendOutMessage(new ExecutionMessage
			{
				OriginalTransactionId = regMsg.TransactionId,
				OrderId = reply.Command.OrderId,
				Balance = (decimal)reply.Command.Remains,
				OrderState = OrderStates.Active,
				ExecutionType = ExecutionTypes.Transaction,
				HasOrderInfo = true,
			});

			ProcessFunds(reply.Command.Funds);

			_hasActiveOrders = true;
		}
		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,
				});
			}
		}
		private void ProcessOrderRegisterMessage(OrderRegisterMessage regMsg)
		{
			var condition = (SterlingOrderCondition)regMsg.Condition;
			var orderType = regMsg.OrderType.Value;

			var order = new STIOrder
			{
				Account = regMsg.PortfolioName, 
				Quantity = (int)regMsg.Volume,
				Display = (int)(regMsg.VisibleVolume ?? regMsg.Volume), 
				ClOrderID = regMsg.TransactionId.To<string>(), 
				LmtPrice = (double)regMsg.Price, 
				Symbol = regMsg.SecurityId.SecurityCode, 
				Destination = regMsg.SecurityId.BoardCode, 
				Tif = regMsg.TimeInForce.ToSterlingTif(regMsg.TillDate), 
				PriceType = orderType.ToSterlingPriceType(condition), 
				User = regMsg.Comment, 
				Side = regMsg.Side.ToSterlingSide()
			};

			if (regMsg.TillDate != null && regMsg.TillDate != DateTimeOffset.MaxValue)
				order.EndTime = regMsg.TillDate.Value.ToString("yyyyMMdd");

			if (regMsg.Currency != null)
				order.Currency = regMsg.Currency.ToString();

			if (orderType == OrderTypes.Conditional)
			{
				order.Discretion = condition.Discretion.ToDouble();
				order.ExecInst = condition.ExecutionInstruction.ToSterling();
				order.ExecBroker = condition.ExecutionBroker;
				order.ExecPriceLmt = condition.ExecutionPriceLimit.ToDouble();
				order.PegDiff = condition.PegDiff.ToDouble();
				order.TrailAmt = condition.TrailingVolume.ToDouble();
				order.TrailInc = condition.TrailingIncrement.ToDouble();
				order.StpPrice = condition.StopPrice.ToDouble();
				order.MinQuantity = condition.MinVolume.ToInt();
				order.AvgPriceLmt = condition.AveragePriceLimit.ToDouble();
				order.Duration = condition.Duration ?? 0;

				order.LocateBroker = condition.LocateBroker;
				order.LocateQty = condition.LocateVolume.ToInt();
				order.LocateTime = condition.LocateTime.ToSterling();

				order.OpenClose = condition.Options.IsOpen.ToSterling();
				order.Maturity = condition.Options.Maturity.ToSterling();
				order.PutCall = condition.Options.Type.ToSterling();
				order.Underlying = condition.Options.UnderlyingCode;
				order.CoverUncover = condition.Options.IsCover.ToSterling();
				order.Instrument = condition.Options.UnderlyingType.ToSterling();
				order.StrikePrice = condition.Options.StrikePrice.ToDouble();
			}

			order.SubmitOrder();
		}
		private void ProcessRegisterMessage(OrderRegisterMessage regMsg)
		{
			if (regMsg.TimeInForce != TimeInForce.PutInQueue && regMsg.TimeInForce != null)
				throw new ArgumentException(LocalizedStrings.Str1867Params.Put(regMsg.TimeInForce));

			var condition = (SmartComOrderCondition)regMsg.Condition;

			_wrapper.RegisterOrder(
				regMsg.PortfolioName, (string)regMsg.SecurityId.Native, regMsg.Side == Sides.Buy ? SmartOrderAction.Buy : SmartOrderAction.Sell,
				regMsg.GetSmartOrderType(), regMsg.TillDate == null || regMsg.TillDate == DateTimeOffset.MaxValue ? SmartOrderValidity.Gtc : SmartOrderValidity.Day,
				(double)regMsg.Price, (int)regMsg.Volume, condition != null ? (double)(condition.StopPrice ?? 0) : 0, (int)regMsg.TransactionId);
		}
		private void ProcessOrderRegisterMessage(OrderRegisterMessage message)
		{
			var transactionId = message.TransactionId.To<string>();
			var lmaxSecId = (long)message.SecurityId.Native;

			LmaxTimeInForce tif;

			switch (message.TimeInForce)
			{
				case TimeInForce.PutInQueue:
				case null:
					tif = message.TillDate == null || message.TillDate == DateTimeOffset.MaxValue ? LmaxTimeInForce.GoodTilCancelled : LmaxTimeInForce.GoodForDay;
					break;
				case TimeInForce.MatchOrCancel:
					tif = LmaxTimeInForce.FillOrKill;
					break;
				case TimeInForce.CancelBalance:
					tif = LmaxTimeInForce.ImmediateOrCancel;
					break;
				default:
					throw new ArgumentOutOfRangeException();
			}

			var volume = message.Volume;

			if (message.Side == Sides.Sell)
				volume = -volume;

			switch (message.OrderType)
			{
				case OrderTypes.Limit:
					_session.PlaceLimitOrder(new LimitOrderSpecification(transactionId, lmaxSecId, message.Price, volume, tif), id => { }, CreateErrorHandler("PlaceLimitOrder"));
					break;
				case OrderTypes.Market:
					_session.PlaceMarketOrder(new MarketOrderSpecification(transactionId, lmaxSecId, volume, tif), id => { }, CreateErrorHandler("PlaceMarketOrder"));
					break;
				case OrderTypes.Conditional:
					var condition = (LmaxOrderCondition)message.Condition;
					_session.PlaceStopOrder(new StopOrderSpecification(transactionId, lmaxSecId, message.Price, volume, tif, condition.StopLossOffset, condition.TakeProfitOffset), id => { }, CreateErrorHandler("PlaceStopOrder"));
					break;
				case OrderTypes.Repo:
				case OrderTypes.ExtRepo:
				case OrderTypes.Rps:
				case OrderTypes.Execute:
				case null:
					throw new NotSupportedException(LocalizedStrings.Str1849Params.Put(message.OrderType));
				default:
					throw new ArgumentOutOfRangeException(nameof(message), message.OrderType, LocalizedStrings.Str1600);
			}
		}
示例#6
0
        /// <summary>
        /// Copy the message into the <paramref name="destination" />.
        /// </summary>
        /// <param name="destination">The object, to which copied information.</param>
        public void CopyTo(OrderRegisterMessage destination)
        {
            base.CopyTo(destination);

            destination.Price         = Price;
            destination.Volume        = Volume;
            destination.VisibleVolume = VisibleVolume;
            destination.Side          = Side;
            destination.TillDate      = TillDate;
            destination.TimeInForce   = TimeInForce;
            destination.IsMarketMaker = IsMarketMaker;
            destination.IsMargin      = IsMargin;
            destination.Slippage      = Slippage;
            destination.IsManual      = IsManual;
        }
示例#7
0
 /// <summary>
 /// Преобразовать <see cref="OrderRegisterMessage"/> в <see cref="ExecutionMessage"/>.
 /// </summary>
 /// <param name="message"><see cref="OrderRegisterMessage"/></param>
 /// <returns><see cref="ExecutionMessage"/></returns>
 public static ExecutionMessage ToExecutionMessage(this OrderRegisterMessage message)
 {
     return(new ExecutionMessage
     {
         SecurityId = message.SecurityId,
         OriginalTransactionId = message.TransactionId,
         OrderType = message.OrderType,
         Price = message.Price,
         Volume = message.Volume,
         Balance = message.Volume,
         Side = message.Side,
         PortfolioName = message.PortfolioName,
         ExecutionType = ExecutionTypes.Order,
         Condition = message.Condition,
         UserOrderId = message.UserOrderId,
     });
 }
		private void ProcessOrderRegister(OrderRegisterMessage regMsg)
		{
			var order = _httpClient.RegisterOrder(regMsg.Side, regMsg.Price, regMsg.Volume);

			_orderInfo.Add(order.Id, RefTuple.Create(regMsg.TransactionId, regMsg.Volume));

			_hasActiveOrders = true;

			SendOutMessage(new ExecutionMessage
			{
				ExecutionType = ExecutionTypes.Order,
				OrderId = order.Id,
				ServerTime = order.Time.ApplyTimeZone(TimeZoneInfo.Utc),
				OriginalTransactionId = regMsg.TransactionId,
				OrderState = OrderStates.Active,
			});
		}
示例#9
0
        /// <summary>
        /// Copy the message into the <paramref name="destination" />.
        /// </summary>
        /// <param name="destination">The object, to which copied information.</param>
        public void CopyTo(OrderRegisterMessage destination)
        {
            base.CopyTo(destination);

            destination.Price          = Price;
            destination.Volume         = Volume;
            destination.VisibleVolume  = VisibleVolume;
            destination.Side           = Side;
            destination.TillDate       = TillDate;
            destination.TimeInForce    = TimeInForce;
            destination.IsMarketMaker  = IsMarketMaker;
            destination.Slippage       = Slippage;
            destination.IsManual       = IsManual;
            destination.MinOrderVolume = MinOrderVolume;
            destination.PositionEffect = PositionEffect;
            destination.PostOnly       = PostOnly;
            destination.Leverage       = Leverage;
        }
		private void ProcessOrderRegister(OrderRegisterMessage message)
		{
			var draft = _client.CreateDraft();

			draft.Comments = message.Comment;
			draft.Account = _client.Accounts[message.PortfolioName];
			draft.Contract = _client.Contracts[message.SecurityId.SecurityCode];
			draft.Route = _client.Routes[message.SecurityId.BoardCode];
			draft.Side = message.Side.ToOec();
			draft.Quantity = (int)message.Volume;

			draft.ClearExtData();
			draft.Price = (double)message.Price;
			draft.Price2 = 0;

			if (message.OrderType == OrderTypes.Conditional)
			{
				var cond = (OpenECryOrderCondition)message.Condition;
				var stopPrice = (double)(cond.StopPrice ?? 0);

				switch (cond.AssetType)
				{
					case OpenECryOrderCondition.AssetTypeEnum.All:
						switch (cond.StopType)
						{
							case OpenECryStopType.StopLimit:
								draft.Type = OrderType.StopLimit;
								draft.Price2 = draft.Price;
								draft.Price = stopPrice;
								break;
							case OpenECryStopType.StopMarket:
								draft.Type = OrderType.Stop;
								draft.Price = stopPrice;
								draft.Price2 = 0;
								break;
							default:
								throw new ArgumentException(LocalizedStrings.Str2553Params.Put(cond.StopType));
						}
						break;

					case OpenECryOrderCondition.AssetTypeEnum.Equity:
					case OpenECryOrderCondition.AssetTypeEnum.Future:

						//if (!draft.Contract.IsEquityAsset && !draft.Contract.IsFuture)
						//	throw new NotSupportedException(LocalizedStrings.Str2554);

						switch (cond.StopType)
						{
							case OpenECryStopType.TrailingStopLimit:
								draft.Type = OrderType.TrailingStopLimit;
								draft.Price2 = draft.Price;
								draft.Price = stopPrice;
								break;
							case OpenECryStopType.TrailingStopMarket:
								draft.Type = OrderType.TrailingStopLoss;
								draft.Price = stopPrice;
								draft.Price2 = 0;
								break;
							default:
								throw new ArgumentException(LocalizedStrings.Str2553Params.Put(cond.StopType));
						}

						if (cond.AssetType == OpenECryOrderCondition.AssetTypeEnum.Equity)
							draft.SetEquityTSData((double)(cond.Delta ?? 0), cond.IsPercentDelta ?? false, cond.TriggerType.ToOec());
						else
							draft.SetTSData((double)(cond.ReferencePrice ?? 0), (double)(cond.Delta ?? 0));

						break;
					default:
						throw new ArgumentException(LocalizedStrings.Str2555Params.Put(cond.AssetType));
				}
			}
			else
			{
				draft.Type = message.OrderType.ToOec();
			}

			draft.Flags = OrderFlags.None;
			draft.Start = OEC.API.Version.MinimumStart;
			draft.End = OEC.API.Version.MaximumEnd;

			switch (message.TimeInForce)
			{
				case null:
				case TimeInForce.PutInQueue:
				{
					draft.Flags = OrderFlags.GTC;

					if (message.ExpiryDate != null && message.ExpiryDate.Value.DateTime != DateTime.Today)
						draft.End = message.ExpiryDate.Value.UtcDateTime;

					break;
				}
				case TimeInForce.MatchOrCancel:
					draft.Flags = OrderFlags.FOK;
					break;
				case TimeInForce.CancelBalance:
					draft.Flags = OrderFlags.IOC;
					break;
				default:
					throw new ArgumentOutOfRangeException();
			}

			if (message.VisibleVolume != null && message.VisibleVolume < message.Volume)
				draft.SetIcebergData((int)message.VisibleVolume.Value);

			var invalid = draft.GetInvalidParts();
			if (invalid != OrderParts.None)
				throw new OpenECryException(LocalizedStrings.Str2556Params.Put(invalid));

			var newOrder = _client.SendOrder(draft);
			_orderTransactions.Add(newOrder, message.TransactionId);
			ProcessOrder(newOrder, message.TransactionId);
		}
示例#11
0
		public static IBSocket SendOrderExpiration(this IBSocket socket, OrderRegisterMessage msg)
		{
			if (msg == null)
				throw new ArgumentNullException("msg");

			if (msg.OrderType != OrderTypes.Conditional)
			{
				switch (msg.TimeInForce)
				{
					case TimeInForce.PutInQueue:
					case null:
					{
						if (msg.TillDate == null || msg.TillDate == DateTimeOffset.MaxValue)
							return socket.Send("GTC");
						else if (msg.TillDate.Value.DateTime != DateTime.Today)
							return socket.Send("GTD");
						else
							return socket.Send("DAY");
					}
					case TimeInForce.MatchOrCancel:
						return socket.Send("FOK");
					case TimeInForce.CancelBalance:
						return socket.Send("IOC");
					default:
						throw new ArgumentOutOfRangeException();
				}
			}
			else if (msg.OrderType == OrderTypes.Conditional)
			{
				var ibCon = (IBOrderCondition)msg.Condition;

				return socket.Send(ibCon.IsMarketOnOpen ? "OPG" : "DAY");
			}
			else
				throw new ArgumentException(LocalizedStrings.Str2501Params.Put(msg.Type), "msg");
		}
示例#12
0
		public int RegisterOrder(OrderRegisterMessage message)
		{
			var marketTime = _ad.SessionTime;

			var secCode = message.SecurityId.SecurityCode;
			var account = message.PortfolioName.AccountFromPortfolioName(); // Портфель
			var placeCode = _adapter.SecurityClassInfo.GetSecurityClass(message.SecurityType, message.SecurityId.BoardCode);
			var endDate = message.TillDate == null || message.TillDate == DateTimeOffset.MaxValue
				? marketTime.Date + TimeHelper.LessOneDay
				: message.TillDate.Value.ToLocalTime(TimeHelper.Moscow); // Срок действия поручения.
			var maxEndDate = DateTime.Now + TimeSpan.FromDays(365);
			if (endDate > maxEndDate)
				endDate = maxEndDate;
			var comments = message.TransactionId.To<string>(); // Комментарий.
			var currency = message.Currency == null || message.Currency == CurrencyTypes.RUB ? 
				"RUR" : message.Currency.ToString();//_securityCurrencies[message.SecurityId.SecurityCode]; // Валюта цены.
			var buySell = message.Side.ToAlfaDirect(); // Покупка/Продажа
			var quantity = (int)message.Volume; // Количество.
			var price = message.Price; // Цена.

			int id;

			_adapter.AddInfoLog("Register: {0} {1}/{2} tran={3}  {4} {5}@{6}, mtime={7}, cur={8}", account, secCode, placeCode, comments, buySell, quantity, price, marketTime, currency);

			if (placeCode == null)
				throw new InvalidOperationException(LocalizedStrings.Str2274Params.Put(message.TransactionId));

			switch (message.OrderType)
			{
				case OrderTypes.Limit:
					id = _ad.CreateLimitOrder(account, placeCode, secCode, endDate, comments, currency, buySell, quantity, (double)price, null, null, null, null, null, "Y", null, null, null, null, null, null, null, null, null, null, -1);
					break;
				case OrderTypes.Market:
					throw new InvalidOperationException(LocalizedStrings.Str2275);
				case OrderTypes.Conditional:
				{
					var condition = (AlfaOrderCondition)message.Condition;

					if (condition.TargetPrice != 0)
						id = _ad.CreateStopOrder(account, placeCode, secCode, endDate, comments, currency, buySell, quantity, (double)condition.StopPrice, (double)condition.Slippage, condition.TargetPrice, -1);
					else if (condition.Level != 0)
						id = _ad.CreateTrailingOrder(account, placeCode, secCode, endDate, comments, currency, buySell, quantity, (double)condition.StopPrice, (double)condition.Level, (double)condition.Slippage, -1);
					else
						id = _ad.CreateStopOrder(account, placeCode, secCode, endDate, comments, currency, buySell, quantity, (double)condition.StopPrice, (double)condition.Slippage, null, -1);

					break;
				}
				case OrderTypes.Repo:
				case OrderTypes.ExtRepo:
				case OrderTypes.Rps:
				case OrderTypes.Execute:
				case null:
					throw new NotSupportedException(LocalizedStrings.Str1601Params.Put(message.OrderType, message.TransactionId));
				default:
					throw new ArgumentOutOfRangeException();
			}

			if (id == 0)
				ThrowInError(tagStateCodes.stcClientError, LocalizedStrings.Str2276Params.Put(message.TransactionId, _ad.LastResultMsg));

			return id;
		}
		/// <summary>
		/// Записать данные по условию заявки.
		/// </summary>
		/// <param name="writer">Писатель FIX данных.</param>
		/// <param name="regMsg">Сообщение, содержащее информацию для регистрации заявки.</param>
		protected override void WriteOrderCondition(IFixWriter writer, OrderRegisterMessage regMsg)
		{
			writer.WriteOrderCondition((QuikOrderCondition)regMsg.Condition, DateTimeFormat);
		}
		private bool NeedCheckVolume(OrderRegisterMessage message, decimal quotesVolume)
		{
			if (!_settings.IncreaseDepthVolume)
				return false;

			var orderSide = message.Side;
			var price = message.Price;

			var quotes = orderSide == Sides.Buy ? _asks : _bids;

			var quote = quotes.FirstOrDefault();

			if (quote.Value == null)
				return false;

			var bestPrice = quote.Key;

			return (orderSide == Sides.Buy ? price >= bestPrice : price <= bestPrice)
				&& quotesVolume <= message.Volume;
		}
		private IEnumerable<ExecutionMessage> IncreaseDepthVolume(OrderRegisterMessage message, DateTimeOffset serverTime, decimal quotesVolume)
		{
			var leftVolume = (message.Volume - quotesVolume) + 1;
			var orderSide = message.Side;

			var quotes = orderSide == Sides.Buy ? _asks : _bids;
			var quote = quotes.LastOrDefault();

			if (quote.Value == null)
				yield break;

			var side = orderSide.Invert();

			var lastVolume = quote.Value.Second.Volume;
			var lastPrice = quote.Value.Second.Price;

			while (leftVolume > 0 && lastPrice != 0)
			{
				lastVolume *= 2;
				lastPrice += GetPriceStep() * (side == Sides.Buy ? -1 : 1);

				leftVolume -= lastVolume;

				yield return CreateMessage(message.LocalTime, serverTime, side, lastPrice, lastVolume);
			}
		}
示例#16
0
        // create and send message
        private void SendCommand(Dictionary<string, object> actions)
        {

            Message message = null;

            switch (actions["ACTION"].ToString())
            {
                case "NEW_ORDER":
                    {
                        message = new OrderRegisterMessage()
                        {
                            SecurityId = _securities.FirstOrDefault(s => s.Code == actions["SECCODE"].ToString() &&
                                                                         s.Class == actions["CLASSCODE"].ToString()).ToSecurityId(),
                            ClientCode = actions["CLIENTCODE"].ToString(),
                            PortfolioName = actions["ACCOUNT"].ToString(),
                            OrderType = (OrderTypes)actions["TYPE"],
                            Price = (decimal)actions["PRICE"],
                            Side = (Sides)actions["OPERATION"],
                            Volume = (decimal)actions["QUANTITY"],
                            TransactionId = _transAdapter.TransactionIdGenerator.GetNextId(),
                            Comment = actions["COMMENT"].ToString()
                        };
                    }
                    break;
                case "KILL_ORDER":
                    {
                        message = new OrderCancelMessage()
                        {
                            OrderId = (long)actions["ORDER_KEY"],
                            OriginalTransactionId = (long)actions["ORIGINAL_TRANS_ID"],
                            TransactionId = _transAdapter.TransactionIdGenerator.GetNextId(),
                        };
                    }
                    break;
                case "KILL_ALL_ORDERS":
                    {
                        message = new OrderGroupCancelMessage()
                        {
                            TransactionId = _transAdapter.TransactionIdGenerator.GetNextId()
                        };
                    }
                    break;
                case "MOVE_ORDERS":
                    {
                        //TODO
                    }
                    break;
                case "REGISTER_SECURITY":
                    {
                        //TODO
                    }
                    break;
                case "UNREGISTER_SECURITY":
                    {
                        //TODO
                    }
                    break;
                case "REGISTER_TRADES":
                    {
                        //TODO
                    }
                    break;
                case "UNREGISTER_TRADES":
                    {
                        //TODO
                    }
                    break;
                case "REGISTER_MARKETDEPTH":
                    {
                        //TODO
                    }
                    break;
                case "UNREGISTER_MARKETDEPTH":
                    {
                        //TODO
                    }
                    break;

                default:
                    break;
            }

            if (message != null)
                _transAdapter.SendInMessage(message);
        }
		private void RegisterOrder(OrderRegisterMessage message)
		{
			if (message == null)
				throw new ArgumentNullException(nameof(message));

			if (message.OrderType == OrderTypes.Execute)
			{
				var ibCon = (IBOrderCondition)message.Condition;

				if (ibCon == null)
					throw new ArgumentException(LocalizedStrings.Str2514Params.Put(message.TransactionId), nameof(message));

				ExerciseOptions(message, ibCon.OptionExercise.IsExercise, message.Volume, message.PortfolioName, ibCon.OptionExercise.IsOverride);
				return;
			}

			var version = (Session.ServerVersion < ServerVersions.V44) ? ServerVersions.V27 : ServerVersions.V43;

			//var security = SessionHolder.Securities[regMsg.SecurityId];

			ProcessRequest(RequestMessages.RegisterOrder, 0, version,
				socket =>
				{
					socket.Send((int)message.TransactionId);

					socket
						.SendContractId(message.SecurityId)
						.SendSecurity(message)
						.SendIf(ServerVersions.V68, s => socket.Send(message.Class))
						.SendSecurityId(message.SecurityId);

					var condition = (IBOrderCondition)message.Condition ?? new IBOrderCondition();

					socket
						.SendSide(message.Side)
						.SendQuantity(message.Volume)
						.SendOrderType(message.OrderType.Value, condition.ExtendedType)
						.Send(message.Price)
						.Send(condition.StopPrice)
						.SendOrderExpiration(message)
						.Send(condition.Oca.Group)
						.SendPortfolio(message.PortfolioName)
						.Send(condition.IsOpenOrClose ? "O" : "C")
						.Send((int)condition.Origin)
						.Send(message.Comment)
						.Send(condition.Transmit)
						.SendIf(ServerVersions.V4, s => s.Send(condition.ParentId))
						.SendIf(ServerVersions.V5, s =>
						{
							socket
								.Send(condition.BlockOrder)
								.Send(condition.SweepToFill)
								.Send(message.VisibleVolume)
								.Send((int)condition.TriggerMethod);

							if (socket.ServerVersion < ServerVersions.V38)
							{
								//will never happen
								socket.Send(false);
							}
							else
							{
								socket.Send(condition.OutsideRth);
							}
						})
						.SendIf(ServerVersions.V7, s => socket.Send(condition.Hidden));

					// TODO
					WeightedIndexSecurity indexSecurity = null;//security as WeightedIndexSecurity;

					if (indexSecurity != null)
					{
						// Send combo legs for BAG requests
						if (socket.ServerVersion >= ServerVersions.V8)
							socket.SendCombo(indexSecurity, condition);

						// Send order combo legs for BAG requests
						if (socket.ServerVersion >= ServerVersions.V57)
						{
							var legs = condition.Combo.Legs.ToArray();

							socket.Send(legs.Length);

							foreach (var leg in legs)
								socket.Send(leg);
						}

						if (socket.ServerVersion >= ServerVersions.V57)
						{
							var comboParams = condition.SmartRouting.ComboParams.ToArray();

							socket.Send(comboParams.Length);

							foreach (var comboParam in comboParams)
							{
								socket
									.Send(comboParam.Item1)
									.Send(comboParam.Item2);
							}
						}
					}

					if (socket.ServerVersion >= ServerVersions.V9)
					{
						socket.Send(string.Empty);
					}

					if (socket.ServerVersion >= ServerVersions.V10)
					{
						socket.Send(condition.SmartRouting.DiscretionaryAmount);
					}

					if (condition.GoodAfterTime == null || socket.ServerVersion < ServerVersions.V11)
						socket.Send(string.Empty);
					else
						socket.Send(condition.GoodAfterTime, IBSocketHelper.TimeFormat);

					if (message.TillDate == null || message.TillDate == DateTimeOffset.MaxValue || socket.ServerVersion < ServerVersions.V12)
						socket.Send(string.Empty);
					else
						socket.Send(message.TillDate.Value, IBSocketHelper.TimeFormat);

					if (socket.ServerVersion >= ServerVersions.V13)
					{
						socket
							.Send(condition.FinancialAdvisor.Group)
							.SendFinancialAdvisor(condition.FinancialAdvisor.Allocation)
							.Send(condition.FinancialAdvisor.Percentage)
							.Send(condition.FinancialAdvisor.Profile);
					}

					if (socket.ServerVersion >= ServerVersions.V18)
					{
						// institutional short sale slot fields.
						socket.SendShortSale(condition.ShortSale, true);
					}

					if (socket.ServerVersion >= ServerVersions.V19)
					{
						socket.Send((int)(condition.Oca.Type ?? 0));

						if (socket.ServerVersion < ServerVersions.V38)
						{
							//will never happen
							socket.Send(false);
						}

						socket
							.SendAgent(condition.Agent)
							.Send(condition.Clearing.SettlingFirm)
							.Send(condition.AllOrNone)
							.Send(condition.MinVolume)
							.Send(condition.PercentOffset)
							.Send(condition.SmartRouting.ETradeOnly)
							.Send(condition.SmartRouting.FirmQuoteOnly)
							.Send(condition.SmartRouting.NbboPriceCap)
							.Send((int?)condition.AuctionStrategy)
							.Send(condition.StartingPrice)
							.Send(condition.StockRefPrice)
							.Send(condition.Delta);

						decimal? lower = null;
						decimal? upper = null;

						if (socket.ServerVersion == ServerVersions.V26)
						{
							// Volatility orders had specific watermark price attribs in server version 26
							var isVol = condition.ExtendedType == IBOrderCondition.ExtendedOrderTypes.Volatility;
							lower = isVol ? condition.StockRangeLower : (decimal?)null;
							upper = isVol ? condition.StockRangeUpper : (decimal?)null;
						}

						socket
							.Send(lower)
							.Send(upper);
					}

					if (socket.ServerVersion >= ServerVersions.V22)
					{
						socket.Send(condition.OverridePercentageConstraints);
					}

					if (socket.ServerVersion >= ServerVersions.V26)
					{
						socket
							.Send(condition.Volatility.Volatility)
							.Send((int?)condition.Volatility.VolatilityTimeFrame)
							.SendDeltaNeutral(condition)
							.Send(condition.Volatility.ContinuousUpdate ? 1 : 0);

						if (socket.ServerVersion == ServerVersions.V26)
						{
							var isVol = condition.ExtendedType == IBOrderCondition.ExtendedOrderTypes.Volatility;

							socket
								.Send(isVol ? condition.StockRangeLower : (decimal?)null)
								.Send(isVol ? condition.StockRangeUpper : (decimal?)null);
						}

						socket.Send(condition.Volatility.IsAverageBestPrice);
					}

					if (socket.ServerVersion >= ServerVersions.V30)
					{
						// TRAIL_STOP_LIMIT stop price
						socket.Send(condition.TrailStopPrice);
					}

					if (socket.ServerVersion >= ServerVersions.V62)
					{
						socket.Send(condition.TrailStopVolumePercentage);
					}

					//Scale Orders require server version 35 or higher.
					if (socket.ServerVersion >= ServerVersions.V35)
					{
						if (socket.ServerVersion >= ServerVersions.V40)
						{
							socket
								.Send(condition.Scale.InitLevelSize)
								.Send(condition.Scale.SubsLevelSize);
						}
						else
						{
							socket
								.Send(string.Empty)
								.Send(condition.Scale.InitLevelSize);
						}

						socket.Send(condition.Scale.PriceIncrement);
					}

					if (socket.ServerVersion >= ServerVersions.V60 && condition.Scale.PriceIncrement > 0)
					{
						socket
							.Send(condition.Scale.PriceAdjustValue)
							.Send(condition.Scale.PriceAdjustInterval)
							.Send(condition.Scale.ProfitOffset)
							.Send(condition.Scale.AutoReset)
							.Send(condition.Scale.InitPosition)
							.Send(condition.Scale.InitFillQty)
							.Send(condition.Scale.RandomPercent);
					}

					if (socket.ServerVersion >= ServerVersions.V69)
					{
						socket
							.Send(condition.Scale.Table)
							.Send(condition.Active.Start, IBSocketHelper.TimeFormat)
							.Send(condition.Active.Stop, IBSocketHelper.TimeFormat);
					}

					socket.SendHedge(condition);

					if (socket.ServerVersion >= ServerVersions.V56)
					{
						socket.Send(condition.SmartRouting.OptOutSmartRouting);
					}

					if (socket.ServerVersion >= ServerVersions.V39)
					{
						socket
							.SendPortfolio(condition.Clearing.Portfolio)
							.SendIntent(condition.Clearing.Intent);
					}

					if (socket.ServerVersion >= ServerVersions.V44)
						socket.Send(condition.SmartRouting.NotHeld);

					if (socket.ServerVersion >= ServerVersions.V40)
					{
						//if (contract.UnderlyingComponent != null)
						//{
						//	UnderlyingComponent underComp = contract.UnderlyingComponent;
						//	send(true);
						//	send(underComp.ContractId);
						//	send(underComp.Delta);
						//	send(underComp.Price);
						//}
						//else
						{
							socket.Send(false);
						}
					}

					if (socket.ServerVersion >= ServerVersions.V41)
					{
						var algoStrategy = condition.Algo.Strategy;
						socket.Send(algoStrategy);

						var algoParams = condition.Algo.Params.ToArray();

						if (!algoStrategy.IsEmpty())
						{
							if (algoParams == null)
							{
								socket.Send(0);
							}
							else
							{
								socket.Send(algoParams.Length);

								foreach (var param in algoParams)
								{
									socket
										.Send(param.Item1)
										.Send(param.Item2);
								}
							}
						}
					}

					if (socket.ServerVersion >= ServerVersions.V71)
					{
						socket.Send(condition.AlgoId);
					}

					if (socket.ServerVersion >= ServerVersions.V36)
					{
						socket.Send(condition.WhatIf);
					}

					// send orderMiscOptions parameter
					if (socket.ServerVersion >= ServerVersions.V70)
					{
						socket.Send(condition.MiscOptions != null
							? condition.MiscOptions.Select(t => t.Item1 + "=" + t.Item2).Join(";")
							: string.Empty);
					}

					if (socket.ServerVersion >= ServerVersions.V73)
					{
						socket.Send(condition.Solicited);
					}

					if (socket.ServerVersion >= ServerVersions.V76)
					{
						socket.Send(condition.RandomizeSize);
						socket.Send(condition.RandomizePrice);
					}
				});
		}
		private void ProcessRegisterMessage(OrderRegisterMessage regMsg)
		{
			OrderParams orderParams;

			switch (regMsg.OrderType)
			{
				case OrderTypes.Limit:
				{
					orderParams = FillParams(regMsg, new OrderParams
					{
						Price = (double)regMsg.Price,
						OrderType = Constants.ORDER_TYPE_LIMIT,
					});
					break;
				}

				case OrderTypes.Market:
				{
					orderParams = FillParams(regMsg, new OrderParams
					{
						OrderType = Constants.ORDER_TYPE_MARKET,
					});
					break;
				}

				case OrderTypes.Conditional:
				{
					var condition = (RithmicOrderCondition)regMsg.Condition;

					var triggerPrice = condition.TriggerPrice;

					if (triggerPrice == null)
						throw new InvalidOperationException(LocalizedStrings.Str3494Params.Put(regMsg.TransactionId));

					if (regMsg.Price == 0)
					{
						orderParams = FillParams(regMsg, new OrderParams
						{
							TriggerPrice = (double)triggerPrice,
							OrderType = Constants.ORDER_TYPE_STOP_MARKET,
						});
					}
					else
					{
						orderParams = FillParams(regMsg, new OrderParams
						{
							TriggerPrice = (double)triggerPrice,
							Price = (double)regMsg.Price,
							OrderType = Constants.ORDER_TYPE_STOP_LIMIT,
						});
					}

					break;
				}
				case OrderTypes.Repo:
				case OrderTypes.ExtRepo:
				case OrderTypes.Rps:
				case OrderTypes.Execute:
					throw new NotSupportedException(LocalizedStrings.Str3495Params.Put(regMsg.TransactionId, regMsg.OrderType));
				default:
					throw new ArgumentOutOfRangeException();
			}

			_client.Session.sendOrderList(new List<OrderParams> { orderParams }.AsReadOnly());
		}
		/// <summary>
		/// Create a copy of <see cref="OrderRegisterMessage"/>.
		/// </summary>
		/// <returns>Copy.</returns>
		public override Message Clone()
		{
			var clone = new OrderRegisterMessage(Type)
			{
				Comment = Comment,
				Condition = Condition,
				TillDate = TillDate,
				OrderType = OrderType,
				PortfolioName = PortfolioName,
				Price = Price,
				RepoInfo = RepoInfo.CloneNullable(),
				RpsInfo = RpsInfo.CloneNullable(),
				SecurityId = SecurityId,
				//SecurityType = SecurityType,
				Side = Side,
				TimeInForce = TimeInForce,
				TransactionId = TransactionId,
				VisibleVolume = VisibleVolume,
				Volume = Volume,
				Currency = Currency,
				UserOrderId = UserOrderId,
				ClientCode = ClientCode,
				BrokerCode = BrokerCode,
			};

			CopyTo(clone);

			return clone;
		}
		private OrderParams FillParams(OrderRegisterMessage regMsg, OrderParams orderParams)
		{
			if (regMsg == null)
				throw new ArgumentNullException(nameof(regMsg));

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

			orderParams.Symbol = regMsg.SecurityId.SecurityCode;
			orderParams.Exchange = regMsg.SecurityId.BoardCode;
			orderParams.Account = _accounts[regMsg.PortfolioName];
			orderParams.BuySellType = regMsg.Side.ToRithmic();
			orderParams.UserMsg = regMsg.Comment;
			orderParams.UserTag = regMsg.UserOrderId;
			orderParams.Qty = (int)regMsg.Volume;
			orderParams.Tag = regMsg.TransactionId.To<string>();
			orderParams.Duration = regMsg.TimeInForce.ToRithmic(regMsg.ExpiryDate);
			orderParams.EntryType = Constants.ORDER_ENTRY_TYPE_AUTO;

			return orderParams;
		}
		/// <summary>
		/// Call the exerciseOptions() method to exercise options. “SMART” is not an allowed exchange in exerciseOptions() calls, and that TWS does a moneyness request for the position in question whenever any API initiated exercise or lapse is attempted.
		/// </summary>
		/// <param name="message">this structure contains a description of the contract to be exercised.  If no multiplier is specified, a default of 100 is assumed.</param>
		/// <param name="isExercise">this can have two values: 1 = specifies exercise 2 = specifies lapse.</param>
		/// <param name="volume">the number of contracts to be exercised.</param>
		/// <param name="portfolioName">specifies whether your setting will override the system's natural action. For example, if your action is "exercise" and the option is not in-the-money, by natural action the option would not exercise. If you have override set to "yes" the natural action would be overridden and the out-of-the money option would be exercised. Values are: 0 = no 1 = yes.</param>
		/// <param name="isOverride">specifies whether your setting will override the system's natural action. For example, if your action is "exercise" and the option is not in-the-money, by natural action the option would not exercise. If you have override set to "yes" the natural action would be overridden and the out-of-the money option would be exercised. Values are: 0 = no 1 = yes.</param>
		private void ExerciseOptions(OrderRegisterMessage message, bool isExercise, decimal volume, string portfolioName, bool isOverride)
		{
			//var option = SessionHolder.Securities[regMsg.SecurityId];

			ProcessRequest(RequestMessages.ExerciseOptions, ServerVersions.V21, ServerVersions.V2, socket =>
				socket
					.Send(message.TransactionId)
					.SendIf(ServerVersions.V68, s => socket.SendContractId(message.SecurityId))
					.SendSecurity(message, false)
					.SendIf(ServerVersions.V68, s => socket.Send(message.Class))
					.Send(isExercise ? 1 : 2)
					.Send((int)volume)
					.Send(portfolioName)
					.Send(isOverride));
		}
		private void ProcessRegisterMessage(OrderRegisterMessage regMsg)
		{
			DateTime? expDate;

			if (regMsg.TillDate == null || regMsg.TillDate == DateTimeOffset.MaxValue)
				expDate = null;
			else
				expDate = regMsg.TillDate.Value.ToLocalTime(TimeHelper.Moscow);

			BaseCommandMessage command;

			switch (regMsg.OrderType)
			{
				case OrderTypes.Limit:
				case OrderTypes.Market:
				{
					command = new NewOrderMessage
					{
						ByMarket = regMsg.OrderType == OrderTypes.Market,
						Client = regMsg.PortfolioName,
						Quantity = regMsg.Volume.To<int>(),
						Unfilled = regMsg.TimeInForce.ToTransaq(),
						BuySell = regMsg.Side.ToTransaq(),
						Price = regMsg.Price,
						SecId = (int)regMsg.SecurityId.Native,
						ExpDate = expDate,
						BrokerRef = regMsg.Comment,
						Hidden = (int)(regMsg.Volume - (regMsg.VisibleVolume ?? regMsg.Volume)),
					};

					break;
				}
				case OrderTypes.Conditional:
				{
					var cond = (TransaqOrderCondition)regMsg.Condition;

					if (cond.Type == TransaqOrderConditionTypes.Algo)
					{
						command = new NewCondOrderMessage
						{
							ByMarket = regMsg.OrderType == OrderTypes.Market,
							Client = regMsg.PortfolioName,
							Quantity = regMsg.Volume.To<int>(),
							BuySell = regMsg.Side.ToTransaq(),
							Price = regMsg.Price,
							SecId = (int)regMsg.SecurityId.Native,
							CondType = cond.AlgoType ?? TransaqAlgoOrderConditionTypes.None,
							CondValue = cond.AlgoValue ?? 0m,
							ValidAfterType = cond.AlgoValidAfterType ?? TransaqAlgoOrderValidTypes.TillCancelled,
							ValidAfter = cond.AlgoValidAfter.ToDt(),
							ValidBeforeType = cond.AlgoValidBeforeType ?? TransaqAlgoOrderValidTypes.TillCancelled,
							ValidBefore = cond.AlgoValidBefore.ToDt(),
							ExpDate = expDate,
							BrokerRef = regMsg.Comment,
							Hidden = (int)(regMsg.Volume - (regMsg.VisibleVolume ?? regMsg.Volume)),
						};
					}
					else// if (regMsg.Condition is TransaqOrderCondition)
					{
						if (!cond.CheckConditionUnitType())
							throw new InvalidOperationException(LocalizedStrings.Str3549);

						var stopOrder = new NewStopOrderMessage
						{
							SecId = (int)regMsg.SecurityId.Native,
							Client = regMsg.PortfolioName,
							BuySell = regMsg.Side.ToTransaq(),
							LinkedOrderNo = cond.LinkedOrderId.To<string>(),
							ExpDate = expDate,
							ValidFor = expDate?.ToUniversalTime(),
						};

						switch (cond.Type)
						{
							case TransaqOrderConditionTypes.StopLoss:
								stopOrder.StopLoss = TransaqHelper.CreateStopLoss(cond);
								break;

							case TransaqOrderConditionTypes.TakeProfit:
								stopOrder.TakeProfit = TransaqHelper.CreateTakeProfit(cond);
								break;

							case TransaqOrderConditionTypes.TakeProfitStopLoss:
								stopOrder.StopLoss = TransaqHelper.CreateStopLoss(cond);
								stopOrder.TakeProfit = TransaqHelper.CreateTakeProfit(cond);
								break;
						}

						command = stopOrder;
					}
					//else
					//	throw new InvalidOperationException(LocalizedStrings.Str3550Params.Put(regMsg.Condition, regMsg.TransactionId));

					break;
				}
				case OrderTypes.Repo:
				{
					command = new NewRepoOrderMessage
					{
						SecId = (int)regMsg.SecurityId.Native,
						Client = regMsg.PortfolioName,
						BuySell = regMsg.Side.ToTransaq(),
						CpFirmId = regMsg.RepoInfo.Partner,
						MatchRef = regMsg.RepoInfo.MatchRef,
						BrokerRef = regMsg.Comment,
						Price = regMsg.Price,
						Quantity = regMsg.Volume.To<int>(),
						SettleCode = regMsg.RepoInfo.SettleCode,
						RefundRate = regMsg.RepoInfo.RefundRate,
						Rate = regMsg.RepoInfo.Rate,
					};

					break;
				}
				case OrderTypes.ExtRepo:
				{
					command = new NewMRepoOrderMessage
					{
						SecId = (int)regMsg.SecurityId.Native,
						Client = regMsg.PortfolioName,
						BuySell = regMsg.Side.ToTransaq(),
						CpFirmId = regMsg.RepoInfo.Partner,
						MatchRef = regMsg.RepoInfo.MatchRef,
						BrokerRef = regMsg.Comment,
						Price = regMsg.Price,
						Quantity = regMsg.Volume.To<int>(),
						SettleCode = regMsg.RepoInfo.SettleCode,
						RefundRate = regMsg.RepoInfo.RefundRate,
						Value = regMsg.RepoInfo.Value,
						Term = regMsg.RepoInfo.Term,
						Rate = regMsg.RepoInfo.Rate,
						StartDiscount = regMsg.RepoInfo.StartDiscount,
						LowerDiscount = regMsg.RepoInfo.LowerDiscount,
						UpperDiscount = regMsg.RepoInfo.UpperDiscount,
						BlockSecurities = regMsg.RepoInfo.BlockSecurities,
					};

					break;
				}
				case OrderTypes.Rps:
				{
					command = new NewRpsOrderMessage
					{
						SecId = (int)regMsg.SecurityId.Native,
						Client = regMsg.PortfolioName,
						BuySell = regMsg.Side.ToTransaq(),
						CpFirmId = regMsg.RpsInfo.Partner,
						MatchRef = regMsg.RpsInfo.MatchRef,
						BrokerRef = regMsg.Comment,
						Price = regMsg.Price,
						Quantity = regMsg.Volume.To<int>(),
						SettleCode = regMsg.RpsInfo.SettleCode,
					};

					break;
				}
				case OrderTypes.Execute:
				{
					//command = new NewReportMessage
					//{
					//	BuySell = regMsg.Side.ToTransaq(),
					//};
					//break;
					throw new NotImplementedException();
				}
				default:
					throw new ArgumentOutOfRangeException();
			}

			var result = SendCommand(command);

			_orders.Add(result.TransactionId, regMsg.TransactionId);
			_ordersTypes.Add(regMsg.TransactionId, command is NewCondOrderMessage ? OrderTypes.Limit : regMsg.OrderType);
		}