예제 #1
0
        /// <summary>
        ///     Обработчик события получения позиции
        /// </summary>
        private async void PositionStatusReceived(AdapterEventArgs <PositionStatus> args)
        {
            using (LogManager.Scope())
            {
                try
                {
                    args.MarkHandled();

                    // Ищем счет для позиции
                    string accountCode;
                    using (accountsLock.ReadLock())
                    {
                        if (!accountCodesById.TryGetValue(args.Message.account_id, out accountCode))
                        {
                            Logger.Error().PrintFormat(
                                "Unable to process position on contract #{0}: account #{1} is unknown",
                                args.Message.contract_id,
                                args.Message.account_id);
                            return;
                        }
                    }

                    // Обрабатываем метаданные контрактов
                    if (args.Message.contract_metadata != null)
                    {
                        await
                        instrumentResolver.HandleMetadataAsync(args.Message.contract_metadata,
                                                               $"A position in \"{accountCode}\" account");
                    }

                    // Ищем инструмент для позиции
                    var instrument = instrumentResolver.GetInstrument(args.Message.contract_id);
                    if (instrument == null)
                    {
                        Logger.Warn().PrintFormat(
                            "Received a position on contract #{0} in account {1} but no matching instrument is found",
                            args.Message.contract_id,
                            accountCode);
                        return;
                    }

                    // Рассчитываем позицию
                    var position = new PositionMessage
                    {
                        Account    = accountCode,
                        Instrument = instrument
                    };

                    var message = new StringBuilder();
                    message.AppendFormat("Position received: {0} [ ", instrument.Code);

                    using (openPositionsLock.Lock())
                    {
                        Dictionary <uint, Dictionary <int, OpenPosition> > d1;
                        if (!openPositions.TryGetValue(args.Message.account_id, out d1))
                        {
                            d1 = new Dictionary <uint, Dictionary <int, OpenPosition> >();
                            openPositions.Add(args.Message.account_id, d1);
                        }

                        Dictionary <int, OpenPosition> d2;
                        if (!d1.TryGetValue(args.Message.contract_id, out d2))
                        {
                            d2 = new Dictionary <int, OpenPosition>();
                            d1.Add(args.Message.contract_id, d2);
                        }

                        if (args.Message.is_snapshot)
                        {
                            d2.Clear();
                        }

                        position.Quantity = 0;
                        foreach (var p in args.Message.open_position)
                        {
                            var fmt = ObjectLogFormatter.Create(PrintOption.Nested, "CQGC_POSITION");
                            fmt.AddField(LogFieldNames.Id, p.id);
                            fmt.AddField(LogFieldNames.Price, p.price);
                            fmt.AddField(LogFieldNames.Quantity, p.qty);
                            fmt.AddField(LogFieldNames.TradeDate, p.trade_date);
                            fmt.AddField(LogFieldNames.TradeUtcTime, p.trade_utc_time);
                            fmt.AddField(LogFieldNames.StatementDate, p.statement_date);

                            message.Append(fmt.Print(PrintOption.Nested));
                            message.Append(", ");

                            position.Quantity = (int)p.qty;
                            position.Price    = (decimal)p.price;

                            d2[p.id] = p;
                        }

                        var volume   = 0d;
                        var quantity = 0u;

                        foreach (var pair in d2)
                        {
                            volume   += pair.Value.price * pair.Value.qty;
                            quantity += pair.Value.qty;
                        }

                        position.Quantity = (int)quantity;
                        position.Price    = quantity != 0u ? (decimal)(volume / quantity) : 0;
                    }

                    if (args.Message.is_short_open_position)
                    {
                        position.Quantity *= -1;
                    }

                    message.Append("]: ");
                    message.Append(LogFields.Price(position.Price));
                    message.Append(LogFields.Quantity(position.Quantity));
                    message.Append(LogFields.IsSnapshot(args.Message.is_snapshot));

                    Logger.Debug().Print(message.ToString().Preformatted());

                    // Отправляем сообщение
                    OnMessageReceived(position);
                }
                catch (Exception e)
                {
                    Logger.Error().Print(e, $"Failed to process {args.Message}");
                }
            }
        }