【问题标题】:How to aggregate historical Forex data from 1 minute level data to 10 minute level by using sql query?如何使用 sql 查询将历史外汇数据从 1 分钟级别的数据汇总到 10 分钟级别的数据?
【发布时间】:2018-12-05 23:42:44
【问题描述】:

我有一个包含历史 FX 历史 1 分钟级别数据的表格,我想根据 1 分钟级别数据选择出 10 分钟数据。

我的表格如下所示:

    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 ,所以预期结果 open 是 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。

  • high 需要是时间跨度的最大值。在高位列中,从 2018.03.26 00:00 到 2018.03.26 00:09,最大值为 0.77283,因此我的预期高位为 0.77283。

  • low 需要是时间跨度的最小值。在低位,从 2018.03.26 00:00 到 2018.03.26 00:09,最小值是 0.77259,所以我的预期低位是 0.77259。

我希望当我有更多数据时这可以继续循环。例如,如果我有 1 小时的数据,当我将数据聚合成 10 分钟的数据时,我预计会有 60/10 = 6 行记录。

我一直在研究这个问题,但找不到合适的解决方案,请有人帮忙吗?非常感谢!

【问题讨论】:

  • 所以您需要查看过去特定数据窗口中的 min/max/last/first 值是多少?您能否提供查询返回的预期结果?
  • 预期结果为:2018.03.26 00:00, 0.77282, 0.77279, 0.77283, 0.77259。如果有20分钟的数据,结果应该是两行,第二行应该是:2018.03.26 00:10, 0.77xxx, 0.77xxx, 0.77xxx, 0.77xxx。
  • 使用哪个dbms?
  • 我用mysql....
  • 你之前尝试过什么?如果您使用的是 MS Sql,则可以使用 Row_Number 选择第 10 条记录(或每 10 条记录)

标签: mysql sql


【解决方案1】:

问题中有很多不清楚的地方。这看起来像货币转换数据,但问题中没有说明(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)

【讨论】:

  • 感谢您指出我的问题中不清楚的部分,我已经更新了。我想我不是尝试按货币汇总,而是尝试按时间戳汇总。
【解决方案2】:

这个可以完成这项工作 - 在 mssql 上进行了测试(我没有 mysql),但它可能对你有帮助。在 mysql 中,您必须仅更改字符串 concat 中的 TOP 1DATEPART 和“+”符号。

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

【讨论】:

    【解决方案3】:

    一种方法是将记录分组并使用函数来检索有关每个组的信息。问题是您没有任何列可以分组。

    在这种情况下,要在 10 分钟内创建记录组,您可以将时间列转换为字符串并截断最后一位数字,例如。如果忽略最后一位,则表中有 10 条记录具有相同的值 '2018.03.26 00:0'。

    关于openclose 列,您需要从组内的第一行和最后一行获取值。 Mysql没有FIRST或者LAST的聚合函数,但是我从这个answer中了解到,你可以使用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 |
    +--------+-----------------+---------+---------+---------+---------+
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-02
      • 2023-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多