需要查询修复和优化帮助(查找每周股票数据的最高价、最高价和最后已知的收盘价)

Posted

技术标签:

【中文标题】需要查询修复和优化帮助(查找每周股票数据的最高价、最高价和最后已知的收盘价)【英文标题】:Need query fix and optimization help (that finds max high, max low for WEEKLY stock data and last known closing week price) 【发布时间】:2020-08-24 03:23:56 【问题描述】:

感谢您提供的任何帮助。我有一个 mysql 查询,它提供股票的每周价格。我不是某个时候作为解决方案编写的脚本的原作者。我最近不得不对其进行调整以满足其他需求。

我没有效率地添加每周(前一周)的收盘价,但直到周五我才能获得本周的收盘价。对于当前一周(顶行),它应该使用本周迄今为止给出的最新收盘价,直到周五收盘。

它运行得很慢,我在这种情况下,如果您查看周线图,我们可以使用 AAPL 的示例。Stockchart of AAPL 以下 SQL 旨在提供该周的每周(最高)最高价、最低(最低)和最后收盘价(通常是星期五,但如果有假期,可能是星期四)。

SELECT 
    my_symbol,
    end_date,
    weekly_high,
    high_date,
    weekly_low,
    low_date,
    (SELECT 
            close
        FROM
            mydb.STOCKS_DAILY
        WHERE
            date = end_date AND symbol = my_symbol) AS close
FROM
    (SELECT 
        wl.symbol AS my_symbol,
            wl.end_date AS end_date,
            wl.weekly_high AS weekly_high,
            MIN(hd.date) AS high_date,
            wl.weekly_low,
            MIN(ld.date) AS low_date
    FROM
        (SELECT 
        s1.symbol,
            w.start_date,
            w.end_date,
            MAX(s1.high) AS weekly_high,
            MIN(s1.low) AS weekly_low
    FROM
        mydb.WEEKLY_LOOKUP AS w
    INNER JOIN mydb.STOCKS_DAILY AS s1 ON s1.date BETWEEN w.start_date AND w.end_date
        AND SYMBOL = 'AAPL'
        AND w.end_date <= DATE('2020-05-07' - INTERVAL 1 WEEK + INTERVAL (6 - DAYOFWEEK('2020-05-07' - INTERVAL 1 WEEK)) DAY)
    GROUP BY s1.symbol , w.start_date
    ORDER BY w.end_date DESC
    LIMIT 34) AS wl
    INNER JOIN mydb.STOCKS_DAILY AS hd ON hd.date BETWEEN wl.start_date AND wl.end_date
        AND hd.symbol = wl.symbol
        AND hd.high = wl.weekly_high
    INNER JOIN mydb.STOCKS_DAILY AS ld ON ld.date BETWEEN wl.start_date AND wl.end_date
        AND ld.symbol = wl.symbol
        AND ld.low = wl.weekly_low
    GROUP BY wl.symbol , wl.start_date , wl.end_date , wl.weekly_high , wl.weekly_low
    ORDER BY wl.end_date DESC) my_tag

** 注意**:很抱歉我不得不使用 styling for the data output below as other formatting choices caused wrapping or other formatting issues. I am trying to ensure it is in a readable format.

WEEKLY_LOOKUP 是一个表格,其中包含每周的开始日期和结束日期作为参考,代表从星期一 (start_date) 到星期五 (end_date) 的一周。我不确定我是否需要这样的东西,或者它是否可以生成?

# START_DATE, END_DATE
2020-05-04 00:00:00, 2020-05-08 00:00:00
2020-04-27 00:00:00, 2020-05-01 00:00:00
2020-04-20 00:00:00, 2020-04-24 00:00:00
2020-04-13 00:00:00, 2020-04-17 00:00:00
2020-04-06 00:00:00, 2020-04-10 00:00:00
2020-03-30 00:00:00, 2020-04-03 00:00:00
2020-03-23 00:00:00, 2020-03-27 00:00:00
2020-03-16 00:00:00, 2020-03-20 00:00:00
2020-03-09 00:00:00, 2020-03-13 00:00:00
2020-03-02 00:00:00, 2020-03-06 00:00:00

这是脚本产生的结果:

# my_symbol, end_date, weekly_high, high_date, weekly_low, low_date, close, current_close
AAPL, 2020-05-08 00:00:00, 305.17, 2020-05-07 00:00:00, 286.317, 2020-05-04 00:00:00, , 303.74
AAPL, 2020-05-01 00:00:00, 299, 2020-05-01 00:00:00, 278.2, 2020-04-28 00:00:00, 289.07, 303.74
AAPL, 2020-04-24 00:00:00, 283.01, 2020-04-24 00:00:00, 265.43, 2020-04-21 00:00:00, 282.97, 303.74
AAPL, 2020-04-17 00:00:00, 288.25, 2020-04-14 00:00:00, 265.83, 2020-04-13 00:00:00, 282.8, 303.74
AAPL, 2020-04-10 00:00:00, 271.7, 2020-04-07 00:00:00, 249.38, 2020-04-06 00:00:00, , 303.74
AAPL, 2020-04-03 00:00:00, 262.49, 2020-03-31 00:00:00, 236.9, 2020-04-02 00:00:00, 241.41, 303.74
AAPL, 2020-03-27 00:00:00, 258.68, 2020-03-26 00:00:00, 212.61, 2020-03-23 00:00:00, 247.74, 303.74
AAPL, 2020-03-20 00:00:00, 259.08, 2020-03-16 00:00:00, 228, 2020-03-20 00:00:00, 229.24, 303.74
AAPL, 2020-03-13 00:00:00, 286.44, 2020-03-10 00:00:00, 248, 2020-03-12 00:00:00, 277.97, 303.74
AAPL, 2020-03-06 00:00:00, 304, 2020-03-03 00:00:00, 277.72, 2020-03-02 00:00:00, 289.03, 303.74
AAPL, 2020-02-28 00:00:00, 304.18, 2020-02-24 00:00:00, 256.37, 2020-02-28 00:00:00, 273.36, 303.74
AAPL, 2020-02-21 00:00:00, 324.65, 2020-02-20 00:00:00, 310.5, 2020-02-21 00:00:00, 313.05, 303.74
AAPL, 2020-02-14 00:00:00, 327.22, 2020-02-12 00:00:00, 313.85, 2020-02-10 00:00:00, 324.95, 303.74
AAPL, 2020-02-07 00:00:00, 325.22, 2020-02-06 00:00:00, 302.22, 2020-02-03 00:00:00, 320.03, 303.74
AAPL, 2020-01-31 00:00:00, 327.85, 2020-01-29 00:00:00, 304.88, 2020-01-27 00:00:00, 309.51, 303.74
AAPL, 2020-01-24 00:00:00, 323.33, 2020-01-24 00:00:00, 315.65, 2020-01-23 00:00:00, 318.31, 303.74
AAPL, 2020-01-17 00:00:00, 318.74, 2020-01-17 00:00:00, 309.55, 2020-01-15 00:00:00, 318.73, 303.74
AAPL, 2020-01-10 00:00:00, 312.67, 2020-01-10 00:00:00, 292.75, 2020-01-06 00:00:00, 310.33, 303.74

关于输出的几点说明:

1) 第一行是当前周。随着每一天的进展 通过星期一、星期二等,它应该检测每周是什么 最高价和每周最低价,并提供最后已知的收盘价。我曾是 能够打印前几周的收盘价,因为他们 落在“星期五”。例如,如果是星期四 5/7,收盘 周四是 302.92。我希望它拉出本周已知的最后一个已知关闭日期。我添加了最后一个已知收盘价的效率低下,因此我可以将其从结果集中提取并以编程方式将其换入本周以解决问题,但这不是最佳解决方案。 2) 您会注意到 4/10 的那一周还有一个空空格 那里。我相信那是耶稣受难日,市场休市。 为了解决这个问题,我的想法是我会回到每周 表从星期五结束日期更改为星期四 结束日期,因此它将使用该每周范围,但在考虑之后 更多,可能会因为 INTERVAL diff 调整而搞砸 总是在寻找星期五的日期。

理想情况下,输出将是(显示收盘价为 5/7,因为我还没有 5/8 数据)提供已知或相关的最后收盘价,直到本周收盘。如果查询是在 5 月 5 日星期二运行的,它会只提取星期一和星期二的数据,并使用 5 月 5 日星期二的最后收盘价 296.76,因为本周还没有收盘。

(05/8 的结束周尚未结束,因为这代表 5/4 - 5/7 的第一行数据)。其他 2 行周一至周五全封闭。

# my_symbol、end_date、weekly_high、high_date、weekly_low、low_date、close
AAPL, 2020-05-08 00:00:00, 305.17, 2020-05-07 00:00:00, 286.317, 2020-05-04 00:00:00, 302.92
AAPL, 2020-05-01 00:00:00, 299, 2020-05-01 00:00:00, 278.2, 2020-04-28 00:00:00, 289.07
AAPL, 2020-04-24 00:00:00, 283.01, 2020-04-24 00:00:00, 265.43, 2020-04-21 00:00:00, 282.97

最后,这个脚本运行起来似乎很慢,因为它必须一次回顾 34 周的股票。不确定如何优化它以仍然以有效的方式提供所需的数据。

感谢您提供的任何帮助。由于我的经验有限,并且尝试不同的事情需要花费大量时间,我认为我应该向董事会求助于专家。

非常感谢。

【问题讨论】:

确保合适的索引可用并被使用。使用 EXPLAIN 查看执行计划。 week_lookup 中的行是否连续?如果我们正在寻找过去的 34 周,似乎可以在 w.end_date 上添加另一个谓词,不仅应该小于最近的星期五,我们是否还知道 end_date 不会超过 34(或 35 ) 几周前,我们可以执行w.end_date &gt;= expr 来阻止查询回顾几十年的历史...... LIMIT 子句被应用last,这是在排序之后,在得到最小值之后和每天的最大值, 嗨,斯宾塞。正确,限制可能是不同的时间段。可能是 52 周或 28 周。在这种情况下,我让查询返回 34 周的结束数据(包括本周的内容)。 我注意到上面从 nbk 编辑的 SQL 删除了截至 5/8 的当前周。它只显示从 5/1 开始。我认为日期/星期的变化是问题所在。它需要捕获本周和最近的收盘价:DATE('2020-05-07' + INTERVAL (6 - DAYOFWEEK('2020-05-07')) DAY) 是否需要另一个 INNER JOIN 以某种方式从本周获取最后收盘价? 我检查了 WEEKLY LOOKUP 确实有 start_date 和 end_date 的索引,其中 end_date 是主键。 【参考方案1】:

计划 A:按照 [groupwise-max] 标签查找每个代码的最新收盘价。 (“最大值”指的是date;有趣的值是close。)大多数 groupwise-max 算法效率低下。 (或者跳过标签,去我的博客:http://mysql.rjweb.org/doc.php/groupwise_max)

B 计划:当您存储每天的收盘价时,使用INSERT ... ON DUPLICATE KEY UPDATE 插入或更新weekly 表中的行。假设记录按顺序排列,这将负责获得最后的收盘价。如果数据可能是乱序的,它就会变得更加混乱。

【讨论】:

以上是关于需要查询修复和优化帮助(查找每周股票数据的最高价、最高价和最后已知的收盘价)的主要内容,如果未能解决你的问题,请参考以下文章

需要帮助优化一个有趣的 MySQL 查询

如何取到所有股票(包括A股B股)某一天的价格(开盘价、最高价、最低价、收盘价,或其中一个价格)???

请教如何用WIND查询某只股票一段时间内的具体走势?

如何将现实世界 5 天的每日股票数据转换为每周模式以获得每周移动平均线

需要帮助优化 mysql 查询以使其按索引快速排序

如何在 R 中使用我的模型来查看真实世界的测试数据如何拟合?