private void DepthClick(object sender, RoutedEventArgs e) { var trader = MainWindow.Instance.Trader; foreach (var security in SecurityPicker.SelectedSecurities) { var window = _quotesWindows.SafeAdd(security, s => { // начинаем получать котировки стакана trader.RegisterMarketDepth(security); // создаем окно со стаканом var wnd = new QuotesWindow { Title = security.Id + " " + LocalizedStrings.MarketDepth }; wnd.MakeHideable(); return(wnd); }); if (window.Visibility == Visibility.Visible) { window.Hide(); } else { window.Show(); window.DepthCtrl.UpdateDepth(trader.GetMarketDepth(security)); } if (!_initialized) { trader.MarketDepthChanged += TraderOnMarketDepthChanged; _initialized = true; } } }
private void DepthClick(object sender, RoutedEventArgs e) { var trader = MainWindow.Instance.Trader; foreach (var security in SecurityPicker.SelectedSecurities) { var window = _quotesWindows.SafeAdd(security, s => { // subscribe on order book flow trader.RegisterOrderLog(security); // create order book window var wnd = new QuotesWindow { Title = security.Id + " " + LocalizedStrings.MarketDepth }; wnd.MakeHideable(); return(wnd); }); if (window.Visibility == Visibility.Visible) { window.Hide(); } else { window.Show(); window.DepthCtrl.UpdateDepth(trader.GetMarketDepth(security)); } if (!_initialized) { trader.MarketDepthChanged += TraderOnMarketDepthChanged; _initialized = true; } } }
private void QuotesClick(object sender, RoutedEventArgs e) { var window = _quotesWindows.SafeAdd((Security)SecuritiesDetails.SelectedValue, security => { // начинаем получать котировки стакана MainWindow.Instance.Trader.RegisterMarketDepth(security); // создаем окно со стаканом var wnd = new QuotesWindow { Title = security.Code + " котировки" }; wnd.MakeHideable(); return(wnd); }); if (window.Visibility == Visibility.Visible) { window.Hide(); } else { window.Show(); } }
private void ShowLevel1(Security security) { var window = _level1Windows.SafeAdd(security.Code, s => { // create level1 window var wnd = new Level1Window { Title = security + LocalizedStrings.Str3693 }; wnd.MakeHideable(); return(wnd); }); if (window.Visibility != Visibility.Visible) { window.Show(); } if (!_initialized) { MainWindow.Instance.Trader.NewMessage += TraderOnNewMessage; _initialized = true; } }
public void AddValue(Candle candle, ICandleBuilderSourceValue value) { if (candle == null) { throw new ArgumentNullException("candle"); } if (value == null) { throw new ArgumentNullException("value"); } _candleValues.SafeAdd(candle).AddLast(value); _valuesStat.Add(value); if (_firstValueTime == 0) { _firstValueTime = value.Time.UtcTicks; } _lastValueTime = value.Time.UtcTicks; RecycleValues(); }
private SecurityData GetData(Security security) { return(_securityData.SafeAdd(security)); }
private Dictionary <SecurityId, TMessage> GetDict <TMessage>(MessageTypes type) { return((Dictionary <SecurityId, TMessage>)_messages.SafeAdd(type, key => new Dictionary <SecurityId, TMessage>())); }
/// <summary> /// Send message. /// </summary> /// <param name="message">Message.</param> protected override void OnSendInMessage(Message message) { if (message.IsBack) { var adapter = message.Adapter; if (adapter == null) { throw new InvalidOperationException(); } adapter.SendInMessage(message); return; } switch (message.Type) { case MessageTypes.Reset: ProcessReset(message); break; case MessageTypes.Connect: { if (_isFirstConnect) { _isFirstConnect = false; } else { ProcessReset(new ResetMessage()); } _hearbeatAdapters.AddRange(GetSortedAdapters().Select(CreateWrappers).ToDictionary(a => a, a => { var hearbeatAdapter = new HeartbeatMessageAdapter(a); ((IMessageAdapter)hearbeatAdapter).Parent = this; hearbeatAdapter.NewOutMessage += m => OnInnerAdapterNewOutMessage(a, m); return(hearbeatAdapter); })); if (_hearbeatAdapters.Count == 0) { throw new InvalidOperationException(LocalizedStrings.Str3650); } _hearbeatAdapters.Values.ForEach(a => a.SendInMessage(message)); break; } case MessageTypes.Disconnect: { _connectedAdapters.Cache.ForEach(a => a.SendInMessage(message)); break; } case MessageTypes.Portfolio: { var pfMsg = (PortfolioMessage)message; ProcessPortfolioMessage(pfMsg.PortfolioName, pfMsg); break; } case MessageTypes.OrderRegister: case MessageTypes.OrderReplace: case MessageTypes.OrderCancel: case MessageTypes.OrderGroupCancel: { var ordMsg = (OrderMessage)message; ProcessAdapterMessage(ordMsg.PortfolioName, ordMsg); break; } case MessageTypes.OrderPairReplace: { var ordMsg = (OrderPairReplaceMessage)message; ProcessAdapterMessage(ordMsg.Message1.PortfolioName, ordMsg); break; } case MessageTypes.MarketData: { IMessageAdapter[] adapters = null; if (message.Adapter != null) { var wrapper = _hearbeatAdapters.Values.FirstOrDefault(w => GetUnderlyingAdapter(w) == message.Adapter); if (wrapper != null) { adapters = new IMessageAdapter[] { wrapper } } ; } if (adapters == null) { adapters = _messageTypeAdapters.TryGetValue(message.Type)?.Cache; } if (adapters == null) { throw new InvalidOperationException(LocalizedStrings.Str629Params.Put(message.Type)); } var mdMsg = (MarketDataMessage)message; switch (mdMsg.DataType) { case MarketDataTypes.News: adapters.ForEach(a => a.SendInMessage(mdMsg)); break; default: { var key = mdMsg.CreateKey(); var state = _subscriptionStates.TryGetValue2(key); if (mdMsg.IsSubscribe) { if (state != null) { switch (state) { case SubscriptionStates.Subscribed: { var adapter = _subscriptions.TryGetValue(key); if (adapter != null) { adapter.SendInMessage(mdMsg); } else { RaiseMarketDataMessage(null, mdMsg.OriginalTransactionId, new InvalidOperationException(state.Value.ToString()), true); } break; } case SubscriptionStates.Subscribing: //case SubscriptionStates.Unsubscribing: _suspendedSubscriptions.SafeAdd(key).Add(mdMsg); break; default: throw new ArgumentOutOfRangeException(); } break; } else { _subscriptionStates.Add(key, SubscriptionStates.Subscribing); } } else { var canProcess = false; switch (state) { case SubscriptionStates.Subscribed: canProcess = true; //_subscriptionStates[key] = SubscriptionStates.Unsubscribing; break; case SubscriptionStates.Subscribing: //case SubscriptionStates.Unsubscribing: RaiseMarketDataMessage(null, mdMsg.OriginalTransactionId, new InvalidOperationException(state.Value.ToString()), false); break; case null: RaiseMarketDataMessage(null, mdMsg.OriginalTransactionId, null, false); break; default: throw new ArgumentOutOfRangeException(); } if (!canProcess) { break; } } if (mdMsg.TransactionId != 0) { _subscriptionKeys.Add(mdMsg.TransactionId, key); } if (mdMsg.IsSubscribe) { //if (_subscriptionQueue.ContainsKey(key)) // return; var enumerator = adapters.Cast <IMessageAdapter>().GetEnumerator(); _subscriptionQueue.Add(key, enumerator); ProcessSubscriptionAction(enumerator, mdMsg, mdMsg.TransactionId); } else { var adapter = _subscriptions.TryGetValue(key); if (adapter != null) { //_subscriptions.Remove(key); adapter.SendInMessage(message); } } break; } } break; } case MessageTypes.ChangePassword: { var adapter = GetSortedAdapters().FirstOrDefault(a => a.SupportedMessages.Contains(MessageTypes.ChangePassword)); if (adapter == null) { throw new InvalidOperationException(LocalizedStrings.Str629Params.Put(message.Type)); } adapter.SendInMessage(message); break; } default: { if (message.Adapter != null) { message.Adapter.SendInMessage(message); break; } var adapters = _messageTypeAdapters.TryGetValue(message.Type)?.Cache; if (adapters == null) { throw new InvalidOperationException(LocalizedStrings.Str629Params.Put(message.Type)); } adapters.ForEach(a => a.SendInMessage(message)); break; } } }
private SyncObject GetSync(DateTime time) { return(_syncRoots.SafeAdd(time)); }
/// <summary> /// Метод обработки исходящих сообщений для <see cref="OutMessageProcessor"/>. /// </summary> /// <param name="message">Сообщение.</param> /// <param name="adapter">Адаптер.</param> protected virtual void OnOutMessageProcessor(Message message, IMessageAdapter adapter) { if (this != adapter) { return; } switch (message.Type) { case MessageTypes.ClearMessageQueue: OutMessageProcessor.Clear((ClearMessageQueueMessage)message); return; case MessageTypes.Security: { NewOutMessage.SafeInvoke(message); if (!SessionHolder.CreateAssociatedSecurity) { break; } var clone = (SecurityMessage)message.Clone(); clone.SecurityId = CloneSecurityId(clone.SecurityId); NewOutMessage.SafeInvoke(clone); break; } case MessageTypes.Level1Change: { NewOutMessage.SafeInvoke(message); var l1Msg = (Level1ChangeMessage)message; if (l1Msg.SecurityId.IsDefault()) { break; } if (SessionHolder.CreateAssociatedSecurity) { // обновление BestXXX для ALL из конкретных тикеров var clone = (Level1ChangeMessage)l1Msg.Clone(); clone.SecurityId = CloneSecurityId(clone.SecurityId); NewOutMessage.SafeInvoke(clone); } if (SessionHolder.CreateDepthFromLevel1) { // генерация стакана из Level1 var builder = _level1DepthBuilders.SafeAdd(l1Msg.SecurityId, c => new Level1DepthBuilder(c)); if (builder.Process(l1Msg)) { var quoteMsg = builder.QuoteChange; NewOutMessage.SafeInvoke(quoteMsg); CreateAssociatedSecurityQuotes(quoteMsg); } } break; } case MessageTypes.QuoteChange: { var quoteMsg = (QuoteChangeMessage)message; NewOutMessage.SafeInvoke(quoteMsg); if (SessionHolder.CreateDepthFromLevel1) { _level1DepthBuilders.SafeAdd(quoteMsg.SecurityId, c => new Level1DepthBuilder(c)).HasDepth = true; } CreateAssociatedSecurityQuotes(quoteMsg); break; } case MessageTypes.Execution: { NewOutMessage.SafeInvoke(message); if (!SessionHolder.CreateAssociatedSecurity) { break; } var execMsg = (ExecutionMessage)message; if (execMsg.SecurityId.IsDefault()) { break; } switch (execMsg.ExecutionType) { case ExecutionTypes.Tick: case ExecutionTypes.OrderLog: { var clone = (ExecutionMessage)message.Clone(); clone.SecurityId = CloneSecurityId(clone.SecurityId); NewOutMessage.SafeInvoke(clone); break; } } break; } default: NewOutMessage.SafeInvoke(message); break; } }
/// <summary> /// Создать хранилище для <see cref="IMarketDataStorage"/>. /// </summary> /// <param name="securityId">Идентификатор инструмента.</param> /// <param name="dataType">Тип маркет-данных.</param> /// <param name="arg">Параметр, ассоциированный с типом <paramref name="dataType"/>. Например, <see cref="Candle.Arg"/>.</param> /// <param name="format">Тип формата.</param> /// <returns>Хранилище для <see cref="IMarketDataStorage"/>.</returns> public override IMarketDataStorageDrive GetStorageDrive(SecurityId securityId, Type dataType, object arg, StorageFormats format) { return(_drives.SafeAdd(Tuple.Create(securityId, dataType, arg, format), key => new LocalMarketDataStorageDrive(this, securityId, CreateFileName(dataType, arg), format, this))); }
public SecurityData GetData(Security security) { return(_securityData.SafeAdd(security)); }
/// <inheritdoc /> public override void SendInMessage(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.SendInMessage(inner); } } else { if (!_subscriptionsById.TryGetValue(mdMsg.OriginalTransactionId, out var info)) { break; } _subscriptionsById.Remove(mdMsg.OriginalTransactionId); foreach (var id in info.LegsSubscriptions) { base.SendInMessage(new MarketDataMessage { TransactionId = TransactionIdGenerator.GetNextId(), IsSubscribe = false, OriginalTransactionId = id }); } } RaiseNewOutMessage(new MarketDataMessage { OriginalTransactionId = mdMsg.TransactionId }); return; } } base.SendInMessage(message); }
/// <summary> /// Получить хранилище транзакций для заданного инструмента. /// </summary> /// <param name="security">Инструмент.</param> /// <param name="type">Тип данных, информация о которых содержится <see cref="ExecutionMessage"/>.</param> /// <param name="drive">Хранилище. Если значение равно <see langword="null"/>, то будет использоваться <see cref="IStorageRegistry.DefaultDrive"/>.</param> /// <param name="format">Тип формата. По-умолчанию передается <see cref="StorageFormats.Binary"/>.</param> /// <returns>Хранилище транзакций.</returns> public IMarketDataStorage <ExecutionMessage> GetExecutionStorage(Security security, ExecutionTypes type, IMarketDataDrive drive = null, StorageFormats format = StorageFormats.Binary) { if (security == null) { throw new ArgumentNullException("security"); } var securityId = security.ToSecurityId(); return(_executionStorages.SafeAdd(Tuple.Create(securityId, type, (drive ?? DefaultDrive).GetStorageDrive(securityId, typeof(ExecutionMessage), type, format)), key => { var secId = key.Item1; var mdDrive = key.Item3; switch (type) { case ExecutionTypes.Tick: { if (security is ContinuousSecurity) { return new ConvertableContinuousSecurityMarketDataStorage <ExecutionMessage, Trade>((ContinuousSecurity)security, null, t => t.ServerTime, t => ToSecurity(t.SecurityId), t => t.ToMessage(), t => t.Time, (s, d) => GetExecutionStorage(s, type, d, format), mdDrive); } else if (security is IndexSecurity) { return new IndexSecurityMarketDataStorage <ExecutionMessage>((IndexSecurity)security, null, d => ToSecurity(d.SecurityId), (s, d) => GetExecutionStorage(s, type, d, format), mdDrive); } else if (security.Board == ExchangeBoard.Associated) { return new ConvertableAllSecurityMarketDataStorage <ExecutionMessage, Trade>(security, null, t => t.ServerTime, t => ToSecurity(t.SecurityId), t => t.Time, (s, d) => GetExecutionStorage(s, type, d, format), mdDrive); } else { IMarketDataSerializer <ExecutionMessage> serializer; switch (format) { case StorageFormats.Binary: serializer = new TradeSerializer(key.Item1); break; case StorageFormats.Csv: serializer = new CsvMarketDataSerializer <ExecutionMessage>(key.Item1, ExecutionTypes.Tick); break; default: throw new ArgumentOutOfRangeException("format"); } return new TradeStorage(security, mdDrive, serializer); } } case ExecutionTypes.Order: case ExecutionTypes.Trade: return new ExecutionStorage(security, mdDrive, new ExecutionSerializer(secId)); case ExecutionTypes.OrderLog: { IMarketDataSerializer <ExecutionMessage> serializer; switch (format) { case StorageFormats.Binary: serializer = new OrderLogSerializer(secId); break; case StorageFormats.Csv: serializer = new CsvMarketDataSerializer <ExecutionMessage>(secId, ExecutionTypes.OrderLog); break; default: throw new ArgumentOutOfRangeException("format"); } return new OrderLogStorage(security, mdDrive, serializer); } default: throw new ArgumentOutOfRangeException("type"); } })); }
/// <summary> /// Получить хранилище свечек для заданного инструмента. /// </summary> /// <param name="candleMessageType">Тип сообщения свечи.</param> /// <param name="security">Инструмент.</param> /// <param name="arg">Параметр свечи.</param> /// <param name="drive">Хранилище. Если значение равно <see langword="null"/>, то будет использоваться <see cref="IStorageRegistry.DefaultDrive"/>.</param> /// <param name="format">Тип формата. По-умолчанию передается <see cref="StorageFormats.Binary"/>.</param> /// <returns>Хранилище свечек.</returns> public IMarketDataStorage <CandleMessage> GetCandleMessageStorage(Type candleMessageType, Security security, object arg, IMarketDataDrive drive = null, StorageFormats format = StorageFormats.Binary) { if (candleMessageType == null) { throw new ArgumentNullException("candleMessageType"); } if (!candleMessageType.IsSubclassOf(typeof(CandleMessage))) { throw new ArgumentOutOfRangeException("candleMessageType", candleMessageType, LocalizedStrings.WrongCandleType); } if (security == null) { throw new ArgumentNullException("security"); } if (arg.IsNull(true)) { throw new ArgumentNullException("arg", LocalizedStrings.EmptyCandleArg); } var securityId = security.ToSecurityId(); return(_candleStorages.SafeAdd(Tuple.Create(securityId, (drive ?? DefaultDrive).GetStorageDrive(securityId, candleMessageType, arg, format)), key => { if (security is ContinuousSecurity) { var type = typeof(CandleContinuousSecurityMarketDataStorage <>).Make(candleMessageType); Func <CandleMessage, DateTimeOffset> getTime = c => c.OpenTime; Func <CandleMessage, Security> getSecurity = c => ToSecurity(c.SecurityId); //Func<Candle, CandleMessage> toMessage = c => c.ToMessage(); //Func<Candle, DateTime> getEntityTime = c => c.OpenTime; Func <Security, IMarketDataDrive, IMarketDataStorage <CandleMessage> > getStorage = (s, d) => GetCandleMessageStorage(candleMessageType, s, arg, d, format); return type.CreateInstance <IMarketDataStorage <CandleMessage> >((ContinuousSecurity)security, arg, getTime, getSecurity, getStorage, key.Item2); } else if (security is IndexSecurity) { return new IndexSecurityMarketDataStorage <CandleMessage>((IndexSecurity)security, arg, c => ToSecurity(c.SecurityId), (s, d) => GetCandleMessageStorage(candleMessageType, s, arg, d, format), key.Item2); } else { IMarketDataSerializer serializer; switch (format) { case StorageFormats.Binary: serializer = typeof(CandleSerializer <>).Make(candleMessageType).CreateInstance <IMarketDataSerializer>(security.ToSecurityId(), arg); break; case StorageFormats.Csv: serializer = typeof(CsvMarketDataSerializer <>).Make(candleMessageType).CreateInstance <IMarketDataSerializer>(security.ToSecurityId(), null, arg, null); break; default: throw new ArgumentOutOfRangeException("format"); } return typeof(CandleStorage <,>).Make(candleMessageType, candleMessageType.ToCandleType()).CreateInstance <IMarketDataStorage <CandleMessage> >(security, arg, key.Item2, serializer); } })); }
public Tuple <News, bool> ProcessNewsMessage(Security security, NewsMessage message) { if (message == null) { throw new ArgumentNullException(nameof(message)); } var isNew = false; News news; if (!message.Id.IsEmpty()) { news = _newsById.SafeAdd(message.Id, key => { isNew = true; var n = EntityFactory.CreateNews(); n.Id = key; return(n); }); } else { isNew = true; news = EntityFactory.CreateNews(); _newsWithoutId.Add(news); } if (isNew) { news.ServerTime = message.ServerTime; news.LocalTime = message.LocalTime; } if (!message.Source.IsEmpty()) { news.Source = message.Source; } if (!message.Headline.IsEmpty()) { news.Headline = message.Headline; } if (security != null) { news.Security = security; } if (!message.Story.IsEmpty()) { news.Story = message.Story; } if (!message.BoardCode.IsEmpty()) { news.Board = ExchangeInfoProvider.GetOrCreateBoard(message.BoardCode); } if (message.Url != null) { news.Url = message.Url; } message.CopyExtensionInfo(news); return(Tuple.Create(news, isNew)); }
/// <inheritdoc /> protected override bool OnSendInMessage(Message message) { switch (message.Type) { case MessageTypes.Reset: { _subscriptions.Clear(); _strategyIdMap.Clear(); _strategySubscriptions.Clear(); lock (_sync) _positionManager.ProcessMessage(message); break; } case MessageTypes.PortfolioLookup: { var lookupMsg = (PortfolioLookupMessage)message; if (lookupMsg.IsSubscribe) { if (!lookupMsg.StrategyId.IsEmpty()) { this.AddDebugLog("Subscription (strategy='{1}') {0} added.", lookupMsg.TransactionId, lookupMsg.StrategyId); _strategyIdMap.Add(lookupMsg.TransactionId, lookupMsg.StrategyId); _strategySubscriptions.SafeAdd(lookupMsg.StrategyId).Add(lookupMsg.TransactionId); RaiseNewOutMessage(lookupMsg.CreateResult()); return(true); } if (lookupMsg.To == null) { this.AddDebugLog("Subscription {0} added.", lookupMsg.TransactionId); _subscriptions.Add(lookupMsg.TransactionId); lock (_sync) _positionManager.ProcessMessage(message); } if (IsEmulate) { RaiseNewOutMessage(lookupMsg.CreateResult()); return(true); } } else { if (_subscriptions.Remove(lookupMsg.OriginalTransactionId)) { this.AddDebugLog("Subscription {0} removed.", lookupMsg.OriginalTransactionId); lock (_sync) _positionManager.ProcessMessage(message); } else if (_strategyIdMap.TryGetAndRemove(lookupMsg.OriginalTransactionId, out var strategyId)) { _strategySubscriptions.TryGetValue(strategyId)?.Remove(lookupMsg.OriginalTransactionId); this.AddDebugLog("Subscription (strategy='{1}') {0} removed.", lookupMsg.OriginalTransactionId, strategyId); return(true); } if (IsEmulate) { //RaiseNewOutMessage(lookupMsg.CreateResponse()); return(true); } } break; } default: { lock (_sync) _positionManager.ProcessMessage(message); break; } } return(base.OnSendInMessage(message)); }
private SecurityData GetData(Security security) => _securityData.SafeAdd(security);
/// <summary> /// To process the new data. /// </summary> /// <param name="message">Market-data message (uses as a subscribe/unsubscribe in outgoing case, confirmation event in incoming case).</param> /// <param name="value">The new data by which it is decided to start or end the current candle creation.</param> /// <returns>A new candles changes.</returns> public IEnumerable <CandleMessage> Process(MarketDataMessage message, ICandleBuilderSourceValue value) { if (message == null) { throw new ArgumentNullException(nameof(message)); } if (value == null) { throw new ArgumentNullException(nameof(value)); } var info = _info.SafeAdd(message, k => new CandleInfo()); if (info == null) { yield break; } var currCandle = info.CurrentCandle; var candle = ProcessValue(message, (TCandleMessage)currCandle, value); if (candle == null) { // skip the value that cannot be processed yield break; } if (candle == currCandle) { if (message.IsCalcVolumeProfile) { if (info.VolumeProfile == null) { throw new InvalidOperationException(); } info.VolumeProfile.Update(value); } //candle.State = CandleStates.Changed; yield return(candle); } else { if (currCandle != null) { info.CurrentCandle = null; info.VolumeProfile = null; currCandle.State = CandleStates.Finished; yield return(currCandle); } info.CurrentCandle = candle; if (message.IsCalcVolumeProfile) { info.VolumeProfile = new VolumeProfile(); info.VolumeProfile.Update(value); candle.PriceLevels = info.VolumeProfile.PriceLevels; } candle.State = CandleStates.Active; yield return(candle); } }
private CachedSynchronizedDictionary <Security, int> GetSubscribers(MarketDataTypes type) { return(_subscribers.SafeAdd(type)); }
private void InitTask(IHydraTask task, HydraTaskSettings settings) { Core.Extensions.Tasks.Add(task); task.Init(settings); _logManager.Sources.Add(task); task.DataLoaded += (security, dataType, arg, time, count) => { if (dataType == typeof(NewsMessage)) { LoadedNews += count; return; } var allSecurity = _taskAllSecurities.SafeAdd(task, key => task.GetAllSecurity()); var taskSecurity = _taskSecurityCache.SafeAdd(task).SafeAdd(security, key => task.Settings.Securities.FirstOrDefault(s => s.Security == key)); HydraTaskSecurity.TypeInfo info; HydraTaskSecurity.TypeInfo allInfo; if (dataType == typeof(ExecutionMessage)) { switch ((ExecutionTypes)arg) { case ExecutionTypes.Tick: { info = taskSecurity == null ? null : taskSecurity.TradeInfo; allInfo = allSecurity == null ? null : allSecurity.TradeInfo; LoadedTrades += count; break; } case ExecutionTypes.OrderLog: { info = taskSecurity == null ? null : taskSecurity.OrderLogInfo; allInfo = allSecurity == null ? null : allSecurity.OrderLogInfo; LoadedOrderLog += count; break; } case ExecutionTypes.Order: case ExecutionTypes.Trade: { info = taskSecurity == null ? null : taskSecurity.ExecutionInfo; allInfo = allSecurity == null ? null : allSecurity.ExecutionInfo; LoadedExecutions += count; break; } default: throw new ArgumentOutOfRangeException("arg"); } } else if (dataType == typeof(QuoteChangeMessage)) { info = taskSecurity == null ? null : taskSecurity.DepthInfo; allInfo = allSecurity == null ? null : allSecurity.DepthInfo; LoadedDepths += count; } else if (dataType == typeof(Level1ChangeMessage)) { info = taskSecurity == null ? null : taskSecurity.Level1Info; allInfo = allSecurity == null ? null : allSecurity.Level1Info; LoadedLevel1 += count; } else if (dataType.IsSubclassOf(typeof(CandleMessage))) { info = taskSecurity == null ? null : taskSecurity.CandleInfo; allInfo = allSecurity == null ? null : allSecurity.CandleInfo; LoadedCandles += count; } else { throw new ArgumentOutOfRangeException("dataType", dataType, LocalizedStrings.Str1018); } if (allInfo != null) { allInfo.Count += count; allInfo.LastTime = time.LocalDateTime; task.Settings.Securities.Update(allSecurity); } if (info == null) { return; } info.Count += count; info.LastTime = time.LocalDateTime; task.Settings.Securities.Update(taskSecurity); }; }
private void ProcessMarketDataMessage(MarketDataMessage mdMsg) { var smartId = (string)mdMsg.SecurityId.Native; if (smartId.IsEmpty()) { throw new InvalidOperationException(LocalizedStrings.Str1853Params.Put(mdMsg.SecurityId)); } switch (mdMsg.DataType) { case MarketDataTypes.Level1: { if (mdMsg.IsSubscribe) { _wrapper.SubscribeSecurity(smartId); } else { _wrapper.UnSubscribeSecurity(smartId); } break; } case MarketDataTypes.MarketDepth: { if (mdMsg.IsSubscribe) { _wrapper.SubscribeMarketDepth(smartId); } else { _wrapper.UnSubscribeMarketDepth(smartId); } break; } case MarketDataTypes.Trades: { if (mdMsg.From == null) { if (mdMsg.IsSubscribe) { _wrapper.SubscribeTrades(smartId); } else { _wrapper.UnSubscribeTrades(smartId); } } else { const int maxTradeCount = 1000000; this.AddDebugLog("RequestHistoryTrades SecId = {0} From {1} Count = {2}", smartId, mdMsg.From, maxTradeCount); _wrapper.RequestHistoryTrades(smartId, mdMsg.From.Value.ToLocalTime(TimeHelper.Moscow), maxTradeCount); } break; } case MarketDataTypes.CandleTimeFrame: { var count = mdMsg.Count ?? 0; var direction = (SmartComHistoryDirections)mdMsg.ExtensionInfo["Direction"]; if (direction == SmartComHistoryDirections.Forward) { count = -count; } var tf = (TimeSpan)mdMsg.Arg; _candleTransactions.SafeAdd(smartId)[tf] = Tuple.Create(mdMsg.TransactionId, new List <CandleMessage>()); this.AddDebugLog("RequestHistoryBars SecId {0} TF {1} From {2} Count {3}", smartId, tf, mdMsg.From, count); _wrapper.RequestHistoryBars(smartId, tf, (mdMsg.From ?? DateTimeOffset.MinValue).ToLocalTime(TimeHelper.Moscow), (int)count); break; } default: { SendOutMarketDataNotSupported(mdMsg.TransactionId); return; } } var reply = (MarketDataMessage)mdMsg.Clone(); reply.OriginalTransactionId = mdMsg.TransactionId; SendOutMessage(reply); }
private XmlSerializer <TItem> GetSerializer <TItem>() { return((XmlSerializer <TItem>)_serializers.SafeAdd(typeof(TItem), k => new XmlSerializer <TItem>(false))); }
void IStudioCommandService.Register <TCommand>(object listener, bool guiAsync, Action <TCommand> handler) { _handlers.SafeAdd(typeof(TCommand)).SafeAdd(GetScope(listener))[listener] = new CommandTuple(cmd => handler((TCommand)cmd), null, guiAsync); }
private Level1DepthBuilder GetBuilder(SecurityId securityId) { return _level1DepthBuilders.SafeAdd(securityId, c => new Level1DepthBuilder(c)); }
/// <summary> /// Получить тарифный план по его имени. /// </summary> /// <param name="name">Название тарифного плана.</param> /// <returns>Тарифный план.</returns> public CommissionRule[] Get(string name) { return(_profiles.SafeAdd(name, key => Invoke(s => s.GetRules(SessionId, key)))); }
/// <inheritdoc /> public decimal?ProcessMessage(Message message) { switch (message.Type) { case MessageTypes.Reset: { Reset(); break; } case MessageTypes.Level1Change: { var l1Msg = (Level1ChangeMessage)message; var pair = _bestPrices.SafeAdd(l1Msg.SecurityId); var bidPrice = l1Msg.TryGetDecimal(Level1Fields.BestBidPrice); if (bidPrice != null) { pair.First = bidPrice.Value; } var askPrice = l1Msg.TryGetDecimal(Level1Fields.BestAskPrice); if (askPrice != null) { pair.Second = askPrice.Value; } break; } case MessageTypes.QuoteChange: { var quotesMsg = (QuoteChangeMessage)message; if (quotesMsg.State != null) { break; } var pair = _bestPrices.SafeAdd(quotesMsg.SecurityId); var bid = quotesMsg.GetBestBid(); if (bid != null) { pair.First = bid.Value.Price; } var ask = quotesMsg.GetBestAsk(); if (ask != null) { pair.Second = ask.Value.Price; } break; } case MessageTypes.OrderRegister: { var regMsg = (OrderRegisterMessage)message; var prices = _bestPrices.TryGetValue(regMsg.SecurityId); if (prices != null) { var price = regMsg.Side == Sides.Buy ? prices.Second : prices.First; if (price != 0) { _plannedPrices.Add(regMsg.TransactionId, Tuple.Create(regMsg.Side, price)); } } break; } case MessageTypes.Execution: { var execMsg = (ExecutionMessage)message; if (execMsg.HasTradeInfo()) { var plannedPrice = _plannedPrices.TryGetValue(execMsg.OriginalTransactionId); if (plannedPrice != null) { var slippage = execMsg.TradePrice - plannedPrice.Item2; if (plannedPrice.Item1 == Sides.Sell) { slippage = -slippage; } if (slippage < 0 && !CalculateNegative) { slippage = 0; } return(slippage); } } break; } } return(null); }
private void ProcessBestQuote(string symbol, string exchange, double price, int size, int numOfOrders, UpdateType updateType, int ssboe, int usecs, Level1Fields priceField, Level1Fields volumeField) { var secId = new SecurityId { SecurityCode = symbol, BoardCode = exchange }; var time = RithmicUtils.ToTime(ssboe, usecs); SendOutMessage(new Level1ChangeMessage { SecurityId = secId, ServerTime = time, } .TryAdd(priceField, price.ToDecimal()) .TryAdd(volumeField, (decimal)size)); switch (updateType) { // [gene.sato] For best bid/ask the update type does not apply. // The update type is for market depth/level 2 updates. case UpdateType.Undefined: // break; case UpdateType.Solo: { //SendOutMessage(new Level1ChangeMessage //{ // SecurityId = secId, // ServerTime = time, //} //.TryAdd(priceField, price.ToDecimal()) //.TryAdd(volumeField, (decimal)size)); break; } case UpdateType.Begin: case UpdateType.Middle: case UpdateType.Aggregated: { var pair = _quotes .SafeAdd(secId) .SafeAdd(time, key => new RefPair <BidInfo, AskInfo>()); pair.Second = new AskInfo { Price = price, NumOrders = numOfOrders, Size = size, }; break; } case UpdateType.End: FlushQuotes(secId); break; case UpdateType.Clear: break; default: throw new ArgumentOutOfRangeException(); } }
/// <summary> /// Process <see cref="MessageAdapterWrapper.InnerAdapter"/> output message. /// </summary> /// <param name="message">The message.</param> protected override void OnInnerAdapterNewOutMessage(Message message) { switch (message.Type) { case MessageTypes.Security: { var secMsg = (SecurityMessage)message; if (!IsAssociated(secMsg.SecurityId.BoardCode)) { var clone = (SecurityMessage)secMsg.Clone(); clone.SecurityId = CreateAssociatedId(clone.SecurityId); RaiseNewOutMessage(clone); } break; } case MessageTypes.Level1Change: { var level1Msg = (Level1ChangeMessage)message; if (!IsAssociated(level1Msg.SecurityId.BoardCode)) { // обновление BestXXX для ALL из конкретных тикеров var clone = (Level1ChangeMessage)level1Msg.Clone(); clone.SecurityId = CreateAssociatedId(clone.SecurityId); RaiseNewOutMessage(clone); } break; } case MessageTypes.QuoteChange: { var quoteMsg = (QuoteChangeMessage)message; if (quoteMsg.SecurityId.IsDefault()) { return; } //if (IsAssociated(quoteMsg.SecurityId.BoardCode)) // return; var builder = _quoteChangeDepthBuilders .SafeAdd(quoteMsg.SecurityId.SecurityCode, c => new QuoteChangeDepthBuilder(c, AssociatedBoardCode)); quoteMsg = builder.Process(quoteMsg); RaiseNewOutMessage(quoteMsg); break; } case MessageTypes.Execution: { var executionMsg = (ExecutionMessage)message; switch (executionMsg.ExecutionType) { case ExecutionTypes.Tick: case ExecutionTypes.OrderLog: { if (!IsAssociated(executionMsg.SecurityId.BoardCode)) { var clone = (ExecutionMessage)executionMsg.Clone(); clone.SecurityId = CreateAssociatedId(clone.SecurityId); RaiseNewOutMessage(clone); } break; } } break; } } base.OnInnerAdapterNewOutMessage(message); }
public TerminalStrategy() { var cmdSvc = ConfigManager.TryGetService <IStudioCommandService>(); if (cmdSvc == null) { return; } cmdSvc.Register <RegisterOrderCommand>(this, false, cmd => { var order = cmd.Order; if (order.Security == null) { order.Security = Security; } if (order.Portfolio == null) { order.Portfolio = Portfolio; } if (order.Volume == 0) { order.Volume = Volume; //при выставлении заявки с графика объем равен 0 } if (order.Type == OrderTypes.Market && !order.Security.Board.IsSupportMarketOrders) { order.Type = OrderTypes.Limit; order.Price = order.Security.GetMarketPrice(SafeGetConnector(), order.Direction) ?? 0; } order.ShrinkPrice(); RegisterOrder(order); }); cmdSvc.Register <ReRegisterOrderCommand>(this, false, cmd => ReRegisterOrder(cmd.OldOrder, cmd.NewOrder)); cmdSvc.Register <CancelOrderCommand>(this, false, cmd => { if (cmd.Mask != null) { Orders .Where(o => o.Security == cmd.Mask.Security && o.Portfolio == cmd.Mask.Portfolio && o.Price == cmd.Mask.Price && o.State == OrderStates.Active) .ForEach(CancelOrder); } else { cmd.Orders.ForEach(o => { if (o.Security == null) { o.Security = Security; } if (o.Portfolio == null) { o.Portfolio = Portfolio; } CancelOrder(o); }); } }); cmdSvc.Register <RevertPositionCommand>(this, false, cmd => { var pos = PositionManager.Position; if (pos == 0) { this.AddWarningLog(LocalizedStrings.Str3631); return; } if (cmd.Position != null) { ClosePosition(cmd.Position, cmd.Position.CurrentValue.Abs() * 2); } else { if (pos < 0) { this.BuyAtMarket(pos * 2); } else { this.SellAtMarket(pos * 2); } } }); cmdSvc.Register <ClosePositionCommand>(this, false, cmd => { if (PositionManager.Position == 0) { this.AddWarningLog(LocalizedStrings.Str3632); return; } if (cmd.Position != null) { ClosePosition(cmd.Position, cmd.Position.CurrentValue.Abs()); } else { this.ClosePosition(); } }); cmdSvc.Register <CancelAllOrdersCommand>(this, false, cmd => CancelActiveOrders()); cmdSvc.Register <RequestMarketDataCommand>(this, false, cmd => { var security = cmd.Security ?? Security; this.AddDebugLog("RequestMarketDataCommand {0} {1}", cmd.Type, security); if (TrySubscribe(_subscriptions.SafeAdd(cmd.Type), security) && CanProcess) { Subscribe(cmd.Type, security); } }); cmdSvc.Register <RefuseMarketDataCommand>(this, false, cmd => { var security = cmd.Security ?? Security; this.AddDebugLog("RefuseMarketDataCommand {0} {1}", cmd.Type, security); if (TryUnSubscribe(_subscriptions.SafeAdd(cmd.Type), security) && CanProcess) { UnSubscribe(cmd.Type, security); } }); cmdSvc.Register <SubscribeCandleElementCommand>(this, false, cmd => SetSource(cmd.Element, cmd.CandleSeries)); cmdSvc.Register <UnSubscribeCandleElementCommand>(this, false, cmd => RemoveSource(cmd.Element)); cmdSvc.Register <SubscribeIndicatorElementCommand>(this, false, cmd => SetSource(cmd.Element, cmd.CandleSeries, cmd.Indicator)); cmdSvc.Register <UnSubscribeIndicatorElementCommand>(this, false, cmd => RemoveSource(cmd.Element)); cmdSvc.Register <SubscribeTradeElementCommand>(this, false, cmd => Subscribe(_tradeElements, cmd.Security, cmd.Element)); cmdSvc.Register <UnSubscribeTradeElementCommand>(this, false, cmd => UnSubscribe(_tradeElements, cmd.Element)); cmdSvc.Register <SubscribeOrderElementCommand>(this, false, cmd => Subscribe(_orderElements, cmd.Security, cmd.Element)); cmdSvc.Register <UnSubscribeOrderElementCommand>(this, false, cmd => UnSubscribe(_orderElements, cmd.Element)); cmdSvc.Register <RequestTradesCommand>(this, false, cmd => new NewTradesCommand(SafeGetConnector().Trades).Process(this)); cmdSvc.Register <RequestPortfoliosCommand>(this, false, cmd => new PortfolioCommand(Portfolio, true).Process(this)); cmdSvc.Register <RequestPositionsCommand>(this, false, cmd => PositionManager.Positions.ForEach(p => new PositionCommand(CurrentTime, p, true).Process(this))); }