(do ;; --------------------------------------------------------- ;; 1. Hilfsfunktion: Berechnet den WMA für einen gegebenen ;; Zeitpunkt auf einer Series. ;; --------------------------------------------------------- (def calc-wma (fn [s len] (do (def cnt (count s)) ;; Wenn nicht genug Daten da sind, gib 0 oder den letzten Wert zurück (if (< cnt len) 0.0 (do ;; Summe der Gewichte: n * (n + 1) / 2 (def weight-sum (/ (* len (+ len 1)) 2)) ;; Rekursive Berechnung der gewichteten Summe ;; Wir iterieren von 0 bis len-1 rückwärts (def w-total ((fn [i acc] (if (>= i len) acc (do ;; Gewicht: (len - i) -> Höchstes Gewicht für aktuelles Element (def w (- len i)) ;; Wert holen: (get s (count - 1 - i)) (def val (get s (- (- cnt 1) i))) ;; Tail-Recursion (recur (+ i 1) (+ acc (* w val))) ))) 0 0.0)) ;; Start bei i=0, acc=0.0 ;; Ergebnis: Gewichtete Summe / Summe der Gewichte (/ w-total weight-sum) ))))) ;; --------------------------------------------------------- ;; 2. Die HMA Factory ;; --------------------------------------------------------- (def create-hma (fn [len] (do ;; Konstanten vorberechnen (def half-len (Round (/ len 2))) (def sqrt-len (Round (sqrt len))) ;; !!! WICHTIG !!! ;; HMA benötigt eine Glättung der Differenz. ;; Da 'calc-wma' eine Series als Input erwartet, müssen wir ;; die Zwischenwerte (diff) in einer eigenen Series speichern. ;; Diese Series wird in der Closure "gefangen" (captured). (def diff-series (new-series :Float)) ;; Die eigentliche Funktion, die zurückgegeben wird (fn [source-series] (do ;; Schritt 1: WMA(n/2) * 2 (def wma-half (calc-wma source-series half-len)) ;; Schritt 2: WMA(n) (def wma-full (calc-wma source-series len)) ;; Schritt 3: Differenz berechnen (def diff (- (* 2 wma-half) wma-full)) ;; Schritt 4: Differenz in die interne Series schieben (add-item diff-series diff) ;; Schritt 5: WMA(sqrt(n)) auf der Differenz-Series berechnen (calc-wma diff-series sqrt-len) )) ))) )