SQL - 计算可变长度的可变移动平均值

Posted

技术标签:

【中文标题】SQL - 计算可变长度的可变移动平均值【英文标题】:SQL - Calculating variable moving average over variable lenghts 【发布时间】:2013-04-28 20:22:27 【问题描述】:

FIRST:这个问题不是重复的。我已经在这里问过这个问题,它已作为副本关闭。虽然它类似于 *** 上的其他线程,但实际上要复杂得多。在假设它是重复的之前,请阅读该帖子:

我正在尝试计算可变日期与可变移动平均线的交叉。

即:我想提示用户输入 3 个值和 1 个选项。输入是通过 Web 前端进行的,因此我可以根据输入构建/编辑查询,或者在需要时进行多个查询。

X = 1st moving average term  (N day moving average. Any number 1-N)
Y = 2nd moving average term. (N day moving average. Any number 1-N)
Z = Amount of days back from present to search for the occurance of:
option = Over/Under: (> or <. X passing over Y, or X passing Under Y)


X day moving average passing over OR under Y day moving average
within the past Z days.

我的数据库是结构化的:

tbl_daily_data

id
stock_id
date
adj_close

还有:

tbl_stocks

stock_id
symbol

我有一个 btree 索引:

daily_data(stock_id, date, adj_close)

stock_id

我被困在这个查询上,并且在编写它时遇到了很多麻烦。如果变量是固定的,这似乎是微不足道的,但因为 X、Y、Z 都是 100% 相互独立的(例如,过去 100 天内的 5 天移动平均线,或过去 5 天内的 100 天移动平均线) ) 我在编码时遇到了很多麻烦。

请帮忙! :(

编辑:有人告诉我更多上下文可能会有所帮助?

我们正在创建一个开放式股票分析系统,用户可以在其中执行趋势分析。我有一个包含 3500 只股票及其价格历史的数据库,可以追溯到 1970 年。

此查询将每天运行,以查找符合特定条件的股票 例如:

10日均线穿越20日均线5以内 天

5 天内 20 天低于 10 天移动平均线

100 天内 55 天低于 22 天移动平均线

但是每个用户可能对不同的分析感兴趣,所以我不能只存储每行的移动平均值,它必须被计算出来。

【问题讨论】:

你有没有机会在一组参数下发布一个小数据集和你想要的查询输出? 好的,马上来...示例数据:zbt-psu.org/daily_data.zip 用一些参数编辑了上述问题。输出 = 对于满足输入参数的每只/每只股票:股票的代码、两个计算的移动平均线和股票的代码。输出每只股票在选定时期内的每日价格历史记录也很好,但这不是必需的。 【参考方案1】:

我不确定我是否完全理解这个问题......但这样的事情可能会帮助你到达你需要去的地方:sqlfiddle

SET @X:=5;
SET @Y:=3;
set @Z:=25;
set @option:='under';

select * from ( 

SELECT stock_id,
datediff(current_date(), date) days_ago, 
     adj_close,
     (
     SELECT
          AVG(adj_close) AS moving_average
     FROM
          tbl_daily_data T2
     WHERE
          (
               SELECT
                    COUNT(*)
               FROM
                    tbl_daily_data T3
               WHERE
                    date BETWEEN T2.date AND T1.date
          ) BETWEEN 1 AND @X
     ) move_av_1,
    (
     SELECT
          AVG(adj_close) AS moving_average
     FROM
          tbl_daily_data T2
     WHERE
          (
               SELECT
                    COUNT(*)
               FROM
                    tbl_daily_data T3
               WHERE
                    date BETWEEN T2.date AND T1.date
          ) BETWEEN 1 AND @Y
     ) move_av_2

FROM
     tbl_daily_data T1

where   
datediff(current_date(), date) <= @z
) x
where 
  case when @option ='over'  and move_av_1 > move_av_2 then 1 else 0 end + 
  case when @option ='under' and move_av_2 > move_av_1 then 1 else 0 end  > 0
order by stock_id, days_ago

根据@Tom H 的回答:How do I calculate a moving average using mysql?

【讨论】:

我也不明白这个问题,但 +1 表示尝试;对我来说看起来很棒。我唯一的建议是使用 OP 的参数名称(X、Y、Z 和选项)更清楚。 伊恩:哇,干得好。这对我来说是正确的。但是,我在 20 小时前尝试过跑步。它还在运行....哈哈。 哎呀——我猜有很多数据!我想你有日期索引? 好的,现在是 5 月 17 日。查询尚未完成。是的,它已编入索引....大声笑将不得不尝试改进它...

以上是关于SQL - 计算可变长度的可变移动平均值的主要内容,如果未能解决你的问题,请参考以下文章

熊猫滚动适用于可变窗口长度

youcans 的 OpenCV 例程200篇167.基于移动平均的可变阈值处理

3 Excel 中的可变加权平均值

从数据子集计算平均值和方差的在线算法

基于不同列的具有可变窗口的 Pandas 滚动平均值

如何访问自定义 SQL 标量函数中的前几行?