如何计算postgres的指数移动平均线?

Try*_*lks 19 sql postgresql statistics

我正在尝试在postgres上实现指数移动平均线(EMA),但是当我检查文档并考虑它时,我尝试的越多,我就越困惑.

公式为EMA(x):

EMA(x1) = x1
EMA(xn) = α * xn + (1 - α) * EMA(xn-1)

对于聚合器来说,它似乎是完美的,保持最后计算元素的结果正是这里必须完成的.但是聚合器会产生一个结果(缩减或折叠),这里我们需要一个结果列表(一列)(如map).我一直在检查程序和功能是如何工作的,但是AFAIK它们产生一个单独的输出而不是列.我已经看到了很多程序和函数,但是我无法弄清楚它是如何与关系代数交互的,特别是在做这样的事情时,EMA.

到目前为止,我没有运气搜索互联网.但是EMA的定义非常简单,我希望有可能将这个定义翻译成postgres中的一个简单而有效的东西,因为在我的上下文中迁移到NoSQL会过多.

谢谢.

PD:在这里您可以看到一个示例:https:
//docs.google.com/spreadsheet/ccc?key = 0AvfclSzBscS6dDJCNWlrT3NYdDJxbkh3cGJ2S2V0cVE

ara*_*nid 20

您可以定义自己的聚合函数,然后将其与窗口规范一起使用,以获取每个阶段的聚合输出,而不是单个值.

因此,聚合是一个状态,一个转换函数用于修改每一行的状态,还可以选择一个最终化函数将状态转换为输出值.对于这样的简单情况,只需一个变换函数就足够了.

create function ema_func(numeric, numeric) returns numeric
  language plpgsql as $$
declare
  alpha numeric := 0.5;
begin
  -- uncomment the following line to see what the parameters mean
  -- raise info 'ema_func: % %', $1, $2;
  return case
              when $1 is null then $2
              else alpha * $2 + (1 - alpha) * $1
         end;
end
$$;
create aggregate ema(basetype = numeric, sfunc = ema_func, stype = numeric);
Run Code Online (Sandbox Code Playgroud)

这给了我:

steve@steve@[local] =# select x, ema(x, 0.1) over(w), ema(x, 0.2) over(w) from data window w as (order by n asc) limit 5;
     x     |      ema      |      ema      
-----------+---------------+---------------
 44.988564 |     44.988564 |     44.988564
   39.5634 |    44.4460476 |    43.9035312
 38.605724 |   43.86201524 |   42.84396976
 38.209646 |  43.296778316 |  41.917105008
 44.541264 | 43.4212268844 | 42.4419368064
Run Code Online (Sandbox Code Playgroud)

这些数字似乎与您添加到问题中的电子表格相匹配.

此外,您可以定义函数以将alpha作为参数从语句中传递:

create or replace function ema_func(state numeric, inval numeric, alpha numeric)
  returns numeric
  language plpgsql as $$
begin
  return case
         when state is null then inval
         else alpha * inval + (1-alpha) * state
         end;
end
$$;

create aggregate ema(numeric, numeric) (sfunc = ema_func, stype = numeric);

select x, ema(x, 0.5 /* alpha */) over (order by n asc) from data
Run Code Online (Sandbox Code Playgroud)

此外,这个函数实际上非常简单,根本不需要在plpgsql中,但可以只是一个sql函数,尽管你不能在其中一个中按名称引用参数:

create or replace function ema_func(state numeric, inval numeric, alpha numeric)
  returns numeric
  language sql as $$
select case
       when $1 is null then $2
       else $3 * $2 + (1-$3) * $1
       end
$$;
Run Code Online (Sandbox Code Playgroud)