Example #1
0
        // ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local
        private void MergeCandle(string assetPair, CandleTimeInterval interval, ICandle candle)
        {
            if (candle.AssetPairId != assetPair)
            {
                throw new InvalidOperationException($"Candle {candle.ToJson()} has invalid AssetPriceId");
            }
            if (candle.TimeInterval != interval)
            {
                throw new InvalidOperationException($"Candle {candle.ToJson()} has invalid TimeInterval");
            }
            if (candle.PriceType != PriceType)
            {
                throw new InvalidOperationException($"Candle {candle.ToJson()} has invalid PriceType");
            }

            // 1. Check if candle with specified time already exist
            // 2. If found - merge, else - add to list

            var tick = GetIntervalTick(candle.Timestamp, interval);

            // Considering that Candles is ordered by Tick
            for (var i = 0; i < Candles.Count; ++i)
            {
                var currentCandle = Candles[i];

                // While currentCandle.Tick < tick - just skipping

                // That's it, merge to existing candle
                if (currentCandle.Tick == tick)
                {
                    currentCandle.InplaceMergeWith(candle);
                    return;
                }

                // No candle is found but there are some candles after, so we should insert candle right before them
                if (currentCandle.Tick > tick)
                {
                    Candles.Insert(i, candle.ToItem(tick));
                    return;
                }
            }

            // No candle is found, and no candles after, so just add to the end
            Candles.Add(candle.ToItem(tick));
        }
        /// <summary>
        /// Creates mid candle of two candles (ask and bid)
        /// </summary>
        /// <param name="askCandle">first candle</param>
        /// <param name="bidCandle">second candle</param>
        public static ICandle Create(ICandle askCandle, ICandle bidCandle)
        {
            if (askCandle == null || bidCandle == null)
            {
                return(askCandle ?? bidCandle);
            }

            if (askCandle.AssetPairId != bidCandle.AssetPairId)
            {
                throw new InvalidOperationException($"Can't create mid candle of different asset pairs. candle1={askCandle.ToJson()}, candle2={bidCandle.ToJson()}");
            }

            if (askCandle.PriceType != CandlePriceType.Ask)
            {
                throw new InvalidOperationException($"Ask candle should has according price type. candle={askCandle.ToJson()}");
            }

            if (bidCandle.PriceType != CandlePriceType.Bid)
            {
                throw new InvalidOperationException($"Bid candle should has according price type. candle={bidCandle.ToJson()}");
            }

            if (askCandle.TimeInterval != bidCandle.TimeInterval)
            {
                throw new InvalidOperationException($"Can't create mid candle of different time intervals. candle1={askCandle.ToJson()}, candle2={bidCandle.ToJson()}");
            }

            if (askCandle.Timestamp != bidCandle.Timestamp)
            {
                throw new InvalidOperationException($"Can't create mid candle from candles with different timestamps. candle1={askCandle.ToJson()}, candle2={bidCandle.ToJson()}");
            }

            return(Candle.Create(
                       open: (askCandle.Open + bidCandle.Open) / 2,
                       close: (askCandle.Close + bidCandle.Close) / 2,
                       high: (askCandle.High + bidCandle.High) / 2,
                       low: (askCandle.Low + bidCandle.Low) / 2,
                       assetPair: askCandle.AssetPairId,
                       priceType: CandlePriceType.Mid,
                       timeInterval: askCandle.TimeInterval,
                       timestamp: askCandle.Timestamp,
                       tradingVolume: askCandle.LastUpdateTimestamp > bidCandle.LastUpdateTimestamp
                    ? askCandle.TradingVolume
                    : bidCandle.TradingVolume,
                       tradingOppositeVolume: askCandle.LastUpdateTimestamp > bidCandle.LastUpdateTimestamp
                    ? askCandle.TradingOppositeVolume
                    : bidCandle.TradingOppositeVolume,
                       lastTradePrice: askCandle.LastUpdateTimestamp > bidCandle.LastUpdateTimestamp
                    ? askCandle.LastTradePrice
                    : bidCandle.LastTradePrice,
                       lastUpdateTimestamp: askCandle.LastUpdateTimestamp > bidCandle.LastUpdateTimestamp
                    ? askCandle.LastUpdateTimestamp
                    : bidCandle.LastUpdateTimestamp));
        }