Example #1
0
        protected override void OnSave(BitArrayWriter writer, IEnumerable <TCandleMessage> candles, CandleMetaInfo metaInfo)
        {
            if (metaInfo.IsEmpty())
            {
                var firstCandle = candles.First();

                var low = firstCandle.LowPrice;

                if ((low % metaInfo.PriceStep) == 0)
                {
                    metaInfo.FirstPrice = metaInfo.LastPrice = low;
                }
                else
                {
                    metaInfo.FirstFractionalPrice = metaInfo.LastFractionalPrice = low;
                }

                metaInfo.ServerOffset = firstCandle.OpenTime.Offset;
                metaInfo.FirstSeqNum  = metaInfo.PrevSeqNum = firstCandle.SeqNum;
            }

            writer.WriteInt(candles.Count());

            var allowNonOrdered  = metaInfo.Version >= MarketDataVersions.Version49;
            var isUtc            = metaInfo.Version >= MarketDataVersions.Version50;
            var allowDiffOffsets = metaInfo.Version >= MarketDataVersions.Version53;
            var useLevels        = metaInfo.Version >= MarketDataVersions.Version54;
            var bigRange         = metaInfo.Version >= MarketDataVersions.Version57;
            var isTickPrecision  = bigRange;
            var useLong          = metaInfo.Version >= MarketDataVersions.Version58;
            var buildFrom        = metaInfo.Version >= MarketDataVersions.Version59;
            var seqNum           = metaInfo.Version >= MarketDataVersions.Version60;

            foreach (var candle in candles)
            {
                if (candle.State == CandleStates.Active)
                {
                    throw new ArgumentException(LocalizedStrings.CandleActiveNotSupport.Put(candle), nameof(candle));
                }

                writer.WriteVolume(candle.TotalVolume, metaInfo, SecurityId);

                if (metaInfo.Version < MarketDataVersions.Version52)
                {
                    writer.WriteVolume(candle.RelativeVolume ?? 0, metaInfo, SecurityId);
                }
                else
                {
                    writer.Write(candle.RelativeVolume != null);

                    if (candle.RelativeVolume != null)
                    {
                        writer.WriteVolume(candle.RelativeVolume.Value, metaInfo, SecurityId);
                    }
                }

                if (metaInfo.Version < MarketDataVersions.Version56)
                {
                    var prevPrice = metaInfo.LastPrice;
                    writer.WritePrice(candle.LowPrice, ref prevPrice, metaInfo, SecurityId);
                    metaInfo.LastPrice = prevPrice;

                    prevPrice = metaInfo.LastPrice;
                    writer.WritePrice(candle.OpenPrice, ref prevPrice, metaInfo, SecurityId);

                    prevPrice = metaInfo.LastPrice;
                    writer.WritePrice(candle.ClosePrice, ref prevPrice, metaInfo, SecurityId);

                    prevPrice = metaInfo.LastPrice;
                    writer.WritePrice(candle.HighPrice, ref prevPrice, metaInfo, SecurityId);
                }
                else
                {
                    writer.WritePriceEx(candle.LowPrice, metaInfo, SecurityId, useLong);

                    if (candle.OpenPrice <= candle.ClosePrice)
                    {
                        writer.Write(true);

                        writer.WritePriceEx(candle.OpenPrice, metaInfo, SecurityId, useLong);
                        writer.WritePriceEx(candle.ClosePrice, metaInfo, SecurityId, useLong);
                    }
                    else
                    {
                        writer.Write(false);

                        writer.WritePriceEx(candle.ClosePrice, metaInfo, SecurityId, useLong);
                        writer.WritePriceEx(candle.OpenPrice, metaInfo, SecurityId, useLong);
                    }

                    writer.WritePriceEx(candle.HighPrice, metaInfo, SecurityId, useLong);
                }

                if (!candle.CloseTime.IsDefault() && candle.OpenTime > candle.CloseTime)
                {
                    throw new ArgumentException(LocalizedStrings.MoreThanCloseTime.Put(candle.OpenTime, candle.CloseTime));
                }

                var lastOffset = metaInfo.LastServerOffset;
                metaInfo.LastTime         = writer.WriteTime(candle.OpenTime, metaInfo.LastTime, LocalizedStrings.Str998, allowNonOrdered, isUtc, metaInfo.ServerOffset, allowDiffOffsets, isTickPrecision, ref lastOffset);
                metaInfo.LastServerOffset = lastOffset;

                if (metaInfo.Version >= MarketDataVersions.Version46)
                {
                    var isAll = !candle.HighTime.IsDefault() && !candle.LowTime.IsDefault();

                    DateTimeOffset first;
                    DateTimeOffset second;

                    writer.Write(isAll);

                    if (isAll)
                    {
                        var isOrdered = candle.HighTime <= candle.LowTime;
                        writer.Write(isOrdered);

                        first  = isOrdered ? candle.HighTime : candle.LowTime;
                        second = isOrdered ? candle.LowTime : candle.HighTime;
                    }
                    else
                    {
                        writer.Write(!candle.HighTime.IsDefault());
                        writer.Write(!candle.LowTime.IsDefault());

                        first  = candle.HighTime.IsDefault() ? candle.LowTime : candle.HighTime;
                        second = default;
                    }

                    if (!first.IsDefault())
                    {
                        if (first.Offset != lastOffset && !allowDiffOffsets)
                        {
                            throw new ArgumentException(LocalizedStrings.WrongTimeOffset.Put(first, lastOffset));
                        }

                        if (!candle.CloseTime.IsDefault() && first > candle.CloseTime)
                        {
                            throw new ArgumentException(LocalizedStrings.MoreThanCloseTime.Put(first, candle.CloseTime));
                        }

                        metaInfo.LastTime = writer.WriteTime(first, metaInfo.LastTime, LocalizedStrings.Str999, allowNonOrdered, isUtc, metaInfo.ServerOffset, allowDiffOffsets, isTickPrecision, ref lastOffset, bigRange);
                    }

                    if (!second.IsDefault())
                    {
                        if (second.Offset != lastOffset && !allowDiffOffsets)
                        {
                            throw new ArgumentException(LocalizedStrings.WrongTimeOffset.Put(second, lastOffset));
                        }

                        if (!candle.CloseTime.IsDefault() && second > candle.CloseTime)
                        {
                            throw new ArgumentException(LocalizedStrings.MoreThanCloseTime.Put(second, candle.CloseTime));
                        }

                        metaInfo.LastTime = writer.WriteTime(second, metaInfo.LastTime, LocalizedStrings.Str1000, allowNonOrdered, isUtc, metaInfo.ServerOffset, allowDiffOffsets, isTickPrecision, ref lastOffset, bigRange);
                    }
                }

                if (metaInfo.Version >= MarketDataVersions.Version47)
                {
                    writer.Write(!candle.CloseTime.IsDefault());

                    if (!candle.CloseTime.IsDefault())
                    {
                        if (candle.CloseTime.Offset != lastOffset && !allowDiffOffsets)
                        {
                            throw new ArgumentException(LocalizedStrings.WrongTimeOffset.Put(candle.CloseTime, lastOffset));
                        }

                        metaInfo.LastTime = writer.WriteTime(candle.CloseTime, metaInfo.LastTime, LocalizedStrings.Str1001, allowNonOrdered, isUtc, metaInfo.ServerOffset, allowDiffOffsets, isTickPrecision, ref lastOffset, bigRange);
                    }
                }
                else
                {
                    var time = writer.WriteTime(candle.CloseTime, metaInfo.LastTime, LocalizedStrings.Str1001, allowNonOrdered, isUtc, metaInfo.ServerOffset, allowDiffOffsets, false, ref lastOffset);

                    if (metaInfo.Version >= MarketDataVersions.Version41)
                    {
                        metaInfo.LastTime = time;
                    }
                }

                if (metaInfo.Version >= MarketDataVersions.Version46)
                {
                    if (metaInfo.Version < MarketDataVersions.Version51)
                    {
                        writer.WriteVolume(candle.OpenVolume ?? 0m, metaInfo, SecurityId);
                        writer.WriteVolume(candle.HighVolume ?? 0m, metaInfo, SecurityId);
                        writer.WriteVolume(candle.LowVolume ?? 0m, metaInfo, SecurityId);
                        writer.WriteVolume(candle.CloseVolume ?? 0m, metaInfo, SecurityId);
                    }
                    else
                    {
                        if (candle.OpenVolume == null)
                        {
                            writer.Write(false);
                        }
                        else
                        {
                            writer.Write(true);
                            writer.WriteVolume(candle.OpenVolume.Value, metaInfo, SecurityId);
                        }

                        if (candle.HighVolume == null)
                        {
                            writer.Write(false);
                        }
                        else
                        {
                            writer.Write(true);
                            writer.WriteVolume(candle.HighVolume.Value, metaInfo, SecurityId);
                        }

                        if (candle.LowVolume == null)
                        {
                            writer.Write(false);
                        }
                        else
                        {
                            writer.Write(true);
                            writer.WriteVolume(candle.LowVolume.Value, metaInfo, SecurityId);
                        }

                        if (candle.CloseVolume == null)
                        {
                            writer.Write(false);
                        }
                        else
                        {
                            writer.Write(true);
                            writer.WriteVolume(candle.CloseVolume.Value, metaInfo, SecurityId);
                        }
                    }
                }

                writer.WriteInt((int)candle.State);

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

                var oi = candle.OpenInterest;

                if (metaInfo.Version < MarketDataVersions.Version48)
                {
                    writer.WriteVolume(oi ?? 0m, metaInfo, SecurityId);
                }
                else
                {
                    writer.Write(oi != null);

                    if (oi != null)
                    {
                        writer.WriteVolume(oi.Value, metaInfo, SecurityId);
                    }
                }

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

                writer.Write(candle.DownTicks != null);

                if (candle.DownTicks != null)
                {
                    writer.WriteInt(candle.DownTicks.Value);
                }

                writer.Write(candle.UpTicks != null);

                if (candle.UpTicks != null)
                {
                    writer.WriteInt(candle.UpTicks.Value);
                }

                writer.Write(candle.TotalTicks != null);

                if (candle.TotalTicks != null)
                {
                    writer.WriteInt(candle.TotalTicks.Value);
                }

                if (!useLevels)
                {
                    continue;
                }

                var priceLevels = candle.PriceLevels;

                writer.Write(priceLevels != null);

                if (priceLevels != null)
                {
                    priceLevels = priceLevels.ToArray();

                    writer.WriteInt(priceLevels.Count());

                    foreach (var level in priceLevels)
                    {
                        if (metaInfo.Version < MarketDataVersions.Version56)
                        {
                            var prevPrice = metaInfo.LastPrice;
                            writer.WritePrice(level.Price, ref prevPrice, metaInfo, SecurityId);
                            metaInfo.LastPrice = prevPrice;
                        }
                        else
                        {
                            writer.WritePriceEx(level.Price, metaInfo, SecurityId);
                        }

                        writer.WriteInt(level.BuyCount);
                        writer.WriteInt(level.SellCount);

                        writer.WriteVolume(level.BuyVolume, metaInfo, SecurityId);
                        writer.WriteVolume(level.SellVolume, metaInfo, SecurityId);

                        if (metaInfo.Version >= MarketDataVersions.Version55)
                        {
                            writer.WriteVolume(level.TotalVolume, metaInfo, SecurityId);
                        }

                        var volumes = level.BuyVolumes;

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

                            volumes = volumes.ToArray();

                            writer.WriteInt(volumes.Count());

                            foreach (var volume in volumes)
                            {
                                writer.WriteVolume(volume, metaInfo, SecurityId);
                            }
                        }

                        volumes = level.SellVolumes;

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

                            volumes = volumes.ToArray();

                            writer.WriteInt(volumes.Count());

                            foreach (var volume in volumes)
                            {
                                writer.WriteVolume(volume, metaInfo, SecurityId);
                            }
                        }
                    }
                }

                if (!buildFrom)
                {
                    continue;
                }

                writer.WriteBuildFrom(candle.BuildFrom);

                if (!seqNum)
                {
                    continue;
                }

                writer.WriteSeqNum(candle, metaInfo);
            }
        }
Example #2
0
        protected override void OnSave(BitArrayWriter writer, IEnumerable <TCandleMessage> candles, CandleMetaInfo metaInfo)
        {
            if (metaInfo.IsEmpty())
            {
                var firstCandle = candles.First();

                metaInfo.FirstPrice   = firstCandle.LowPrice;
                metaInfo.LastPrice    = firstCandle.LowPrice;
                metaInfo.ServerOffset = firstCandle.OpenTime.Offset;
            }

            writer.WriteInt(candles.Count());

            var allowNonOrdered  = metaInfo.Version >= MarketDataVersions.Version49;
            var isUtc            = metaInfo.Version >= MarketDataVersions.Version50;
            var allowDiffOffsets = metaInfo.Version >= MarketDataVersions.Version53;

            foreach (var candle in candles)
            {
                writer.WriteVolume(candle.TotalVolume, metaInfo, SecurityId);

                if (metaInfo.Version < MarketDataVersions.Version52)
                {
                    writer.WriteVolume(candle.RelativeVolume ?? 0, metaInfo, SecurityId);
                }
                else
                {
                    writer.Write(candle.RelativeVolume != null);

                    if (candle.RelativeVolume != null)
                    {
                        writer.WriteVolume(candle.RelativeVolume.Value, metaInfo, SecurityId);
                    }
                }

                if (metaInfo.Version < MarketDataVersions.Version56)
                {
                    writer.WritePrice(candle.LowPrice, metaInfo.LastPrice, metaInfo, SecurityId);
                    metaInfo.LastPrice = candle.LowPrice;

                    writer.WritePrice(candle.OpenPrice, metaInfo.LastPrice, metaInfo, SecurityId);
                    writer.WritePrice(candle.ClosePrice, metaInfo.LastPrice, metaInfo, SecurityId);
                    writer.WritePrice(candle.HighPrice, metaInfo.LastPrice, metaInfo, SecurityId);
                }
                else
                {
                    writer.WritePriceEx(candle.LowPrice, metaInfo, SecurityId);

                    if (candle.OpenPrice <= candle.ClosePrice)
                    {
                        writer.Write(true);

                        writer.WritePriceEx(candle.OpenPrice, metaInfo, SecurityId);
                        writer.WritePriceEx(candle.ClosePrice, metaInfo, SecurityId);
                    }
                    else
                    {
                        writer.Write(false);

                        writer.WritePriceEx(candle.ClosePrice, metaInfo, SecurityId);
                        writer.WritePriceEx(candle.OpenPrice, metaInfo, SecurityId);
                    }

                    writer.WritePriceEx(candle.HighPrice, metaInfo, SecurityId);
                }

                var lastOffset = metaInfo.LastServerOffset;
                metaInfo.LastTime         = writer.WriteTime(candle.OpenTime, metaInfo.LastTime, LocalizedStrings.Str998, allowNonOrdered, isUtc, metaInfo.ServerOffset, allowDiffOffsets, ref lastOffset);
                metaInfo.LastServerOffset = lastOffset;

                if (metaInfo.Version >= MarketDataVersions.Version46)
                {
                    var isAll = !candle.HighTime.IsDefault() && !candle.LowTime.IsDefault();

                    DateTimeOffset first;
                    DateTimeOffset second;

                    writer.Write(isAll);

                    if (isAll)
                    {
                        var isOrdered = candle.HighTime <= candle.LowTime;
                        writer.Write(isOrdered);

                        first  = isOrdered ? candle.HighTime : candle.LowTime;
                        second = isOrdered ? candle.LowTime : candle.HighTime;
                    }
                    else
                    {
                        writer.Write(!candle.HighTime.IsDefault());
                        writer.Write(!candle.LowTime.IsDefault());

                        if (candle.HighTime.IsDefault())
                        {
                            first  = candle.LowTime;
                            second = default(DateTimeOffset);
                        }
                        else
                        {
                            first  = candle.HighTime;
                            second = default(DateTimeOffset);
                        }
                    }

                    if (!first.IsDefault())
                    {
                        if (first.Offset != lastOffset)
                        {
                            throw new ArgumentException(LocalizedStrings.WrongTimeOffset.Put(first, lastOffset));
                        }

                        metaInfo.LastTime = writer.WriteTime(first, metaInfo.LastTime, LocalizedStrings.Str999, allowNonOrdered, isUtc, metaInfo.ServerOffset, allowDiffOffsets, ref lastOffset);
                    }

                    if (!second.IsDefault())
                    {
                        if (second.Offset != lastOffset)
                        {
                            throw new ArgumentException(LocalizedStrings.WrongTimeOffset.Put(second, lastOffset));
                        }

                        metaInfo.LastTime = writer.WriteTime(second, metaInfo.LastTime, LocalizedStrings.Str1000, allowNonOrdered, isUtc, metaInfo.ServerOffset, allowDiffOffsets, ref lastOffset);
                    }
                }

                if (metaInfo.Version >= MarketDataVersions.Version47)
                {
                    writer.Write(!candle.CloseTime.IsDefault());

                    if (!candle.CloseTime.IsDefault())
                    {
                        if (candle.CloseTime.Offset != lastOffset)
                        {
                            throw new ArgumentException(LocalizedStrings.WrongTimeOffset.Put(candle.CloseTime, lastOffset));
                        }

                        metaInfo.LastTime = writer.WriteTime(candle.CloseTime, metaInfo.LastTime, LocalizedStrings.Str1001, allowNonOrdered, isUtc, metaInfo.ServerOffset, allowDiffOffsets, ref lastOffset);
                    }
                }
                else
                {
                    var time = writer.WriteTime(candle.CloseTime, metaInfo.LastTime, LocalizedStrings.Str1001, allowNonOrdered, isUtc, metaInfo.ServerOffset, allowDiffOffsets, ref lastOffset);

                    if (metaInfo.Version >= MarketDataVersions.Version41)
                    {
                        metaInfo.LastTime = time;
                    }
                }

                if (metaInfo.Version >= MarketDataVersions.Version46)
                {
                    if (metaInfo.Version < MarketDataVersions.Version51)
                    {
                        writer.WriteVolume(candle.OpenVolume ?? 0m, metaInfo, SecurityId);
                        writer.WriteVolume(candle.HighVolume ?? 0m, metaInfo, SecurityId);
                        writer.WriteVolume(candle.LowVolume ?? 0m, metaInfo, SecurityId);
                        writer.WriteVolume(candle.CloseVolume ?? 0m, metaInfo, SecurityId);
                    }
                    else
                    {
                        if (candle.OpenVolume == null)
                        {
                            writer.Write(false);
                        }
                        else
                        {
                            writer.Write(true);
                            writer.WriteVolume(candle.OpenVolume.Value, metaInfo, SecurityId);
                        }

                        if (candle.HighVolume == null)
                        {
                            writer.Write(false);
                        }
                        else
                        {
                            writer.Write(true);
                            writer.WriteVolume(candle.HighVolume.Value, metaInfo, SecurityId);
                        }

                        if (candle.LowVolume == null)
                        {
                            writer.Write(false);
                        }
                        else
                        {
                            writer.Write(true);
                            writer.WriteVolume(candle.LowVolume.Value, metaInfo, SecurityId);
                        }

                        if (candle.CloseVolume == null)
                        {
                            writer.Write(false);
                        }
                        else
                        {
                            writer.Write(true);
                            writer.WriteVolume(candle.CloseVolume.Value, metaInfo, SecurityId);
                        }
                    }
                }

                writer.WriteInt((int)candle.State);

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

                var oi = candle.OpenInterest;

                if (metaInfo.Version < MarketDataVersions.Version48)
                {
                    writer.WriteVolume(oi ?? 0m, metaInfo, SecurityId);
                }
                else
                {
                    writer.Write(oi != null);

                    if (oi != null)
                    {
                        writer.WriteVolume(oi.Value, metaInfo, SecurityId);
                    }
                }

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

                writer.Write(candle.DownTicks != null);

                if (candle.DownTicks != null)
                {
                    writer.WriteInt(candle.DownTicks.Value);
                }

                writer.Write(candle.UpTicks != null);

                if (candle.UpTicks != null)
                {
                    writer.WriteInt(candle.UpTicks.Value);
                }

                writer.Write(candle.TotalTicks != null);

                if (candle.TotalTicks != null)
                {
                    writer.WriteInt(candle.TotalTicks.Value);
                }

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

                var priceLevels = candle.PriceLevels;

                writer.Write(priceLevels != null);

                if (priceLevels == null)
                {
                    continue;
                }

                priceLevels = priceLevels.ToArray();

                writer.WriteInt(priceLevels.Count());

                foreach (var level in priceLevels)
                {
                    if (metaInfo.Version < MarketDataVersions.Version56)
                    {
                        writer.WritePrice(level.Price, metaInfo.LastPrice, metaInfo, SecurityId);
                    }
                    else
                    {
                        writer.WritePriceEx(level.Price, metaInfo, SecurityId);
                    }

                    writer.WriteInt(level.BuyCount);
                    writer.WriteInt(level.SellCount);

                    writer.WriteVolume(level.BuyVolume, metaInfo, SecurityId);
                    writer.WriteVolume(level.SellVolume, metaInfo, SecurityId);

                    if (metaInfo.Version >= MarketDataVersions.Version55)
                    {
                        writer.WriteVolume(level.TotalVolume, metaInfo, SecurityId);
                    }

                    var volumes = level.BuyVolumes;

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

                        volumes = volumes.ToArray();

                        writer.WriteInt(volumes.Count());

                        foreach (var volume in volumes)
                        {
                            writer.WriteVolume(volume, metaInfo, SecurityId);
                        }
                    }

                    volumes = level.SellVolumes;

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

                        volumes = volumes.ToArray();

                        writer.WriteInt(volumes.Count());

                        foreach (var volume in volumes)
                        {
                            writer.WriteVolume(volume, metaInfo, SecurityId);
                        }
                    }
                }
            }
        }