如何为滚动数据库中存储的PostgreSQL数据库的市场数据计算价格变动标准

时间:2020-05-24 00:34:57

标签: sql postgresql hibernate

我有一个postgreSQL 10数据库,其中有一个名为Period的表,该表存储了几种加密货币的历史价格数据。我正在尝试查询此数据,以查找价格在滚动时间内上涨了一定百分比的地方,即一天之内上涨了5%。相关的表列为“ product_id”,自unix时代以来以秒为单位的“ end_time”和“关闭”该期间的收盘价。

更新以进行澄清:

  • 我想查询数据库中每个按end_time排序的时间段
  • 我希望结果具有其他计算列(在我的示例中,我将其称为buy_signalsell_signal,但它们对应于下面的min_period / max_period),基于以下逻辑
    1. 查找在当前期间(1440分钟,表格每分钟有一行)的一天内的最高收盘价为max_period的期间
    2. 找到在当前期间的一天之内出现的最低收盘价为min_period的期间并且其中min_period.end_time < max_period.end_time
    3. 如果min_periodmax_period的收盘价之间的差大于5%,则与包含buy_signal的行相对应的min_period列为true,并且sell_signal行的max_period列为真

大多数内容非常简单明了,但我在#2中用粗体字表示。似乎我实际上需要获得对max_period的引用/别名,才能将该条件添加到min_period查询中。

给出以下简化数据:

id     product_id     start_time     end_time     close
0       BTC-USD         100000        100060       100
1       BTC-USD         100060        100120        99
2       BTC-USD         100120        100180       101
3       BTC-USD         100180        100240       105
4       BTC-USD         100240        100300       104
5       BTC-USD         100300        100360       102
6       BTC-USD         100360        100420       100
7       BTC-USD         100420        100480        98

我希望能够使用其他计算出的列来查询这些时间段,以指示何时出现局部最小值/最大值,以及何时最小值和最大值之间的差异大于阈值。例如:

id     product_id     start_time     end_time     close     buy_signal     sell_signal
0       BTC-USD         100000        100060       100
1       BTC-USD         100060        100120        99         true
2       BTC-USD         100120        100180       101
3       BTC-USD         100180        100240       105                         true
4       BTC-USD         100240        100300       104
5       BTC-USD         100300        100360       102
6       BTC-USD         100360        100420       100
7       BTC-USD         100420        100480        98

id为7的通知行是本地最小值,但不在本地最大值之前。

此查询的复杂性远远超出了我的SQL经验,我花了数周时间在业余时间浏览堆栈溢出答案和SQL功能,但据我所知,这个丑陋的查询已经做到:

SELECT
    end_time,
    close,
    MAX(close) OVER (ORDER BY end_time ROWS BETWEEN CURRENT ROW AND 1439 FOLLOWING) AS max_close,
    MIN(close) OVER (ORDER BY end_time ROWS BETWEEN CURRENT ROW AND 1439 FOLLOWING) AS min_close,
    ((MAX(close) OVER (ORDER BY end_time ROWS BETWEEN CURRENT ROW AND 1439 FOLLOWING) - 
      MIN(close) OVER (ORDER BY end_time ROWS BETWEEN CURRENT ROW AND 1439 FOLLOWING)) / 
      MIN(close) OVER (ORDER BY end_time ROWS BETWEEN CURRENT ROW AND 1439 FOLLOWING)) AS change_percent,
    CASE WHEN
        ((MAX(close) OVER (ORDER BY end_time ROWS BETWEEN CURRENT ROW AND 1439 FOLLOWING) - 
          MIN(close) OVER (ORDER BY end_time ROWS BETWEEN CURRENT ROW AND 1439 FOLLOWING)) / 
          MIN(close) OVER (ORDER BY end_time ROWS BETWEEN CURRENT ROW AND 1439 FOLLOWING)) > 0.05
        THEN true
    END AS buy_signal
FROM Period
WHERE product_id='BTC-USD'

一个明显的问题是,这不能区分最小和最大的顺序。它选择窗口中的最小值,而不考虑基于end_time最小值在时间上早于最大值。我一直在努力将时间过滤器与窗口结合起来,以找到价格最高的价格之前的最低价格,然后将所有内容组合在一起。另一个(可以接受的)限制是,一次只适用于一个product_id,但理想情况下,我希望查询结果包括end_time排序的多个不同product_id,且信号是product_id特定的。

我的目标是将分页查询结果输入到Java应用程序(我正在使用Hibernate)中,该应用程序使用买卖信号来训练模型。我可以使用Java应用程序对数据进行预处理,但是对于数百万行而言,执行和添加比查询选项更多的复杂性将花费数小时。很长的问题很抱歉,但我不想遗漏任何内容。任何帮助将不胜感激。

0 个答案:

没有答案