Beispiel #1
0
        protected override void OnSave(BitArrayWriter writer, IEnumerable <ExecutionMessage> messages, OrderLogMetaInfo metaInfo)
        {
            if (metaInfo.IsEmpty() && !messages.IsEmpty())
            {
                var item = messages.First();

                metaInfo.FirstOrderId       = metaInfo.LastOrderId = item.OrderId ?? default;
                metaInfo.FirstTransactionId = metaInfo.LastTransactionId = item.TransactionId;
                metaInfo.ServerOffset       = item.ServerTime.Offset;
                metaInfo.FirstSeqNum        = metaInfo.PrevSeqNum = item.SeqNum;
            }

            writer.WriteInt(messages.Count());

            var allowNonOrdered  = metaInfo.Version >= MarketDataVersions.Version47;
            var isUtc            = metaInfo.Version >= MarketDataVersions.Version48;
            var allowDiffOffsets = metaInfo.Version >= MarketDataVersions.Version52;
            var isTickPrecision  = metaInfo.Version >= MarketDataVersions.Version53;
            var useBalance       = metaInfo.Version >= MarketDataVersions.Version54;
            var buildFrom        = metaInfo.Version >= MarketDataVersions.Version55;
            var seqNum           = metaInfo.Version >= MarketDataVersions.Version56;
            var useLong          = metaInfo.Version >= MarketDataVersions.Version57;
            var largeDecimal     = metaInfo.Version >= MarketDataVersions.Version57;
            var stringId         = metaInfo.Version >= MarketDataVersions.Version58;

            foreach (var message in messages)
            {
                var hasTrade = message.TradeId != null || message.TradePrice != null || !message.TradeStringId.IsEmpty();
                var orderId  = message.OrderId;

                if (orderId is null)
                {
                    if (!stringId)
                    {
                        throw new ArgumentOutOfRangeException(nameof(messages), message.TransactionId, LocalizedStrings.Str925);
                    }
                }

                if (message.ExecutionType != ExecutionTypes.OrderLog)
                {
                    throw new ArgumentOutOfRangeException(nameof(messages), message.ExecutionType, LocalizedStrings.Str1695Params.Put(message));
                }

                // sell market orders has zero price (if security do not have min allowed price)
                // execution ticks (like option execution) may be a zero cost
                // ticks for spreads may be a zero cost or less than zero
                //if (item.Price < 0)
                //	throw new ArgumentOutOfRangeException(nameof(messages), item.Price, LocalizedStrings.Str926Params.Put(item.OrderId));

                var volume = message.SafeGetVolume();
                if (volume <= 0 && message.OrderState != OrderStates.Done)
                {
                    throw new ArgumentOutOfRangeException(nameof(messages), volume, LocalizedStrings.Str927Params.Put(message.TransactionId));
                }

                long?tradeId = null;

                if (hasTrade)
                {
                    tradeId = message.TradeId;

                    if (tradeId is null || tradeId <= 0)
                    {
                        if (!stringId)
                        {
                            throw new ArgumentOutOfRangeException(nameof(messages), tradeId, LocalizedStrings.Str1012Params.Put(message.TransactionId));
                        }
                    }

                    // execution ticks (like option execution) may be a zero cost
                    // ticks for spreads may be a zero cost or less than zero
                    //if (item.TradePrice <= 0)
                    //	throw new ArgumentOutOfRangeException(nameof(messages), item.TradePrice, LocalizedStrings.Str929Params.Put(item.TradeId, item.OrderId));
                }

                metaInfo.LastOrderId = writer.SerializeId(orderId ?? 0, metaInfo.LastOrderId);

                var orderPrice = message.OrderPrice;

                if (metaInfo.Version < MarketDataVersions.Version45)
                {
                    writer.WritePriceEx(orderPrice, metaInfo, SecurityId, false, false);
                }
                else
                {
                    var isAligned = (orderPrice % metaInfo.LastPriceStep) == 0;
                    writer.Write(isAligned);

                    if (isAligned)
                    {
                        if (metaInfo.FirstOrderPrice == 0)
                        {
                            metaInfo.FirstOrderPrice = metaInfo.LastOrderPrice = orderPrice;
                        }

                        var prevPrice = metaInfo.LastOrderPrice;
                        writer.WritePrice(orderPrice, ref prevPrice, metaInfo, SecurityId, true);
                        metaInfo.LastOrderPrice = prevPrice;
                    }
                    else
                    {
                        if (metaInfo.FirstFractionalPrice == 0)
                        {
                            metaInfo.FirstFractionalPrice = metaInfo.LastFractionalPrice = orderPrice;
                        }

                        metaInfo.LastFractionalPrice = writer.WriteDecimal(orderPrice, metaInfo.LastFractionalPrice);
                    }
                }

                writer.WriteVolume(volume, metaInfo, largeDecimal);

                writer.Write(message.Side == Sides.Buy);

                var lastOffset = metaInfo.LastServerOffset;
                metaInfo.LastTime         = writer.WriteTime(message.ServerTime, metaInfo.LastTime, LocalizedStrings.Str1013, allowNonOrdered, isUtc, metaInfo.ServerOffset, allowDiffOffsets, isTickPrecision, ref lastOffset);
                metaInfo.LastServerOffset = lastOffset;

                if (hasTrade)
                {
                    writer.Write(true);

                    if (metaInfo.FirstTradeId == 0)
                    {
                        metaInfo.FirstTradeId = metaInfo.LastTradeId = tradeId ?? default;
                    }

                    metaInfo.LastTradeId = writer.SerializeId(tradeId ?? default, metaInfo.LastTradeId);

                    writer.WritePriceEx(message.GetTradePrice(), metaInfo, SecurityId, useLong, largeDecimal);

                    if (metaInfo.Version >= MarketDataVersions.Version54)
                    {
                        writer.WriteInt((int)message.OrderState);
                    }
                }
                else
                {
                    writer.Write(false);

                    if (metaInfo.Version >= MarketDataVersions.Version54)
                    {
                        writer.WriteInt((int)message.OrderState);
                    }
                    else
                    {
                        writer.Write(message.OrderState == OrderStates.Active);
                    }
                }

                if (metaInfo.Version < MarketDataVersions.Version31)
                {
                    continue;
                }

                writer.WriteNullableInt((int?)message.OrderStatus);

                if (metaInfo.Version < MarketDataVersions.Version33)
                {
                    continue;
                }

                if (metaInfo.Version < MarketDataVersions.Version50)
                {
                    writer.WriteInt((int)(message.TimeInForce ?? TimeInForce.PutInQueue));
                }
                else
                {
                    writer.Write(message.TimeInForce != null);

                    if (message.TimeInForce != null)
                    {
                        writer.WriteInt((int)message.TimeInForce.Value);
                    }
                }

                if (metaInfo.Version >= MarketDataVersions.Version49)
                {
                    writer.Write(message.IsSystem != null);

                    if (message.IsSystem != null)
                    {
                        writer.Write(message.IsSystem.Value);
                    }
                }
                else
                {
                    writer.Write(message.IsSystem ?? true);
                }

                if (metaInfo.Version < MarketDataVersions.Version34)
                {
                    continue;
                }

                metaInfo.LastTransactionId = writer.SerializeId(message.TransactionId, metaInfo.LastTransactionId);

                if (metaInfo.Version < MarketDataVersions.Version40)
                {
                    continue;
                }

                if (metaInfo.Version < MarketDataVersions.Version46)
                {
                    writer.WriteLong(0 /*item.Latency.Ticks*/);
                }

                var portfolio   = message.PortfolioName;
                var isEmptyPf   = portfolio == null;
                var isAnonymous = !isEmptyPf && portfolio == Portfolio.AnonymousPortfolio.Name;

                if (isEmptyPf)
                {
                    writer.Write(false);
                }
                else
                {
                    if (isAnonymous)
                    {
                        if (metaInfo.Version < MarketDataVersions.Version54)
                        {
                            writer.Write(false);
                        }
                        else
                        {
                            writer.Write(true);
                            writer.Write(true);                             // is anonymous
                        }
                    }
                    else
                    {
                        writer.Write(true);

                        if (metaInfo.Version > MarketDataVersions.Version54)
                        {
                            writer.Write(false);                             // not anonymous
                        }
                        metaInfo.Portfolios.TryAdd(message.PortfolioName);
                        writer.WriteInt(metaInfo.Portfolios.IndexOf(message.PortfolioName));
                    }
                }

                if (metaInfo.Version < MarketDataVersions.Version51)
                {
                    continue;
                }

                writer.WriteNullableInt((int?)message.Currency);

                if (!useBalance)
                {
                    continue;
                }

                if (message.Balance == null)
                {
                    writer.Write(false);
                }
                else
                {
                    writer.Write(true);

                    if (message.Balance.Value == 0)
                    {
                        writer.Write(false);
                    }
                    else
                    {
                        writer.Write(true);
                        writer.WriteDecimal(message.Balance.Value, 0);
                    }
                }

                if (!buildFrom)
                {
                    continue;
                }

                writer.WriteBuildFrom(message.BuildFrom);

                if (!seqNum)
                {
                    continue;
                }

                writer.WriteSeqNum(message, metaInfo);

                if (!stringId)
                {
                    continue;
                }

                writer.Write(orderId is null);
                writer.WriteStringEx(message.OrderStringId);

                writer.Write(tradeId is null);
                writer.WriteStringEx(message.TradeStringId);

                if (message.OrderBuyId != null)
                {
                    writer.Write(true);
                    metaInfo.LastOrderId = writer.SerializeId(message.OrderBuyId.Value, metaInfo.LastOrderId);
                }
                else
                {
                    writer.Write(false);
                }

                if (message.OrderSellId != null)
                {
                    writer.Write(true);
                    metaInfo.LastOrderId = writer.SerializeId(message.OrderSellId.Value, metaInfo.LastOrderId);
                }
                else
                {
                    writer.Write(false);
                }

                writer.WriteNullableBool(message.IsUpTick);
                writer.WriteNullableDecimal(message.Yield);
                writer.WriteNullableInt(message.TradeStatus);
                writer.WriteNullableDecimal(message.OpenInterest);
                writer.WriteNullableInt((int?)message.OriginSide);
            }
        }