Last active
August 20, 2018 02:24
-
-
Save lnostdal/9075a6eb2899bf3c97ca7af23e333f14 to your computer and use it in GitHub Desktop.
Moving average in Clojure using JVM arrays vs. transducer variant
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; ...and yes; I know there are more efficient ways to do this. | |
(defn sma ^doubles [^doubles pseries ^long ma-len] | |
"Simple Moving Average: https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average | |
Returns a JVM double[]. Head is padded with ##NaN entries to align it with `pseries`." | |
(if (= ma-len 1) | |
pseries | |
(let [pseries-len (alength pseries), ret (double-array pseries-len ##NaN)] | |
;; Dealing with NaN isn't needed here as SMA doesn't carry previous results on forever like e.g. EMA does. | |
(loop [pseries-idx (- ma-len 1)] | |
(if (>= pseries-idx pseries-len) | |
ret | |
(do | |
(loop [prt-idx 0, prt-sum 0.0] | |
(if (= prt-idx ma-len) | |
(aset ret pseries-idx (/ prt-sum ma-len)) | |
(recur (+ prt-idx 1) (+ prt-sum (aget pseries (- pseries-idx prt-idx)))))) | |
(recur (inc pseries-idx)))))))) | |
(defn t-sma [^long ma-len] | |
(fn [xf] | |
(let [q (EvictingQueue/create ma-len)] | |
(fn | |
([] (xf)) | |
([result] (xf result)) | |
([result ^double price] | |
(.add q price) | |
(if (zero? (do (.remainingCapacity q))) | |
(xf result (com.google.common.math.Stats/meanOf q)) | |
(xf result ##NaN))))))) | |
;; quantataraxia.core> (println (seq (sma (double-array (range 1.0 20.0)) 10))) | |
;; (##NaN ##NaN ##NaN ##NaN ##NaN ##NaN ##NaN ##NaN ##NaN 5.5 6.5 7.5 8.5 9.5 10.5 11.5 12.5 13.5 14.5) | |
;; nil | |
;; quantataraxia.core> (println (sequence (t-sma 10) (range 1.0 20.0))) | |
;; (##NaN ##NaN ##NaN ##NaN ##NaN ##NaN ##NaN ##NaN ##NaN 5.5 6.5 7.5 8.5 9.5 10.5 11.5 12.5 13.5 14.5) | |
;; nil |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment