Example #1
0
 public bool CanAddGap(GapInfo gap)
 {
     if (Gaps.Count == 0)
         return true;
     if (Gaps.Count >= maxGapCount)
         return true;
     var newLength = totalLengthDays + (gap.end - gap.start).TotalDays;
     return newLength <= maxTotalLengthDays;
 }
Example #2
0
        public bool CanAddGap(GapInfo gap)
        {
            if (Gaps.Count == 0)
            {
                return(true);
            }
            if (Gaps.Count >= maxGapCount)
            {
                return(true);
            }
            var newLength = totalLengthDays + (gap.end - gap.start).TotalDays;

            return(newLength <= maxTotalLengthDays);
        }
Example #3
0
 public void AddGap(GapInfo gap)
 {
     Gaps.Add(gap);
     totalLengthDays += (gap.end - gap.start).TotalDays;
 }
        /// <summary>
        /// получение карты потенциальных гэпов;
        /// она составляются по отсутвующим данным в котировке ticker-а,
        /// но учитывает карту гэпов сервера, составленную по предыдущим запросам
        /// </summary>
        /// <param name="ticker"></param>
        /// <param name="timeStart"></param>
        /// <param name="quoteCacheFolder"></param>
        /// <param name="worker"></param>
        /// <param name="nowTime"></param>
        /// <returns></returns>
        public static List <GapInfo> VerifyTickerHistory(string ticker, DateTime timeStart,
                                                         string quoteCacheFolder,
                                                         BackgroundWorker worker,
                                                         DateTime nowTime = default(DateTime))
        {
            if (worker != null && worker.CancellationPending)
            {
                return(new List <GapInfo>());
            }
            if (nowTime == default(DateTime))
            {
                nowTime = DateTime.Now;
            }

            var histStart = GapMap.Instance.GetServerTickerHistoryStart(ticker);

            if (timeStart < histStart)
            {
                timeStart = histStart;
            }

            // получить список гэпов, предположительно, имеющихся на сервере
            var serverGaps = GapMap.Instance.GetServerGaps(ticker);

            // получить имеющуюся историю
            var candles = AtomCandleStorage.Instance.GetAllMinuteCandles(ticker);

            if (candles == null || candles.Count == 0)
            {
                var loadedHist = AtomCandleStorage.Instance.LoadFromFile(quoteCacheFolder, ticker);
                if (loadedHist.HasValue)
                {
                    candles = AtomCandleStorage.Instance.GetAllMinuteCandles(ticker);
                }
            }
            candles = candles ?? new List <CandleData>();

            if (worker != null && worker.CancellationPending)
            {
                return(new List <GapInfo>());
            }

            // определить гэпы
            var gaps = candles.Count > 0
                           ? QuoteCacheManager.GetGaps(candles, timeStart, nowTime)
                           : new List <DateSpan> {
                new DateSpan(timeStart, nowTime)
            };

            // исключить фрагменты, отсутствующие на сервере
            if (serverGaps != null && serverGaps.IsActual)
            {
                GapMap.ExcludeGapsThatLackedOnServer(ref gaps, serverGaps.serverGaps);
            }
            else
            {
                // получить время первой записи в БД и удалить / порезать все гэпы, начинающиеся
                // позже, чем первая запись базы
                var gapsTrimmed = new List <DateSpan>();

                foreach (var gap in gaps)
                {
                    if (gap.end <= histStart)
                    {
                        continue;
                    }
                    if (gap.start < histStart)
                    {
                        gapsTrimmed.Add(new DateSpan(histStart, gap.end));
                    }
                    else
                    {
                        gapsTrimmed.Add(gap);
                    }
                }

                gaps = gapsTrimmed;
            }

            var gapInfos = gaps.Select(g => new GapInfo {
                start = g.start, end = g.end
            }).ToList();

            // склеиваем рядом стоящие гэпы
            GapInfo.StickSmallGaps(ref gapInfos, 30);

            if (worker != null && worker.CancellationPending)
            {
                return(new List <GapInfo>());
            }

            return(gapInfos);
        }
        /// <summary>
        /// устранение гэпов
        /// </summary>
        /// <param name="ticker"></param>
        /// <param name="startTime"></param>
        /// <param name="gaps"></param>
        /// <param name="quoteCacheFolder"></param>
        /// <param name="worker"></param>
        /// <param name="gapsUpdatedAction"></param>
        public static void FillGapsByTicker(string ticker,
                                            DateTime startTime,
                                            List <GapInfo> gaps,
                                            string quoteCacheFolder,
                                            BackgroundWorker worker,
                                            Action <string, List <GapInfo> > gapsUpdatedAction)
        {
            // закачать с сервера
            // параллельно обновляя контрол
            var candlesOld = AtomCandleStorage.Instance.GetAllMinuteCandles(ticker) ?? new List <CandleData>();
            var candlesNew = new List <CandleData>();
            var oldIndex   = 0;

            if (worker != null && worker.CancellationPending)
            {
                return;
            }

            for (var i = 0; i < gaps.Count; i++)
            {
                var gap = gaps[i];
                // добавить имеющиеся свечи
                for (; oldIndex < candlesOld.Count; oldIndex++)
                {
                    if (candlesOld[oldIndex].timeOpen > gap.start)
                    {
                        break;
                    }
                    candlesNew.Add(candlesOld[oldIndex]);
                }

                // подкачать свечи с сервера
                var indexToInsert = i;
                var wasInserted   = false;

                var status = LoadQuotesFromServer(ticker, gap.start, gap.end.AddMinutes(1),
                                                  candlesNew,
                                                  (time, gapStatus) =>
                {
                    // добавить или обновить временный гэп
                    var passedGap = new GapInfo {
                        start = gap.start, end = time, status = gapStatus
                    };
                    if (!wasInserted)
                    {
                        gaps.Insert(indexToInsert, passedGap);
                        wasInserted = true;
                    }
                    else
                    {
                        gaps[indexToInsert] = passedGap;
                    }
                    gaps[indexToInsert + 1] = new GapInfo
                    {
                        start  = time.AddMinutes(1),
                        end    = gaps[indexToInsert + 1].end,
                        status = gaps[indexToInsert + 1].status
                    };
                    // перерисовать контрол
                    gapsUpdatedAction(ticker, gaps);
                },
                                                  worker);
                if (wasInserted)
                {
                    gaps.RemoveAt(indexToInsert);
                }

                if (status == GapInfo.GapStatus.FailedToFill)
                {
                    // в старом списке могли быть какие-то котировки на интервале гэпа - добавить их
                    for (; oldIndex < candlesOld.Count; oldIndex++)
                    {
                        if (candlesOld[oldIndex].timeOpen > gap.end)
                        {
                            break;
                        }
                        candlesNew.Add(candlesOld[oldIndex]);
                    }
                }

                // перекрасить гэп другим цветом
                gaps[i] = new GapInfo
                {
                    start  = gap.start,
                    end    = gap.end,
                    status = status
                };
                if (worker != null && worker.CancellationPending)
                {
                    return;
                }
                if (currentTickerCancelled)
                {
                    currentTickerCancelled = false;
                    return;
                }

                gapsUpdatedAction(ticker, gaps);

                // сместиться вперед в списке старых свеч
                for (; oldIndex < candlesOld.Count; oldIndex++)
                {
                    if (candlesOld[oldIndex].timeOpen > gap.end)
                    {
                        break;
                    }
                }
            }

            if (worker != null && worker.CancellationPending)
            {
                return;
            }

            if (candlesNew.Count == 0)
            {
                return;
            }

            // добавить "хвостик" - недостающие свечки
            var lastTime = candlesNew[candlesNew.Count - 1].timeOpen;

            for (; oldIndex < candlesOld.Count; oldIndex++)
            {
                if (candlesOld[oldIndex].timeOpen <= lastTime)
                {
                    continue;
                }
                candlesNew.Add(candlesOld[oldIndex]);
            }

            if (candlesNew.Count <= candlesOld.Count)
            {
                return;
            }

            // убрать дублирующиеся свечки
            for (var i = 1; i < candlesNew.Count; i++)
            {
                if (candlesNew[i].timeOpen <= candlesNew[i - 1].timeOpen)
                {
                    candlesNew.RemoveAt(i);
                    i--;
                }
            }

            if (worker != null && worker.CancellationPending)
            {
                return;
            }
            // дырки, оставшиеся в истории, и есть серверные гэпы
            if (candlesNew.Count > 0)
            {
                var updatedGapsInfo = QuoteCacheManager.GetGaps(candlesNew, startTime, DateTime.Now);
                GapMap.Instance.UpdateGaps(ticker, updatedGapsInfo);
                GapMap.Instance.SaveToFile();
            }
            if (worker != null && worker.CancellationPending)
            {
                return;
            }

            // сохранить свечи в хранилище и в файл
            AtomCandleStorage.Instance.RewriteCandles(ticker, candlesNew);
            AtomCandleStorage.Instance.FlushInFile(quoteCacheFolder, ticker);
        }
        /// <summary>
        /// устранение гэпов
        /// </summary>
        /// <param name="ticker"></param>
        /// <param name="startTime"></param>
        /// <param name="gaps"></param>
        /// <param name="quoteCacheFolder"></param>
        /// <param name="worker"></param>
        /// <param name="gapsUpdatedAction"></param>
        public static void FillGapsByTicker(string ticker,
                                            DateTime startTime,
                                            List<GapInfo> gaps,
                                            string quoteCacheFolder,
                                            BackgroundWorker worker,
                                            Action<string, List<GapInfo>> gapsUpdatedAction)
        {
            // закачать с сервера
            // параллельно обновляя контрол
            var candlesOld = AtomCandleStorage.Instance.GetAllMinuteCandles(ticker) ?? new List<CandleData>();
            var candlesNew = new List<CandleData>();
            var oldIndex = 0;

            if (worker != null && worker.CancellationPending) return;

            for (var i = 0; i < gaps.Count; i++)
            {
                var gap = gaps[i];
                // добавить имеющиеся свечи
                for (; oldIndex < candlesOld.Count; oldIndex++)
                {
                    if (candlesOld[oldIndex].timeOpen > gap.start) break;
                    candlesNew.Add(candlesOld[oldIndex]);
                }

                // подкачать свечи с сервера
                var indexToInsert = i;
                var wasInserted = false;

                var status = LoadQuotesFromServer(ticker, gap.start, gap.end.AddMinutes(1),
                    candlesNew,
                    (time, gapStatus) =>
                    {
                        // добавить или обновить временный гэп
                        var passedGap = new GapInfo { start = gap.start, end = time, status = gapStatus };
                        if (!wasInserted)
                        {
                            gaps.Insert(indexToInsert, passedGap);
                            wasInserted = true;
                        }
                        else
                            gaps[indexToInsert] = passedGap;
                        gaps[indexToInsert + 1] = new GapInfo
                        {
                            start = time.AddMinutes(1),
                            end = gaps[indexToInsert + 1].end,
                            status = gaps[indexToInsert + 1].status
                        };
                        // перерисовать контрол
                        gapsUpdatedAction(ticker, gaps);
                    },
                    worker);
                if (wasInserted)
                    gaps.RemoveAt(indexToInsert);

                if (status == GapInfo.GapStatus.FailedToFill)
                {
                    // в старом списке могли быть какие-то котировки на интервале гэпа - добавить их
                    for (; oldIndex < candlesOld.Count; oldIndex++)
                    {
                        if (candlesOld[oldIndex].timeOpen > gap.end) break;
                        candlesNew.Add(candlesOld[oldIndex]);
                    }
                }

                // перекрасить гэп другим цветом
                gaps[i] = new GapInfo
                {
                    start = gap.start,
                    end = gap.end,
                    status = status
                };
                if (worker != null && worker.CancellationPending) return;
                if (currentTickerCancelled)
                {
                    currentTickerCancelled = false;
                    return;
                }

                gapsUpdatedAction(ticker, gaps);

                // сместиться вперед в списке старых свеч
                for (; oldIndex < candlesOld.Count; oldIndex++)
                {
                    if (candlesOld[oldIndex].timeOpen > gap.end) break;
                }
            }

            if (worker != null && worker.CancellationPending) return;

            if (candlesNew.Count == 0) return;

            // добавить "хвостик" - недостающие свечки
            var lastTime = candlesNew[candlesNew.Count - 1].timeOpen;
            for (; oldIndex < candlesOld.Count; oldIndex++)
            {
                if (candlesOld[oldIndex].timeOpen <= lastTime) continue;
                candlesNew.Add(candlesOld[oldIndex]);
            }

            if (candlesNew.Count <= candlesOld.Count)
                return;

            // убрать дублирующиеся свечки
            for (var i = 1; i < candlesNew.Count; i++)
            {
                if (candlesNew[i].timeOpen <= candlesNew[i - 1].timeOpen)
                {
                    candlesNew.RemoveAt(i);
                    i--;
                }
            }

            if (worker != null && worker.CancellationPending) return;
            // дырки, оставшиеся в истории, и есть серверные гэпы
            if (candlesNew.Count > 0)
            {
                var updatedGapsInfo = QuoteCacheManager.GetGaps(candlesNew, startTime, DateTime.Now);
                GapMap.Instance.UpdateGaps(ticker, updatedGapsInfo);
                GapMap.Instance.SaveToFile();
            }
            if (worker != null && worker.CancellationPending) return;

            // сохранить свечи в хранилище и в файл
            AtomCandleStorage.Instance.RewriteCandles(ticker, candlesNew);
            AtomCandleStorage.Instance.FlushInFile(quoteCacheFolder, ticker);
        }
Example #7
0
 public void AddGap(GapInfo gap)
 {
     Gaps.Add(gap);
     totalLengthDays += (gap.end - gap.start).TotalDays;
 }