Как агрегировать исторические данные Forex от данных 1-минутного уровня до 10-минутного уровня с помощью SQL-запроса? - PullRequest
0 голосов
/ 27 июня 2018

У меня есть таблица с историческими данными за 1 минуту на уровне FX, я хотел бы выбрать данные за 10 минут на основе данных уровня за 1 минуту.

Моя таблица выглядит так:

    ccy     Time                open     high       low      close
    AUDUSD  2018.03.26 00:00    0.77282  0.77283    0.77265  0.77265
    AUDUSD  2018.03.26 00:01    0.77264  0.77266    0.77261  0.77266
    AUDUSD  2018.03.26 00:02    0.77264  0.77265    0.77259  0.77264
    AUDUSD  2018.03.26 00:03    0.77262  0.77262    0.7726   0.77262
    AUDUSD  2018.03.26 00:04    0.77262  0.77262    0.77262  0.77262
    AUDUSD  2018.03.26 00:05    0.7726   0.7726     0.7726   0.7726
    AUDUSD  2018.03.26 00:06    0.77259  0.77262    0.77259  0.77261
    AUDUSD  2018.03.26 00:07    0.77262  0.77265    0.77262  0.77264
    AUDUSD  2018.03.26 00:08    0.77263  0.77272    0.77262  0.77272
    AUDUSD  2018.03.26 00:09    0.77273  0.77278    0.77271  0.77274
    AUDUSD  2018.03.26 00:10    0.77273  0.77282    0.77271  0.77279
    AUDUSD  2018.03.26 00:11    0.77282  0.77293    0.77281  0.77291
    AUDUSD  2018.03.26 00:12    0.77291  0.77293    0.77287  0.77287
    AUDUSD  2018.03.26 00:13    0.77288  0.77288    0.77288  0.77288
    AUDUSD  2018.03.26 00:14    0.77288  0.77288    0.77277  0.77279
    AUDUSD  2018.03.26 00:15    0.77278  0.77279    0.77255  0.77262
    AUDUSD  2018.03.26 00:16    0.77261  0.77271    0.77261  0.77271
    AUDUSD  2018.03.26 00:17    0.77271  0.77273    0.77264  0.77271
    AUDUSD  2018.03.26 00:18    0.77273  0.77282    0.77273  0.77281
    AUDUSD  2018.03.26 00:19    0.77281  0.77285    0.77281  0.77283

Как видите, метка времени - каждая 1 минута, и выше - выборка данных за 20 минут.

Мой ожидаемый результат:

    ccy     Time                open     high       low      close
    AUDUSD  2018.03.26 00:00    0.77282  0.77283    0.77259  0.77274
    AUDUSD  2018.03.26 00:10    0.77273  0.77293    0.77255  0.77283
  • Открытие должно быть ценой открытия каждой начальной точки промежутка времени, например, с 2018.03.26 00:00 до 2018.03.26 00:09, начальной точкой является 2018.03.26 00:00 Таким образом, ожидаемый результат открытия - открытие 2018.03.26 00:00, что составляет 0.77282.

  • Закрытие должно быть ценой закрытия каждой конечной точки промежутка времени, например, с 2018.03.26 00:00 до 2018.03.26 00:09, конечной точкой является 2018.03.26 00:09 Таким образом, ожидаемый результат закрытия - закрытие 2018.03.26 00:09, что составляет 0,77274.

  • Максимальное значение должно быть максимальным значением промежутка времени. В столбце максимума с 2018.03.26 по 00:00 до 2018.03.26 00:09 максимальное значение составляет 0,77283, поэтому мой ожидаемый максимум - 0,77283.

  • Низким должно быть минимальное значение промежутка времени. В нижнем столбце с 2018.03.26 00:00 до 2018.03.26 00:09 минимальное значение составляет 0,77259, поэтому мой ожидаемый минимум - 0,77259.

И я надеюсь, что это может продолжаться, пока у меня есть больше данных. Так, например, если у меня есть данные за 1 час, я ожидал, что при объединении данных в данные за 10 минут будет 60/10 = 6 записей строк.

Я какое-то время работал над этим, но не могу найти правильного решения, может кто-нибудь, пожалуйста, помогите? Большое спасибо!

Ответы [ 3 ]

0 голосов
/ 27 июня 2018

Есть ряд вещей, которые не ясны в этом вопросе. Это похоже на данные о конвертации валюты, но в вопросе это не указано (ccy?), И похоже, что вы хотите агрегировать по ccy, но это не указано в вопросе, нет указания на то, что вы хотите передать в запросе ( диапазон интервалов, тип интервала и т. д.). Но для начала приведу пример подхода, ключевая проблема, которую я вижу, это получение первых и последних значений

drop table if exists t;
create table t(ccy varchar(6),Tm datetime,open decimal(10,5),high decimal(10,5), low decimal(10,5), close decimal(10,5));
insert into t values
(    'AUDUSD',  '2018-03-26 00:00'  ,  0.77282 , 0.77283  ,  0.77265 , 0.77265),
(    'AUDUSD',  '2018-03-26 00:01'  ,  0.77264 , 0.77266  ,  0.77261 , 0.77266),
(    'AUDUSD',  '2018-03-26 00:02'  ,  0.77264 , 0.77265  ,  0.77259 , 0.77264),
(    'AUDUSD',  '2018-03-26 00:03'  ,  0.77262 , 0.77262  ,  0.7726  , 0.77262),
(    'AUDUSD',  '2018-03-26 00:04'  ,  0.77262 , 0.77262  ,  0.77262 , 0.77262),
(    'AUDUSD',  '2018-03-26 00:05'  ,  0.7726  , 0.7726   ,  0.7726  , 0.7726),
(    'AUDUSD',  '2018-03-26 00:06'  ,  0.77259 , 0.77262  ,  0.77259 , 0.77261),
(    'AUDUSD',  '2018-03-26 00:07'  ,  0.77262 , 0.77265  ,  0.77262 , 0.77264),
(    'AUDUSD',  '2018-03-26 00:08'  ,  0.77263 , 0.77272  ,  0.77262 , 0.77272),
(    'AUDUSD',  '2018-03-26 00:09'  ,  0.77273 , 0.77278  ,  0.77271 , 0.77274),
(    'AUDUSD',  '2018-03-26 00:10'  ,  0.77273 , 0.77282  ,  0.77271 , 0.77279);

select ccy, (select open from t t1 where t1.ccy = t.ccy order by t1.tm asc limit 1) periodopen,
                (select close from t t1 where t1.ccy = t.ccy order by t1.tm desc limit 1) period_close,
                max(high) period_high,
                min(low) period_low 
from t
where t.tm between '2018-03-26 00:00' and '2018-03-26 00:10:00'
group by ccy;

+--------+------------+--------------+-------------+------------+
| ccy    | periodopen | period_close | period_high | period_low |
+--------+------------+--------------+-------------+------------+
| AUDUSD |    0.77282 |      0.77279 |     0.77283 |    0.77259 |
+--------+------------+--------------+-------------+------------+
1 row in set (0.00 sec)
0 голосов
/ 27 июня 2018

Этот делает работу - проверено на mssql (у меня нет mysql), но, возможно, это полезно для вас. В mysql вы должны изменить только символы TOP 1 , DATEPART и " + " в строке concat.

CREATE TABLE [dbo].[T1](
    [F_CCY] [varchar](20) NULL,
    [F_TIME] [datetime] NULL,
    [F_OPEN] [numeric](10, 8) NULL,
    [F_HIGH] [numeric](10, 8) NULL,
    [F_LOW] [numeric](10, 8) NULL,
    [F_CLOSE] [numeric](10, 8) NULL
);

INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26', 0.77282, 0.77283, 0.77265, 0.77265);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:01:00', 0.77264, 0.77266, 0.77261, 0.77266);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:02:00', 0.77264, 0.77265, 0.77259, 0.77264);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:03:00', 0.77262, 0.77262, 0.7726, 0.77262);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:04:00', 0.77262, 0.77262, 0.77262, 0.77262);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:05:00', 0.7726, 0.7726, 0.7726, 0.7726);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:06:00', 0.77259, 0.77262, 0.77259, 0.77261);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:07:00', 0.77262, 0.77265, 0.77262, 0.77264);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:08:00', 0.77263, 0.77272, 0.77262, 0.77272);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:09:00', 0.77273, 0.77278, 0.77271, 0.77274);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:10:00', 0.77273, 0.77282, 0.77271, 0.77279);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:11:00', 0.77282, 0.77283, 0.77265, 0.77265);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:12:00', 0.77264, 0.77266, 0.77261, 0.77266);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:13:00', 0.77264, 0.77265, 0.77259, 0.77264);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:14:00', 0.77262, 0.77262, 0.7726, 0.77262);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:15:00', 0.77262, 0.77262, 0.77262, 0.77262);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:16:00', 0.7726, 0.7726, 0.7726, 0.7726);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:17:00', 0.77259, 0.77262, 0.77259, 0.77261);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:18:00', 0.77262, 0.77265, 0.77262, 0.77264);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:19:00', 0.77263, 0.77272, 0.77262, 0.77272);
INSERT INTO T1 (F_CCY, F_TIME, F_OPEN, F_HIGH, F_LOW, F_CLOSE) VALUES('AUDUSD', '2018-03-26 00:20:00', 0.77273, 0.77278, 0.77271, 0.77274);


SELECT
    T.F_ccy as "ccy"
    , MIN(T.F_TIME) as "Time"
    ,
    (SELECT
        TOP 1 FIRST_VALUE(X.F_OPEN) OVER(ORDER BY X.F_TIME)
    FROM
        T1 X
    WHERE
        X.F_ccy=T.F_ccy
        AND X.F_TIME>=CAST(CAST(CAST(T.F_TIME AS DATE) AS VARCHAR(10)) + ' ' + CAST(DATEPART(HOUR, T.F_TIME) AS VARCHAR(2)) + ':' + CAST((DATEPART(MINUTE, T.F_TIME)/10)*10 AS VARCHAR(2)) AS DATETIME)
        AND X.F_TIME<CAST(CAST(CAST(T.F_TIME AS DATE) AS VARCHAR(10)) + ' ' + CAST(DATEPART(HOUR, T.F_TIME) AS VARCHAR(2)) + ':' + CAST(((DATEPART(MINUTE, T.F_TIME)/10)+1)*10 AS VARCHAR(2)) AS DATETIME)
    ) AS "open"
    ,
    (SELECT
        TOP 1 LAST_VALUE(X.F_OPEN) OVER(ORDER BY X.F_TIME)
    FROM
        T1 X
    WHERE
        X.F_ccy=T.F_ccy
        AND X.F_TIME>=CAST(CAST(CAST(T.F_TIME AS DATE) AS VARCHAR(10)) + ' ' + CAST(DATEPART(HOUR, T.F_TIME) AS VARCHAR(2)) + ':' + CAST((DATEPART(MINUTE, T.F_TIME)/10)*10 AS VARCHAR(2)) AS DATETIME)
        AND X.F_TIME<CAST(CAST(CAST(T.F_TIME AS DATE) AS VARCHAR(10)) + ' ' + CAST(DATEPART(HOUR, T.F_TIME) AS VARCHAR(2)) + ':' + CAST(((DATEPART(MINUTE, T.F_TIME)/10)+1)*10 AS VARCHAR(2)) AS DATETIME)      
        ) AS "close"
    , MAX(T.F_HIGH) as "high"
    , MIN(T.F_LOW) as "low"
FROM
    T1 T
GROUP BY
    T.F_ccy
    , CAST(T.F_TIME AS DATE)
    , DATEPART(HOUR, T.F_TIME)
    , DATEPART(MINUTE, T.F_TIME)/10
0 голосов
/ 27 июня 2018

Один из способов - сгруппировать записи и использовать функции для получения информации о каждой группе. Проблема в том, что у вас нет столбцов для группировки.

В этом случае, чтобы создать группы записей в течение 10 минут, вы можете преобразовать столбец Time в строку и обрезать последнюю цифру, например. в таблице 10 записей с одинаковым значением «2018.03.26 00: 0», если игнорировать последнюю цифру.

Что касается столбцов open и close, вам необходимо получить значения из первой и последней строк внутри групп. Mysql не имеет агрегатной функции FIRST или LAST, но из этого ответа я узнал, что вы можете использовать GROUP_CONCAT для их моделирования.

select
    ccy,
    SUBSTRING(DATE_FORMAT(Time, '%Y.%m.%d %H:%i'),1,15) as time_group, 
    SUBSTRING_INDEX(GROUP_CONCAT(CAST(open AS CHAR) ORDER BY Time), ',', 1 ) as open,
    MAX(high) as high, 
    MIN(low) as low,
    SUBSTRING_INDEX(GROUP_CONCAT(CAST(close AS CHAR) ORDER BY Time DESC), ',', 1 ) as close
from table_name
group by ccy, time_group;

это результат

+--------+-----------------+---------+---------+---------+---------+
| ccy    | time_group      | open    | high    | low     | close   |
+--------+-----------------+---------+---------+---------+---------+
| AUDUSD | 2018.03.26 00:0 | 0.77282 | 0.77283 | 0.77259 | 0.77274 |
| AUDUSD | 2018.03.26 00:1 | 0.77273 | 0.77293 | 0.77255 | 0.77283 |
+--------+-----------------+---------+---------+---------+---------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...