Требуется исправление запроса и помощь по оптимизации (которая находит максимальный максимум, максимальный минимум для ЕЖЕНЕДЕЛЬНЫХ данных о запасах и последнюю известную цену на закрытие недели) - PullRequest
0 голосов
/ 08 мая 2020

Спасибо за любую помощь, которую вы можете оказать. У меня есть запрос MySQL, который должен предоставить еженедельные цены на акции. Я не являюсь первоначальным автором сценария, который когда-то был написан как решение. Недавно мне пришлось адаптировать его для другой потребности.

Я неэффективно добавил цену закрытия для каждой недели (предыдущей), но я не могу получить цену закрытия для текущей недели, пока она не дойдет до пятницы. Для текущей недели (верхняя строка) он должен использовать последнюю цену закрытия, указанную на данный момент за неделю, до закрытия в пятницу.

Он работает очень медленно, и я В этом случае мы можем использовать пример AAPL, если вы посмотрите на недельный график.
Фондовая диаграмма 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.</p> <p>The WEEKLY_LOOKUP is a table that contains the START and END dates of each week as reference that represent a week from Monday (start_date) to Friday (end_date). I am not sure if I need to have something like that or if that is something that can get generated in?</p> <pre><code># 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) Первая строка - это текущая неделя. С каждым днем ​​до понедельника, вторника и т. Д. c. он должен определять, что является недельным максимумом и недельным минимумом, и предоставлять последнюю известную цену закрытия. Я смог напечатать цену закрытия за предыдущие недели, поскольку они приходятся на «пятницу». Например, если сегодня четверг, 7 мая, закрытие четверга было 302,92. Я бы хотел, чтобы он вытащил последнюю известную дату закрытия, которая известна за неделю. Я неэффективно добавил последнюю известную цену закрытия, чтобы я мог просто извлечь ее из набора результатов и программно заменить ее на текущую неделю, чтобы исправить проблему, но это не лучшее решение.
  • 2) Вы будете обратите внимание на неделю 4/10, что там также есть пустое пространство. Я считаю, что это была Страстная пятница, и рынки были закрыты. Чтобы исправить это, я думал, что я бы go вернулся к недельной таблице, чтобы изменить для этой недели дату окончания пятницы на дату окончания четверга, чтобы он использовал этот недельный диапазон, но, подумав об этом больше, мог бы запутались из-за того, что выполняется настройка INTERVAL diff, которая всегда ищет дату пятницы.

В идеале результат будет (при этом показано закрытие 5/7, поскольку у меня нет данные 5/8 еще), который предоставляет последнюю известную или связанную цену закрытия до закрытия недели. Если бы запрос был запущен во вторник 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
</code>

Наконец, похоже, что этот скрипт работает очень медленно, так как ему приходится проверять 34 недели назад для акции. Не уверен, как это можно оптимизировать, чтобы по-прежнему предоставлять необходимые данные, но эффективно.

Спасибо за любую помощь, которую вы можете предложить. Из-за моего ограниченного опыта и многих часов пробуя разные вещи, я подумал, что должен обратиться к совету к экспертам.

С большой признательностью.

1 Ответ

0 голосов
/ 09 мая 2020

План A: Следуйте тегу [groupwise-max], чтобы найти последнюю цену закрытия для каждого тикера. («Макс» относится к date; интересное значение - close.) Большинство алгоритмов группового максимума неэффективны. (Или пропустите тег и go в свой блог: http://mysql.rjweb.org/doc.php/groupwise_max)

План B: при сохранении закрытия на каждый день используйте INSERT ... ON DUPLICATE KEY UPDATE для вставки или обновления строка в таблице weekly. Предполагая, что записи поступают в порядке, это позаботится о получении последней цены закрытия. Если данные могут поступать в неправильном порядке, они становятся более беспорядочными.

...