Я попытался реализовать его так, чтобы он сканировал входной вектор только один раз, используя формулу приращения, и возвращал следующие EMA и EMVAR в каждом цикле, используя только предыдущее значение каждого, и достиг того же результата, что и вы.
myemdev:{sqrt (flip {((1f-x)*y[0]+x*d*d;y[1]+x*d:z-y[1])}[x]\[(0;first y);y]) 0}
q)myemdev[(1%3);1,10#0]
0 0.4714045 0.496904 0.4566233 0.3981362 0.3381504 0.2829914 0.2347385 0.1936388 0.1591718 0.1305404
Но, несмотря на то, что он только циклически повторяет ввод, этот метод занимает значительно больше времени, чем ваш.
q)\t {sqrt 0f (1f-x)\0f^(1f-x)*x*d*d:y-prev ema[x;y]}[1%3;1,100000#0]
4
q)\t {sqrt (flip {((1f-x)*y[0]+x*d*d;y[1]+x*d:z-y[1])}[x]\[(0;first y);y]) 0}[1%3;1,100000#0]
189
q)\t ema[1%3;100000#0]
1
q)\t {{z+(1f-x)*y}[x]\[first y;y*x]}[1%3;1,100000#0]
57
Глядя на эти две функции, которые дают идентичные результаты, ясно, что методв форме {x y\z}
намного быстрее, чем та же функция, что и лямбда, хотя я не уверен в реализации оптимизации под капотом.
q)\t {(1)(1+x)\(x*y)}[0.005;1,1000000#0]
15
q)\t {{z+x*(1+y)}\[1;x;(x*y)]}[0.005;1,1000000#0]
711
Хотя в вашем методе используются два сканирования, обаимеют форму {x y\z}
и поэтому, с моей точки зрения, очень эффективны.Преимущество только одного сканирования входных данных с использованием чисто инкрементного метода перевешивается невозможностью поместить его в эту более эффективную форму, как (1f-x;1f)*y
в переставленном методе здесь: {sqrt (flip {(1f-x;1f)*y+x*(d,1f)*d:z-y[1]}[x]\[(0;first y);y]) 0}
не может быть предварительно вычислено, как мыне все доступные нам значения EMA (они рассчитываются для каждого цикла по мере необходимости).
Я буду продолжать искать улучшения в обоих методах, и мне было бы интересно узнать, сможет ли кто-нибудь превзойти ваш метод в терминахКПД