0

我有一些金融报价数据,只有第二个分辨率。数据本身按时间顺序排列。

Date        Time      Bid     Ask
06/07/2015  19:09:29  0.7623  0.76262
06/07/2015  19:09:29  0.7623  0.76271
06/07/2015  19:09:29  0.7623  0.76276

我正在寻找一些需要我能够知道亚秒级的分析。所以我最初的想法是“伪造”毫秒。当同一秒内有多个滴答声(数据点)时,我将假设它们在那一秒内均匀分布。因此,由于同一秒内有 3 个刻度,我假设第一个发生在第二个开始时,第二个发生在 0.333,第三个发生在 0.666。

两个问题。

  1. 这种方法(伪造毫秒)是存储实际订单的最佳方式吗?

  2. 我有相当多的数据要导入,所以我想我会在上传原始数据的两阶段过程中进行操作,然后使用执行毫秒计算的选择插入到我的目标表中。因此,我们将不胜感激对以下查询/方法的任何帮助。


CREATE TEMPORARY TABLE dataload (
    id serial
  , dt date
  , tm time
  , bid numeric(10,5)
  , ask numeric(10,5)
);

COPY dataload (dt, tm, bid, ask) FROM '/path/to/data.csv' WITH CSV HEADER;

-- INSERT INTO actual_table
SELECT
    dt
  , tm
  , (dt||tm)::timestamp -- Need to hack the milliseconds here
from dataload
group by dt, tm;
4

2 回答 2

1

如果您无法获得改进的数据,最好以与其背后的现实相匹配的方式对其进行建模。

因此,添加假秒可能不是一个好主意,因为您会掩盖真实情况。

相反,您可以在一秒钟内添加一个具有订单排名的字段。这可以很容易地完成row_number() over (partition by date, time)

如果这有助于减少数据的大小,您总是可以将该数字转换为秒的一部分。

于 2016-05-03T23:21:27.673 回答
1

我一般不喜欢伪造数据。准确存储给定的内容会更准确,并使用第二列来指示排序。这将花费一些额外的存储空间,但缺乏混乱可能会弥补这一点。

除非您有充分的理由,否则我也不会将时间与日期分开存储。

最好使用file_fdw而不是中间表,以避免额外的复制步骤。问题是 file_fdw 没有给您行号或任何其他排序方式,以允许您使用 row_number() 创建亚秒级排序。所以我们需要使用一个函数。

CREATE TABLE tick(
  tick_timestamp      timestamptz      NOT NULL
  , tick_sequence     smallint         NOT NULL
  , CONSTRAINT tick__pk_tick_timestamp__tick_sequence PRIMARY KEY( tick_timestamp, tick_sequence )
  , bid               numeric(10,5)    NOT NULL
  , ask               numeric(10,5)    NOT NULL
);
CREATE FOREIGN TABLE tick_csv( tick_date date, tick_time time, bid numeric, ask numeric ) ...;
CREATE FUNCTION get_tick() RETURNS SETOF tick_csv LANGUAGE sql AS $$SELECT * FROM tick_csv$$;
COMMENT ON FUNCTION get_tick() IS $$This function is necessary because file_fdw provides no means of obtaining row numbers, which we need for safe ordering. This function allows use of WITH ORDINALITY to get a row number.$$;
INSERT INTO tick( tick_timestamp, tick_sequence, bid, ask )
  SELECT tick_timestamp
      -- Generate a series that resets for each second
      , row_number() OVER( PARTITION BY tick_timestamp ORDER BY ordinality )
      , bid
      , ask
    FROM (
      SELECT *, ( tick_date + tick_time ) AT TIME ZONE 'America/New_York' AS tick_timestamp -- CHANGE TO CORRECT TIMEZONE
        FROM get_ticks() WITH ordinality
    ) raw
;

您可能想省略函数位并使用临时序列之类的东西来生成行号。这样做的问题是它不能防止计划者创建一个重新排序外部表输出的计划。仅执行顺序扫描的简单操作不应该发生这种情况,但是如果您决定加入其他表,那么您很容易得到乱序行。这个 SQL 函数安全的原因是因为它不会被内联,因为我们使用的是 WITH ORDINALITY(并且因为它没有被定义为 STABLE,你可能可以这样做)。

于 2016-05-04T00:20:52.277 回答