首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MySQL累计产品分组依据

问MySQL累计产品分组依据
EN

Stack Overflow用户
提问于 2018-02-25 12:29:27
回答 2查看 2.7K关注 0票数 3

我一直在使用WRDS/CRSP数据集(由UPenn维护的用于学术研究的股票价格数据库)。我一直在下载Python语言的数据并将其插入到我本地的MySQL数据库中。

数据如下所示,主键在(quote_date,security_id)上:

代码语言:javascript
复制
quote_date  security_id tr              accum_index
10-Jan-86   10002       null            1000
13-Jan-86   10002       -0.026595745    973.4042548
14-Jan-86   10002       0.005464481     978.7234036
15-Jan-86   10002       -0.016304348    962.7659569
16-Jan-86   10002       0               962.7659569
17-Jan-86   10002       0               962.7659569
20-Jan-86   10002       0               962.7659569
21-Jan-86   10002       0.005524862     968.0851061
22-Jan-86   10002       -0.005494506    962.765957
23-Jan-86   10002       0               962.765957
24-Jan-86   10002       -0.005524862    957.4468078
27-Jan-86   10002       0.005555556     962.7659569
28-Jan-86   10002       0               962.7659569
29-Jan-86   10002       0               962.7659569
30-Jan-86   10002       0               962.7659569
31-Jan-86   10002       0.027624309     989.3617013
3-Feb-86    10002       0.016129032     1005.319148
4-Feb-86    10002       0.042328041     1047.872338
5-Feb-86    10002       0.04568528      1095.744679

我需要计算accum_index列,它基本上是股票总回报的一个索引,计算方法如下:

代码语言:javascript
复制
accum_index_t = accum_index_{t-1} * (1 + tr_t)

该表有80m行。我已经编写了一些代码来迭代每个security_id并计算累积乘积,如下所示:

代码语言:javascript
复制
select @sid := min(security_id)
from stock_prices;

create temporary table prices (
    quote_date datetime,
    security_id int,
    tr double null,
    accum_index double null,
    PRIMARY KEY (quote_date, security_id)
);

while @sid is not null
do

    select 'security_id', @sid;
    select @accum := null;

    insert into prices
    select quote_date, security_id, tr, accum_index
    from stock_prices
    where security_id = @sid
    order by quote_date asc;

    update prices
    set accum_index = (@accum := ifnull(@accum * (1 + tr), 1000.0));

    update stock_prices p use index(PRIMARY), prices a use index(PRIMARY)
    set p.accum_index = a.accum_index
    where p.security_id = a.security_id
    and p.quote_date = a.quote_date;

    select @sid := min(security_id)
    from stock_prices
    where security_id > @sid;

    delete from prices;

end while;

drop table prices;

但这太慢了,在我的笔记本电脑上,每个安全性都需要大约一分钟的时间,并且需要数年时间来计算这个级数。有没有办法将其矢量化?

干杯,史蒂夫

EN

回答 2

Stack Overflow用户

发布于 2018-09-18 02:27:44

如果您使用的是MySQL 8,则可以使用window functions创建累积产品。不幸的是,据我所知,在任何PROD()数据库中都没有SQL聚合/窗口函数,除了you can emulate it using EXP(SUM(LOG(factor)))

代码语言:javascript
复制
SELECT
  quote_date,
  security_id,
  tr,
  1000 * (EXP(SUM(LOG(1 + COALESCE(tr, 1)))
    OVER (PARTITION BY security_id ORDER BY quote_date)) - 1)
    AS accum_index
FROM stock_prices

dbfiddle here。

票数 5
EN

Stack Overflow用户

发布于 2021-05-21 22:22:55

如果您使用的是MySQL 5,则可以逐行模拟此函数,将当前电流与上一个tr相乘。然后我们取最后一行的累加值。

tr是百分比价值,现在?因此,让我们将1加到每个tr。

第一个存储值将为中性1。

试试这个:

代码语言:javascript
复制
SET @variation = 1;
SET @row_number = 0;

SELECT accumulateTr
FROM
    (SELECT
        @row_number := (@row_number + 1) AS rowNumber,
        @variation := (1 + variation) * @variation AS accumulateTr
     FROM
        prices) accumulatedTrs
ORDER BY rowNumber DESC
LIMIT 1;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48970227

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档