Пример #1
0
        private async Task <SubscriptionResult> SubscribeAsync(Instrument instrument, SubscriptionFlags flags)
        {
            using (LogManager.Scope())
            {
                InstrumentSubscription subscription = null;
                ContractMetadata       metadata     = null;

                var hasSubscriptionLock = false;
                try
                {
                    // Получаем параметры подписки на инструмент
                    using (subscriptionsLock.Lock())
                    {
                        subscriptionsByInstrument.TryGetValue(instrument, out subscription);
                    }

                    if (subscription == null)
                    {
                        // Получаем ID инструмента
                        var contractId = await instrumentResolver.GetContractIdAsync(instrument);

                        if (contractId == uint.MaxValue)
                        {
                            return(SubscriptionResult.Error(instrument, "Symbol is not resolved in tree node for CQG"));
                        }

                        using (subscriptionsLock.Lock())
                        {
                            if (!subscriptionsByInstrument.TryGetValue(instrument, out subscription))
                            {
                                if (!subscriptionsByContractId.TryGetValue(contractId, out subscription))
                                {
                                    subscription = new InstrumentSubscription(instrumentResolver, instrument, contractId);
                                    // Сразу захватываем блокировку
                                    subscription.AcquireFlagsLock();
                                    hasSubscriptionLock = true;
                                    subscriptionsByContractId.Add(contractId, subscription);

                                    contractMetadatas.TryGetValue(contractId, out metadata);
                                }

                                subscriptionsByInstrument.Add(instrument, subscription);
                            }
                        }
                    }
                    else
                    {
                        // Захватываем блокировку
                        subscription.AcquireFlagsLock();
                        hasSubscriptionLock = true;
                    }

                    // Подписываемся на инструмент с учетом флагов подписки
                    if ((subscription.Flags & flags) != flags)
                    {
                        // Нужные флаги подписки не проставлены, требуется доподписаться
                        MarketDataSubscription.Level?level = null;
                        switch (subscription.Flags | flags)
                        {
                        case SubscriptionFlags.InstrumentParams:
                            level = MarketDataSubscription.Level.TRADES_BBA_VOLUMES;
                            break;

                        case SubscriptionFlags.OrderBook:
                            level = MarketDataSubscription.Level.TRADES_BBA_DOM;
                            break;

                        case SubscriptionFlags.InstrumentParams | SubscriptionFlags.OrderBook:
                            level = MarketDataSubscription.Level.TRADES_BBA_DOM;
                            break;
                        }

                        if (level != null)
                        {
                            subscription.Flags |= flags;
                            RequestMarketDataSubscription(subscription, level.Value);
                        }
                    }

                    // При необходимости обрабатываем метаданные и выбрасываем события
                    if (metadata != null)
                    {
                        Process(subscription, metadata, (s, data) => s.Handle(data));
                    }

                    // Готово
                    var result = SubscriptionResult.OK(instrument);
                    return(result);
                }
                catch (OperationCanceledException)
                {
                    _Log.Warn().Print($"Unable to subscribe to {instrument} (operation has been cancelled)");
                    return(SubscriptionResult.Error(instrument, "Operation has been cancelled"));
                }
                catch (Exception e)
                {
                    _Log.Error().Print(e, $"Unable to subscribe to {instrument}");
                    return(SubscriptionResult.Error(instrument, e.Message));
                }
                finally
                {
                    if (subscription != null && hasSubscriptionLock)
                    {
                        subscription.ReleaseFlagsLock();
                    }
                }
            }
        }
Пример #2
0
        /// <summary>
        ///     Постановка заявки
        /// </summary>
        private async void SendTransactionInternal(NewOrderTransaction transaction)
        {
            using (LogManager.Scope())
            {
                try
                {
                    // Получаем счет для транзакции
                    int accountId;
                    var hasAccountId = true;
                    using (accountsLock.ReadLock())
                    {
                        if (!accountIdsByCode.TryGetValue(transaction.Account, out accountId))
                        {
                            hasAccountId = false;
                        }
                    }

                    if (!hasAccountId)
                    {
                        OnMessageReceived(TransactionReply.Rejected(
                                              transaction,
                                              $"Account \"{transaction.Account}\" is unknown"));
                        return;
                    }

                    // Получаем инструмент для транзации
                    uint contractId;
                    try
                    {
                        contractId = await instrumentResolver.GetContractIdAsync(transaction.Instrument);

                        if (contractId == uint.MaxValue)
                        {
                            return;
                        }
                    }
                    catch (OperationCanceledException)
                    {
                        OnMessageReceived(TransactionReply.Rejected(
                                              transaction,
                                              $"Instrument \"{transaction.Instrument.Code}\" is unknown"));
                        return;
                    }

                    // Пребразовываем цену
                    var price = instrumentResolver.ConvertPrice(contractId, transaction.Price);
                    if (price == null)
                    {
                        OnMessageReceived(TransactionReply.Rejected(transaction, "Unable to convert price"));
                        return;
                    }

                    // Формируем запрос
                    var msg = new OrderRequest
                    {
                        new_order = new NewOrder
                        {
                            order = new WebAPI.Order
                            {
                                cl_order_id = transaction.TransactionId.ToString("N"),
                                account_id  = accountId,
                                contract_id = contractId,
                                side        = (uint)ConvertionHelper.GetSide(transaction.Operation),
                                order_type  = (uint)ConvertionHelper.GetOrderType(transaction.Type),
                                duration    = (uint)ConvertionHelper.GetDuration(transaction.ExecutionCondition),
                                limit_price = price.Value,
                                qty         = transaction.Quantity,
                                is_manual   = transaction.IsManual,

                                user_attribute =
                                {
                                    new UserAttribute
                                    {
                                        name  = CommentAttributeName,
                                        value = transaction.Comment
                                    }
                                }
                            },
                            suspend = false
                        },
                        request_id = adapter.GetNextRequestId()
                    };

                    // Запоминаем заявку
                    using (ordersLock.Lock())
                    {
                        var order = new Order(transaction);
                        ordersByTransactionId.Add(transaction.TransactionId, order);
                    }

                    // Запоминаем транзакцию
                    StoreTransaction(msg.request_id, transaction);

                    Logger.Debug().PrintFormat("Sending {0}", transaction);
                    adapter.SendMessage(msg);
                }
                catch (Exception e)
                {
                    Logger.Error().Print(e, $"Failed to send {transaction}");
                    OnMessageReceived(TransactionReply.Rejected(transaction, "Unable to send order"));
                }
            }
        }
        private async Task <TimeBarRequest> PrepareTimeBarRequestAsync(
            Instrument instrument,
            DateTime begin,
            DateTime end,
            HistoryProviderSpan span,
            TimeBarRequest.RequestType type)
        {
            var contractId = await instrumentResolver.GetContractIdAsync(instrument);

            if (contractId == uint.MaxValue)
            {
                return(await Task.FromResult <TimeBarRequest>(null));
            }

            TimeBarParameters.BarUnit barUnit;
            uint unitsNumber = 0;

            switch (span)
            {
            case HistoryProviderSpan.Minute:
                barUnit     = TimeBarParameters.BarUnit.MIN;
                unitsNumber = 1;
                break;

            case HistoryProviderSpan.Minute5:
                barUnit     = TimeBarParameters.BarUnit.MIN;
                unitsNumber = 5;
                break;

            case HistoryProviderSpan.Minute10:
                barUnit     = TimeBarParameters.BarUnit.MIN;
                unitsNumber = 10;
                break;

            case HistoryProviderSpan.Minute15:
                barUnit     = TimeBarParameters.BarUnit.MIN;
                unitsNumber = 15;
                break;

            case HistoryProviderSpan.Minute30:
                barUnit     = TimeBarParameters.BarUnit.MIN;
                unitsNumber = 30;
                break;

            case HistoryProviderSpan.Hour:
                barUnit     = TimeBarParameters.BarUnit.HOUR;
                unitsNumber = 1;
                break;

            case HistoryProviderSpan.Hour4:
                barUnit     = TimeBarParameters.BarUnit.HOUR;
                unitsNumber = 4;
                break;

            case HistoryProviderSpan.Day:
                // Для DAY units_number не заполняется
                barUnit = TimeBarParameters.BarUnit.DAY;
                break;

            case HistoryProviderSpan.Week:
                // Для WEEK units_number не заполняется
                barUnit = TimeBarParameters.BarUnit.WEEK;
                break;

            case HistoryProviderSpan.Month:
                // Для MONTH units_number не заполняется
                barUnit = TimeBarParameters.BarUnit.MONTH;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(span), span, $"Invalid time span - {span}");
            }

            var message = new TimeBarRequest
            {
                request_id          = adapter.GetNextRequestId(),
                request_type        = (uint)type,
                time_bar_parameters = new TimeBarParameters
                {
                    contract_id   = contractId,
                    bar_unit      = (uint)barUnit,
                    units_number  = unitsNumber,
                    from_utc_time = adapter.ResolveDateTime(begin),
                    to_utc_time   = adapter.ResolveDateTime(end)
                }
            };

            return(message);
        }