postgresql - postgresql for in loop of a select statement - 通过迭代更新变量的问题
问题描述
我编写了一个函数来计算价格的指数移动平均线,该价格循环遍历 SELECT 语句的结果。移动平均线的长度为 26 天。对于前 25 行,EMA 的值为空。第 26 天只是前 26 个值的简单平均值。26 之后的任何行的 EMA 值为(当前行价格 - 前一行 EMA)*(2/27) + previous_row_EMA。
下面的循环使用 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
解决方案
我不确定问题出在哪里,但我在表达式中看到一个可能错误的点:
_EMAL = (_PCLOSE - last_ema26)*(2/27) + last_ema26;
Postgres 默认使用整数除法。可能2/27
不会返回您期望的结果
postgres=# select 2/27;
┌──────────┐
│ ?column? │
╞══════════╡
│ 0 │
└──────────┘
(1 row)
如果你想计算某个比率,那么你不应该使用整数常量
postgres=# select 2.0/27.0;
┌────────────────────────┐
│ ?column? │
╞════════════════════════╡
│ 0.07407407407407407407 │
└────────────────────────┘
(1 row)
推荐阅读
- c# - JSON.NET 无法反序列化 ulong 标志类型枚举
- python - 如果我不清除缓存,为什么我的 Flask 应用程序不呈现 CSS?
- php - PHP POST api 在邮递员中工作,但在颤振应用程序中不工作
- c - 不相交路径 - 查找矩阵中不相交路径的最大数量
- r - 如何知道 R 中某个命名颜色的 rgb 颜色代码?
- python - 将 sympy 函数转换为 lambda 函数
- swift - 如何截取整个屏幕的屏幕截图
- php - 如何在 laravel 7 中使用语言环境前缀发送 id
- javascript - plotly:在存储的 JSON 字符串中公开“config”对象,以便于使用 Plotly.JS 函数
- ios - 如何阻止 iOS 要求保存不正确的密码?