/// <summary> /// Подписаться на получение свечек. /// </summary> /// <param name="series">Серия свечек.</param> /// <param name="from">Начальная дата, с которой необходимо получать данные.</param> /// <param name="to">Конечная дата, до которой необходимо получать данные.</param> public void SubscribeCandles(CandleSeries series, DateTimeOffset from, DateTimeOffset to) { SubscribeCandles(series, from, to, TransactionIdGenerator.GetNextId()); }
public PointOfSaleServiceBuilder WithGenerator(TransactionIdGenerator generator) { this.generator = generator; return(this); }
/// <summary> /// Process <see cref="MessageAdapterWrapper.InnerAdapter"/> output message. /// </summary> /// <param name="message">The message.</param> protected override void OnInnerAdapterNewOutMessage(Message message) { if (message.IsBack) { base.OnInnerAdapterNewOutMessage(message); return; } List <Message> messages = null; List <Message> clones = null; switch (message.Type) { case MessageTypes.Connect: { var connectMsg = (ConnectMessage)message; if (connectMsg.Error == null && IsRestoreOnReconnect) { messages = new List <Message>(); lock (_sync) { messages.AddRange(_subscribers.Values.Select(p => p.Message)); messages.AddRange(_newsSubscribers.Values.Select(p => p.Message)); messages.AddRange(_pfSubscribers.Values.Select(p => p.First)); ClearSubscribers(); } if (messages.Count == 0) { messages = null; } } break; } case ExtendedMessageTypes.RestoringSubscription: { if (IsRestoreOnReconnect) { messages = new List <Message>(); lock (_sync) { messages.AddRange(_subscribers.Values.Select(p => p.Message)); messages.AddRange(_newsSubscribers.Values.Select(p => p.Message)); messages.AddRange(_pfSubscribers.Values.Select(p => p.First)); ClearSubscribers(); } if (messages.Count == 0) { messages = null; } } break; } case MessageTypes.MarketData: { if (ProcessOutMarketDataMessage((MarketDataMessage)message)) { return; } break; } case MessageTypes.CandleTimeFrame: case MessageTypes.CandlePnF: case MessageTypes.CandleRange: case MessageTypes.CandleRenko: case MessageTypes.CandleTick: case MessageTypes.CandleVolume: { clones = ReplicateMessages(message); break; } case MessageTypes.Execution: { var execMsg = (ExecutionMessage)message; switch (execMsg.ExecutionType) { case ExecutionTypes.Tick: case ExecutionTypes.OrderLog: { clones = ReplicateMessages(message); break; } } break; } case MessageTypes.News: { clones = ReplicateMessages(message); break; } } base.OnInnerAdapterNewOutMessage(message); if (clones != null) { foreach (var clone in clones) { base.OnInnerAdapterNewOutMessage(clone); } } if (messages != null) { foreach (var m in messages) { var msg = m.Clone(); msg.IsBack = true; msg.Adapter = this; if (msg is MarketDataMessage mdMsg) { mdMsg.TransactionId = TransactionIdGenerator.GetNextId(); } else if (msg is PortfolioMessage pfMsg) { pfMsg.TransactionId = TransactionIdGenerator.GetNextId(); } base.OnInnerAdapterNewOutMessage(msg); } } }
/// <summary> /// Зарегистрировать транзакцию. /// </summary> /// <param name="transaction">Транзакция.</param> public void RegisterTransaction(Transaction transaction) { if (transaction == null) { throw new ArgumentNullException(nameof(transaction)); } if (transaction.GetInstruction <long>(Transaction.TransactionId) != 0) { throw new ArgumentException(); } var transactionId = transaction.TryGetTransactionId(); if (transactionId == 0) { transactionId = TransactionIdGenerator.GetNextId(); } if (transactionId <= 0 || transactionId > uint.MaxValue) { throw new InvalidOperationException(LocalizedStrings.Str1700Params.Put(transactionId)); } FormatTransaction.SafeInvoke(transaction.SetTransactionId(transactionId)); _transactions.Add(transactionId, transaction); if (IsAsyncMode) { Api.SendAsyncTransaction(transaction.ToString()); } else { Exception error = null; // http://stocksharp.com/forum/yaf_postst2247_Oshibka-pri-kotirovanii--sinkhronnyie-tranzaktsii.aspx var execution = transaction.Message.ToExecutionMessage(); if (execution == null) { throw new ArgumentException(LocalizedStrings.Str1835, nameof(transaction)); } var isReRegistering = transaction.TransactionType == TransactionTypes.ReRegister; var isRegistering = transaction.TransactionType == TransactionTypes.Register || isReRegistering; var apiMessage = ""; try { long orderId; uint transId; OrderStatus status; var transactionTxt = transaction.ToString(); Api.SendSyncTransaction(transactionTxt, out status, out transId, out orderId, out apiMessage); var isMatchOrCancel = (transaction.Message.Type == MessageTypes.OrderRegister || transaction.Message.Type == MessageTypes.OrderReplace) && ((OrderRegisterMessage)transaction.Message).TimeInForce == TimeInForce.MatchOrCancel; if ((!isMatchOrCancel && status != OrderStatus.Accepted) || (isMatchOrCancel && !TransactionHelper.IfFOKCancelMessage(apiMessage) && orderId == 0)) { throw new InvalidOperationException(LocalizedStrings.Str1836Params.Put(transactionTxt, apiMessage)); } execution.OrderStatus = status; execution.SystemComment = apiMessage; if (isRegistering) { ProcessTransactionReply(execution, transaction, orderId, apiMessage, Codes.Success, null); } } catch (Exception ex) { var apiEx = ex as ApiException; if (isRegistering) { ProcessTransactionReply(execution, transaction, 0, apiMessage, apiEx != null ? apiEx.Code : Codes.Failed, ex); } else { execution.OrderState = OrderStates.Failed; execution.Error = apiEx ?? new ApiException(Codes.Failed, apiMessage); SendOutMessage(execution); } error = ex; } if (error != null) { error.Throw(); } } }
/// <inheritdoc /> protected override void OnInnerAdapterNewOutMessage(Message message) { long TryReplaceOriginId(long id) { if (id == 0) { return(0); } lock (_sync) return(_replaceId.TryGetValue(id, out var prevId) ? prevId : id); } var prevOriginId = 0L; var newOriginId = 0L; if (message is IOriginalTransactionIdMessage originIdMsg1) { newOriginId = originIdMsg1.OriginalTransactionId; prevOriginId = originIdMsg1.OriginalTransactionId = TryReplaceOriginId(newOriginId); } switch (message.Type) { case MessageTypes.SubscriptionResponse: { lock (_sync) { if (((SubscriptionResponseMessage)message).IsOk()) { if (_subscriptionsById.TryGetValue(prevOriginId, out var info)) { // no need send response after re-subscribe cause response was handled prev time if (_replaceId.ContainsKey(newOriginId)) { if (info.State != SubscriptionStates.Stopped) { return; } } else { ChangeState(info, SubscriptionStates.Active); } } } else { if (!_historicalRequests.Remove(prevOriginId)) { if (_subscriptionsById.TryGetAndRemove(prevOriginId, out var info)) { ChangeState(info, SubscriptionStates.Error); _replaceId.Remove(newOriginId); } } } } break; } case MessageTypes.SubscriptionOnline: { lock (_sync) { if (!_subscriptionsById.TryGetValue(prevOriginId, out var info)) { break; } if (_replaceId.ContainsKey(newOriginId)) { // no need send response after re-subscribe cause response was handled prev time if (info.State == SubscriptionStates.Online) { return; } } else { ChangeState(info, SubscriptionStates.Online); } } break; } case MessageTypes.SubscriptionFinished: { lock (_sync) { if (_replaceId.ContainsKey(newOriginId)) { return; } _historicalRequests.Remove(prevOriginId); } break; } default: { if (message is ISubscriptionIdMessage subscrMsg) { lock (_sync) { var ids = subscrMsg.GetSubscriptionIds(); if (ids.Length == 0) { if (subscrMsg.OriginalTransactionId != 0 && _historicalRequests.ContainsKey(subscrMsg.OriginalTransactionId)) { subscrMsg.SetSubscriptionIds(subscriptionId: subscrMsg.OriginalTransactionId); } } else { lock (_sync) { if (_replaceId.Count > 0) { subscrMsg.SetSubscriptionIds(ids.Select(id => _replaceId.TryGetValue2(id) ?? id).ToArray()); } } } } } break; } } base.OnInnerAdapterNewOutMessage(message); switch (message.Type) { case ExtendedMessageTypes.ReconnectingFinished: { ProcessSuspendedMessage supended = null; lock (_sync) { _replaceId.Clear(); _reMapSubscriptions.Clear(); _reMapSubscriptions.AddRange(_subscriptionsById.Values.Distinct().Select(i => { var subscription = i.Subscription.TypedClone(); subscription.TransactionId = TransactionIdGenerator.GetNextId(); _replaceId.Add(subscription.TransactionId, i.Subscription.TransactionId); this.AddInfoLog("Re-map subscription: {0}->{1} for '{2}'.", i.Subscription.TransactionId, subscription.TransactionId, i.Subscription); return((Message)subscription); })); if (_reMapSubscriptions.Count > 0) { supended = new ProcessSuspendedMessage(this); } } if (supended != null) { base.OnInnerAdapterNewOutMessage(supended); } break; } } }
/// <summary> /// Send message. /// </summary> /// <param name="message">Message.</param> public override void SendInMessage(Message message) { if (message.IsBack) { if (message.Adapter == this) { message.Adapter = null; message.IsBack = false; } else { base.SendInMessage(message); return; } } switch (message.Type) { case MessageTypes.Reset: { lock (_sync) { ClearSubscribers(); //_pendingMessages.Clear(); } base.SendInMessage(message); break; } case MessageTypes.Disconnect: { if (!IsRestoreOnReconnect) { var messages = new List <Message>(); lock (_sync) { if (_newsSubscribers.Count > 0) { messages.AddRange(_newsSubscribers.Values.Select(p => p.First)); } if (_subscribers.Count > 0) { messages.AddRange(_subscribers.Values.Select(p => p.First)); } if (_candleSubscribers.Count > 0) { messages.AddRange(_candleSubscribers.Values.Select(p => p.First)); } if (_pfSubscribers.Count > 0) { messages.AddRange(_pfSubscribers.Values.Select(p => p.First)); } ClearSubscribers(); } foreach (var m in messages) { var msg = m.Clone(); if (msg is MarketDataMessage mdMsg) { mdMsg.TransactionId = TransactionIdGenerator.GetNextId(); mdMsg.IsSubscribe = false; } else { var pfMsg = (PortfolioMessage)msg; pfMsg.TransactionId = TransactionIdGenerator.GetNextId(); pfMsg.IsSubscribe = false; } base.SendInMessage(msg); } } base.SendInMessage(message); break; } case MessageTypes.MarketData: ProcessInMarketDataMessage((MarketDataMessage)message); break; case MessageTypes.Portfolio: ProcessInPortfolioMessage((PortfolioMessage)message); break; default: base.SendInMessage(message); break; } }
/// <inheritdoc /> protected override void OnInnerAdapterNewOutMessage(Message message) { long TryReplaceOriginId(long id) { if (id == 0) { return(0); } lock (_sync) return(_replaceId.TryGetValue(id, out var prevId) ? prevId : id); } var prevOriginId = 0L; var newOriginId = 0L; if (message is IOriginalTransactionIdMessage originIdMsg1) { newOriginId = originIdMsg1.OriginalTransactionId; prevOriginId = originIdMsg1.OriginalTransactionId = TryReplaceOriginId(newOriginId); } bool UpdateSubscriptionResult(bool isOk, Func <long, Message> createReply) { HashSet <long> subscribers = null; lock (_sync) { if (isOk) { if (_subscriptionsById.TryGetValue(prevOriginId, out var info)) { // no need send response after re-subscribe cause response was handled prev time if (_replaceId.ContainsKey(newOriginId)) { if (info.State != SubscriptionStates.Stopped) { return(false); } } else { ChangeState(info, SubscriptionStates.Active); } } } else { if (!_historicalRequests.Remove(prevOriginId)) { if (_subscriptionsById.TryGetAndRemove(prevOriginId, out var info)) { ChangeState(info, SubscriptionStates.Error); _replaceId.Remove(newOriginId); _subscriptionsByKey.RemoveByValue(info); var set = new HashSet <long>(info.Subscribers.Cache); set.Remove(prevOriginId); subscribers = set; } } } } if (subscribers != null) { foreach (var subscriber in subscribers) { base.OnInnerAdapterNewOutMessage(createReply(subscriber)); } } return(true); } switch (message.Type) { case MessageTypes.MarketData: { var responseMsg = (MarketDataMessage)message; if (!UpdateSubscriptionResult(responseMsg.IsOk(), subscriber => new MarketDataMessage { OriginalTransactionId = subscriber, Error = responseMsg.Error, IsNotSupported = responseMsg.IsNotSupported, })) { return; } break; } case MessageTypes.SubscriptionOnline: { lock (_sync) { if (!_subscriptionsById.TryGetValue(prevOriginId, out var info)) { break; } if (_replaceId.ContainsKey(newOriginId)) { // no need send response after re-subscribe cause response was handled prev time if (info.State == SubscriptionStates.Online) { return; } } else { ChangeState(info, SubscriptionStates.Online); } } break; } case MessageTypes.MarketDataFinished: case MessageTypes.SecurityLookupResult: case MessageTypes.PortfolioLookupResult: case MessageTypes.OrderStatus: { lock (_sync) { if (_replaceId.ContainsKey(newOriginId)) { return; } _historicalRequests.Remove(prevOriginId); } break; } case MessageTypes.Portfolio: { var pfMsg = (PortfolioMessage)message; // reply on RegisterPortfolio subscription do not contains any portfolio info if (pfMsg.PortfolioName.IsEmpty()) { if (!UpdateSubscriptionResult(pfMsg.Error == null, subscriber => new PortfolioMessage { OriginalTransactionId = subscriber, Error = pfMsg.Error, })) { return; } } break; } default: { if (message is ISubscriptionIdMessage subscrMsg) { lock (_sync) { if (subscrMsg.OriginalTransactionId != 0 && _historicalRequests.ContainsKey(subscrMsg.OriginalTransactionId)) { subscrMsg.SetSubscriptionIds(subscriptionId: subscrMsg.OriginalTransactionId); } else { if (subscrMsg.OriginalTransactionId != 0 && _subscriptionsById.TryGetValue(subscrMsg.OriginalTransactionId, out var info)) { } else { var dataType = message.Type.ToDataType((message as CandleMessage)?.Arg ?? (message as ExecutionMessage)?.ExecutionType); var secId = GetSecurityId(dataType, (subscrMsg as ISecurityIdMessage)?.SecurityId ?? default); if (!_subscriptionsByKey.TryGetValue(Tuple.Create(dataType, secId), out info)) { break; } } subscrMsg.SetSubscriptionIds(info.Subscribers.Cache); } } } break; } } base.OnInnerAdapterNewOutMessage(message); switch (message.Type) { case ExtendedMessageTypes.ReconnectingFinished: { Message[] subscriptions; lock (_sync) { _replaceId.Clear(); subscriptions = _subscriptionsById.Values.Distinct().Select(i => { var subscription = (ISubscriptionMessage)i.Subscription.Clone(); subscription.TransactionId = TransactionIdGenerator.GetNextId(); _replaceId.Add(subscription.TransactionId, i.Subscription.TransactionId); this.AddInfoLog("Re-map subscription: {0}->{1} for '{2}'.", i.Subscription.TransactionId, subscription.TransactionId, i.Subscription); return(((Message)subscription).LoopBack(this)); }).ToArray(); } foreach (var subscription in subscriptions) { base.OnInnerAdapterNewOutMessage(subscription); } break; } } }
private void ProcessOrderStatus() { if (_requestOrderFirst) { _requestOrderFirst = false; var orders = _httpClient.RequestOpenOrders().ToArray(); foreach (var o in orders) { var order = o; _orderInfo.SafeAdd(order.Id, key => RefTuple.Create(TransactionIdGenerator.GetNextId(), (decimal)order.Amount)); } var trades = _httpClient.RequestUserTransactions().ToArray(); foreach (var trade in trades.OrderBy(t => t.Id)) { var info = _orderInfo.TryGetValue(trade.OrderId); if (info == null) { continue; } info.Second -= (decimal)trade.BtcAmount; } _hasActiveOrders = false; foreach (var order in orders) { _hasActiveOrders = true; ProcessOrder(order); } _hasMyTrades = false; foreach (var trade in trades) { ProcessExecution(trade); } return; } if (_hasMyTrades) { var transactions = _httpClient.RequestUserTransactions(); _hasMyTrades = false; foreach (var trade in transactions.Where(t => t.Type == 2).OrderBy(t => t.Id)) { ProcessExecution(trade); } } if (_hasActiveOrders) { var orders = _httpClient.RequestOpenOrders(); _hasActiveOrders = false; foreach (var order in orders) { _hasActiveOrders = true; ProcessOrder(order); } } }
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), Price = 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.Price, 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.Price - stopPrice : stopPrice - msg.Price }; } 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); } }
/// <inheritdoc /> protected override void OnSendInMessage(Message message) { switch (message.Type) { case MessageTypes.Reset: case MessageTypes.Disconnect: { lock (_syncObject) { _partialRequests.Clear(); _original.Clear(); _unsubscribeRequests.Clear(); _liveRequests.Clear(); } break; } case MessageTypes.OrderStatus: case MessageTypes.PortfolioLookup: { var subscriptionMsg = (ISubscriptionMessage)message; if (subscriptionMsg.IsSubscribe) { var from = subscriptionMsg.From; var to = subscriptionMsg.To; if (from != null || to != null) { var step = InnerAdapter.GetHistoryStepSize(DataType.Transactions, out _); // adapter do not provide historical request if (step == TimeSpan.Zero) { if (to != null) { // finishing current history request if (message.Type == MessageTypes.PortfolioLookup) { RaiseNewOutMessage(message.Type.ToResultType().CreateLookupResult(subscriptionMsg.TransactionId)); } return; } else { // or sending further only live subscription subscriptionMsg.From = null; subscriptionMsg.To = null; _liveRequests.Add(subscriptionMsg.TransactionId, false); } } } else { _liveRequests.Add(subscriptionMsg.TransactionId, false); } } break; } case MessageTypes.MarketData: { var mdMsg = (MarketDataMessage)message; if (mdMsg.IsSubscribe) { var from = mdMsg.From; var to = mdMsg.To; if (from != null || to != null) { var step = InnerAdapter.GetHistoryStepSize(mdMsg.ToDataType(), out var iterationInterval); // adapter do not provide historical request if (step == TimeSpan.Zero) { if (to != null) { // finishing current history request RaiseNewOutMessage(new MarketDataFinishedMessage { OriginalTransactionId = mdMsg.TransactionId }); return; } else { // or sending further only live subscription mdMsg.From = null; mdMsg.To = null; _liveRequests.Add(mdMsg.TransactionId, false); break; } } var info = new DownloadInfo(this, (MarketDataMessage)mdMsg.Clone(), step, iterationInterval); message = info.InitNext(); lock (_syncObject) { _original.Add(info.Origin.TransactionId, info); _partialRequests.Add(info.CurrTransId, info); } } else { _liveRequests.Add(mdMsg.TransactionId, false); } } else { lock (_syncObject) { if (!_original.TryGetValue(mdMsg.OriginalTransactionId, out var info)) { break; } var transId = TransactionIdGenerator.GetNextId(); _unsubscribeRequests.Add(transId, Tuple.Create(mdMsg.TransactionId, info)); mdMsg.OriginalTransactionId = info.CurrTransId; mdMsg.TransactionId = transId; } } break; } case ExtendedMessageTypes.PartialDownload: { var partialMsg = (PartialDownloadMessage)message; lock (_syncObject) { if (!_original.TryGetValue(partialMsg.OriginalTransactionId, out var info)) { break; } var mdMsg = info.InitNext(); if (mdMsg.To == null) { _liveRequests.Add(mdMsg.TransactionId, true); _original.Remove(partialMsg.OriginalTransactionId); _partialRequests.RemoveWhere(p => p.Value == info); } else { _partialRequests.Add(info.CurrTransId, info); } message = mdMsg; } break; } } base.OnSendInMessage(message); }
/// <inheritdoc /> protected override bool OnSendInMessage(Message message) { void AddInfo(OrderRegisterMessage regMsg) { if (regMsg is null) { throw new ArgumentNullException(nameof(regMsg)); } if (regMsg.OrderType == OrderTypes.Market || regMsg.Price == 0) { return; } if (regMsg.TimeInForce == TimeInForce.MatchOrCancel || regMsg.TimeInForce == TimeInForce.CancelBalance) { return; } lock (_sync) { foreach (var info in _byId.Values) { if (info.BookSubscription.SecurityId == regMsg.SecurityId) { info.AddOrder(regMsg); } } } } switch (message.Type) { case MessageTypes.Reset: { lock (_sync) { _byId.Clear(); _byBookId.Clear(); _byOrderStatusId.Clear(); _online.Clear(); _unsubscribeRequests.Clear(); } break; } case MessageTypes.OrderRegister: case MessageTypes.OrderReplace: { AddInfo((OrderRegisterMessage)message); break; } case MessageTypes.OrderPairReplace: { var pairMsg = (OrderPairReplaceMessage)message; AddInfo(pairMsg.Message1); AddInfo(pairMsg.Message2); break; } case MessageTypes.MarketData: { var mdMsg = (MarketDataMessage)message; if (mdMsg.IsSubscribe) { if (mdMsg.SecurityId == default) { break; } if (mdMsg.DataType2 != DataType.FilteredMarketDepth) { break; } var transId = mdMsg.TransactionId; mdMsg = mdMsg.TypedClone(); mdMsg.TransactionId = TransactionIdGenerator.GetNextId(); mdMsg.DataType2 = DataType.MarketDepth; var orderStatus = new OrderStatusMessage { TransactionId = TransactionIdGenerator.GetNextId(), IsSubscribe = true, States = new[] { OrderStates.Active }, SecurityId = mdMsg.SecurityId, }; var info = new FilteredMarketDepthInfo(transId, new Subscription(mdMsg, mdMsg), new Subscription(orderStatus, orderStatus)); lock (_sync) { _byId.Add(transId, info); _byBookId.Add(mdMsg.TransactionId, info); _byOrderStatusId.Add(orderStatus.TransactionId, info); } this.AddInfoLog("Filtered book {0} started (Book={1} / Orders={2}).", transId, mdMsg.TransactionId, orderStatus.TransactionId); base.OnSendInMessage(mdMsg); base.OnSendInMessage(orderStatus); return(true); } else { MarketDataMessage bookUnsubscribe = null; OrderStatusMessage ordersUnsubscribe = null; lock (_sync) { if (!_byId.TryGetValue(mdMsg.OriginalTransactionId, out var info)) { break; } info.UnSubscribeId = mdMsg.TransactionId; if (info.BookSubscription.State.IsActive()) { bookUnsubscribe = new MarketDataMessage { TransactionId = TransactionIdGenerator.GetNextId(), OriginalTransactionId = info.BookSubscription.TransactionId, IsSubscribe = false, }; _unsubscribeRequests.Add(bookUnsubscribe.TransactionId, Tuple.Create(info, true)); } if (info.OrdersSubscription.State.IsActive()) { ordersUnsubscribe = new OrderStatusMessage { TransactionId = TransactionIdGenerator.GetNextId(), OriginalTransactionId = info.OrdersSubscription.TransactionId, IsSubscribe = false, }; _unsubscribeRequests.Add(ordersUnsubscribe.TransactionId, Tuple.Create(info, false)); } } if (bookUnsubscribe == null && ordersUnsubscribe == null) { RaiseNewOutMessage(new SubscriptionResponseMessage { OriginalTransactionId = mdMsg.TransactionId, Error = new InvalidOperationException(LocalizedStrings.SubscriptionNonExist.Put(mdMsg.OriginalTransactionId)), }); } else { this.AddInfoLog("Filtered book {0} unsubscribing.", mdMsg.OriginalTransactionId); if (bookUnsubscribe != null) { base.OnSendInMessage(bookUnsubscribe); } if (ordersUnsubscribe != null) { base.OnSendInMessage(ordersUnsubscribe); } } return(true); } } } return(base.OnSendInMessage(message)); }
private void ProcessConnectMessage(BaseConnectionMessage message) { var isConnect = message is ConnectMessage; var adapter = message.Adapter; if (adapter == null) { if (message.Error != null) RaiseConnectionError(message.Error); return; } var state = _adapterStates[adapter]; switch (state) { case ConnectionStates.Connecting: { if (isConnect) { if (message.Error == null) { _adapterStates[adapter] = ConnectionStates.Connected; if (ConnectionState == ConnectionStates.Connecting) { if (RaiseConnectedOnFirstAdapter) { // raise Connected event only one time for the first adapter RaiseConnected(); } else { var isAllConnected = _adapterStates.CachedValues.All(v => v == ConnectionStates.Connected); // raise Connected event only one time when the last adapter connection successfully if (isAllConnected) RaiseConnected(); } } RaiseConnectedEx(adapter); if (adapter.PortfolioLookupRequired) SendInMessage(new PortfolioLookupMessage { TransactionId = TransactionIdGenerator.GetNextId() }); if (adapter.OrderStatusRequired) { var transactionId = TransactionIdGenerator.GetNextId(); _entityCache.AddOrderStatusTransactionId(transactionId); SendInMessage(new OrderStatusMessage { TransactionId = transactionId }); } if (adapter.SecurityLookupRequired) SendInMessage(new SecurityLookupMessage { TransactionId = TransactionIdGenerator.GetNextId() }); if (message is RestoredConnectMessage) RaiseRestored(); } else { _adapterStates[adapter] = ConnectionStates.Failed; // raise ConnectionError only one time if (ConnectionState == ConnectionStates.Connecting) { RaiseConnectionError(message.Error); if (message.Error is TimeoutException) RaiseTimeOut(); } else RaiseError(message.Error); RaiseConnectionErrorEx(adapter, message.Error); } } else { _adapterStates[adapter] = ConnectionStates.Failed; // raise ConnectionError only one time if (ConnectionState == ConnectionStates.Connecting) RaiseConnectionError(new InvalidOperationException(LocalizedStrings.Str683, message.Error)); else RaiseError(message.Error); RaiseConnectionErrorEx(adapter, message.Error); } return; } case ConnectionStates.Disconnecting: { if (isConnect) { _adapterStates[adapter] = ConnectionStates.Failed; var error = new InvalidOperationException(LocalizedStrings.Str684, message.Error); // raise ConnectionError only one time if (ConnectionState == ConnectionStates.Disconnecting) RaiseConnectionError(error); else RaiseError(error); RaiseConnectionErrorEx(adapter, message.Error); } else { if (message.Error == null) { _adapterStates[adapter] = ConnectionStates.Disconnected; var isLast = _adapterStates.CachedValues.All(v => v != ConnectionStates.Disconnecting); // raise Disconnected only one time for the last adapter if (isLast) RaiseDisconnected(); RaiseDisconnectedEx(adapter); } else { _adapterStates[adapter] = ConnectionStates.Failed; // raise ConnectionError only one time if (ConnectionState == ConnectionStates.Disconnecting) RaiseConnectionError(message.Error); else RaiseError(message.Error); RaiseConnectionErrorEx(adapter, message.Error); } } return; } case ConnectionStates.Connected: { if (isConnect && message.Error != null) { _adapterStates[adapter] = ConnectionStates.Failed; var error = new InvalidOperationException(LocalizedStrings.Str683, message.Error); RaiseConnectionError(error); RaiseConnectionErrorEx(adapter, error); return; } break; } case ConnectionStates.Disconnected: case ConnectionStates.Failed: { //StopMarketTimer(); break; } default: throw new ArgumentOutOfRangeException(); } // так как соединение установлено, то выдаем ошибку через Error, чтобы не сбрасывать состояние var error2 = new InvalidOperationException(LocalizedStrings.Str685Params.Put(state, message.GetType().Name), message.Error); RaiseError(error2); RaiseConnectionErrorEx(adapter, error2); }
/// <inheritdoc /> protected override void OnInnerAdapterNewOutMessage(Message message) { long TryReplaceOriginId(long id) { lock (_sync) return(_replaceId.TryGetValue(id, out var prevId) ? prevId : id); } var newOriginId = 0L; if (message is IOriginalTransactionIdMessage originIdMsg1) { newOriginId = originIdMsg1.OriginalTransactionId; originIdMsg1.OriginalTransactionId = TryReplaceOriginId(newOriginId); } switch (message.Type) { case MessageTypes.MarketData: { var responseMsg = (MarketDataMessage)message; var originId = responseMsg.OriginalTransactionId; lock (_sync) { if (responseMsg.IsOk()) { // no need send response after re-subscribe cause response was handled prev time if (_replaceId.ContainsKey(newOriginId)) { return; } } else { if (!_historicalRequests.Remove(originId)) { if (_subscriptionsById.TryGetValue(originId, out var info)) { _replaceId.Remove(newOriginId); _subscriptionsById.Remove(originId); _subscriptionsByKey.RemoveByValue(info); } } } } break; } case MessageTypes.MarketDataFinished: case MessageTypes.SecurityLookupResult: case MessageTypes.PortfolioLookupResult: case MessageTypes.OrderStatus: { var resultMsg = (IOriginalTransactionIdMessage)message; lock (_sync) { _replaceId.Remove(newOriginId); _historicalRequests.Remove(resultMsg.OriginalTransactionId); } break; } default: { if (message is ISubscriptionIdMessage subscrMsg) { lock (_sync) { if (subscrMsg.OriginalTransactionId != 0 && _historicalRequests.Contains(subscrMsg.OriginalTransactionId)) { subscrMsg.SubscriptionId = subscrMsg.OriginalTransactionId; } else { if (subscrMsg.OriginalTransactionId != 0 && _subscriptionsById.TryGetValue(subscrMsg.OriginalTransactionId, out var info)) { } else { var dataType = message.Type.ToDataType((message as CandleMessage)?.Arg ?? (message as ExecutionMessage)?.ExecutionType); var secId = GetSecurityId(dataType, (subscrMsg as ISecurityIdMessage)?.SecurityId ?? default); if (!_subscriptionsByKey.TryGetValue(Tuple.Create(dataType, secId), out info)) { break; } } subscrMsg.SubscriptionIds = info.Subscribers.Cache; } } } break; } } base.OnInnerAdapterNewOutMessage(message); switch (message.Type) { case ExtendedMessageTypes.ReconnectingFinished: { Message[] subscriptions; lock (_sync) { _replaceId.Clear(); subscriptions = _subscriptionsById.Values.Distinct().Select(i => { var subscription = (ISubscriptionMessage)i.Subscription.Clone(); subscription.TransactionId = TransactionIdGenerator.GetNextId(); _replaceId.Add(subscription.TransactionId, i.Subscription.TransactionId); var msg = (Message)subscription; msg.Adapter = this; msg.IsBack = true; return(msg); }).ToArray(); } foreach (var subscription in subscriptions) { base.OnInnerAdapterNewOutMessage(subscription); } break; } } }
/// <inheritdoc /> protected override void OnInnerAdapterNewOutMessage(Message message) { List <Message> extra = null; switch (message.Type) { case MessageTypes.Disconnect: case ExtendedMessageTypes.ReconnectingFinished: { ClearState(); break; } case MessageTypes.SubscriptionResponse: { var responseMsg = (SubscriptionResponseMessage)message; if (responseMsg.Error != null) { lock (_sync) { if (_parents.TryGetAndRemove(responseMsg.OriginalTransactionId, out var parent)) { extra = new List <Message>(); foreach (var child in parent.Child.Values) { var childId = child.Origin.TransactionId; if (_allChilds.TryGetValue(childId, out var tuple) && tuple.Second == SubscriptionStates.Stopped) { // loopback subscription not yet come, so will reply later tuple.Second = SubscriptionStates.Error; } else { extra.Add(new SubscriptionResponseMessage { OriginalTransactionId = childId, Error = responseMsg.Error }); } } } } } break; } case MessageTypes.SubscriptionFinished: { var finishMsg = (SubscriptionFinishedMessage)message; lock (_sync) { if (_parents.TryGetAndRemove(finishMsg.OriginalTransactionId, out var parent)) { extra = new List <Message>(); foreach (var child in parent.Child.Values) { var childId = child.Origin.TransactionId; if (_allChilds.TryGetValue(childId, out var tuple) && tuple.Second == SubscriptionStates.Stopped) { // loopback subscription not yet come, so will reply later tuple.Second = SubscriptionStates.Finished; } else { extra.Add(new SubscriptionFinishedMessage { OriginalTransactionId = childId }); } } } } break; } default: { if (message is ISubscriptionIdMessage subscrMsg && message is ISecurityIdMessage secIdMsg) { SubscriptionSecurityAllMessage allMsg = null; bool CheckSubscription(long parentId) { lock (_sync) { if (_parents.TryGetValue(parentId, out var parent)) { // parent subscription has security id (not null) if (parent.Origin.SecurityId == secIdMsg.SecurityId) { return(true); } if (!parent.Child.TryGetValue(secIdMsg.SecurityId, out var child)) { allMsg = new SubscriptionSecurityAllMessage(); parent.Origin.CopyTo(allMsg); allMsg.ParentTransactionId = parentId; allMsg.TransactionId = TransactionIdGenerator.GetNextId(); allMsg.SecurityId = secIdMsg.SecurityId; child = new ChildSubscription(allMsg.TypedClone()); child.Subscribers.Add(allMsg.TransactionId, child.Origin); parent.Child.Add(secIdMsg.SecurityId, child); allMsg.LoopBack(this, MessageBackModes.Chain); _allChilds.Add(allMsg.TransactionId, RefTuple.Create(parentId, SubscriptionStates.Stopped)); this.AddDebugLog("New ALL map: {0}/{1} TrId={2}-{3}", child.Origin.SecurityId, child.Origin.DataType2, allMsg.ParentTransactionId, allMsg.TransactionId); } //var subscriptionIds = subscrMsg.GetSubscriptionIds().Where(i => i != parentId).Concat(child.Subscribers.Cache); subscrMsg.SetSubscriptionIds(child.Subscribers.CachedKeys); if (!child.State.IsActive()) { child.Suspended.Add(message); message = null; this.AddDebugLog("ALL suspended: {0}/{1}, cnt={2}", child.Origin.SecurityId, child.Origin.DataType2, child.Suspended.Count); } return(true); } } return(false); } foreach (var id in subscrMsg.GetSubscriptionIds()) { if (CheckSubscription(id)) { break; } } if (allMsg != null) { base.OnInnerAdapterNewOutMessage(allMsg); } } break; } } if (message != null) { base.OnInnerAdapterNewOutMessage(message); } if (extra != null) { foreach (var m in extra) { base.OnInnerAdapterNewOutMessage(m); } } }
public PointOfSaleService(ScanBarcodeQuery query, TransactionIdGenerator generator) { this.query = query; this.generator = generator; this.scannedItems = new List <Item>(); }
/// <inheritdoc /> protected override void OnSendInMessage(Message message) { switch (message.Type) { case MessageTypes.Reset: { _subscriptions.Clear(); _subscriptionsById.Clear(); break; } case MessageTypes.MarketData: { var mdMsg = (MarketDataMessage)message; if (mdMsg.SecurityId.IsDefault()) { break; } var security = _securityProvider.LookupById(mdMsg.SecurityId); if (security == null) { if (!mdMsg.IsBasket()) { break; } security = mdMsg.ToSecurity(_exchangeInfoProvider).ToBasket(_processorProvider); } else if (!security.IsBasket()) { break; } if (mdMsg.IsSubscribe) { var processor = _processorProvider.CreateProcessor(security); var info = new SubscriptionInfo(processor, mdMsg.TransactionId); var dict = _subscriptions.SafeAdd(mdMsg.DataType); _subscriptionsById.Add(mdMsg.TransactionId, info); var inners = new MarketDataMessage[processor.BasketLegs.Length]; for (var i = 0; i < inners.Length; i++) { var inner = (MarketDataMessage)mdMsg.Clone(); inner.TransactionId = TransactionIdGenerator.GetNextId(); inner.SecurityId = processor.BasketLegs[i]; inners[i] = inner; info.LegsSubscriptions.Add(inner.TransactionId); dict.Add(inner.TransactionId, info); } foreach (var inner in inners) { base.OnSendInMessage(inner); } } else { if (!_subscriptionsById.TryGetValue(mdMsg.OriginalTransactionId, out var info)) { break; } _subscriptionsById.Remove(mdMsg.OriginalTransactionId); foreach (var id in info.LegsSubscriptions) { base.OnSendInMessage(new MarketDataMessage { TransactionId = TransactionIdGenerator.GetNextId(), IsSubscribe = false, OriginalTransactionId = id }); } } RaiseNewOutMessage(new MarketDataMessage { OriginalTransactionId = mdMsg.TransactionId }); return; } } base.OnSendInMessage(message); }
/// <summary> /// Process <see cref="MessageAdapterWrapper.InnerAdapter"/> output message. /// </summary> /// <param name="message">The message.</param> protected override void OnInnerAdapterNewOutMessage(Message message) { List <Message> messages = null; switch (message.Type) { case MessageTypes.Connect: { var connectMsg = (ConnectMessage)message; if (connectMsg.Error == null && IsRestoreOnReconnect) { messages = new List <Message>(); lock (_sync) { messages.AddRange(_subscribers.Values.Select(p => p.First)); messages.AddRange(_newsSubscribers.Values.Select(p => p.First)); messages.AddRange(_candleSubscribers.Values.Select(p => p.First)); messages.AddRange(_pfSubscribers.Values.Select(p => p.First)); ClearSubscribers(); } if (messages.Count == 0) { messages = null; } } break; } // TODO //case MessageTypes.MarketData: // ProcessOutMarketDataMessage((MarketDataMessage)message); // break; } base.OnInnerAdapterNewOutMessage(message); if (messages != null) { foreach (var m in messages) { var msg = m.Clone(); msg.IsBack = true; msg.Adapter = this; if (msg is MarketDataMessage mdMsg) { mdMsg.TransactionId = TransactionIdGenerator.GetNextId(); } else { var pfMsg = (PortfolioMessage)msg; pfMsg.TransactionId = TransactionIdGenerator.GetNextId(); } base.OnInnerAdapterNewOutMessage(msg); } } }
private void ProcessOrderStatus(OrderStatusMessage message) { if (message == null) { var portfolioRefresh = false; var orders = _httpClient.RequestOpenOrders(); var ids = _orderInfo.Keys.ToSet(); foreach (var order in orders) { ids.Remove(order.Id); var info = _orderInfo.TryGetValue(order.Id); if (info == null) { info = RefTuple.Create(TransactionIdGenerator.GetNextId(), (decimal)order.Amount); _orderInfo.Add(order.Id, info); ProcessOrder(order, (decimal)order.Amount, info.First, 0); portfolioRefresh = true; } else { // balance existing orders tracked by trades } } var trades = GetTrades(); foreach (var trade in trades) { ProcessTrade(trade); } foreach (var id in ids) { // can be removed from ProcessTrade if (!_orderInfo.TryGetAndRemove(id, out var info)) { return; } SendOutMessage(new ExecutionMessage { ExecutionType = ExecutionTypes.Transaction, HasOrderInfo = true, OrderId = id, OriginalTransactionId = info.First, ServerTime = CurrentTime.ConvertToUtc(), OrderState = OrderStates.Done, }); portfolioRefresh = true; } if (portfolioRefresh) { ProcessPortfolioLookup(null); } } else { if (!message.IsSubscribe) { return; } var orders = _httpClient.RequestOpenOrders().ToArray(); foreach (var order in orders) { var info = RefTuple.Create(TransactionIdGenerator.GetNextId(), (decimal)order.Amount); _orderInfo.Add(order.Id, info); ProcessOrder(order, (decimal)order.Amount, info.First, message.TransactionId); } var trades = GetTrades(); foreach (var trade in trades) { ProcessTrade(trade); } SendSubscriptionResult(message); } }
private void ProcessOrderStatus() { if (_requestOrderFirst) { _requestOrderFirst = false; var orders = _client.GetOrders().Items.Values; foreach (var o in orders) { var order = o; _orderInfo.SafeAdd(order.Id, key => RefTuple.Create(TransactionIdGenerator.GetNextId(), (decimal)order.Volume)); } var trades = _client.GetMyTrades(0).Items.Values; foreach (var trade in trades.OrderBy(t => t.Id)) { var info = _orderInfo.TryGetValue(trade.OrderId); if (info == null) { continue; } info.Second -= (decimal)trade.Volume; } _hasActiveOrders = false; foreach (var order in orders) { _hasActiveOrders = true; ProcessOrder(order); } _hasMyTrades = false; foreach (var trade in trades) { ProcessExecution(trade); } return; } if (_hasMyTrades) { var mtReply = _client.GetMyTrades(_lastMyTradeId + 1); _hasMyTrades = false; foreach (var trade in mtReply.Items.Values.OrderBy(t => t.Id)) { ProcessExecution(trade); } } if (_hasActiveOrders) { var orderReply = _client.GetOrders(); _hasActiveOrders = false; foreach (var order in orderReply.Items.Values) { _hasActiveOrders = true; ProcessOrder(order); } } }
private void ProcessOrderStatusMessage() { foreach (var accountId in _accountIds.CachedValues) { int?maxOrderId = null; while (true) { var orders = _restClient.GetOrders(accountId, maxOrderId); var count = 0; foreach (var order in orders) { count++; maxOrderId = order.Id - 1; OandaOrderCondition condition = null; OrderTypes orderType; if (order.Type != "market" && order.Type != "limit") { orderType = OrderTypes.Conditional; condition = new OandaOrderCondition { IsMarket = order.Type == _orderImit, TakeProfitOffset = (decimal?)order.TakeProfit, StopLossOffset = (decimal?)order.StopLoss, UpperBound = (decimal?)order.UpperBound, LowerBound = (decimal?)order.LowerBound, TrailingStopLossOffset = order.TrailingStop, }; } else { orderType = order.Type == "market" ? OrderTypes.Market : OrderTypes.Limit; } SendOutMessage(new ExecutionMessage { OrderType = orderType, ExecutionType = ExecutionTypes.Order, OrderId = order.Id, ServerTime = order.Time.FromOanda(), Price = (decimal)order.Price, Volume = order.Units, Side = order.Side.To <Sides>(), SecurityId = order.Instrument.ToSecurityId(), ExpiryDate = order.Expiry == null ? (DateTimeOffset?)null : order.Expiry.Value.FromOanda(), Condition = condition, PortfolioName = GetPortfolioName(accountId), }); } if (count < 50) { break; } } int?maxTradeId = null; while (true) { var trades = _restClient.GetTrades(accountId, maxTradeId); var count = 0; foreach (var trade in trades) { count++; maxTradeId = trade.Id - 1; var takeProfit = Math.Abs(trade.TakeProfit) < 0.0000001 ? (decimal?)null : (decimal)trade.TakeProfit; var stopLoss = Math.Abs(trade.StopLoss) < 0.0000001 ? (decimal?)null : (decimal)trade.StopLoss; var tralingStop = trade.TrailingStop == 0 ? (int?)null : trade.TrailingStop; var isConditional = takeProfit != null || stopLoss != null || tralingStop != null; var transId = TransactionIdGenerator.GetNextId(); SendOutMessage(new ExecutionMessage { ExecutionType = ExecutionTypes.Order, OrderType = isConditional ? OrderTypes.Conditional : OrderTypes.Limit, OrderId = trade.Id, OriginalTransactionId = transId, ServerTime = trade.Time.FromOanda(), Price = (decimal)trade.Price, Volume = trade.Units, Balance = 0, Side = trade.Side.To <Sides>(), SecurityId = trade.Instrument.ToSecurityId(), OrderState = isConditional ? OrderStates.Active : OrderStates.Done, PortfolioName = GetPortfolioName(accountId), Condition = isConditional ? new OandaOrderCondition { TakeProfitOffset = takeProfit, StopLossOffset = stopLoss, TrailingStopLossOffset = tralingStop, } : null, }); if (!isConditional) { SendOutMessage(new ExecutionMessage { ExecutionType = ExecutionTypes.Trade, OrderId = trade.Id, OriginalTransactionId = transId, TradeId = trade.Id, TradePrice = (decimal)trade.Price, Volume = trade.Units, ServerTime = trade.Time.FromOanda(), SecurityId = trade.Instrument.ToSecurityId(), PortfolioName = GetPortfolioName(accountId), }); } } if (count < 50) { break; } } } }
/// <summary>Коллбэк результата запроса списка заявок.</summary> /// <param name="portName">Имя портфеля.</param> /// <param name="data">Результат запроса списка заявок.</param> /// <param name="ex">Ошибка запроса списка заявок.</param> private void ClientOnOrdersData(string portName, List <Order> data, Exception ex) { if (ex != null) { SendOutError(ex); return; } foreach (var nativeOrder in data) { if (!IsOrderSupported(nativeOrder)) { continue; } var leg = nativeOrder.legDetails[0]; var secId = new SecurityId { SecurityCode = leg.symbolInfo.symbol, BoardCode = "EQ" }; var transId = _ordersByTransactionId.TryGetKey(nativeOrder.orderId); if (transId == 0) { transId = TransactionIdGenerator.GetNextId(); SaveOrder(transId, nativeOrder.orderId); } var tuple = _orderStateMap[nativeOrder.orderStatus]; var msg = new ExecutionMessage { SecurityId = secId, PortfolioName = portName, Side = leg.orderAction.ETradeActionToSide(), Price = nativeOrder.limitPrice.To <decimal>(), Volume = leg.orderedQuantity.To <decimal>(), Balance = (leg.orderedQuantity - leg.filledQuantity).To <decimal>(), OriginalTransactionId = transId, OrderId = nativeOrder.orderId, ExecutionType = ExecutionTypes.Order, OrderType = nativeOrder.priceType.ETradePriceTypeToOrderType(), ServerTime = ETradeUtil.ETradeTimestampToUTC(nativeOrder.orderExecutedTime > 0 ? nativeOrder.orderExecutedTime : nativeOrder.orderPlacedTime), OrderState = tuple.Item1, OrderStatus = tuple.Item2, }; switch (msg.OrderType) { case OrderTypes.Limit: { msg.Price = (decimal)nativeOrder.limitPrice; break; } case OrderTypes.Conditional: { if (nativeOrder.priceType == "STOP") { msg.Condition = new ETradeOrderCondition { StopType = ETradeStopTypes.StopMarket, StopPrice = (decimal)nativeOrder.stopPrice }; } else if (nativeOrder.priceType == "STOP_LIMIT") { msg.Condition = new ETradeOrderCondition { StopType = ETradeStopTypes.StopLimit, StopPrice = (decimal)nativeOrder.stopPrice }; msg.Price = nativeOrder.limitPrice.To <decimal>(); } else { this.AddErrorLog(LocalizedStrings.Str3374Params, nativeOrder.priceType); } break; } } SendOutMessage(msg); } }
/// <inheritdoc /> public override void SendInMessage(Message message) { if (message.IsBack) { if (message.Adapter == this) { message.Adapter = null; message.IsBack = false; } else { base.SendInMessage(message); return; } } switch (message.Type) { case MessageTypes.Reset: { lock (_sync) { if (!IsRestoreOnErrorReconnect) { ClearSubscribers(); } _subscriptionRequests.Clear(); _passThroughtIds.Clear(); } base.SendInMessage(message); break; } case MessageTypes.Disconnect: { var messages = new List <Message>(); lock (_sync) { messages.AddRange(_newsSubscribers.Values.Select(p => p.Message.Clone())); messages.AddRange(_subscribers.Values.Select(p => p.Message.Clone())); messages.AddRange(_pfSubscribers.Values.Select(p => p.Message.Clone())); if (IsRestoreOnNormalReconnect) { _subscriptionRequests.AddRange(messages.Select(m => m.Clone())); } else { ClearSubscribers(); } } foreach (var msg in messages) { if (msg is MarketDataMessage mdMsg) { mdMsg.OriginalTransactionId = mdMsg.TransactionId; mdMsg.TransactionId = TransactionIdGenerator.GetNextId(); mdMsg.IsSubscribe = false; if (IsRestoreOnNormalReconnect) { _passThroughtIds.Add(mdMsg.TransactionId); } } else if (msg is PortfolioMessage pfMsg) { pfMsg.TransactionId = TransactionIdGenerator.GetNextId(); pfMsg.IsSubscribe = false; if (IsRestoreOnNormalReconnect) { _passThroughtIds.Add(pfMsg.TransactionId); } } base.SendInMessage(msg); } base.SendInMessage(message); break; } case MessageTypes.MarketData: ProcessInMarketDataMessage((MarketDataMessage)message); break; case MessageTypes.Portfolio: ProcessInPortfolioMessage((PortfolioMessage)message); break; default: base.SendInMessage(message); break; } }
/// <inheritdoc /> public override void SendInMessage(Message message) { if (message.IsBack) { if (message.Adapter == this) { message.IsBack = false; } else { base.SendInMessage(message); return; } } switch (message.Type) { case MessageTypes.Reset: { lock (_syncObject) { _partialRequests.Clear(); _original.Clear(); _unsubscribeRequests.Clear(); } break; } case MessageTypes.MarketData: { var mdMsg = (MarketDataMessage)message; if (mdMsg.IsSubscribe) { var from = mdMsg.From; if (from != null) { var length = (mdMsg.To ?? DateTimeOffset.Now) - from.Value; var step = InnerAdapter.GetHistoryStepSize(mdMsg, out var iterationInterval); if (length > step) { var info = new DownloadInfo(this, (MarketDataMessage)mdMsg.Clone(), step, iterationInterval); message = info.InitNext(); lock (_syncObject) { _original.Add(info.Origin.TransactionId, info); _partialRequests.Add(info.CurrTransId, info); } } } } else { lock (_syncObject) { if (!_original.TryGetValue(mdMsg.OriginalTransactionId, out var info)) { break; } var transId = TransactionIdGenerator.GetNextId(); _unsubscribeRequests.Add(transId, Tuple.Create(mdMsg.TransactionId, info)); mdMsg.OriginalTransactionId = info.CurrTransId; mdMsg.TransactionId = transId; } } break; } case ExtendedMessageTypes.PartialDownload: { var partialMsg = (PartialDownloadMessage)message; lock (_syncObject) { lock (_syncObject) { if (!_original.TryGetValue(partialMsg.OriginalTransactionId, out var info)) { break; } var mdMsg = info.InitNext(); if (mdMsg.To == null) { _original.Remove(partialMsg.OriginalTransactionId); _partialRequests.RemoveWhere(p => p.Value == info); } else { _partialRequests.Add(info.CurrTransId, info); } message = mdMsg; } } break; } } base.SendInMessage(message); }
/// <summary> /// Отправить сообщение. /// </summary> /// <param name="message">Сообщение.</param> protected override void OnSendInMessage(Message message) { switch (message.Type) { case MessageTypes.Reset: { _isHistoricalSubscribed = false; if (_session != null) { try { _session.Stop(); _session.Logout(OnLogoutSuccess, OnLogoutFailure); } catch (Exception ex) { SendOutError(ex); } _session = null; } SendOutMessage(new ResetMessage()); break; } case MessageTypes.Connect: { if (_session != null) { throw new InvalidOperationException(LocalizedStrings.Str1619); } if (_api != null) { throw new InvalidOperationException(LocalizedStrings.Str3378); } _isDownloadSecurityFromSite = IsDownloadSecurityFromSite; _api = new LmaxApi(IsDemo ? "https://web-order.london-demo.lmax.com" : "https://api.lmaxtrader.com"); _api.Login(new LoginRequest(Login, Password.To <string>(), IsDemo ? ProductType.CFD_DEMO : ProductType.CFD_LIVE), OnLoginOk, OnLoginFailure); break; } case MessageTypes.Disconnect: { if (_session == null) { throw new InvalidOperationException(LocalizedStrings.Str1856); } _session.Stop(); _session.Logout(OnLogoutSuccess, OnLogoutFailure); _session = null; break; } case MessageTypes.PortfolioLookup: { ProcessPortfolioLookupMessage(); break; } case MessageTypes.OrderStatus: { ProcessOrderStatusMessage(); break; } case MessageTypes.Time: { _session.RequestHeartbeat(new HeartbeatRequest(TransactionIdGenerator.GetNextId().To <string>()), () => { }, CreateErrorHandler("RequestHeartbeat")); break; } case MessageTypes.OrderRegister: { ProcessOrderRegisterMessage((OrderRegisterMessage)message); break; } case MessageTypes.OrderCancel: { ProcessOrderCancelMessage((OrderCancelMessage)message); break; } case MessageTypes.SecurityLookup: { ProcessSecurityLookupMessage((SecurityLookupMessage)message); break; } case MessageTypes.MarketData: { ProcessMarketDataMessage((MarketDataMessage)message); break; } } }
private SubscriptionSecurityAllMessage CheckSubscription(ref Message message) { lock (_sync) { if (_parents.Count == 0) { return(null); } if (message is ISubscriptionIdMessage subscrMsg && message is ISecurityIdMessage secIdMsg) { foreach (var parentId in subscrMsg.GetSubscriptionIds()) { if (_parents.TryGetValue(parentId, out var parent)) { // parent subscription has security id (not null) if (parent.Origin.SecurityId == secIdMsg.SecurityId) { return(null); } SubscriptionSecurityAllMessage allMsg = null; if (!parent.Child.TryGetValue(secIdMsg.SecurityId, out var child)) { allMsg = new SubscriptionSecurityAllMessage(); parent.Origin.CopyTo(allMsg); allMsg.ParentTransactionId = parentId; allMsg.TransactionId = TransactionIdGenerator.GetNextId(); allMsg.SecurityId = secIdMsg.SecurityId; child = new ChildSubscription(allMsg.TypedClone()); child.Subscribers.Add(allMsg.TransactionId, child.Origin); parent.Child.Add(secIdMsg.SecurityId, child); allMsg.LoopBack(this, MessageBackModes.Chain); _allChilds.Add(allMsg.TransactionId, RefTuple.Create(parentId, SubscriptionStates.Stopped)); this.AddDebugLog("New ALL map: {0}/{1} TrId={2}-{3}", child.Origin.SecurityId, child.Origin.DataType2, allMsg.ParentTransactionId, allMsg.TransactionId); } //var subscriptionIds = subscrMsg.GetSubscriptionIds().Where(i => i != parentId).Concat(child.Subscribers.Cache); subscrMsg.SetSubscriptionIds(child.Subscribers.CachedKeys); if (!child.State.IsActive()) { child.Suspended.Add(message); message = null; this.AddDebugLog("ALL suspended: {0}/{1}, cnt={2}", child.Origin.SecurityId, child.Origin.DataType2, child.Suspended.Count); } return(allMsg); } } } } return(null); }
public PointOfSaleServiceBuilder() { this.query = new InMemoryItemRegistry(); this.generator = new Mock <TransactionIdGenerator>().Object; this.display = new Mock <Display>().Object; }