Esempio n. 1
0
        private void MarketDataResolved(AdapterEventArgs <InformationReport> args)
        {
            var contractId = args.Message.symbol_resolution_report.contract_metadata.contract_id;

            ResolutionRequest request;

            using (resolutionRequestsLock.Lock())
            {
                if (!resolutionRequestsById.TryGetValue(args.Message.id, out request))
                {
                    return;
                }

                using (cacheLock.Lock())
                {
                    cachedContractIds[request.Instrument] = contractId;
                    cachedContracts[contractId]           = request.Instrument;
                    cachedContractPriceScales[contractId] = (decimal)args.Message.symbol_resolution_report.contract_metadata.correct_price_scale;
                }

                resolutionRequestsById.Remove(request.Id);
                resolutionRequestsByInstrument.Remove(request.Instrument);
            }

            request.Resolve(contractId);
            args.MarkHandled();
            OnInstrumentResolved(contractId);
            _Log.Debug().Print("Instrument is resolved", LogFields.Instrument(request.Instrument), LogFields.ContractId(contractId), LogFields.RequestId(request.Id));
        }
 public static bool GetFormatKeyOf(LogFields field, out char chKey)
 {
     chKey = '\0';
     if (field == LogFields.Location)
     {
         chKey = 'L';
     }
     if (field == LogFields.Method)
     {
         chKey = 'M';
     }
     if (field == LogFields.FileLocation)
     {
         chKey = 'f';
     }
     if (field == LogFields.FullMessage)
     {
         chKey = 'F';
     }
     if (field == LogFields.LogStack)
     {
         chKey = 'S';
     }
     if (field == LogFields.LogCurrent)
     {
         chKey = 's';
     }
     return(chKey != '\0');
 }
Esempio n. 3
0
        /// <summary>
        ///     Socket connection error event handler. Called when error rose up.
        /// </summary>
        private void OnSocketError(object sender, ErrorEventArgs e)
        {
            Log.Error().Print(e.Exception, "WS:OnSocketError", LogFields.Login(settings?.Username));

            // статус Terminated мы не меняем, он финальный, сбрасывается только при перезапуске транспорта
            connectionStatus = connectionStatus != ConnectionStatus.Terminated ? ConnectionStatus.Disconnected : connectionStatus;
            OnConnectionStatusChanged(connectionStatus);

            using (socketLock.Lock())
            {
                if (socket != null)
                {
                    try
                    {
                        if (socket.State == WebSocketState.Open)
                        {
                            socket.Close();
                        }

                        // NOTE вообще тут надо бы делать socket.Dispose(), но из-за этого возникает race condition
                        // socket.Dispose();
                    }
                    catch (Exception exception)
                    {
                        Log.Error().Print(exception, "WS:OnSocketError: Error while disposing error socket");
                    }
                    finally
                    {
                        socket = null;
                    }
                }
            }

            socketErrorEvent.Set();
        }
Esempio n. 4
0
        /// <summary>
        /// Обработка неудачной транзакции
        /// </summary>
        /// <param name="message"></param>
        private void ProcessFailedTransactionReply(QLTransactionReply message)
        {
            var newOrderTransaction    = container.GetNewOrderTransaction(message.trans_id);
            var killOrderTransaction   = container.GetKillOrderTransactionByTransId(message.trans_id);
            var modifyOrderTransaction = container.GetModifyOrderTransactionByTransId(message.trans_id);

            switch (message.status)
            {
            case 13:     // отвергнута как кросс сделка
                Logger.Error().Print("Transaction failed, due to potential cross trade", LogFields.Message(message));
                break;

            default:
                Logger.Error().Print("Transaction failed", LogFields.Message(message));
                break;
            }

            OnMessageReceived(message: new TransactionReply
            {
                Success       = message.Successful,
                Message       = message.result_msg,
                TransactionId = newOrderTransaction?.TransactionId
                                ?? killOrderTransaction?.TransactionId
                                ?? modifyOrderTransaction?.TransactionId
                                ?? Guid.Empty
            });

            container.RemoveProcessedPendingReply(message);
        }
Esempio n. 5
0
        /// <summary>
        ///     Socket connection close event handler. Called when connection closed.
        /// </summary>
        private void OnSocketClose(object sender, EventArgs e)
        {
            Log.Debug().Print("WS:OnSocketClose", LogFields.Login(settings?.Username));

            // статус Terminated мы не меняем, он финальный, сбрасывается только при перезапуске транспорта
            connectionStatus = connectionStatus != ConnectionStatus.Terminated ? ConnectionStatus.Disconnected : connectionStatus;
            OnConnectionStatusChanged(connectionStatus);

            using (socketLock.Lock())
            {
                try
                {
                    socket?.Dispose();
                }
                catch (Exception ex)
                {
                    Log.Error().Print(ex, "WS:OnSocketClose failed to process an event");
                }
                finally
                {
                    socketClosedEvent.Set();
                    socket = null;
                }
            }
        }
Esempio n. 6
0
        /// <summary>
        ///     Получить исторические данные
        /// </summary>
        /// <param name="consumer">
        ///     Потребитель исторических данных
        /// </param>
        /// <param name="instrument">
        ///     Инструмент
        /// </param>
        /// <param name="begin">
        ///     Начало диапазона
        /// </param>
        /// <param name="end">
        ///     Конец диапазона
        /// </param>
        /// <param name="span">
        ///     Интервал свечей для исторических данных
        /// </param>
        /// <param name="cancellationToken">
        ///     Токен отмены
        /// </param>
        /// <returns>
        ///     Исторические данные
        /// </returns>
        /// <remarks>
        ///     Провайдер вправе переопределить параметры исторических графиков - диапазон, интервал,
        ///     если он не в состоянии предоставить запрошенные данные.
        /// </remarks>
        /// <exception cref="NoHistoryDataException">
        ///     Бросается, если исторические данные за указанный период недоступны
        /// </exception>
        public async Task GetHistoryDataAsync(
            IHistoryDataConsumer consumer,
            Instrument instrument,
            DateTime begin,
            DateTime end,
            HistoryProviderSpan span,
            CancellationToken cancellationToken = new CancellationToken())
        {
            var symbol = await adapter.ResolveSymbolAsync(instrument);

            if (symbol == null)
            {
                consumer.Error($"Unable to resolve symbol for {instrument}");
                return;
            }

            QLAdapter.Log.Debug().Print($"Candles request: {symbol}, span {span}, from {begin} to {end}");
            var dataRequestMessage = new QLHistoryDataRequest(symbol, span);
            var request            = new HistoryDataRequest(dataRequestMessage.id, instrument, begin, end, span);

            using (requestsLock.Lock())
            {
                requests[request.Id] = request;
            }

            // Поддержка отмены запроса
            cancellationToken.RegisterSafe(() => request.TrySetCanceled());

            adapter.SendMessage(dataRequestMessage);

            var data = await request.Task;

            QLAdapter.Log.Debug().Print("Push candles to consumer. ", LogFields.RequestId(request.Id));
            consumer.Update(data, HistoryDataUpdateType.Batch);
        }
Esempio n. 7
0
        /// <summary>
        ///     Обработчик события по статусу заявки
        /// </summary>
        private async void OrderStatusReceived(AdapterEventArgs <OrderStatus> args)
        {
            using (LogManager.Scope())
            {
                try
                {
                    Logger.Debug().Print(
                        "Order status received",
                        LogFields.ExchangeOrderId(args.Message.order_id),
                        LogFields.ChainOrderId(args.Message.chain_order_id),
                        LogFields.State(ConvertionHelper.GetOrderState(args.Message)),
                        LogFields.AccountId(args.Message.account_id),
                        LogFields.ExecOrderId(args.Message.exec_order_id)
                        );

                    args.MarkHandled();

                    // Обрабатываем метаданные контрактов
                    if (args.Message.contract_metadata != null)
                    {
                        foreach (var metadata in args.Message.contract_metadata)
                        {
                            await instrumentResolver.HandleMetadataAsync(metadata);
                        }
                    }

                    // Пытаемся выбрать заявку из контейнера
                    Order order;
                    using (ordersLock.Lock())
                        ordersByOrderExchangeId.TryGetValue(args.Message.chain_order_id, out order);

                    Message message;
                    // Обрабатываем изменение статуса заявки
                    if (order != null)
                    {
                        message = HandleOrderStateAsOrderStateChange(order, args.Message);
                    }
                    // Обрабатываем заявку как новую
                    else
                    {
                        message = HandleOrderStateAsNewOrder(args.Message, out order);
                    }

                    // Отправляем сообщение и TransactionReply
                    if (message != null)
                    {
                        OnMessageReceived(message);
                        TryEmitTransactionReplies(args.Message);

                        // Обрабатываем сделки
                        TryEmitFills(args.Message, order);
                    }
                }
                catch (Exception e)
                {
                    Logger.Error().Print(e, $"Failed to process {args.Message}");
                }
            }
        }
Esempio n. 8
0
 /// <summary>
 /// Удалить отложенный ответ на транзакцию
 /// </summary>
 public void RemoveProcessedPendingReply(QLTransactionReply tr)
 {
     log.Debug().Print("Remove processed TR", LogFields.TransactionId(tr.trans_id));
     using (locker.WriteLock())
     {
         pendingTransactionReplies.Remove(tr);
     }
 }
Esempio n. 9
0
        /// <summary>
        ///     Обработка отказа по заявке
        /// </summary>
        private void OrderRequestRejectReceived(AdapterEventArgs <OrderRequestReject> args)
        {
            args.MarkHandled();

            var message = $"[{args.Message.reject_code}] {args.Message.text_message}";

            Logger.Error().Print("CQG order rejected", LogFields.Message(message));

            TrySendTransactionReplyRejected(args.Message.request_id, message);
        }
Esempio n. 10
0
        /// <summary>
        ///     Обработчик события изменения статуса подписки
        /// </summary>
        private void TradeSubscriptionStatusReceived(AdapterEventArgs <TradeSubscriptionStatus> args)
        {
            args.MarkHandled();

            Logger.Debug().Print(
                "Trade subscription status received",
                LogFields.Id(args.Message.id),
                LogFields.Status((TradeSubscriptionStatus.StatusCode)args.Message.status_code),
                LogFields.Message(args.Message.text_message)
                );
        }
        public void SetUserField(string field, string value)
        {
            string convertedField = LogFields.ConvertField(field);

            if (ContainsFiled(convertedField))
            {
                Remove(convertedField);
            }

            Put(convertedField, value);
        }
		public static bool GetFormatKeyOf( LogFields field, out char chKey )
		{
			chKey = '\0';
			if(field == LogFields.Location) chKey = 'L';
			if(field == LogFields.Method) chKey = 'M';
			if(field == LogFields.FileLocation) chKey = 'f';
			if(field == LogFields.FullMessage) chKey = 'F';
			if(field == LogFields.LogStack) chKey = 'S';
			if(field == LogFields.LogCurrent) chKey = 's';
			return chKey != '\0';
		}
Esempio n. 13
0
        private async Task HandleAsync(QLFill message)
        {
            try
            {
                Logger.Debug().Print($"Handle(QLFill): {message}");

                var instrument = await adapter.ResolveInstrumentAsync(message.sec_code);

                if (instrument == null)
                {
                    Logger.Error().Print($"Unable to resolve instrument for {message.sec_code}");
                    return;
                }

                // если заявка отправлялась в текущей сессии работы программы, то нужно убедиться, что oscm по ней уже отправлялся
                if (container.IsCurrentSessionOrder(message.order_num))
                {
                    var lastOscm = container.GetLastOrderStateChangeForOrderId(message.order_num);
                    if (lastOscm == null)
                    {
                        Logger.Debug()
                        .Print("Handle(QLFill): Fill will be processed later, no OSCM received",
                               LogFields.Message(message));
                        container.PutPendingFill(message);
                        return;
                    }
                }
                else if (container.HasUnrepliedTransactions())
                {
                    Logger.Debug()
                    .Print($"Handle(QLFill): Fill will be processed later, there are unreplied transactions",
                           LogFields.Message(message));
                    container.PutPendingFill(message);
                    return;
                }

                OnMessageReceived(new FillMessage
                {
                    Instrument      = instrument,
                    Account         = message.account,
                    Quantity        = (uint)message.qty,
                    ClientCode      = message.account,
                    ExchangeId      = message.trade_num.ToString(),
                    ExchangeOrderId = message.order_num.ToString(),
                    Price           = message.price,
                    Operation       = message.Operation,
                    DateTime        = message.Time
                });
            }
            catch (Exception e)
            {
                Logger.Error().Print(e, $"Failed to handle {message}");
            }
        }
Esempio n. 14
0
        private static void MarketDataSubscriptionStatusReceived(AdapterEventArgs <MarketDataSubscriptionStatus> args)
        {
            args.MarkHandled();

            _Log.Debug().Print(
                $"Subscription status for contract #{args.Message.contract_id}: Level={1}, Status={2}. {3}",
                LogFields.Level((MarketDataSubscription.Level)args.Message.level),
                LogFields.Status((MarketDataSubscriptionStatus.StatusCode)args.Message.status_code),
                LogFields.Message(args.Message.text_message)
                );
        }
Esempio n. 15
0
        /// <summary>
        ///     Обработка результата логина
        /// </summary>
        private void Handle(LogonResult msg)
        {
            var resultCode = (LogonResult.ResultCode)msg.result_code;

            switch (resultCode)
            {
            case LogonResult.ResultCode.SUCCESS:
                Log.Info().Print($"Connected to CQG with login {settings?.Username}");
                if (!DateTime.TryParseExact(
                        msg.base_time,
                        "yyyy-MM-ddTHH:mm:ss",
                        CultureInfo.InvariantCulture,
                        DateTimeStyles.AssumeUniversal,
                        out baseTime))
                {
                    baseTime = DateTime.UtcNow;
                    Log.Warn().Print($"Unable to parse base_time = msg.base_time. Order and fill timestamps might be corrupted. Historical data won't work at all.");
                }

                //[ENABLE_CQGC_TRACE]WebApiTrace.SetBaseTime(baseTime);
                connectionStatus = ConnectionStatus.Connected;
                OnConnectionStatusChanged(connectionStatus);
                logoffEfent.Reset();
                RequestInitializingData();

                return;

            case LogonResult.ResultCode.FAILURE:
                break;

            case LogonResult.ResultCode.NO_ONETIME_PASSWORD:
                break;

            case LogonResult.ResultCode.PASSWORD_EXPIRED:
                return;

            case LogonResult.ResultCode.CONCURRENT_SESSION:
                break;

            case LogonResult.ResultCode.REDIRECTED:
                break;
            }

            Log.Error().Print("Unable to log in", LogFields.Result(resultCode), LogFields.Message(msg.text_message));
            connectionStatus = ConnectionStatus.Terminated;
            OnConnectionStatusChanged(connectionStatus);

            using (socketLock.Lock())
            {
                Log.Debug().Print("Closing CQG socket");
                socket?.Close();
            }
        }
Esempio n. 16
0
 private void CreateTcpClient()
 {
     if (tcpCient == null)
     {
         Log.Debug().Print("(Re)creating TcpClient", LogFields.IP(ip), LogFields.Port(port));
         tcpCient = new TcpClient
         {
             ExclusiveAddressUse = true,
             NoDelay             = true,
             ReceiveBufferSize   = 1000000
         };
     }
 }
Esempio n. 17
0
        /// <summary>
        /// Сохранить сделку, требующую отложенной обработки
        /// </summary>
        /// <param name="message"></param>
        public void PutPendingFill(QLFill message)
        {
            log.Debug().Print("Postpone fill processing", LogFields.Message(message));
            using (locker.WriteLock())
            {
                if (pendingFills.ContainsKey(message.trade_num))
                {
                    log.Warn().Print($"Fill duplicate received", LogFields.Id(message.trade_num));
                    return;
                }

                pendingFills[message.trade_num] = message;
            }
        }
Esempio n. 18
0
        /// <summary>
        ///     Socket connection open event handler. Called when connection opened successfully.
        /// </summary>
        private void OnSocketOpen(object sender, EventArgs args)
        {
            Log.Debug().Print("WS:OnSocketOpen", LogFields.Login(settings?.Username));

            try
            {
                socketClosedEvent.Reset();
                SendLogon();
            }
            catch (Exception e)
            {
                Log.Error().Print(e, "WS:OnSocketOpen failed to process an event");
            }
        }
        /// <summary>
        /// Handels the initialization of the Field setups, creating a list of cruise methods and
        /// </summary>
        public void HandleFieldSetupLoad()
        {
            var allTreeFields = TreeFields;

            //check to see if Cruise method list has been initialized
            if (CruiseMethods == null)
            {
                try
                {
                    var methods = Database.From <EditTemplateCruiseMethod>().Read().ToList();
                    foreach (var method in methods)
                    {
                        var treeFields = Database.From <TreeFieldSetupDefaultDO>()
                                         .Where("Method = @p1").OrderBy("FieldOrder").Read(method.Code).ToList();

                        method.TreeFields = new BindingList <TreeFieldSetupDefaultDO>(treeFields);

                        var unselectedTreeFields = allTreeFields.Except(treeFields, TreeFieldDefaultComparer.Instance)
                                                   .Select(tfs => new TreeFieldSetupDefaultDO(tfs)
                        {
                            Method = method.Code
                        })
                                                   .ToList();
                        method.UnselectedTreeFields = new BindingList <TreeFieldSetupDefaultDO>(unselectedTreeFields);
                    }
                    CruiseMethods = new BindingList <EditTemplateCruiseMethod>(methods);
                }
                catch { }
            }

            if (SelectedLogFields == null)
            {
                try
                {
                    var logFields = Database.From <LogFieldSetupDefaultDO>()
                                    .OrderBy("FieldOrder").Read().ToList();
                    SelectedLogFields = new BindingList <LogFieldSetupDefaultDO>(logFields);
                    var unselectedLogFields = LogFields.Except(logFields, LogFieldDefaultComparer.Instance)
                                              .Select(lfs => new LogFieldSetupDefaultDO(lfs)).ToList();
                    UnselectedLogFields = new BindingList <LogFieldSetupDefaultDO>(unselectedLogFields);
                }
                catch
                {
                    SelectedLogFields = null;
                }

                View.UpdateFieldSetup();
            }
        }
Esempio n. 20
0
 /// <summary>
 /// Предварительная обработка ответа на транзакцию
 /// </summary>
 /// <param name="message"></param>
 private void PreprocessTransactionReply(QLTransactionReply message)
 {
     if (!string.IsNullOrEmpty(message.result_msg) &&
         (
             message.result_msg.Contains("Вы не можете снять данную заявку") ||
             message.result_msg.Contains("Не найдена заявка для удаления")
         ))
     {
         Logger.Warn().Print(
             $"Failed kill transaction will be treated as successfull, status will be changed from {message.status} to 3",
             LogFields.Message(message)
             );
         message.status = 3;
     }
 }
Esempio n. 21
0
        /// <summary>
        ///     Создаёт и открывает сокет
        /// </summary>
        private void CreateAndOpenSocket()
        {
            using (socketLock.Lock())
            {
                Log.Info().Print("Connecting to CQG Continuum", LogFields.URL(settings.ConnectionUrl), LogFields.Login(settings.Username));
                socket?.Dispose();

                socket               = new WebSocket(settings.ConnectionUrl);
                socket.Opened       += OnSocketOpen;
                socket.Closed       += OnSocketClose;
                socket.Error        += OnSocketError;
                socket.DataReceived += OnSocketData;
                socket.Open();
            }
        }
Esempio n. 22
0
        /// <summary>
        /// Сохранить идентификатор полученной сделки. Для дальнейшего анализа на получение дубликата сообщения
        /// </summary>
        /// <param name="id">Биржевой идентификатор сделки</param>
        /// <returns>true - если сделка уже есть в контейнере, иначе false</returns>
        public bool PutFillId(QLFill fill)
        {
            using (lockerReceivedFills.WriteLock())
            {
                if (receivedFills.Contains(fill.trade_num))
                {
                    log.Warn().Print($"Fill duplicate received", LogFields.Id(fill.trade_num));
                    return(true);
                }

                receivedFills.Add(fill.trade_num);
            }

            return(false);
        }
Esempio n. 23
0
        private async Task <Contract> ResolveContractStubAsync(Instrument instrument)
        {
            var instrumentData = await instrumentConverter.ResolveInstrumentAsync(adapter, instrument);

            if (instrumentData == null)
            {
                _Log.Error().Print("Unable to resolve vendor symbol for an instrument",
                                   LogFields.Instrument(instrument));
                return(null);
            }

            var contract = GetContractStub(instrumentData);

            return(contract);
        }
Esempio n. 24
0
        /// <summary>
        ///     Обработка результата выхода из системы
        /// </summary>
        private void Handle(LoggedOff msg)
        {
            if (msg != null)
            {
                Log.Info().Print($"Logoff received. Closing socket", LogFields.Login(settings?.Username));
                using (socketLock.Lock())
                {
                    socket?.Close();
                }

                logoffEfent.Set();
            }

            connectionStatus = ConnectionStatus.Connecting;
            OnConnectionStatusChanged(connectionStatus);
        }
Esempio n. 25
0
        /// <summary>
        ///     Обработка заявки как уже существующей
        /// </summary>
        private OrderStateChangeMessage HandleOrderStateAsOrderStateChange(Order order, OrderStatus message)
        {
            Logger.Debug().Print(
                "Order state change received",
                LogFields.ExchangeOrderId(message.order_id),
                LogFields.ChainOrderId(message.chain_order_id),
                LogFields.State(ConvertionHelper.GetOrderState(message)),
                LogFields.AccountId(message.account_id),
                LogFields.ExecOrderId(message.exec_order_id)
                );

            using (ordersLock.Lock())
            {
                Guid transactionId;
                if (!Guid.TryParse(message.order.cl_order_id, out transactionId))
                {
                    Logger.Debug().Print(
                        $"Unable to parse {LogFieldNames.TransactionId} from {LogFields.ClOrderId(message.order.cl_order_id)}. Use order's {LogFieldNames.TransactionId}"
                        );
                    transactionId = order.TransactionId;
                }

                var change = new OrderStateChangeMessage
                {
                    OrderExchangeId = message.chain_order_id,
                    TransactionId   = transactionId,
                    ActiveQuantity  = message.remaining_qty,
                    FilledQuantity  = message.fill_qty,
                    Price           = instrumentResolver.ConvertPriceBack(order.Instrument, message.order.limit_price),
                    ChangeTime      = adapter.ResolveDateTime(message.status_utc_time),
                    Quantity        = message.remaining_qty + message.fill_qty,
                    State           = ConvertionHelper.GetOrderState(message)
                };

                // Обработка изменения order_id (происходит при модификации заявки)
                if (order.OrderExchangeId != change.OrderExchangeId)
                {
                    ordersByOrderExchangeId.Remove(order.OrderExchangeId);
                    ordersByOrderExchangeId.Add(change.OrderExchangeId, order);
                }

                orderStatusByChainOrderId[message.chain_order_id] = message;

                //order.AcceptStateMessage(change);
                return(change);
            }
        }
Esempio n. 26
0
        /// <summary>
        ///     Отправить сообщение логина
        /// </summary>
        private void SendLogon()
        {
            var logon = new Logon
            {
                user_name               = settings.Username,
                password                = settings.Password,
                client_app_id           = "ItGlobal",
                client_version          = ClientVersion,
                collapsing_level        = (uint)RealTimeCollapsing.Level.DOM_BBA_TRADES,
                drop_concurrent_session = true,
                protocol_version_major  = (uint)ProtocolVersionMajor.PROTOCOL_VERSION_MAJOR,
                protocol_version_minor  = (uint)ProtocolVersionMinor.PROTOCOL_VERSION_MINOR
            };

            Log.Debug().Print("Sending logon message", LogFields.Login(settings?.Username));
            SendMessage(logon);
        }
Esempio n. 27
0
        /// <summary>
        ///     Обновить контракт по его метаданным
        /// </summary>
        /// <param name="metadata">
        ///     Метаданные контракта
        /// </param>
        /// <param name="dependentObjectDescription">
        ///     Строковое описание объекта, который зависит от инструмента
        /// </param>
        public async Task HandleMetadataAsync(ContractMetadata metadata, string dependentObjectDescription = null)
        {
            using (LogManager.Scope())
            {
                _Log.Debug().Print(
                    "Contract metadata received",
                    LogFields.ContractId(metadata.contract_id),
                    LogFields.Symbol(metadata.contract_symbol),
                    LogFields.CorrectPriceScale(metadata.correct_price_scale),
                    LogFields.DisplayPriceScale(metadata.display_price_scale)
                    );
                using (cacheLock.Lock())
                {
                    if (cachedContracts.ContainsKey(metadata.contract_id))
                    {
                        _Log.Debug().Print("Already cached", LogFields.ContractId(metadata.contract_id));
                        return;
                    }
                }

                Instrument instrument = await InstrumentConverter.ResolveSymbolAsync(adapter, metadata.contract_symbol, dependentObjectDescription);

                if (instrument == null)
                {
                    _Log.Warn().Print("Instrument not resolved", LogFields.Symbol(metadata.contract_symbol));
                    return;
                }

                using (cacheLock.Lock())
                {
                    _Log.Debug().Print(
                        "Caching instrument",
                        LogFields.ContractId(metadata.contract_id),
                        LogFields.Symbol(metadata.contract_symbol),
                        LogFields.Instrument(instrument)
                        );

                    cachedContractIds[instrument]                   = metadata.contract_id;
                    cachedContracts[metadata.contract_id]           = instrument;
                    cachedContractPriceScales[metadata.contract_id] = (decimal)metadata.correct_price_scale;
                }

                OnInstrumentResolved(metadata.contract_id);
            }
        }
Esempio n. 28
0
 public void Send(Transaction transaction)
 {
     try
     {
         transaction.Accept(this);
     }
     catch (TransactionRejectedException exception)
     {
         Reject(transaction, exception.Message);
     }
     catch (Exception exception)
     {
         _Log.Error()
         .Print(exception, "Unable to send transaction", LogFields.Transaction(transaction),
                LogFields.Message(exception.Message));
         Reject(transaction, "Transaction execution failed: {0}", exception.Message);
     }
 }
Esempio n. 29
0
        /// <summary>
        ///     Преобразовать цену из формата CQG
        /// </summary>
        /// <param name="contractId">
        ///     Contract ID
        /// </param>
        /// <param name="price">
        ///     Цена в нотации CQG
        /// </param>
        /// <returns>
        ///      Цена
        /// </returns>
        public decimal ConvertPriceBack(uint contractId, long price)
        {
            using (cacheLock.Lock())
            {
                decimal scale;
                if (!cachedContractPriceScales.TryGetValue(contractId, out scale))
                {
                    _Log.Error().Print(
                        "Can't find price scale for contract",
                        LogFields.ContractId(contractId),
                        LogFields.Instrument(GetInstrument(contractId)?.Code)
                        );
                    return(price);
                }

                var correctedPrice = scale != 0 ? price * scale : price;
                return(correctedPrice);
            }
        }
Esempio n. 30
0
        /// <summary>
        ///     Обновить контракт по его метаданным
        /// </summary>
        /// <param name="metadata">
        ///     Метаданные контракта
        /// </param>
        public void HandleMetadata(ContractMetadata metadata)
        {
            _Log.Debug().Print(
                "Contract metadata received",
                LogFields.ContractId(metadata.contract_id),
                LogFields.Symbol(metadata.contract_symbol),
                LogFields.CorrectPriceScale(metadata.correct_price_scale),
                LogFields.DisplayPriceScale(metadata.display_price_scale)
                );
            using (cacheLock.Lock())
            {
                if (cachedContracts.ContainsKey(metadata.contract_id))
                {
                    _Log.Debug().Print("Already cached", LogFields.ContractId(metadata.contract_id));
                    return;
                }
            }

            var instrument = InstrumentConverter.ResolveSymbolAsync(adapter, metadata.contract_symbol).Result;

            if (instrument == null)
            {
                _Log.Warn().Print("Instrument not resolved", LogFields.Symbol(metadata.contract_symbol));
                return;
            }

            using (cacheLock.Lock())
            {
                _Log.Debug().Print(
                    "Caching instrument",
                    LogFields.ContractId(metadata.contract_id),
                    LogFields.Symbol(metadata.contract_symbol),
                    LogFields.Instrument(instrument)
                    );

                cachedContractIds[instrument]                   = metadata.contract_id;
                cachedContracts[metadata.contract_id]           = instrument;
                cachedContractPriceScales[metadata.contract_id] = (decimal)metadata.correct_price_scale;
            }

            OnInstrumentResolved(metadata.contract_id);
        }
Esempio n. 31
0
        /// <summary>
        ///     Отправить сообщение в сокет
        /// </summary>
        private void SendMessageImpl(ClientMsg msg)
        {
            using (socketLock.Lock())
            {
                if (socket == null ||
                    socket.State == WebSocketState.Closed ||
                    socket.State == WebSocketState.Closing ||
                    socket.State == WebSocketState.Connecting ||
                    socket.State == WebSocketState.None
                    )
                {
                    Log.Error().Print($"CQG adapter is not connected", LogFields.Login(settings?.Username));
                    return;
                }

                try
                {
                    byte[] serverMessageRaw;
                    using (var memoryStream = new MemoryStream())
                    {
                        Serializer.Serialize(memoryStream, msg);
                        serverMessageRaw = memoryStream.ToArray();
                    }

                    //[ENABLE_CQGC_TRACE]WebApiTrace.OutMessage(msg);
                    socket.Send(serverMessageRaw, 0, serverMessageRaw.Length);
                }
                catch (Exception ex)
                {
                    // В случае сбоя - отключаемся
                    Log.Error().Print(ex, "Failed to send a message");

                    if (socket != null)
                    {
                        Stop();
                        socket?.Dispose();
                    }

                    connectionStatus = ConnectionStatus.Disconnected;
                }
            }
        }