Я написал функцию для вычисления экспоненциальной скользящей средней для цен, которая перебирает результаты оператора SELECT. Длина скользящей средней составляет 26 дней. Для первых 25 строк значение EMA равно нулю. 26-й день - это просто среднее значение первых 26 значений. Любая строка после 26 имеет значение EMA (текущая цена строки - предыдущая строка EMA) * (2/27) + previous_row_EMA.
Ниже l oop делает это с помощью операторов CASE. Я объявил переменную "sumlong" и установил ее в ноль. Переменная sumlong хранит текущее суммирование первых 25 строк. Второй оператор CASE вычисляет простое скользящее среднее за 26 дней. Я также объявил переменную «last_EMA26» в качестве временного держателя для использования в следующей итерации.
Кажется, что 26-я строка рассчитывается правильно, однако любая строка после 26-й строки, похоже, не содержит вычисления и использует то же значение, что и 26-я строка. Есть идеи, что я делаю не так? Не стесняйтесь оставлять отзывы о том, как я мог бы сделать этот код более эффективным. Я уверен, что это не самый эффективный способ, но я учусь.
CREATE OR REPLACE FUNCTION MACD()
RETURNS TABLE(
_ID INTEGER,
_CUSIP TEXT,
_DATETIME TIMESTAMP WITHOUT TIME ZONE,
_PCLOSE NUMERIC,
_ROWNUM BIGINT,
_EMAL NUMERIC
)
AS $$
DECLARE
sumlong numeric := 0.00;
sumshort numeric := 0.00;
last_ema26 numeric := 0.00;
BEGIN
FOR _ID, _CUSIP, _DATETIME, _PCLOSE, _ROWNUM IN
SELECT ID, CUSIP, datetime, pclose, k
FROM
(SELECT ID, CUSIP, datetime, (dhist::json->>'close')::numeric AS pclose, ROW_NUMBER () OVER(w) as K
FROM dailyhist
WHERE cusip = '00130H105'
WINDOW w AS (PARTITION BY CUSIP ORDER BY datetime)
) EMA
LOOP
CASE
WHEN _ROWNUM < 26 THEN
_EMAL := NULL;
sumlong := sumlong + _PCLOSE;
RAISE NOTICE '1 counter is: %, row: %, close: % emal: %, lastema: %', sumlong, _ROWNUM, _PCLOSE, _EMAL, last_ema26;
WHEN _ROWNUM = 26 THEN
_EMAL:= (sumlong + _PCLOSE)/26;
last_ema26 := _EMAL;
RAISE NOTICE '2 counter is: %, row: %, close: % emal: %, lastema: %', sumlong, _ROWNUM, _PCLOSE, _EMAL, last_ema26;
WHEN _ROWNUM > 26 THEN
_EMAL = (_PCLOSE - last_ema26)*(2/27) + last_ema26;
last_ema26 := _EMAL;
RAISE NOTICE '3 counter is: %, row: %, close: % emal: %, lastema: %', sumlong, _ROWNUM, _PCLOSE, _EMAL, last_ema26;
END CASE;
RETURN NEXT;
END LOOP;
END;$$
LANGUAGE 'plpgsql';
SELECT * FROM MACD();
Я также включил часть вывода:
NOTICE: 1 counter is: 3.37517, row: 1, close: 3.37517 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 6.79201, row: 2, close: 3.41684 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 10.18801, row: 3, close: 3.396 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 13.60485, row: 4, close: 3.41684 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 17.06336, row: 5, close: 3.45851 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 20.48020, row: 6, close: 3.41684 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 23.77203, row: 7, close: 3.29183 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 27.06386, row: 8, close: 3.29183 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 30.60570, row: 9, close: 3.54184 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 34.43922, row: 10, close: 3.83352 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 38.33525, row: 11, close: 3.89603 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 42.16877, row: 12, close: 3.83352 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 46.00229, row: 13, close: 3.83352 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 50.04416, row: 14, close: 4.04187 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 54.29437, row: 15, close: 4.25021 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 58.54458, row: 16, close: 4.25021 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 62.58645, row: 17, close: 4.04187 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 66.62832, row: 18, close: 4.04187 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 70.48268, row: 19, close: 3.85436 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 74.23287, row: 20, close: 3.75019 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 77.94139, row: 21, close: 3.70852 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 81.69158, row: 22, close: 3.75019 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 85.48344, row: 23, close: 3.79186 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 89.56698, row: 24, close: 4.08354 emal: <NULL>, lastema: <NULL>
NOTICE: 1 counter is: 93.73385, row: 25, close: 4.16687 emal: <NULL>, lastema: <NULL>
NOTICE: 2 counter is: 93.73385, row: 26, close: 4.20854 emal: 3.7670150000000000, lastema: 3.7670150000000000
NOTICE: 3 counter is: 93.73385, row: 27, close: 4.16687 emal: 3.7670150000000000, lastema: 3.7670150000000000
NOTICE: 3 counter is: 93.73385, row: 28, close: 4.08354 emal: 3.7670150000000000, lastema: 3.7670150000000000
NOTICE: 3 counter is: 93.73385, row: 29, close: 4.12521 emal: 3.7670150000000000, lastema: 3.7670150000000000
NOTICE: 3 counter is: 93.73385, row: 30, close: 4.12521 emal: 3.7670150000000000, lastema: 3.7670150000000000
NOTICE: 3 counter is: 93.73385, row: 31, close: 4.12521 emal: 3.7670150000000000, lastema: 3.7670150000000000
NOTICE: 3 counter is: 93.73385, row: 32, close: 4.0627 emal: 3.7670150000000000, lastema: 3.7670150000000000