Заданное время / интервал для расчета значения открытия / максимума / минимума / закрытия в каждой сгруппированной информации

Предположим, что необработанные данные:

  Timestamp   High Low Volume
  10:24.22345 100   99  10
  10:24.23345 110   97  20
  10:24.33455 97    89  40
  10:25.33455 60    40  50
  10:25.93455 40    20  60

При времени выборки 1 секунда выходные данные должны быть следующими (они сгруппированы по секундам):

  Timestamp   Open Close High  Low Volume 
  10:24         82   83   110   89  70     
  10:25         50   40   60    20  110    
  • Open означает цену самых ранних данных в группе
  • Close означает цену последних данных в группе
  • Volume означает сумму (объем) в группе

Единица выборки варьируется от 1 second, 5 sec, 1 minute, 1 hour, 1 day, ...

Теперь я могу получить High, Low, Volume с помощью следующего SQL:

SELECT date_trunc(\'#{interval}\', ticktime) AS ticktime_stamp,
       max(bid_price) as high,
       min(bid_price) as low,
       sum(bid_volume) as volume,
       max(product_type) as product_type
FROM   czces
WHERE  ticktime >=  \'#{begin_time}\'::timestamp
AND  ticktime <  \'#{end_time}\'::timestamp
AND  product_type =\'#{product_type}\'
GROUP  BY 1
ORDER  BY ticktime_stamp ASC

Но как получить open, close значение в каждой группе на основе вышеуказанного запроса?

2 ответа

Решение

Вы можете использовать оконные функции в сочетании с DISTINCT ON для этого:

SELECT DISTINCT ON (1)
       date_trunc('#{interval}', ticktime) AS ticktime_stamp
     , max(bid_price)         OVER w AS high
     , min(bid_price)         OVER w AS low
     , sum(bid_volume)        OVER w AS volume
     , max(product_type)      OVER w AS product_type
     , min(product_type)      OVER w AS product_type
     , first_value(bid_price) OVER w AS open
     , last_value(bid_price)  OVER w AS close
FROM   czces
WHERE  ticktime >= '#{begin_time}'::timestamp
AND    ticktime <  '#{end_time}'::timestamp
AND    product_type ='#{product_type}'
WINDOW w AS (PARTITION BY date_trunc('#{interval}', ticktime) ORDER BY ticktime
             ROWS BETWEEN UNBOUNDED PRECEDING
                      AND UNBOUNDED FOLLOWING)
ORDER  BY 1;

Объяснение для пользовательской оконной рамы:

Объяснение для DISTINCT ON:

Скорее всего, это искомый запрос, но без реальных данных тестирования трудно быть уверенным.

SELECT
  min(date_trunc('second', "Timestamp")) OVER minutes "Timestamp",
  first_value("Price") OVER minutes "Open",
  last_value("Price") OVER minutes "Close",
  max("High") OVER minutes "High",
  min("Low") OVER minutes "Low",
  sum("Volume") OVER minutes "Volume"
FROM czces
WINDOW minutes AS (
    PARTITION BY date_trunc('second', "Timestamp")
    ORDER BY "Timestamp"
);
Другие вопросы по тегам