【问题标题】:"Running Product" aggregate/ windowed function in PostgreSql?PostgreSql 中的“运行产品”聚合/窗口函数?
【发布时间】:2017-07-21 22:14:54
【问题描述】:

我正在尝试使 PostgreSql 中的日终股票价格正常化。

假设我有一个这样定义的股票表:

create table eod (
  date date not null,
  stock_id int not null,
  split decimal(16,8) not null,
  close decimal(12,6) not null,
  constraint pk_eod primary key (date, stock_id)
);

此表中的数据可能如下所示:

"date","stock_id","eod_split","close"
"2014-06-13",14010920,"1.00000000","182.560000"
"2014-06-13",14010911,"1.00000000","91.280000"
"2014-06-13",14010923,"1.00000000","41.230000"
"2014-06-12",14010911,"1.00000000","92.290000"
"2014-06-12",14010920,"1.00000000","181.220000"
"2014-06-12",14010923,"1.00000000","40.580000"
"2014-06-11",14010920,"1.00000000","182.250000"
"2014-06-11",14010911,"1.00000000","93.860000"
"2014-06-11",14010923,"1.00000000","40.860000"
"2014-06-10",14010911,"1.00000000","94.250000"
"2014-06-10",14010923,"1.00000000","41.110000"
"2014-06-10",14010920,"1.00000000","184.290000"
"2014-06-09",14010920,"1.00000000","186.220000"
"2014-06-09",14010911,"7.00000000","93.700000"
"2014-06-09",14010923,"1.00000000","41.270000"
"2014-06-06",14010923,"1.00000000","41.480000"
"2014-06-06",14010911,"1.00000000","645.570000"
"2014-06-06",14010920,"1.00000000","186.370000"
"2014-06-05",14010920,"1.00000000","185.980000"
"2014-06-05",14010911,"1.00000000","647.350000"
"2014-06-05",14010923,"1.00000000","41.210000"
... 
"2005-03-04",14010920,"1.00000000","92.370000"
"2005-03-04",14010911,"1.00000000","42.810000"
"2005-03-04",14010923,"1.00000000","25.170000"
"2005-03-03",14010923,"1.00000000","25.170000"
"2005-03-03",14010911,"1.00000000","41.790000"
"2005-03-03",14010920,"1.00000000","92.410000"
"2005-03-02",14010920,"1.00000000","92.920000"
"2005-03-02",14010923,"1.00000000","25.260000"
"2005-03-02",14010911,"1.00000000","44.121000"
"2005-03-01",14010920,"1.00000000","93.300000"
"2005-03-01",14010923,"1.00000000","25.280000"
"2005-03-01",14010911,"1.00000000","44.500000"
"2005-02-28",14010923,"1.00000000","25.160000"
"2005-02-28",14010911,"2.00000000","44.860000"
"2005-02-28",14010920,"1.00000000","92.580000"
"2005-02-25",14010923,"1.00000000","25.250000"
"2005-02-25",14010920,"1.00000000","92.800000"
"2005-02-25",14010911,"1.00000000","88.990000"
"2005-02-24",14010923,"1.00000000","25.370000"
"2005-02-24",14010920,"1.00000000","92.640000"
"2005-02-24",14010911,"1.00000000","88.930000"
"2005-02-23",14010923,"1.00000000","25.200000"
"2005-02-23",14010911,"1.00000000","88.230000"
"2005-02-23",14010920,"1.00000000","92.100000"
...
"2003-02-24",14010920,"1.00000000","78.560000"
"2003-02-24",14010911,"1.00000000","14.740000"
"2003-02-24",14010923,"1.00000000","24.070000"
"2003-02-21",14010920,"1.00000000","79.950000"
"2003-02-21",14010923,"1.00000000","24.630000"
"2003-02-21",14010911,"1.00000000","15.000000"
"2003-02-20",14010911,"1.00000000","14.770000"
"2003-02-20",14010920,"1.00000000","79.150000"
"2003-02-20",14010923,"1.00000000","24.140000"
"2003-02-19",14010920,"1.00000000","79.510000"
"2003-02-19",14010911,"1.00000000","14.850000"
"2003-02-19",14010923,"1.00000000","24.530000"
"2003-02-18",14010923,"2.00000000","24.960000"
"2003-02-18",14010911,"1.00000000","15.270000"
"2003-02-18",14010920,"1.00000000","79.330000"
"2003-02-14",14010911,"1.00000000","14.670000"
"2003-02-14",14010920,"1.00000000","77.450000"
"2003-02-14",14010923,"1.00000000","48.300000"
"2003-02-13",14010920,"1.00000000","75.860000"
"2003-02-13",14010911,"1.00000000","14.540000"
"2003-02-13",14010923,"1.00000000","46.990000"

注意“拆分”列。当记录除 1 以外的分割值时,基本上意味着股票按该因子分割。 IOW,当拆分为 2.0 时,已发行股票的数量翻了一番,但从那时起,每一股的价值减半。如果股票价值每股 100 美元,那么现在每股价值 50 美元。

如果你用原始数字来绘制它,这种事情真的很难看。当公司的整体价值没有显着变化时,就会出现陡峭的悬崖……当您进行多次拆分时,您最终会得到一个不能正确反映公司趋势的图表,通常幅度很大。在上面的示例中,如果有 2:1 的拆分,您的股票收盘价将类似于 100、100、100、50、50、50。

我想使用此表以合理有效的方式创建“标准化”价格(有很多记录需要分块)。继续示例,这将显示股票价格为 50、50、50、50、50、50。如果有多次拆分,如果我们忽略实际市值变化,数据应该仍然是一致且平滑的。

我的想法是,如果我可以创建拆分值的“运行产品”聚合的 CTE,及时回溯,我可以定义每只股票的日期范围以及应用于收盘成本的修正值应该是什么,然后将其连接回 eod 表,并在新表中选择每只股票的调整后收盘价。

...问题是,除了一大堆临时表和多步骤流程之外,我无法思考如何做到这一点。我也不知道有任何内置功能可以让这更容易。

谁能告诉我如何生成标准化数据?

【问题讨论】:

    标签: sql postgresql aggregate


    【解决方案1】:

    您不需要 CTE。你只需要一个累积的产品。 Postgres 没有内置的。但是,算术来拯救!

    select eod.*,
           exp(sum(ln(eod_split)) over (partition by stock_id order by date)) as cume_split,
           (close *
            exp(sum(ln(eod_split)) over (partition by stock_id order by date))
           ) as normalized_price
    from eod;
    

    【讨论】:

    • 那不是算术。这就是火箭科学。我什至不明白这里发生了什么,但我会尝试一下,看看我是否能理解它。
    • 看起来这行得通。我需要更多时间来了解它的作用,但它很好、整洁且性能良好。非常感谢!
    • 这个答案纯属黄金!绞尽脑汁如何解决类似的问题,其简单性值得加分 1000 分:)。顺便说一句,戈登很棒的书!
    【解决方案2】:

    搞笑,寻找这个解决方案,我发现一个同事已经问过了。这是这个巧妙解决方案背后的基本代数:https://blog.prepscholar.com/natural-log-rules

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-14
      • 2014-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-27
      • 2012-01-09
      相关资源
      最近更新 更多