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; }
/// <summary> /// Создать <see cref="QuikSessionHolder"/>. /// </summary> /// <param name="transactionIdGenerator">Генератор идентификаторов транзакций.</param> public QuikSessionHolder(IdGenerator transactionIdGenerator) : base(transactionIdGenerator) { CreateTables(); IsAsyncMode = true; Path = QuikTerminal.GetDefaultPath(); SecurityClassInfo.Add("SPBOPT", RefTuple.Create(SecurityTypes.Option, ExchangeBoard.Forts.Code)); SecurityClassInfo.Add("SPBFUT", RefTuple.Create(SecurityTypes.Future, ExchangeBoard.Forts.Code)); // http://stocksharp.com/forum/yaf_postsm11628_Pozitsii-po-dierivativam.aspx#post11628 SecurityClassInfo.Add("OPTUX", RefTuple.Create(SecurityTypes.Option, ExchangeBoard.Ux.Code)); SecurityClassInfo.Add("FUTUX", RefTuple.Create(SecurityTypes.Future, ExchangeBoard.Ux.Code)); //SecurityClassInfo.Add("GTS", RefTuple.Create(SecurityTypes.Stock, ExchangeBoard.UxStock.Code)); // http://groups.google.ru/group/stocksharp/msg/28518b814c925521 SecurityClassInfo.Add("RTSST", RefTuple.Create(SecurityTypes.Stock, ExchangeBoard.Forts.Code)); SecurityClassInfo.Add("QJSIM", RefTuple.Create(SecurityTypes.Stock, ExchangeBoard.MicexJunior.Code)); SecurityClassInfo.Add("RTSIDX", RefTuple.Create(SecurityTypes.Index, ExchangeBoard.Forts.Code)); UtcOffset = TimeHelper.Moscow.BaseUtcOffset; IsTransactionEnabled = true; IsMarketDataEnabled = true; }
/// <summary> /// To get historical ticks. /// </summary> /// <param name="securityId">The instrument identifier for which you need to get all trades.</param> /// <param name="from">Begin period.</param> /// <param name="to">End period.</param> /// <param name="isSuccess">Whether all data were obtained successfully or the download process has been interrupted.</param> /// <returns>Historical ticks.</returns> public IEnumerable <Level1ChangeMessage> GetHistoricalLevel1(SecurityId securityId, DateTimeOffset from, DateTimeOffset to, out bool isSuccess) { this.AddInfoLog(LocalizedStrings.Str2145Params, securityId, from, to); var transactionId = TransactionIdGenerator.GetNextId(); var info = RefTuple.Create(new List <Level1ChangeMessage>(), new SyncObject(), false, securityId, false); _level1Info.Add(transactionId, info); SendInMessage(new MarketDataMessage { SecurityId = securityId, DataType = MarketDataTypes.Level1, From = from, To = to, IsSubscribe = true, TransactionId = transactionId, }); lock (info.Second) { if (!info.Third) { info.Second.Wait(); } } isSuccess = info.Fifth; return(info.First); }
/// <summary> /// Создать <see cref="SmartComMessageAdapter"/>. /// </summary> /// <param name="transactionIdGenerator">Генератор идентификаторов транзакций.</param> public SmartComMessageAdapter(IdGenerator transactionIdGenerator) : base(transactionIdGenerator) { Version = SmartComVersions.V3; SecurityClassInfo.Add("OPT", RefTuple.Create(SecurityTypes.Option, ExchangeBoard.Forts.Code)); SecurityClassInfo.Add("OPTM", RefTuple.Create(SecurityTypes.Option, ExchangeBoard.Forts.Code)); SecurityClassInfo.Add("FUT", RefTuple.Create(SecurityTypes.Future, ExchangeBoard.Forts.Code)); SecurityClassInfo.Add("FXMFD", RefTuple.Create(SecurityTypes.Currency, ExchangeBoard.Mfd.Code)); SecurityClassInfo.Add("WFMFD", RefTuple.Create(SecurityTypes.Index, ExchangeBoard.Mfd.Code)); SecurityClassInfo.Add("WIMFD", RefTuple.Create(SecurityTypes.Index, ExchangeBoard.Mfd.Code)); SecurityClassInfo.Add("EQBR", RefTuple.Create(SecurityTypes.Stock, ExchangeBoard.MicexEqbr.Code)); SecurityClassInfo.Add("TQBR", RefTuple.Create(SecurityTypes.Stock, ExchangeBoard.MicexTqbr.Code)); SecurityClassInfo.Add("TQNE", RefTuple.Create(SecurityTypes.Stock, ExchangeBoard.MicexTqne.Code)); SecurityClassInfo.Add("EQNE", RefTuple.Create(SecurityTypes.Stock, ExchangeBoard.MicexEqne.Code)); SecurityClassInfo.Add("EQOB", RefTuple.Create(SecurityTypes.Bond, ExchangeBoard.MicexEqob.Code)); SecurityClassInfo.Add("EQNB", RefTuple.Create(SecurityTypes.Bond, ExchangeBoard.MicexEqnb.Code)); SecurityClassInfo.Add("EQDB", RefTuple.Create(SecurityTypes.Bond, ExchangeBoard.MicexEqdb.Code)); SecurityClassInfo.Add("EQOS", RefTuple.Create(SecurityTypes.Bond, ExchangeBoard.MicexEqos.Code)); SecurityClassInfo.Add("TQOB", RefTuple.Create(SecurityTypes.Bond, ExchangeBoard.MicexTqob.Code)); SecurityClassInfo.Add("TQLV", RefTuple.Create(SecurityTypes.Stock, ExchangeBoard.MicexTqlv.Code)); PortfolioBoardCodes = new Dictionary <string, string> { { "EQ", ExchangeBoard.MicexEqbr.Code }, { "FOB", ExchangeBoard.MicexFbcb.Code }, { "RTS_FUT", ExchangeBoard.Forts.Code }, }; UpdatePlatform(); this.AddMarketDataSupport(); this.AddTransactionalSupport(); this.RemoveSupportedMessage(MessageTypes.OrderStatus); }
private void SetSource(ChartIndicatorElement element, CandleSeries candleSeries, IIndicator indicator) { RefPair <DateTimeOffset, IDictionary <IChartElement, object> >[] values = null; lock (_syncRoot) { _indicators[element] = indicator; var isNew = !_elementsBySeries.ContainsKey(candleSeries); if (!isNew && CanProcess) { values = ProcessHistoryCandles(element, candleSeries); } else if (isNew) { SubscribeSeries(candleSeries); } var lastDate = values == null || values.IsEmpty() ? DateTimeOffset.MinValue : values.Last().First; _elementsInfo.SafeAdd(element, e => RefTuple.Create(lastDate, candleSeries)); _elementsBySeries.SafeAdd(candleSeries).Add(element); } if (values != null && values.Length > 0) { new ChartDrawCommand(values).Process(this); } }
/// <inheritdoc /> protected override void OnSendInMessage(Message message) { switch (message.Type) { case MessageTypes.Reset: _states.Clear(); break; case MessageTypes.MarketData: { var mdMsg = (MarketDataMessage)message; if (mdMsg.DataType == MarketDataTypes.MarketDepth) { if (mdMsg.IsSubscribe) { if (IsSupportOrderBookIncrements) { _states.Add(mdMsg.TransactionId, RefTuple.Create(new QuotesDict(new BackwardComparer <decimal>()), new QuotesDict(), _none)); } } else { _states.Remove(mdMsg.OriginalTransactionId); } } break; } } base.OnSendInMessage(message); }
public static void Draw(this IChart chart, DateTimeOffset time, IDictionary <IChartElement, object> values) { if (chart == null) { throw new ArgumentNullException(nameof(chart)); } chart.Draw(new[] { RefTuple.Create(time, values) }); }
public void AddOrder(OrderRegisterMessage message) { if (message is null) { throw new ArgumentNullException(nameof(message)); } _ordersInfo[message.TransactionId] = RefTuple.Create(message.Side, message.Price, (decimal?)message.Volume); }
private MarketDataMessage ProcessMarketDataRequest(MarketDataMessage message) { if (message.IsSubscribe) { if (!InnerAdapter.IsMarketDataTypeSupported(DataType.OrderLog)) { return(message); } var isBuild = message.BuildMode == MarketDataBuildModes.Build && message.BuildFrom == DataType.OrderLog; if (message.DataType2 == DataType.MarketDepth) { if (isBuild || !InnerAdapter.IsMarketDataTypeSupported(message.ToDataType())) { var secId = GetSecurityId(message.SecurityId); IOrderLogMarketDepthBuilder builder = null; if (InnerAdapter.IsSecurityRequired(DataType.OrderLog)) { builder = message.DepthBuilder ?? InnerAdapter.CreateOrderLogMarketDepthBuilder(secId); } _subscriptionIds.Add(message.TransactionId, RefTuple.Create(true, builder, new SyncObject())); message = message.TypedClone(); message.DataType2 = DataType.OrderLog; this.AddInfoLog("OL->MD subscribed {0}/{1}.", secId, message.TransactionId); } } else if (message.DataType2 == DataType.Ticks) { if (isBuild || !InnerAdapter.IsMarketDataTypeSupported(message.ToDataType())) { var secId = GetSecurityId(message.SecurityId); _subscriptionIds.Add(message.TransactionId, RefTuple.Create(false, (IOrderLogMarketDepthBuilder)null, new SyncObject())); message = message.TypedClone(); message.DataType2 = DataType.OrderLog; this.AddInfoLog("OL->TICK subscribed {0}/{1}.", secId, message.TransactionId); } } } else { RemoveSubscription(message.OriginalTransactionId); } return(message); }
private void ProcessOrderRegister(OrderRegisterMessage regMsg) { var condition = (BitStampOrderCondition)regMsg.Condition; switch (regMsg.OrderType) { case null: case OrderTypes.Limit: case OrderTypes.Market: break; case OrderTypes.Conditional: { if (!condition.IsWithdraw) { break; } var withdrawId = _httpClient.Withdraw(regMsg.SecurityId.SecurityCode, regMsg.Volume, condition.WithdrawInfo); SendOutMessage(new ExecutionMessage { ExecutionType = ExecutionTypes.Transaction, OrderId = withdrawId, ServerTime = CurrentTime.ConvertToUtc(), OriginalTransactionId = regMsg.TransactionId, OrderState = OrderStates.Done, HasOrderInfo = true, }); ProcessPortfolioLookup(null); return; } default: throw new NotSupportedException(LocalizedStrings.Str1601Params.Put(regMsg.OrderType, regMsg.TransactionId)); } var price = regMsg.OrderType == OrderTypes.Market ? (decimal?)null : regMsg.Price; var result = _httpClient.RegisterOrder(regMsg.SecurityId.ToCurrency(), regMsg.Side.ToString().ToLowerInvariant(), price, regMsg.Volume, condition?.StopPrice, regMsg.TillDate == DateTime.Today, regMsg.TimeInForce == TimeInForce.CancelBalance); _orderInfo.Add(result.Id, RefTuple.Create(regMsg.TransactionId, regMsg.Volume)); SendOutMessage(new ExecutionMessage { ExecutionType = ExecutionTypes.Transaction, OrderId = result.Id, ServerTime = result.Time, OriginalTransactionId = regMsg.TransactionId, OrderState = OrderStates.Active, HasOrderInfo = true, }); }
/// <summary> /// Создать <see cref="SmartComSessionHolder"/>. /// </summary> /// <param name="transactionIdGenerator">Генератор идентификаторов транзакций.</param> public SmartComSessionHolder(IdGenerator transactionIdGenerator) : base(transactionIdGenerator) { Version = SmartComVersions.V3; IsTransactionEnabled = true; IsMarketDataEnabled = true; SecurityClassInfo.Add("OPT", RefTuple.Create(SecurityTypes.Option, ExchangeBoard.Forts.Code)); SecurityClassInfo.Add("OPTM", RefTuple.Create(SecurityTypes.Option, ExchangeBoard.Forts.Code)); SecurityClassInfo.Add("FUT", RefTuple.Create(SecurityTypes.Future, ExchangeBoard.Forts.Code)); }
/// <summary> /// Создать <see cref="AlfaDirectSessionHolder"/>. /// </summary> /// <param name="transactionIdGenerator">Генератор идентификаторов транзакций.</param> public AlfaDirectSessionHolder(IdGenerator transactionIdGenerator) : base(transactionIdGenerator) { SecurityClassInfo.Add("FORTS", RefTuple.Create(SecurityTypes.Stock, ExchangeBoard.Forts.Code)); SecurityClassInfo.Add("INDEX", RefTuple.Create(SecurityTypes.Index, ExchangeBoard.Micex.Code)); SecurityClassInfo.Add("INDEX2", RefTuple.Create(SecurityTypes.Index, "INDEX")); SecurityClassInfo.Add("MICEX_SHR_T", RefTuple.Create(SecurityTypes.Stock, ExchangeBoard.Micex.Code)); SecurityClassInfo.Add("RTS_STANDARD", RefTuple.Create(SecurityTypes.Stock, ExchangeBoard.Forts.Code)); IsTransactionEnabled = true; IsMarketDataEnabled = true; }
public void Process(ExecutionMessage message) { if (message == null) { throw new ArgumentNullException(nameof(message)); } var key = Tuple.Create(message.Side, message.OrderPrice); switch (message.OrderState) { case OrderStates.Done: case OrderStates.Failed: { var pair = _executions.TryGetValue(key); if (pair == null) { break; } var balance = pair.First.TryGetAndRemove(message.OriginalTransactionId); if (pair.First.Count == 0) { _executions.Remove(key); } else { pair.Second -= balance; } break; } case OrderStates.Active: { var balance = message.Balance; if (balance != null) { var pair = _executions.SafeAdd(key, k => RefTuple.Create(new Dictionary <long, decimal>(), 0M)); var prev = pair.First.TryGetValue(message.OriginalTransactionId); pair.First[message.OriginalTransactionId] = balance.Value; pair.Second += balance.Value - prev; } break; } } }
/// <summary> /// Создать <see cref="AlfaDirectMessageAdapter"/>. /// </summary> /// <param name="transactionIdGenerator">Генератор идентификаторов транзакций.</param> public AlfaDirectMessageAdapter(IdGenerator transactionIdGenerator) : base(transactionIdGenerator) { Platform = Platforms.x86; this.AddMarketDataSupport(); this.AddTransactionalSupport(); SecurityClassInfo.Add("FORTS", RefTuple.Create(SecurityTypes.Stock, ExchangeBoard.Forts.Code)); SecurityClassInfo.Add("INDEX", RefTuple.Create(SecurityTypes.Index, ExchangeBoard.Micex.Code)); SecurityClassInfo.Add("INDEX2", RefTuple.Create(SecurityTypes.Index, "INDEX")); SecurityClassInfo.Add("MICEX_SHR_T", RefTuple.Create(SecurityTypes.Stock, ExchangeBoard.Micex.Code)); SecurityClassInfo.Add("RTS_STANDARD", RefTuple.Create(SecurityTypes.Stock, ExchangeBoard.Forts.Code)); }
private void ProcessInPortfolioMessage(PortfolioMessage message) { var sendIn = false; var pfName = message.PortfolioName; RefPair <PortfolioMessage, int> pair; lock (_sync) { pair = _pfSubscribers.TryGetValue(pfName) ?? RefTuple.Create((PortfolioMessage)message.Clone(), 0); var subscribersCount = pair.Second; if (message.IsSubscribe) { subscribersCount++; sendIn = subscribersCount == 1; } else { if (subscribersCount > 0) { subscribersCount--; sendIn = subscribersCount == 0; } //else // sendOutMsg = NonExist(message); } if (subscribersCount > 0) { pair.Second = subscribersCount; _pfSubscribers[pfName] = pair; } else { _pfSubscribers.Remove(pfName); } } if (sendIn) { if (!message.IsSubscribe && message.OriginalTransactionId == 0) { message.OriginalTransactionId = pair.First.TransactionId; } base.SendInMessage(message); } }
private void SetSource(ChartCandleElement element, CandleSeries candleSeries) { lock (_syncRoot) { var isNew = !_elementsBySeries.ContainsKey(candleSeries); if ((isNew || !CanProcess) && isNew) { SubscribeSeries(candleSeries); } _elementsInfo.SafeAdd(element, e => RefTuple.Create(DateTimeOffset.MinValue, candleSeries)); _elementsBySeries.SafeAdd(candleSeries).Add(element); } }
private void ProcessInnerAdapterConnectMessage(IMessageAdapter innerAdapter, ConnectMessage message) { if (message.Error != null) { SessionHolder.AddErrorLog(LocalizedStrings.Str625Params, innerAdapter.GetType().Name, message.Error); } Exception error = null; var canProcess = _innerAdapters.SyncGet(c => { var connected = message.Error == null; _adapterStates[innerAdapter] = RefTuple.Create(connected, message.Error); if (_canRaiseConnected && connected) { _canRaiseConnected = false; _canRaiseDisconnected = true; ResetConnectionErrors(); return(true); } if (_adapterStates.Count == c.Count) { // произошла ошибка и нет ни одного подключенного коннектора if (_adapterStates.Values.All(p => !p.First)) { error = new AggregateException(LocalizedStrings.Str626, _adapterStates.Values.Select(p => p.Second)); return(true); } ResetConnectionErrors(); } return(false); }); if (canProcess) { SendOutMessage(new ConnectMessage { Error = error }); } }
public static void FillDefault(this IDictionary <string, RefPair <SecurityTypes, string> > securityClassInfo) { securityClassInfo.Add("SPBOPT", RefTuple.Create(SecurityTypes.Option, ExchangeBoard.Forts.Code)); securityClassInfo.Add("SPBFUT", RefTuple.Create(SecurityTypes.Future, ExchangeBoard.Forts.Code)); // http://stocksharp.com/forum/yaf_postsm11628_Pozitsii-po-dierivativam.aspx#post11628 securityClassInfo.Add("OPTUX", RefTuple.Create(SecurityTypes.Option, ExchangeBoard.Ux.Code)); securityClassInfo.Add("FUTUX", RefTuple.Create(SecurityTypes.Future, ExchangeBoard.Ux.Code)); //securityClassInfo.Add("GTS", RefTuple.Create(SecurityTypes.Stock, ExchangeBoard.UxStock.Code)); // http://groups.google.ru/group/stocksharp/msg/28518b814c925521 securityClassInfo.Add("RTSST", RefTuple.Create(SecurityTypes.Stock, ExchangeBoard.Forts.Code)); securityClassInfo.Add("QJSIM", RefTuple.Create(SecurityTypes.Stock, ExchangeBoard.MicexJunior.Code)); securityClassInfo.Add("RTSIDX", RefTuple.Create(SecurityTypes.Index, ExchangeBoard.Forts.Code)); }
/// <summary> /// To get historical candles. /// </summary> /// <param name="security">The instrument for which you need to get candles.</param> /// <param name="candleMessageType">The candle message type.</param> /// <param name="arg">The candle parameter (for example, time-frame).</param> /// <param name="count">Maximum ticks count.</param> /// <param name="isSuccess">Whether all data were obtained successfully or the download process has been interrupted.</param> /// <returns>Historical candles.</returns> public IEnumerable <CandleMessage> GetHistoricalCandles(Security security, Type candleMessageType, object arg, long count, out bool isSuccess) { if (security == null) { throw new ArgumentNullException(nameof(security)); } //if (timeFrame <= TimeSpan.Zero) // throw new ArgumentException("Тайм-фрейм должен быть больше 0."); var transactionId = TransactionIdGenerator.GetNextId(); var series = new CandleSeries(candleMessageType.ToCandleType(), security, arg); this.AddInfoLog(LocalizedStrings.Str2146Params, series, count); var info = RefTuple.Create(new List <CandleMessage>(), new SyncObject(), false, series, false); _candleInfo.Add(transactionId, info); var mdMsg = new MarketDataMessage { //SecurityId = GetSecurityId(series.Security), DataType = GetCandleType(series.CandleType), TransactionId = transactionId, Count = count, Arg = arg, IsSubscribe = true, }.FillSecurityInfo(this, series.Security); _candleSeries.Add(transactionId, series); SendInMessage(mdMsg); lock (info.Second) { if (!info.Third) { info.Second.Wait(); } } isSuccess = info.Fifth; return(info.First); }
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.Transaction, OrderId = order.Id, ServerTime = order.Time.ApplyTimeZone(TimeZoneInfo.Utc), OriginalTransactionId = regMsg.TransactionId, OrderState = OrderStates.Active, }); }
private void ProcessSubscribeAction(MarketDataMessage message) { if (message == null) { throw new ArgumentNullException("message"); } var key = Tuple.Create(message.SecurityId, message.DataType); if (_subscriptionQueue.ContainsKey(key)) { return; } var enumerator = GetConnectedAdapters().ToArray().Cast <IMessageAdapter>().GetEnumerator(); _subscriptionQueue.Add(key, RefTuple.Create(enumerator, false)); ProcessSubscriptionAction(enumerator, message); }
private void ProcessInnerAdapterDisconnectMessage(IMessageAdapter innerAdapter, DisconnectMessage message) { if (message.Error != null) { SessionHolder.AddErrorLog(LocalizedStrings.Str627Params, innerAdapter.GetType().Name, message.Error); } Exception error = null; var canProcess = _innerAdapters.SyncGet(c => { _adapterStates[innerAdapter] = RefTuple.Create(false, message.Error); if (_canRaiseDisconnected && _adapterStates.Values.All(p => !p.First)) { _canRaiseConnected = true; _canRaiseDisconnected = false; var errors = _adapterStates.Values.Where(p => p.Second != null).Select(p => p.Second).ToArray(); if (errors.Length != 0) { error = new AggregateException(LocalizedStrings.Str628, errors); ResetConnectionErrors(); } DisposeInnerAdapters(); return(true); } return(false); }); if (canProcess) { SendOutMessage(new DisconnectMessage { Error = error }); } }
/// <summary> /// To get historical candles. /// </summary> /// <param name="security">The instrument for which you need to get candles.</param> /// <param name="candleType">The candle type.</param> /// <param name="arg">The candle parameter (for example, time-frame).</param> /// <param name="from">Begin period.</param> /// <param name="to">End period.</param> /// <param name="isSuccess">Whether all data were obtained successfully or the download process has been interrupted.</param> /// <returns>Historical candles.</returns> public IEnumerable <CandleMessage> GetHistoricalCandles(Security security, Type candleType, object arg, DateTimeOffset from, DateTimeOffset to, out bool isSuccess) { if (security == null) { throw new ArgumentNullException(nameof(security)); } //if (timeFrame <= TimeSpan.Zero) // throw new ArgumentException("Тайм-фрейм должен быть больше 0."); if (from > to) { throw new ArgumentException(LocalizedStrings.Str2147); } var id = TransactionIdGenerator.GetNextId(); var series = new CandleSeries(candleType, security, arg); this.AddInfoLog(LocalizedStrings.Str2148Params, series, from, to); var info = RefTuple.Create(new List <CandleMessage>(), new SyncObject(), false, series, false); _candleInfo.Add(id, info); SubscribeCandles(series, from, to, id); lock (info.Second) { if (!info.Third) { info.Second.Wait(); } } isSuccess = info.Fifth; return(info.First); }
/// <summary> /// Создать <see cref="SmartComMessageAdapter"/>. /// </summary> /// <param name="transactionIdGenerator">Генератор идентификаторов транзакций.</param> public SmartComMessageAdapter(IdGenerator transactionIdGenerator) : base(transactionIdGenerator) { Version = SmartComVersions.V3; SecurityClassInfo.Add("OPT", RefTuple.Create(SecurityTypes.Option, ExchangeBoard.Forts.Code)); SecurityClassInfo.Add("OPTM", RefTuple.Create(SecurityTypes.Option, ExchangeBoard.Forts.Code)); SecurityClassInfo.Add("FUT", RefTuple.Create(SecurityTypes.Future, ExchangeBoard.Forts.Code)); PortfolioBoardCodes = new Dictionary <string, string> { { "EQ", ExchangeBoard.MicexEqbr.Code }, { "FOB", ExchangeBoard.MicexFbcb.Code }, { "RTS_FUT", ExchangeBoard.Forts.Code }, }; UpdatePlatform(); this.AddMarketDataSupport(); this.AddTransactionalSupport(); this.RemoveSupportedMessage(MessageTypes.OrderStatus); }
/// <summary> /// To get historical ticks. /// </summary> /// <param name="security">The instrument for which you need to get all trades.</param> /// <param name="from">Begin period.</param> /// <param name="to">End period.</param> /// <param name="isSuccess">Whether all data were obtained successfully or the download process has been interrupted.</param> /// <returns>Historical ticks.</returns> public IEnumerable <ExecutionMessage> GetHistoricalTicks(Security security, DateTime from, DateTime to, out bool isSuccess) { if (security == null) { throw new ArgumentNullException(nameof(security)); } this.AddInfoLog(LocalizedStrings.Str2145Params, security, from, to); var transactionId = TransactionIdGenerator.GetNextId(); var info = RefTuple.Create(new List <ExecutionMessage>(), new SyncObject(), false, security, false); _ticksInfo.Add(transactionId, info); SendInMessage(new MarketDataMessage { SecurityId = security.ToSecurityId(), DataType = MarketDataTypes.Trades, From = from, To = to, IsSubscribe = true, TransactionId = transactionId, }); lock (info.Second) { if (!info.Third) { info.Second.Wait(); } } isSuccess = info.Fifth; return(info.First); }
private void ProcessMessage <TMessage>(SecurityId securityId, TMessage message, Func <TMessage, TMessage, TMessage> processSuspend) where TMessage : Message { var native = securityId.Native; if (native != null) { SecurityId?fullSecurityId; lock (_syncRoot) fullSecurityId = _securityIds.TryGetValue2(native); if (fullSecurityId == null) { lock (_syncRoot) { var tuple = _suspendedOutMessages.SafeAdd(securityId, key => RefTuple.Create((List <Message>)null, (Dictionary <MessageTypes, Message>)null)); var clone = message.Clone(); if (processSuspend == null) { if (tuple.First == null) { tuple.First = new List <Message>(); } tuple.First.Add(clone); } else { if (tuple.Second == null) { tuple.Second = new Dictionary <MessageTypes, Message>(); } var prev = tuple.Second.TryGetValue(clone.Type); tuple.Second[clone.Type] = prev == null ? clone : processSuspend((TMessage)prev, (TMessage)clone); } } return; } message.ReplaceSecurityId(fullSecurityId.Value); } else { var securityCode = securityId.SecurityCode; var boardCode = securityId.BoardCode; var isSecCodeEmpty = securityCode.IsEmpty(); if (isSecCodeEmpty && message.Type != MessageTypes.Execution) { throw new InvalidOperationException(); } if (!isSecCodeEmpty && boardCode.IsEmpty()) { SecurityId?foundId = null; lock (_syncRoot) { foreach (var id in _securityIds.Values) { if (!id.SecurityCode.CompareIgnoreCase(securityCode)) { continue; } if (securityId.SecurityType != null && securityId.SecurityType != id.SecurityType) { continue; } foundId = id; } if (foundId == null) { var tuple = _suspendedOutMessages.SafeAdd(securityId, key => RefTuple.Create(new List <Message>(), (Dictionary <MessageTypes, Message>)null)); tuple.First.Add(message.Clone()); return; } } message.ReplaceSecurityId(foundId.Value); //// если указан код и тип инструмента, то пытаемся найти инструмент по ним //if (securityId.SecurityType != null) //{ //} //else // throw new ArgumentException(nameof(securityId), LocalizedStrings.Str682Params.Put(securityCode, securityId.SecurityType)); } } base.OnInnerAdapterNewOutMessage(message); }
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); } } }
/// <inheritdoc /> protected override bool OnSendInMessage(Message message) { switch (message.Type) { case MessageTypes.Reset: ClearState(); break; case MessageTypes.MarketData: { var mdMsg = (MarketDataMessage)message; if (mdMsg.IsSubscribe) { var transId = mdMsg.TransactionId; lock (_sync) { if (_allChilds.TryGetValue(transId, out var tuple)) { if (tuple.Second != SubscriptionStates.Stopped) { if (tuple.Second == SubscriptionStates.Finished) { RaiseNewOutMessage(new SubscriptionFinishedMessage { OriginalTransactionId = transId, }); } else { RaiseNewOutMessage(new SubscriptionResponseMessage { OriginalTransactionId = transId, Error = new InvalidOperationException(LocalizedStrings.SubscriptionInvalidState.Put(transId, tuple.Second)), }); } return(true); } var child = _parents[tuple.First].Child[mdMsg.SecurityId]; child.State = SubscriptionStates.Active; _toFlush.AddRange(child.Suspended.CopyAndClear()); this.AddDebugLog("New ALL map (active): {0}/{1} TrId={2}", child.Origin.SecurityId, child.Origin.DataType2, mdMsg.TransactionId); RaiseNewOutMessage(new SubscriptionResponseMessage { OriginalTransactionId = transId }); return(true); } else { if (!IsSecurityRequired(mdMsg.DataType2) || mdMsg.SecurityId == default) { var existing = _parents.FirstOrDefault(p => p.Value.Origin.DataType2 == mdMsg.DataType2).Value; if (existing == null) { var parent = new ParentSubscription(mdMsg.TypedClone()); _parents.Add(transId, parent); // first child is parent _allChilds.Add(transId, RefTuple.Create(transId, SubscriptionStates.Stopped)); // do not specify security cause adapter doesn't require it mdMsg.SecurityId = default; Extensions.AllSecurity.CopyEx(mdMsg, false); } else { var childs = existing.Child; if (mdMsg.SecurityId != default) { var child = childs.SafeAdd(mdMsg.SecurityId, key => new ChildSubscription(mdMsg.TypedClone())); child.Subscribers.Add(transId, mdMsg.TypedClone()); } else { foreach (var pair in childs) { pair.Value.Subscribers.Add(transId, mdMsg.TypedClone()); } } RaiseNewOutMessage(new SubscriptionResponseMessage { OriginalTransactionId = transId }); return(true); } } } } } else { var childIds = ArrayHelper.Empty <long>(); lock (_sync) { if (_allChilds.TryGetAndRemove(mdMsg.OriginalTransactionId, out var tuple)) { this.AddDebugLog("Sec ALL child {0} unsubscribe.", mdMsg.OriginalTransactionId); Exception error = null; if (!tuple.Second.IsActive()) { error = new InvalidOperationException(LocalizedStrings.SubscriptionInvalidState.Put(mdMsg.OriginalTransactionId, tuple.Second)); } else { var childs = _parents[tuple.First].Child; var pair = childs.FirstOrDefault(p => p.Value.Origin.TransactionId == mdMsg.OriginalTransactionId); var childSubscription = pair.Value; if (childSubscription == null) { error = new InvalidOperationException(LocalizedStrings.SubscriptionNonExist.Put(mdMsg.OriginalTransactionId)); } else { if (childSubscription.Subscribers.Remove(mdMsg.OriginalTransactionId)) { if (childSubscription.Subscribers.Count == 0) { childs.Remove(pair.Key); } } else { error = new InvalidOperationException(LocalizedStrings.SubscriptionNonExist.Put(mdMsg.OriginalTransactionId)); } } } RaiseNewOutMessage(new SubscriptionResponseMessage { OriginalTransactionId = mdMsg.TransactionId, Error = error, }); return(true); } if (_parents.TryGetAndRemove(mdMsg.OriginalTransactionId, out var tuple2)) { childIds = tuple2.Child.Values.Select(s => s.Origin.TransactionId).ToArray(); } } foreach (var id in childIds) { RaiseNewOutMessage(new SubscriptionFinishedMessage { OriginalTransactionId = id }); } } break; } } return(base.OnSendInMessage(message)); }
private SubscriptionSecurityAllMessage CheckSubscription(ref Message message) { lock (_sync) { if (_toFlush.Count > 0) { var toFlush = _toFlush.CopyAndClear(); this.AddDebugLog("Flush {0} suspended.", toFlush.Length); foreach (var msg in toFlush) { RaiseNewOutMessage(msg); } } 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); }
private MarketDataMessage ProcessMarketDataRequest(MarketDataMessage message) { if (message.IsSubscribe) { if (!InnerAdapter.IsMarketDataTypeSupported(MarketDataTypes.OrderLog)) { return(message); } var isBuild = message.BuildMode == MarketDataBuildModes.Build && message.BuildFrom == MarketDataTypes.OrderLog; switch (message.DataType) { case MarketDataTypes.MarketDepth: { if (isBuild || !InnerAdapter.IsMarketDataTypeSupported(message.DataType)) { var secId = GetSecurityId(message.SecurityId); IOrderLogMarketDepthBuilder builder = null; if (InnerAdapter.IsSecurityRequired(DataType.OrderLog)) { builder = InnerAdapter.CreateOrderLogMarketDepthBuilder(secId); } _subscriptionIds.Add(message.TransactionId, RefTuple.Create(secId, true, builder)); message = (MarketDataMessage)message.Clone(); message.DataType = MarketDataTypes.OrderLog; this.AddInfoLog("OL->MD subscribed {0}/{1}.", secId, message.TransactionId); } break; } case MarketDataTypes.Trades: { if (isBuild || !InnerAdapter.IsMarketDataTypeSupported(message.DataType)) { var secId = GetSecurityId(message.SecurityId); _subscriptionIds.Add(message.TransactionId, RefTuple.Create(secId, false, (IOrderLogMarketDepthBuilder)null)); message = (MarketDataMessage)message.Clone(); message.DataType = MarketDataTypes.OrderLog; this.AddInfoLog("OL->TICK subscribed {0}/{1}.", secId, message.TransactionId); } break; } } } else { var tuple = _subscriptionIds.TryGetAndRemove(message.OriginalTransactionId); if (tuple != null) { this.AddInfoLog("OL->{0} unsubscribed {1}/{2}.", tuple.Second ? "MD" : "TICK", tuple.First, message.OriginalTransactionId); } } return(message); }