Агрегировать и группировать по дате и времени - PullRequest
0 голосов
/ 02 сентября 2018

Имея эти данные (SQL):

enter image description here

Я вызываю (каждую минуту с таймером) данные, затем группирую в 30-минутный интервал с помощью этого метода:

public void GetData()
{
    try
    {
        using (crypto_dbEntities1 context = new crypto_dbEntities1(con))
        {
            var result = context.kraken_btc.Where(x => x.date >= LastRecordedPoint).ToList();
            result = AggregateCandlesIntoRequestedTimePeriod(Period.Minute, Period.HalfAnHour, result);

            foreach (var data in result.OrderBy(x => x.date))
            {
                data.date = DateTime.SpecifyKind(data.date.DateTime, DateTimeKind.Utc).ToUniversalTime();

                Point pb = new Point
                       {
                            Date = data.date.DateTime.ToLocalTime(),
                            JDate = (long)data.javaDate,
                            Open = (double)data.open,
                            High = (double)data.hight,
                            Close = (double)data.close,
                            Low = (double)data.low,
                            Volume = (long)data.volume,
                       };

                if (pb.Date <= LastRecordedPoint)
                {
                   MainCollection.Last().Date = data.date.DateTime.ToLocalTime();
                   MainCollection.Last().Close = (double)data.close;
                   MainCollection.Last().High = (double)data.hight;
                   MainCollection.Last().Open = (double)data.open;
                   MainCollection.Last().Low = (double)data.low;
                   MainCollection.Last().Volume = (long)data.volume;

                   Debug.WriteLine(pb.Date + " Updated data ..");
               }
               else
               {
                   MainCollection.Add(pb);
               }

               LastRecordedPoint = pb.Date;
            }
        }
    }
    catch (Exception err)
    {
        MessageBox.Show(err.ToString());
    }
}

public enum Period
{
    Minute = 1,
    FiveMinutes = 5,
    TenMinutes = 10,
    QuarterOfAnHour = 15,
    HalfAnHour = 30,
    Hour = 60
}

private List<kraken_btc> AggregateCandlesIntoRequestedTimePeriod(Period rawPeriod, Period requestedPeriod, List<kraken_btc> candles)
{
    int rawPeriodDivisor = (int)requestedPeriod;
    candles = candles.GroupBy(g => new { TimeBoundary = new DateTime(g.date.Year, g.date.Month, g.date.Day, g.date.Hour, (g.date.Minute / rawPeriodDivisor) * rawPeriodDivisor, 0) })
                     .Select(s => new kraken_btc
                        {
                            date = s.Key.TimeBoundary,
                            hight = s.Max(z => z.hight),
                            low = s.Min(z => z.low),
                            open = s.First().open,
                            close = s.Last().close,
                            volume = s.Sum(z => z.volume),
                        })
                     .OrderBy(o => o.date)
                     .ToList();

    return candles;
}

И он выполняет работу по агрегации данных, но проблема в том, что мне нужно подождать 30 минут, чтобы моя серия наконец обновилась, если вы посмотрите на последнюю свечу, ее время 17.30, когда база данных имеет данные за 17.47 (im UTC +2.00 ).

Итак, вопрос в том, как я могу сгруппировать данные и начать рисовать неполную свечу в 18.00, как это делает вся платформа обмена ...

enter image description here

1 Ответ

0 голосов
/ 05 сентября 2018

Оператор GroupBy округляет даты, поэтому все данные с 17:30 до 17:47 округляются до 17: 30.

Я бы переместил код для вычисления TimeBoundary в его собственный метод, чтобы вы могли полностью его модульно протестировать, используя методы RoundUp / RoundDown из этого вопроса Как можно округлить время до ближайших X минут? по redent84

public static DateTime RoundUp(this DateTime dt, TimeSpan d)
{
    var modTicks = dt.Ticks % d.Ticks;
    var delta = modTicks != 0 ? d.Ticks - modTicks : 0;
    return new DateTime(dt.Ticks + delta, dt.Kind);
}

public static DateTime RoundDown(this DateTime dt, TimeSpan d)
{
    var delta = dt.Ticks % d.Ticks;
    return new DateTime(dt.Ticks - delta, dt.Kind);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...